Ok. I didn't make 2.4.0 in 2000. Tough. I tried, but we had some
[davej-history.git] / drivers / scsi / ips.c
blobd98c57686479ef40eb833deaf642b98ac9d73969
1 /*****************************************************************************/
2 /* ips.c -- driver for the IBM ServeRAID controller */
3 /* */
4 /* Written By: Keith Mitchell, IBM Corporation */
5 /* */
6 /* Copyright (C) 1999 IBM Corporation */
7 /* */
8 /* This program is free software; you can redistribute it and/or modify */
9 /* it under the terms of the GNU General Public License as published by */
10 /* the Free Software Foundation; either version 2 of the License, or */
11 /* (at your option) any later version. */
12 /* */
13 /* This program is distributed in the hope that it will be useful, */
14 /* but WITHOUT ANY WARRANTY; without even the implied warranty of */
15 /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
16 /* GNU General Public License for more details. */
17 /* */
18 /* NO WARRANTY */
19 /* THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR */
20 /* CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT */
21 /* LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, */
22 /* MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is */
23 /* solely responsible for determining the appropriateness of using and */
24 /* distributing the Program and assumes all risks associated with its */
25 /* exercise of rights under this Agreement, including but not limited to */
26 /* the risks and costs of program errors, damage to or loss of data, */
27 /* programs or equipment, and unavailability or interruption of operations. */
28 /* */
29 /* DISCLAIMER OF LIABILITY */
30 /* NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY */
31 /* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL */
32 /* DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND */
33 /* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR */
34 /* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE */
35 /* USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED */
36 /* HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES */
37 /* */
38 /* You should have received a copy of the GNU General Public License */
39 /* along with this program; if not, write to the Free Software */
40 /* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
41 /* */
42 /* Bugs/Comments/Suggestions should be mailed to: */
43 /* ipslinux@us.ibm.com */
44 /* */
45 /*****************************************************************************/
47 /*****************************************************************************/
48 /* Change Log */
49 /* */
50 /* 0.99.02 - Breakup commands that are bigger than 8 * the stripe size */
51 /* 0.99.03 - Make interrupt routine handle all completed request on the */
52 /* adapter not just the first one */
53 /* - Make sure passthru commands get woken up if we run out of */
54 /* SCBs */
55 /* - Send all of the commands on the queue at once rather than */
56 /* one at a time since the card will support it. */
57 /* 0.99.04 - Fix race condition in the passthru mechanism -- this required */
58 /* the interface to the utilities to change */
59 /* - Fix error recovery code */
60 /* 0.99.05 - Fix an oops when we get certain passthru commands */
61 /* 1.00.00 - Initial Public Release */
62 /* Functionally equivalent to 0.99.05 */
63 /* 3.60.00 - Bump max commands to 128 for use with ServeRAID firmware 3.60 */
64 /* - Change version to 3.60 to coincide with ServeRAID release */
65 /* numbering. */
66 /* 3.60.01 - Remove bogus error check in passthru routine */
67 /* 3.60.02 - Make DCDB direction based on lookup table */
68 /* - Only allow one DCDB command to a SCSI ID at a time */
69 /* 4.00.00 - Add support for ServeRAID 4 */
70 /* 4.00.01 - Add support for First Failure Data Capture */
71 /* 4.00.02 - Fix problem with PT DCDB with no buffer */
72 /* 4.00.03 - Add alternative passthru interface */
73 /* - Add ability to flash ServeRAID BIOS */
74 /* 4.00.04 - Rename structures/constants to be prefixed with IPS_ */
75 /* 4.00.05 - Remove wish_block from init routine */
76 /* - Use linux/spinlock.h instead of asm/spinlock.h for kernels */
77 /* 2.3.18 and later */
78 /* - Sync with other changes from the 2.3 kernels */
79 /* 4.00.06 - Fix timeout with initial FFDC command */
80 /* 4.00.06a - Port to 2.4 (trivial) -- Christoph Hellwig <hch@caldera.de> */
81 /* 4.10.00 - Add support for ServeRAID 4M/4L */
82 /* 4.10.13 - Fix for dynamic unload and proc file system */
83 /* 4.20.03 - Rename version to coincide with new release schedules */
84 /* Performance fixes */
85 /* Fix truncation of /proc files with cat */
86 /* Merge in changes through kernel 2.4.0test1ac21 */
87 /* 4.20.13 - Fix some failure cases / reset code */
88 /* - Hook into the reboot_notifier to flush the controller cache */
89 /* */
90 /*****************************************************************************/
93 * Conditional Compilation directives for this driver:
95 * IPS_DEBUG - Turn on debugging info
98 * Parameters:
100 * debug:<number> - Set debug level to <number>
101 * NOTE: only works when IPS_DEBUG compile directive
102 * is used.
104 * 1 - Normal debug messages
105 * 2 - Verbose debug messages
106 * 11 - Method trace (non interrupt)
107 * 12 - Method trace (includes interrupt)
109 * noreset - Don't reset the controller
110 * nocmdline - Turn off passthru support
111 * noi2o - Don't use I2O Queues (ServeRAID 4 only)
112 * nommap - Don't use memory mapped I/O
116 #include <linux/module.h>
118 #include <asm/io.h>
119 #include <asm/byteorder.h>
120 #include <linux/stddef.h>
121 #include <linux/version.h>
122 #include <linux/string.h>
123 #include <linux/errno.h>
124 #include <linux/kernel.h>
125 #include <linux/ioport.h>
126 #include <linux/malloc.h>
127 #include <linux/vmalloc.h>
128 #include <linux/delay.h>
129 #include <linux/sched.h>
130 #include <linux/pci.h>
131 #include <linux/proc_fs.h>
132 #include <linux/reboot.h>
134 #include <linux/blk.h>
135 #include <linux/types.h>
137 #ifndef NO_IPS_CMDLINE
138 #include <scsi/sg.h>
139 #endif
141 #include "sd.h"
142 #include "scsi.h"
143 #include "hosts.h"
144 #include "ips.h"
146 #include <linux/stat.h>
147 #include <linux/config.h>
149 #if LINUX_VERSION_CODE >= LinuxVersionCode(2,3,18)
150 #include <linux/spinlock.h>
151 #else
152 #include <asm/spinlock.h>
153 #endif
155 #if LINUX_VERSION_CODE >= LinuxVersionCode(2,3,13)
156 #include <linux/init.h>
157 #endif
159 #include <linux/smp.h>
161 #ifdef MODULE
162 static char *ips = NULL;
163 MODULE_PARM(ips, "s");
164 #endif
167 * DRIVER_VER
169 #define IPS_VERSION_HIGH "4.20"
170 #define IPS_VERSION_LOW ".20 "
172 #if LINUX_VERSION_CODE < LinuxVersionCode(2,3,27)
173 struct proc_dir_entry proc_scsi_ips = {
175 3, "ips",
176 S_IFDIR | S_IRUGO | S_IXUGO, 2
178 #endif
180 #if !defined(__i386__)
181 #error "This driver has only been tested on the x86 platform"
182 #endif
184 #if LINUX_VERSION_CODE < LinuxVersionCode(2,2,0)
185 #error "This driver only works with kernel 2.2.0 and later"
186 #endif
188 #if !defined(NO_IPS_CMDLINE) && ((SG_BIG_BUFF < 8192) || !defined(SG_BIG_BUFF))
189 #error "To use the command-line interface you need to define SG_BIG_BUFF"
190 #endif
192 #ifdef IPS_DEBUG
193 #define METHOD_TRACE(s, i) if (ips_debug >= (i+10)) printk(KERN_NOTICE s "\n");
194 #define DEBUG(i, s) if (ips_debug >= i) printk(KERN_NOTICE s "\n");
195 #define DEBUG_VAR(i, s, v...) if (ips_debug >= i) printk(KERN_NOTICE s "\n", v);
196 #else
197 #define METHOD_TRACE(s, i)
198 #define DEBUG(i, s)
199 #define DEBUG_VAR(i, s, v...)
200 #endif
203 * global variables
205 static const char * ips_name = "ips";
206 static struct Scsi_Host * ips_sh[IPS_MAX_ADAPTERS]; /* Array of host controller structures */
207 static ips_ha_t * ips_ha[IPS_MAX_ADAPTERS]; /* Array of HA structures */
208 static unsigned int ips_next_controller = 0;
209 static unsigned int ips_num_controllers = 0;
210 static unsigned int ips_released_controllers = 0;
211 static int ips_cmd_timeout = 60;
212 static int ips_reset_timeout = 60 * 5;
213 static int ips_force_memio = 1; /* Always use Memory Mapped I/O */
214 static int ips_force_i2o = 1; /* Always use I2O command delivery */
215 static int ips_resetcontroller = 1; /* Reset the controller */
216 static int ips_cmdline = 1; /* Support for passthru */
218 #ifdef IPS_DEBUG
219 static int ips_debug = 0; /* Debug mode */
220 #endif
223 * Necessary forward function protoypes
225 static int ips_halt(struct notifier_block *nb, ulong event, void *buf);
227 #define MAX_ADAPTER_NAME 9
229 static char ips_adapter_name[][30] = {
230 "ServeRAID",
231 "ServeRAID II",
232 "ServeRAID on motherboard",
233 "ServeRAID on motherboard",
234 "ServeRAID 3H",
235 "ServeRAID 3L",
236 "ServeRAID 4H",
237 "ServeRAID 4M",
238 "ServeRAID 4L"
241 static struct notifier_block ips_notifier = {
242 ips_halt, NULL, 0
246 * Direction table
248 static char ips_command_direction[] = {
249 IPS_DATA_NONE, IPS_DATA_NONE, IPS_DATA_IN, IPS_DATA_IN, IPS_DATA_OUT,
250 IPS_DATA_IN, IPS_DATA_IN, IPS_DATA_OUT, IPS_DATA_IN, IPS_DATA_UNK,
251 IPS_DATA_OUT, IPS_DATA_OUT, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK,
252 IPS_DATA_IN, IPS_DATA_NONE, IPS_DATA_IN, IPS_DATA_IN, IPS_DATA_OUT,
253 IPS_DATA_IN, IPS_DATA_OUT, IPS_DATA_NONE, IPS_DATA_NONE, IPS_DATA_OUT,
254 IPS_DATA_NONE, IPS_DATA_IN, IPS_DATA_NONE, IPS_DATA_IN, IPS_DATA_OUT,
255 IPS_DATA_NONE, IPS_DATA_UNK, IPS_DATA_IN, IPS_DATA_UNK, IPS_DATA_IN,
256 IPS_DATA_UNK, IPS_DATA_OUT, IPS_DATA_IN, IPS_DATA_UNK, IPS_DATA_UNK,
257 IPS_DATA_IN, IPS_DATA_IN, IPS_DATA_OUT, IPS_DATA_NONE, IPS_DATA_UNK,
258 IPS_DATA_IN, IPS_DATA_OUT, IPS_DATA_OUT, IPS_DATA_OUT, IPS_DATA_OUT,
259 IPS_DATA_OUT, IPS_DATA_NONE, IPS_DATA_IN, IPS_DATA_NONE, IPS_DATA_NONE,
260 IPS_DATA_IN, IPS_DATA_OUT, IPS_DATA_OUT, IPS_DATA_OUT, IPS_DATA_OUT,
261 IPS_DATA_IN, IPS_DATA_OUT, IPS_DATA_IN, IPS_DATA_OUT, IPS_DATA_OUT,
262 IPS_DATA_OUT, IPS_DATA_IN, IPS_DATA_IN, IPS_DATA_IN, IPS_DATA_NONE,
263 IPS_DATA_UNK, IPS_DATA_NONE, IPS_DATA_NONE, IPS_DATA_NONE, IPS_DATA_UNK,
264 IPS_DATA_NONE, IPS_DATA_OUT, IPS_DATA_IN, IPS_DATA_UNK, IPS_DATA_UNK,
265 IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK,
266 IPS_DATA_OUT, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK,
267 IPS_DATA_IN, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK,
268 IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK,
269 IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK,
270 IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK,
271 IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK,
272 IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK,
273 IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK,
274 IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK,
275 IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK,
276 IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK,
277 IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK,
278 IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK,
279 IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK,
280 IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK,
281 IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK,
282 IPS_DATA_NONE, IPS_DATA_NONE, IPS_DATA_UNK, IPS_DATA_IN, IPS_DATA_NONE,
283 IPS_DATA_OUT, IPS_DATA_UNK, IPS_DATA_NONE, IPS_DATA_UNK, IPS_DATA_OUT,
284 IPS_DATA_OUT, IPS_DATA_OUT, IPS_DATA_OUT, IPS_DATA_OUT, IPS_DATA_NONE,
285 IPS_DATA_UNK, IPS_DATA_IN, IPS_DATA_OUT, IPS_DATA_IN, IPS_DATA_IN,
286 IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK,
287 IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK,
288 IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK,
289 IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK,
290 IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK,
291 IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK,
292 IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK,
293 IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK,
294 IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK,
295 IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_OUT,
296 IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK,
297 IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK,
298 IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK,
299 IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK
303 * Function prototypes
305 int ips_detect(Scsi_Host_Template *);
306 int ips_release(struct Scsi_Host *);
307 int ips_eh_abort(Scsi_Cmnd *);
308 int ips_eh_reset(Scsi_Cmnd *);
309 int ips_queue(Scsi_Cmnd *, void (*) (Scsi_Cmnd *));
310 int ips_biosparam(Disk *, kdev_t, int *);
311 const char * ips_info(struct Scsi_Host *);
312 void do_ipsintr(int, void *, struct pt_regs *);
313 static int ips_hainit(ips_ha_t *);
314 static int ips_map_status(ips_ha_t *, ips_scb_t *, ips_stat_t *);
315 static int ips_send(ips_ha_t *, ips_scb_t *, ips_scb_callback);
316 static int ips_send_wait(ips_ha_t *, ips_scb_t *, int, int);
317 static int ips_send_cmd(ips_ha_t *, ips_scb_t *);
318 static int ips_online(ips_ha_t *, ips_scb_t *);
319 static int ips_inquiry(ips_ha_t *, ips_scb_t *);
320 static int ips_rdcap(ips_ha_t *, ips_scb_t *);
321 static int ips_msense(ips_ha_t *, ips_scb_t *);
322 static int ips_reqsen(ips_ha_t *, ips_scb_t *);
323 static int ips_allocatescbs(ips_ha_t *);
324 static int ips_reset_copperhead(ips_ha_t *);
325 static int ips_reset_copperhead_memio(ips_ha_t *);
326 static int ips_reset_morpheus(ips_ha_t *);
327 static int ips_issue_copperhead(ips_ha_t *, ips_scb_t *);
328 static int ips_issue_copperhead_memio(ips_ha_t *, ips_scb_t *);
329 static int ips_issue_i2o(ips_ha_t *, ips_scb_t *);
330 static int ips_issue_i2o_memio(ips_ha_t *, ips_scb_t *);
331 static int ips_isintr_copperhead(ips_ha_t *);
332 static int ips_isintr_copperhead_memio(ips_ha_t *);
333 static int ips_isintr_morpheus(ips_ha_t *);
334 static int ips_wait(ips_ha_t *, int, int);
335 static int ips_write_driver_status(ips_ha_t *, int);
336 static int ips_read_adapter_status(ips_ha_t *, int);
337 static int ips_read_subsystem_parameters(ips_ha_t *, int);
338 static int ips_read_config(ips_ha_t *, int);
339 static int ips_clear_adapter(ips_ha_t *, int);
340 static int ips_readwrite_page5(ips_ha_t *, int, int);
341 static int ips_init_copperhead(ips_ha_t *);
342 static int ips_init_copperhead_memio(ips_ha_t *);
343 static int ips_init_morpheus(ips_ha_t *);
344 static int ips_isinit_copperhead(ips_ha_t *);
345 static int ips_isinit_copperhead_memio(ips_ha_t *);
346 static int ips_isinit_morpheus(ips_ha_t *);
347 static u32 ips_statupd_copperhead(ips_ha_t *);
348 static u32 ips_statupd_copperhead_memio(ips_ha_t *);
349 static u32 ips_statupd_morpheus(ips_ha_t *);
350 static void ips_select_queue_depth(struct Scsi_Host *, Scsi_Device *);
351 static void ips_chkstatus(ips_ha_t *, IPS_STATUS *);
352 static void ips_enable_int_copperhead(ips_ha_t *);
353 static void ips_enable_int_copperhead_memio(ips_ha_t *);
354 static void ips_enable_int_morpheus(ips_ha_t *);
355 static void ips_intr_copperhead(ips_ha_t *);
356 static void ips_intr_morpheus(ips_ha_t *);
357 static void ips_next(ips_ha_t *, int);
358 static void ipsintr_blocking(ips_ha_t *, struct ips_scb *);
359 static void ipsintr_done(ips_ha_t *, struct ips_scb *);
360 static void ips_done(ips_ha_t *, ips_scb_t *);
361 static void ips_free(ips_ha_t *);
362 static void ips_init_scb(ips_ha_t *, ips_scb_t *);
363 static void ips_freescb(ips_ha_t *, ips_scb_t *);
364 static void ips_statinit(ips_ha_t *);
365 static void ips_statinit_memio(ips_ha_t *);
366 static void ips_fix_ffdc_time(ips_ha_t *, ips_scb_t *, time_t);
367 static void ips_ffdc_reset(ips_ha_t *, int);
368 static void ips_ffdc_time(ips_ha_t *, int);
369 static ips_scb_t * ips_getscb(ips_ha_t *);
370 static inline void ips_putq_scb_head(ips_scb_queue_t *, ips_scb_t *);
371 static inline void ips_putq_scb_tail(ips_scb_queue_t *, ips_scb_t *);
372 static inline ips_scb_t * ips_removeq_scb_head(ips_scb_queue_t *);
373 static inline ips_scb_t * ips_removeq_scb(ips_scb_queue_t *, ips_scb_t *);
374 static inline void ips_putq_wait_head(ips_wait_queue_t *, Scsi_Cmnd *);
375 static inline void ips_putq_wait_tail(ips_wait_queue_t *, Scsi_Cmnd *);
376 static inline Scsi_Cmnd * ips_removeq_wait_head(ips_wait_queue_t *);
377 static inline Scsi_Cmnd * ips_removeq_wait(ips_wait_queue_t *, Scsi_Cmnd *);
378 static inline void ips_putq_copp_head(ips_copp_queue_t *, ips_copp_wait_item_t *);
379 static inline void ips_putq_copp_tail(ips_copp_queue_t *, ips_copp_wait_item_t *);
380 static inline ips_copp_wait_item_t * ips_removeq_copp(ips_copp_queue_t *, ips_copp_wait_item_t *);
381 static inline ips_copp_wait_item_t * ips_removeq_copp_head(ips_copp_queue_t *);
382 static int ips_erase_bios(ips_ha_t *);
383 static int ips_program_bios(ips_ha_t *, char *, int);
384 static int ips_verify_bios(ips_ha_t *, char *, int);
385 static int ips_erase_bios_memio(ips_ha_t *);
386 static int ips_program_bios_memio(ips_ha_t *, char *, int);
387 static int ips_verify_bios_memio(ips_ha_t *, char *, int);
389 #ifndef NO_IPS_CMDLINE
390 static int ips_is_passthru(Scsi_Cmnd *);
391 static int ips_make_passthru(ips_ha_t *, Scsi_Cmnd *, ips_scb_t *);
392 static int ips_usrcmd(ips_ha_t *, ips_passthru_t *, ips_scb_t *);
393 static int ips_newusrcmd(ips_ha_t *, ips_passthru_t *, ips_scb_t *);
394 static void ips_cleanup_passthru(ips_ha_t *, ips_scb_t *);
395 #endif
397 int ips_proc_info(char *, char **, off_t, int, int, int);
398 static int ips_host_info(ips_ha_t *, char *, off_t, int);
399 static void copy_mem_info(IPS_INFOSTR *, char *, int);
400 static int copy_info(IPS_INFOSTR *, char *, ...);
402 /*--------------------------------------------------------------------------*/
403 /* Exported Functions */
404 /*--------------------------------------------------------------------------*/
406 /****************************************************************************/
407 /* */
408 /* Routine Name: ips_setup */
409 /* */
410 /* Routine Description: */
411 /* */
412 /* setup parameters to the driver */
413 /* */
414 /****************************************************************************/
415 #if LINUX_VERSION_CODE >= LinuxVersionCode(2,3,13)
416 static int
417 ips_setup(char *ips_str) {
418 #else
419 void
420 ips_setup(char *ips_str, int *dummy) {
421 #endif
422 int i;
423 char *p;
424 char *key;
425 char *value;
426 char tokens[3] = {',', '.', 0};
427 IPS_OPTION options[] = {
428 {"noreset", &ips_resetcontroller, 0},
429 #ifdef IPS_DEBUG
430 {"debug", &ips_debug, 1},
431 #endif
432 {"noi2o", &ips_force_i2o, 0},
433 {"nommap", &ips_force_memio, 0},
434 {"nocmdline", &ips_cmdline, 0},
437 METHOD_TRACE("ips_setup", 1);
439 for (key = strtok(ips_str, tokens); key; key = strtok(NULL, tokens)) {
440 p = key;
442 /* Search for value */
443 while ((p) && (*p != ':'))
444 p++;
446 if (p) {
447 *p = '\0';
448 value = p+1;
449 } else
450 value = NULL;
453 * We now have key/value pairs.
454 * Update the variables
456 for (i = 0; i < (sizeof(options) / sizeof(options[0])); i++) {
457 if (strnicmp(key, options[i].option_name, strlen(ips_str)) == 0) {
458 if (value)
459 *options[i].option_flag = simple_strtoul(value, NULL, 0);
460 else
461 *options[i].option_flag = options[i].option_value;
463 break;
467 #if LINUX_VERSION_CODE >= LinuxVersionCode(2,3,13)
468 return (1);
469 #endif
472 #if LINUX_VERSION_CODE >= LinuxVersionCode(2,3,13)
473 __setup("ips=", ips_setup);
474 #endif
476 /****************************************************************************/
477 /* */
478 /* Routine Name: ips_detect */
479 /* */
480 /* Routine Description: */
481 /* */
482 /* Detect and initialize the driver */
483 /* */
484 /* NOTE: this routine is called under the io_request_lock spinlock */
485 /* */
486 /****************************************************************************/
488 ips_detect(Scsi_Host_Template *SHT) {
489 struct Scsi_Host *sh;
490 ips_ha_t *ha;
491 u32 io_addr;
492 u32 mem_addr;
493 u32 io_len;
494 u32 mem_len;
495 u16 planer;
496 u8 revision_id;
497 u8 bus;
498 u8 func;
499 u8 irq;
500 u16 deviceID[2];
501 int i;
502 int j;
503 char *ioremap_ptr;
504 char *mem_ptr;
505 struct pci_dev *dev[2];
506 struct pci_dev *morpheus = NULL;
507 struct pci_dev *trombone = NULL;
508 #if LINUX_VERSION_CODE < LinuxVersionCode(2,3,14)
509 u32 currbar;
510 u32 maskbar;
511 u8 barnum;
512 #endif
514 METHOD_TRACE("ips_detect", 1);
516 #ifdef MODULE
517 if (ips)
518 #if LINUX_VERSION_CODE >= LinuxVersionCode(2,3,13)
519 ips_setup(ips);
520 #else
521 ips_setup(ips, NULL);
522 #endif
523 #endif
525 SHT->proc_info = ips_proc_info;
526 #if LINUX_VERSION_CODE < LinuxVersionCode(2,3,27)
527 SHT->proc_dir = &proc_scsi_ips;
528 #else
529 SHT->proc_name = "ips";
530 #endif
532 #if defined(CONFIG_PCI)
534 /* initalize number of controllers */
535 ips_num_controllers = 0;
536 ips_next_controller = 0;
537 ips_released_controllers = 0;
539 if (!pci_present())
540 return (0);
542 morpheus = pci_find_device(IPS_VENDORID, IPS_MORPHEUS_DEVICEID, morpheus);
543 trombone = pci_find_device(IPS_VENDORID, IPS_COPPERHEAD_DEVICEID, trombone);
545 /* determine which controller to probe first */
546 if (!morpheus) {
547 /* we only have trombone */
548 dev[0] = trombone;
549 dev[1] = NULL;
550 deviceID[0] = IPS_COPPERHEAD_DEVICEID;
551 } else if (!trombone) {
552 /* we only have morpheus */
553 dev[0] = morpheus;
554 dev[1] = NULL;
555 deviceID[0] = IPS_MORPHEUS_DEVICEID;
556 } else {
557 /* we have both in the system */
558 if (trombone->bus < morpheus->bus) {
559 dev[0] = trombone;
560 dev[1] = morpheus;
561 deviceID[0] = IPS_COPPERHEAD_DEVICEID;
562 deviceID[1] = IPS_MORPHEUS_DEVICEID;
563 } else if (trombone->bus > morpheus->bus) {
564 dev[0] = morpheus;
565 dev[1] = trombone;
566 deviceID[0] = IPS_MORPHEUS_DEVICEID;
567 deviceID[1] = IPS_COPPERHEAD_DEVICEID;
568 } else {
569 /* further detection required */
570 if (trombone->devfn < morpheus->devfn) {
571 dev[0] = trombone;
572 dev[1] = morpheus;
573 deviceID[0] = IPS_COPPERHEAD_DEVICEID;
574 deviceID[1] = IPS_MORPHEUS_DEVICEID;
575 } else {
576 dev[0] = morpheus;
577 dev[1] = trombone;
578 deviceID[0] = IPS_MORPHEUS_DEVICEID;
579 deviceID[1] = IPS_COPPERHEAD_DEVICEID;
584 /* Now scan the controllers */
585 for (i = 0; i < 2; i++) {
586 if (!dev[i])
587 break;
589 do {
590 if (ips_next_controller >= IPS_MAX_ADAPTERS)
591 break;
593 #if LINUX_VERSION_CODE >= LinuxVersionCode(2,4,0)
594 if (pci_enable_device(dev[i]))
595 break;
596 #endif
598 /* stuff that we get in dev */
599 irq = dev[i]->irq;
600 bus = dev[i]->bus->number;
601 func = dev[i]->devfn;
603 /* Init MEM/IO addresses to 0 */
604 mem_addr = 0;
605 io_addr = 0;
606 mem_len = 0;
607 io_len = 0;
609 for (j = 0; j < 2; j++) {
610 #if LINUX_VERSION_CODE >= LinuxVersionCode(2,4,0)
611 if (!pci_resource_start(dev[i], j))
612 break;
614 if (pci_resource_flags(dev[i], j) & IORESOURCE_IO) {
615 io_addr = pci_resource_start(dev[i], j);
616 io_len = pci_resource_len(dev[i], j);
617 } else {
618 mem_addr = pci_resource_start(dev[i], j);
619 mem_len = pci_resource_len(dev[i], j);
621 #elif LINUX_VERSION_CODE >= LinuxVersionCode(2,3,14)
622 if (!dev[i]->resource[j].start)
623 break;
625 if ((dev[i]->resource[j].start & PCI_BASE_ADDRESS_SPACE) == PCI_BASE_ADDRESS_SPACE_IO) {
626 io_addr = dev[i]->resource[j].start;
627 io_len = dev[i]->resource[j].end - dev[i]->resource[j].start + 1;
628 } else {
629 mem_addr = dev[i]->resource[j].start;
630 mem_len = dev[i]->resource[j].end - dev[i]->resource[j].start + 1;
632 #else
633 if (!dev[i]->base_address[j])
634 break;
636 if ((dev[i]->base_address[j] & PCI_BASE_ADDRESS_SPACE) == PCI_BASE_ADDRESS_SPACE_IO) {
637 barnum = PCI_BASE_ADDRESS_0 + (j * 4);
638 io_addr = dev[i]->base_address[j] & PCI_BASE_ADDRESS_IO_MASK;
640 /* Get Size */
641 pci_read_config_dword(dev[i], barnum, &currbar);
642 pci_write_config_dword(dev[i], barnum, ~0);
643 pci_read_config_dword(dev[i], barnum, &maskbar);
644 pci_write_config_dword(dev[i], barnum, currbar);
646 io_len = ~(maskbar & PCI_BASE_ADDRESS_IO_MASK) + 1;
647 } else {
648 barnum = PCI_BASE_ADDRESS_0 + (j * 4);
649 mem_addr = dev[i]->base_address[j] & PCI_BASE_ADDRESS_MEM_MASK;
651 /* Get Size */
652 pci_read_config_dword(dev[i], barnum, &currbar);
653 pci_write_config_dword(dev[i], barnum, ~0);
654 pci_read_config_dword(dev[i], barnum, &maskbar);
655 pci_write_config_dword(dev[i], barnum, currbar);
657 mem_len = ~(maskbar & PCI_BASE_ADDRESS_MEM_MASK) + 1;
659 #endif
662 /* setup memory mapped area (if applicable) */
663 if (mem_addr) {
664 u32 base;
665 u32 offs;
667 DEBUG_VAR(1, "(%s%d) detect, Memory region %x, size: %d",
668 ips_name, ips_next_controller, mem_addr, mem_len);
670 #if LINUX_VERSION_CODE >= LinuxVersionCode(2,3,17)
671 if (check_mem_region(mem_addr, mem_len)) {
672 /* Couldn't allocate io space */
673 printk(KERN_WARNING "(%s%d) couldn't allocate IO space %x len %d.\n",
674 ips_name, ips_next_controller, io_addr, io_len);
676 ips_next_controller++;
678 continue;
681 request_mem_region(mem_addr, mem_len, "ips");
682 #endif
684 base = mem_addr & PAGE_MASK;
685 offs = mem_addr - base;
687 ioremap_ptr = ioremap(base, PAGE_SIZE);
688 mem_ptr = ioremap_ptr + offs;
689 } else {
690 ioremap_ptr = NULL;
691 mem_ptr = NULL;
694 /* setup I/O mapped area (if applicable) */
695 if (io_addr) {
696 DEBUG_VAR(1, "(%s%d) detect, IO region %x, size: %d",
697 ips_name, ips_next_controller, io_addr, io_len);
699 if (check_region(io_addr, io_len)) {
700 /* Couldn't allocate io space */
701 printk(KERN_WARNING "(%s%d) couldn't allocate IO space %x len %d.\n",
702 ips_name, ips_next_controller, io_addr, io_len);
704 ips_next_controller++;
706 continue;
709 request_region(io_addr, io_len, "ips");
712 /* get planer status */
713 if (pci_read_config_word(dev[i], 0x04, &planer)) {
714 printk(KERN_WARNING "(%s%d) can't get planer status.\n",
715 ips_name, ips_next_controller);
717 ips_next_controller++;
719 continue;
722 /* check to see if an onboard planer controller is disabled */
723 if (!(planer & 0x000C)) {
725 DEBUG_VAR(1, "(%s%d) detect, Onboard ServeRAID disabled by BIOS",
726 ips_name, ips_next_controller);
728 ips_next_controller++;
730 continue;
733 DEBUG_VAR(1, "(%s%d) detect bus %d, func %x, irq %d, io %x, mem: %x, ptr: %x",
734 ips_name, ips_next_controller, bus, func, irq, io_addr, mem_addr, (u32) mem_ptr);
736 /* get the revision ID */
737 if (pci_read_config_byte(dev[i], 0x08, &revision_id)) {
738 printk(KERN_WARNING "(%s%d) can't get revision id.\n",
739 ips_name, ips_next_controller);
741 ips_next_controller++;
743 continue;
746 /* found a controller */
747 sh = scsi_register(SHT, sizeof(ips_ha_t));
749 if (sh == NULL) {
750 printk(KERN_WARNING "(%s%d) Unable to register controller with SCSI subsystem - skipping controller\n",
751 ips_name, ips_next_controller);
753 ips_next_controller++;
755 continue;
758 ha = IPS_HA(sh);
759 memset(ha, 0, sizeof(ips_ha_t));
761 /* Initialize spin lock */
762 spin_lock_init(&ha->scb_lock);
763 spin_lock_init(&ha->copp_lock);
764 spin_lock_init(&ha->ips_lock);
765 spin_lock_init(&ha->copp_waitlist.lock);
766 spin_lock_init(&ha->scb_waitlist.lock);
767 spin_lock_init(&ha->scb_activelist.lock);
769 ips_sh[ips_next_controller] = sh;
770 ips_ha[ips_next_controller] = ha;
771 ips_num_controllers++;
772 ha->active = 1;
774 ha->enq = kmalloc(sizeof(IPS_ENQ), GFP_ATOMIC|GFP_DMA);
776 if (!ha->enq) {
777 printk(KERN_WARNING "(%s%d) Unable to allocate host inquiry structure - skipping contoller\n",
778 ips_name, ips_next_controller);
780 ha->active = 0;
781 ips_free(ha);
782 ips_next_controller++;
783 ips_num_controllers--;
785 continue;
788 ha->adapt = kmalloc(sizeof(IPS_ADAPTER), GFP_ATOMIC|GFP_DMA);
790 if (!ha->adapt) {
791 printk(KERN_WARNING "(%s%d) Unable to allocate host adapt structure - skipping controller\n",
792 ips_name, ips_next_controller);
793 ha->active = 0;
794 ips_free(ha);
795 ips_next_controller++;
796 ips_num_controllers--;
798 continue;
801 ha->conf = kmalloc(sizeof(IPS_CONF), GFP_ATOMIC|GFP_DMA);
803 if (!ha->conf) {
804 printk(KERN_WARNING "(%s%d) Unable to allocate host conf structure - skipping controller\n",
805 ips_name, ips_next_controller);
807 ha->active = 0;
808 ips_free(ha);
809 ips_next_controller++;
810 ips_num_controllers--;
812 continue;
815 ha->nvram = kmalloc(sizeof(IPS_NVRAM_P5), GFP_ATOMIC|GFP_DMA);
817 if (!ha->nvram) {
818 printk(KERN_WARNING "(%s%d) Unable to allocate host nvram structure - skipping controller\n",
819 ips_name, ips_next_controller);
821 ha->active = 0;
822 ips_free(ha);
823 ips_next_controller++;
824 ips_num_controllers--;
826 continue;
829 ha->subsys = kmalloc(sizeof(IPS_SUBSYS), GFP_ATOMIC|GFP_DMA);
831 if (!ha->subsys) {
832 printk(KERN_WARNING "(%s%d) Unable to allocate host subsystem structure - skipping controller\n",
833 ips_name, ips_next_controller);
835 ha->active = 0;
836 ips_free(ha);
837 ips_next_controller++;
838 ips_num_controllers--;
840 continue;
843 ha->dummy = kmalloc(sizeof(IPS_IO_CMD), GFP_ATOMIC|GFP_DMA);
845 if (!ha->dummy) {
846 printk(KERN_WARNING "(%s%d) Unable to allocate host dummy structure - skipping controller\n",
847 ips_name, ips_next_controller);
849 ha->active = 0;
850 ips_free(ha);
851 ips_next_controller++;
852 ips_num_controllers--;
854 continue;
857 ha->ioctl_data = kmalloc(IPS_IOCTL_SIZE, GFP_ATOMIC|GFP_DMA);
858 ha->ioctl_datasize = IPS_IOCTL_SIZE;
859 if (!ha->ioctl_data) {
860 printk(KERN_WARNING "(%s%d) Unable to allocate ioctl data - skipping controller\n",
861 ips_name, ips_next_controller);
863 ha->active = 0;
864 ips_free(ha);
865 ips_next_controller++;
866 ips_num_controllers--;
868 continue;
871 /* Store away needed values for later use */
872 sh->io_port = io_addr;
873 sh->n_io_port = io_addr ? 255 : 0;
874 sh->unique_id = (io_addr) ? io_addr : mem_addr;
875 sh->irq = irq;
876 sh->select_queue_depths = ips_select_queue_depth;
877 sh->sg_tablesize = sh->hostt->sg_tablesize;
878 sh->can_queue = sh->hostt->can_queue;
879 sh->cmd_per_lun = sh->hostt->cmd_per_lun;
880 sh->unchecked_isa_dma = sh->hostt->unchecked_isa_dma;
881 sh->use_clustering = sh->hostt->use_clustering;
883 #if LINUX_VERSION_CODE < LinuxVersionCode(2,3,32)
884 sh->wish_block = FALSE;
885 #endif
887 /* Store info in HA structure */
888 ha->irq = irq;
889 ha->io_addr = io_addr;
890 ha->io_len = io_len;
891 ha->mem_addr = mem_addr;
892 ha->mem_len = mem_len;
893 ha->mem_ptr = mem_ptr;
894 ha->ioremap_ptr = ioremap_ptr;
895 ha->host_num = ips_next_controller;
896 ha->revision_id = revision_id;
897 ha->device_id = deviceID[i];
898 ha->pcidev = dev[i];
901 * Setup Functions
903 if (IPS_IS_MORPHEUS(ha)) {
904 /* morpheus */
905 ha->func.isintr = ips_isintr_morpheus;
906 ha->func.isinit = ips_isinit_morpheus;
907 ha->func.issue = ips_issue_i2o_memio;
908 ha->func.init = ips_init_morpheus;
909 ha->func.statupd = ips_statupd_morpheus;
910 ha->func.reset = ips_reset_morpheus;
911 ha->func.intr = ips_intr_morpheus;
912 ha->func.enableint = ips_enable_int_morpheus;
913 } else if (IPS_USE_MEMIO(ha)) {
914 /* copperhead w/MEMIO */
915 ha->func.isintr = ips_isintr_copperhead_memio;
916 ha->func.isinit = ips_isinit_copperhead_memio;
917 ha->func.init = ips_init_copperhead_memio;
918 ha->func.statupd = ips_statupd_copperhead_memio;
919 ha->func.statinit = ips_statinit_memio;
920 ha->func.reset = ips_reset_copperhead_memio;
921 ha->func.intr = ips_intr_copperhead;
922 ha->func.erasebios = ips_erase_bios_memio;
923 ha->func.programbios = ips_program_bios_memio;
924 ha->func.verifybios = ips_verify_bios_memio;
925 ha->func.enableint = ips_enable_int_copperhead_memio;
927 if (IPS_USE_I2O_DELIVER(ha))
928 ha->func.issue = ips_issue_i2o_memio;
929 else
930 ha->func.issue = ips_issue_copperhead_memio;
931 } else {
932 /* copperhead */
933 ha->func.isintr = ips_isintr_copperhead;
934 ha->func.isinit = ips_isinit_copperhead;
935 ha->func.init = ips_init_copperhead;
936 ha->func.statupd = ips_statupd_copperhead;
937 ha->func.statinit = ips_statinit;
938 ha->func.reset = ips_reset_copperhead;
939 ha->func.intr = ips_intr_copperhead;
940 ha->func.erasebios = ips_erase_bios;
941 ha->func.programbios = ips_program_bios;
942 ha->func.verifybios = ips_verify_bios;
943 ha->func.enableint = ips_enable_int_copperhead;
945 if (IPS_USE_I2O_DELIVER(ha))
946 ha->func.issue = ips_issue_i2o;
947 else
948 ha->func.issue = ips_issue_copperhead;
952 * Initialize the card if it isn't already
954 if (!(*ha->func.isinit)(ha)) {
955 if (!(*ha->func.init)(ha)) {
957 * Initialization failed
959 printk(KERN_WARNING "(%s%d) unable to initialize controller - skipping controller\n",
960 ips_name, ips_next_controller);
962 ha->active = 0;
963 ips_free(ha);
964 ips_next_controller++;
965 ips_num_controllers--;
967 continue;
971 /* install the interrupt handler */
972 if (request_irq(irq, do_ipsintr, SA_SHIRQ, ips_name, ha)) {
973 printk(KERN_WARNING "(%s%d) unable to install interrupt handler - skipping controller\n",
974 ips_name, ips_next_controller);
976 ha->active = 0;
977 ips_free(ha);
978 ips_next_controller++;
979 ips_num_controllers--;
981 continue;
985 * Allocate a temporary SCB for initialization
987 ha->scbs = (ips_scb_t *) kmalloc(sizeof(ips_scb_t), GFP_ATOMIC|GFP_DMA);
988 if (!ha->scbs) {
989 /* couldn't allocate a temp SCB */
990 printk(KERN_WARNING "(%s%d) unable to allocate CCBs - skipping contoller\n",
991 ips_name, ips_next_controller);
993 ha->active = 0;
994 ips_free(ha);
995 free_irq(ha->irq, ha);
996 ips_next_controller++;
997 ips_num_controllers--;
999 continue;
1002 memset(ha->scbs, 0, sizeof(ips_scb_t));
1003 ha->scbs->sg_list = (IPS_SG_LIST *) kmalloc(sizeof(IPS_SG_LIST) * IPS_MAX_SG, GFP_ATOMIC|GFP_DMA);
1004 if (!ha->scbs->sg_list) {
1005 /* couldn't allocate a temp SCB S/G list */
1006 printk(KERN_WARNING "(%s%d) unable to allocate CCBs - skipping contoller\n",
1007 ips_name, ips_next_controller);
1009 ha->active = 0;
1010 ips_free(ha);
1011 free_irq(ha->irq, ha);
1012 ips_next_controller++;
1013 ips_num_controllers--;
1015 continue;
1018 ha->max_cmds = 1;
1020 ips_next_controller++;
1021 } while ((dev[i] = pci_find_device(IPS_VENDORID, deviceID[i], dev[i])));
1025 * Do Phase 2 Initialization
1026 * Controller init
1028 for (i = 0; i < ips_next_controller; i++) {
1029 ha = ips_ha[i];
1030 sh = ips_sh[i];
1032 if (!ha->active) {
1033 scsi_unregister(sh);
1034 ips_ha[i] = NULL;
1035 ips_sh[i] = NULL;
1037 continue;
1040 if (!ips_hainit(ha)) {
1041 printk(KERN_WARNING "(%s%d) unable to initialize controller - skipping\n",
1042 ips_name, i);
1044 ha->active = 0;
1045 ips_free(ha);
1046 free_irq(ha->irq, ha);
1047 scsi_unregister(sh);
1048 ips_ha[i] = NULL;
1049 ips_sh[i] = NULL;
1050 ips_num_controllers--;
1052 continue;
1056 * Free the temporary SCB
1058 kfree(ha->scbs->sg_list);
1059 kfree(ha->scbs);
1060 ha->scbs = NULL;
1062 /* allocate CCBs */
1063 if (!ips_allocatescbs(ha)) {
1064 printk(KERN_WARNING "(%s%d) unable to allocate CCBs - skipping contoller\n",
1065 ips_name, i);
1067 ha->active = 0;
1068 ips_free(ha);
1069 free_irq(ha->irq, ha);
1070 scsi_unregister(sh);
1071 ips_ha[i] = NULL;
1072 ips_sh[i] = NULL;
1073 ips_num_controllers--;
1075 continue;
1078 /* finish setting values */
1079 sh->max_id = ha->ntargets;
1080 sh->max_lun = ha->nlun;
1081 sh->max_channel = ha->nbus - 1;
1082 sh->can_queue = ha->max_cmds-1;
1085 if (ips_num_controllers > 0)
1086 register_reboot_notifier(&ips_notifier);
1088 return (ips_num_controllers);
1090 #else
1092 /* No PCI -- No ServeRAID */
1093 return (0);
1094 #endif /* CONFIG_PCI */
1097 /****************************************************************************/
1098 /* */
1099 /* Routine Name: ips_release */
1100 /* */
1101 /* Routine Description: */
1102 /* */
1103 /* Remove a driver */
1104 /* */
1105 /****************************************************************************/
1107 ips_release(struct Scsi_Host *sh) {
1108 ips_scb_t *scb;
1109 ips_ha_t *ha;
1110 int i;
1112 METHOD_TRACE("ips_release", 1);
1114 for (i = 0; i < IPS_MAX_ADAPTERS && ips_sh[i] != sh; i++);
1116 if (i == IPS_MAX_ADAPTERS)
1117 panic("(%s) release, invalid Scsi_Host pointer.\n",
1118 ips_name);
1120 ha = IPS_HA(sh);
1122 if (!ha)
1123 return (FALSE);
1125 /* flush the cache on the controller */
1126 scb = &ha->scbs[ha->max_cmds-1];
1128 ips_init_scb(ha, scb);
1130 scb->timeout = ips_cmd_timeout;
1131 scb->cdb[0] = IPS_CMD_FLUSH;
1133 scb->cmd.flush_cache.op_code = IPS_CMD_FLUSH;
1134 scb->cmd.flush_cache.command_id = IPS_COMMAND_ID(ha, scb);
1135 scb->cmd.flush_cache.state = IPS_NORM_STATE;
1136 scb->cmd.flush_cache.reserved = 0;
1137 scb->cmd.flush_cache.reserved2 = 0;
1138 scb->cmd.flush_cache.reserved3 = 0;
1139 scb->cmd.flush_cache.reserved4 = 0;
1141 printk("(%s%d) Flushing Cache.\n", ips_name, ha->host_num);
1143 /* send command */
1144 if (ips_send_wait(ha, scb, ips_cmd_timeout, IPS_INTR_ON) == IPS_FAILURE)
1145 printk("(%s%d) Incomplete Flush.\n", ips_name, ha->host_num);
1147 printk("(%s%d) Flushing Complete.\n", ips_name, ha->host_num);
1149 ips_sh[i] = NULL;
1150 ips_ha[i] = NULL;
1152 /* free extra memory */
1153 ips_free(ha);
1155 /* Free I/O Region */
1156 if (ha->io_addr)
1157 release_region(ha->io_addr, ha->io_len);
1159 #if LINUX_VERSION_CODE >= LinuxVersionCode(2,3,17)
1160 if (ha->mem_addr)
1161 release_mem_region(ha->mem_addr, ha->mem_len);
1162 #endif
1164 /* free IRQ */
1165 free_irq(ha->irq, ha);
1167 ips_released_controllers++;
1169 if (ips_num_controllers == ips_released_controllers)
1170 unregister_reboot_notifier(&ips_notifier);
1172 return (FALSE);
1175 /****************************************************************************/
1176 /* */
1177 /* Routine Name: ips_halt */
1178 /* */
1179 /* Routine Description: */
1180 /* */
1181 /* Perform cleanup when the system reboots */
1182 /* */
1183 /****************************************************************************/
1184 static int
1185 ips_halt(struct notifier_block *nb, ulong event, void *buf) {
1186 ips_scb_t *scb;
1187 ips_ha_t *ha;
1188 int i;
1190 if ((event != SYS_RESTART) && (event != SYS_HALT) &&
1191 (event != SYS_POWER_OFF))
1192 return (NOTIFY_DONE);
1194 for (i = 0; i < ips_next_controller; i++) {
1195 ha = (ips_ha_t *) ips_ha[i];
1197 if (!ha)
1198 continue;
1200 if (!ha->active)
1201 continue;
1203 /* flush the cache on the controller */
1204 scb = &ha->scbs[ha->max_cmds-1];
1206 ips_init_scb(ha, scb);
1208 scb->timeout = ips_cmd_timeout;
1209 scb->cdb[0] = IPS_CMD_FLUSH;
1211 scb->cmd.flush_cache.op_code = IPS_CMD_FLUSH;
1212 scb->cmd.flush_cache.command_id = IPS_COMMAND_ID(ha, scb);
1213 scb->cmd.flush_cache.state = IPS_NORM_STATE;
1214 scb->cmd.flush_cache.reserved = 0;
1215 scb->cmd.flush_cache.reserved2 = 0;
1216 scb->cmd.flush_cache.reserved3 = 0;
1217 scb->cmd.flush_cache.reserved4 = 0;
1219 printk("(%s%d) Flushing Cache.\n", ips_name, ha->host_num);
1221 /* send command */
1222 if (ips_send_wait(ha, scb, ips_cmd_timeout, IPS_INTR_ON) == IPS_FAILURE)
1223 printk("(%s%d) Incomplete Flush.\n", ips_name, ha->host_num);
1224 else
1225 printk("(%s%d) Flushing Complete.\n", ips_name, ha->host_num);
1228 unregister_reboot_notifier(&ips_notifier);
1229 return (NOTIFY_OK);
1232 /****************************************************************************/
1233 /* */
1234 /* Routine Name: ips_eh_abort */
1235 /* */
1236 /* Routine Description: */
1237 /* */
1238 /* Abort a command (using the new error code stuff) */
1239 /* */
1240 /****************************************************************************/
1242 ips_eh_abort(Scsi_Cmnd *SC) {
1243 ips_ha_t *ha;
1244 ips_copp_wait_item_t *item;
1246 METHOD_TRACE("ips_eh_abort", 1);
1248 if (!SC)
1249 return (FAILED);
1251 ha = (ips_ha_t *) SC->host->hostdata;
1253 if (!ha)
1254 return (FAILED);
1256 if (!ha->active)
1257 return (FAILED);
1259 if (SC->serial_number != SC->serial_number_at_timeout) {
1260 /* HMM, looks like a bogus command */
1261 DEBUG(1, "Abort called with bogus scsi command");
1263 return (FAILED);
1266 if (test_and_set_bit(IPS_IN_ABORT, &ha->flags))
1267 return (FAILED);
1269 /* See if the command is on the copp queue */
1270 IPS_QUEUE_LOCK(&ha->copp_waitlist);
1271 item = ha->copp_waitlist.head;
1272 while ((item) && (item->scsi_cmd != SC))
1273 item = item->next;
1274 IPS_QUEUE_UNLOCK(&ha->copp_waitlist);
1276 if (item) {
1277 /* Found it */
1278 ips_removeq_copp(&ha->copp_waitlist, item);
1279 clear_bit(IPS_IN_ABORT, &ha->flags);
1281 return (SUCCESS);
1284 /* See if the command is on the wait queue */
1285 if (ips_removeq_wait(&ha->scb_waitlist, SC)) {
1286 /* command not sent yet */
1287 clear_bit(IPS_IN_ABORT, &ha->flags);
1289 return (SUCCESS);
1290 } else {
1291 /* command must have already been sent */
1292 clear_bit(IPS_IN_ABORT, &ha->flags);
1294 return (FAILED);
1298 /****************************************************************************/
1299 /* */
1300 /* Routine Name: ips_eh_reset */
1301 /* */
1302 /* Routine Description: */
1303 /* */
1304 /* Reset the controller (with new eh error code) */
1305 /* */
1306 /* NOTE: this routine is called under the io_request_lock spinlock */
1307 /* */
1308 /****************************************************************************/
1310 ips_eh_reset(Scsi_Cmnd *SC) {
1311 int ret;
1312 int i;
1313 u32 cpu_flags;
1314 ips_ha_t *ha;
1315 ips_scb_t *scb;
1316 ips_copp_wait_item_t *item;
1318 METHOD_TRACE("ips_eh_reset", 1);
1320 #ifdef NO_IPS_RESET
1321 return (FAILED);
1322 #else
1324 if (!SC) {
1325 DEBUG(1, "Reset called with NULL scsi command");
1327 return (FAILED);
1330 ha = (ips_ha_t *) SC->host->hostdata;
1332 if (!ha) {
1333 DEBUG(1, "Reset called with NULL ha struct");
1335 return (FAILED);
1338 if (!ha->active)
1339 return (FAILED);
1341 if (test_and_set_bit(IPS_IN_RESET, &ha->flags))
1342 return (FAILED);
1344 /* See if the command is on the copp queue */
1345 IPS_QUEUE_LOCK(&ha->copp_waitlist);
1346 item = ha->copp_waitlist.head;
1347 while ((item) && (item->scsi_cmd != SC))
1348 item = item->next;
1349 IPS_QUEUE_UNLOCK(&ha->copp_waitlist);
1351 if (item) {
1352 /* Found it */
1353 ips_removeq_copp(&ha->copp_waitlist, item);
1354 clear_bit(IPS_IN_RESET, &ha->flags);
1356 return (SUCCESS);
1359 /* See if the command is on the wait queue */
1360 if (ips_removeq_wait(&ha->scb_waitlist, SC)) {
1361 /* command not sent yet */
1362 clear_bit(IPS_IN_RESET, &ha->flags);
1364 return (SUCCESS);
1368 * command must have already been sent
1369 * reset the controller
1371 printk(KERN_NOTICE "(%s%d) Resetting controller.\n",
1372 ips_name, ha->host_num);
1373 ret = (*ha->func.reset)(ha);
1375 if (!ret) {
1376 Scsi_Cmnd *scsi_cmd;
1378 printk(KERN_NOTICE
1379 "(%s%d) Controller reset failed - controller now offline.\n",
1380 ips_name, ha->host_num);
1382 /* Now fail all of the active commands */
1383 DEBUG_VAR(1, "(%s%d) Failing active commands",
1384 ips_name, ha->host_num);
1386 while ((scb = ips_removeq_scb_head(&ha->scb_activelist))) {
1387 scb->scsi_cmd->result = DID_ERROR << 16;
1388 scb->scsi_cmd->scsi_done(scb->scsi_cmd);
1389 ips_freescb(ha, scb);
1392 /* Now fail all of the pending commands */
1393 DEBUG_VAR(1, "(%s%d) Failing pending commands",
1394 ips_name, ha->host_num);
1396 while ((scsi_cmd = ips_removeq_wait_head(&ha->scb_waitlist))) {
1397 scsi_cmd->result = DID_ERROR;
1398 scsi_cmd->scsi_done(scsi_cmd);
1401 ha->active = FALSE;
1402 clear_bit(IPS_IN_RESET, &ha->flags);
1404 return (FAILED);
1407 if (!ips_clear_adapter(ha, IPS_INTR_IORL)) {
1408 Scsi_Cmnd *scsi_cmd;
1410 printk(KERN_NOTICE
1411 "(%s%d) Controller reset failed - controller now offline.\n",
1412 ips_name, ha->host_num);
1414 /* Now fail all of the active commands */
1415 DEBUG_VAR(1, "(%s%d) Failing active commands",
1416 ips_name, ha->host_num);
1418 while ((scb = ips_removeq_scb_head(&ha->scb_activelist))) {
1419 scb->scsi_cmd->result = DID_ERROR << 16;
1420 scb->scsi_cmd->scsi_done(scb->scsi_cmd);
1421 ips_freescb(ha, scb);
1424 /* Now fail all of the pending commands */
1425 DEBUG_VAR(1, "(%s%d) Failing pending commands",
1426 ips_name, ha->host_num);
1428 while ((scsi_cmd = ips_removeq_wait_head(&ha->scb_waitlist))) {
1429 scsi_cmd->result = DID_ERROR << 16;
1430 scsi_cmd->scsi_done(scsi_cmd);
1433 ha->active = FALSE;
1434 clear_bit(IPS_IN_RESET, &ha->flags);
1436 return (FAILED);
1439 /* FFDC */
1440 if (ha->subsys->param[3] & 0x300000) {
1441 struct timeval tv;
1443 do_gettimeofday(&tv);
1444 IPS_HA_LOCK(cpu_flags);
1445 ha->last_ffdc = tv.tv_sec;
1446 ha->reset_count++;
1447 IPS_HA_UNLOCK(cpu_flags);
1448 ips_ffdc_reset(ha, IPS_INTR_IORL);
1451 /* Now fail all of the active commands */
1452 DEBUG_VAR(1, "(%s%d) Failing active commands",
1453 ips_name, ha->host_num);
1455 while ((scb = ips_removeq_scb_head(&ha->scb_activelist))) {
1456 scb->scsi_cmd->result = (DID_RESET << 16) | (SUGGEST_RETRY << 24);
1457 scb->scsi_cmd->scsi_done(scb->scsi_cmd);
1458 ips_freescb(ha, scb);
1461 /* Reset DCDB active command bits */
1462 for (i = 1; i < ha->nbus; i++)
1463 ha->dcdb_active[i-1] = 0;
1465 /* Reset the number of active IOCTLs */
1466 IPS_HA_LOCK(cpu_flags);
1467 ha->num_ioctl = 0;
1468 IPS_HA_UNLOCK(cpu_flags);
1470 clear_bit(IPS_IN_RESET, &ha->flags);
1472 if (!test_bit(IPS_IN_INTR, &ha->flags)) {
1474 * Only execute the next command when
1475 * we are not being called from the
1476 * interrupt handler. The interrupt
1477 * handler wants to do this and since
1478 * interrupts are turned off here....
1480 ips_next(ha, IPS_INTR_IORL);
1483 return (SUCCESS);
1485 #endif /* NO_IPS_RESET */
1489 /****************************************************************************/
1490 /* */
1491 /* Routine Name: ips_queue */
1492 /* */
1493 /* Routine Description: */
1494 /* */
1495 /* Send a command to the controller */
1496 /* */
1497 /* NOTE: */
1498 /* Linux obtains io_request_lock before calling this function */
1499 /* */
1500 /****************************************************************************/
1502 ips_queue(Scsi_Cmnd *SC, void (*done) (Scsi_Cmnd *)) {
1503 ips_ha_t *ha;
1504 u32 cpu_flags;
1505 DECLARE_MUTEX_LOCKED(sem);
1507 METHOD_TRACE("ips_queue", 1);
1509 ha = (ips_ha_t *) SC->host->hostdata;
1511 if (!ha)
1512 return (1);
1514 if (!ha->active)
1515 return (DID_ERROR);
1517 #ifndef NO_IPS_CMDLINE
1518 if (ips_is_passthru(SC)) {
1519 IPS_QUEUE_LOCK(&ha->copp_waitlist);
1520 if (ha->copp_waitlist.count == IPS_MAX_IOCTL_QUEUE) {
1521 IPS_QUEUE_UNLOCK(&ha->copp_waitlist);
1522 SC->result = DID_BUS_BUSY << 16;
1523 done(SC);
1525 return (0);
1526 } else {
1527 IPS_QUEUE_UNLOCK(&ha->copp_waitlist);
1529 } else {
1530 #endif
1531 IPS_QUEUE_LOCK(&ha->scb_waitlist);
1532 if (ha->scb_waitlist.count == IPS_MAX_QUEUE) {
1533 IPS_QUEUE_UNLOCK(&ha->scb_waitlist);
1534 SC->result = DID_BUS_BUSY << 16;
1535 done(SC);
1537 return (0);
1538 } else {
1539 IPS_QUEUE_UNLOCK(&ha->scb_waitlist);
1542 #ifndef NO_IPS_CMDLINE
1544 #endif
1546 SC->scsi_done = done;
1548 DEBUG_VAR(2, "(%s%d): ips_queue: cmd 0x%X (%d %d %d)",
1549 ips_name,
1550 ha->host_num,
1551 SC->cmnd[0],
1552 SC->channel,
1553 SC->target,
1554 SC->lun);
1556 /* Check for command to initiator IDs */
1557 if ((SC->channel > 0) && (SC->target == ha->ha_id[SC->channel])) {
1558 SC->result = DID_NO_CONNECT << 16;
1559 done(SC);
1561 return (0);
1564 #ifndef NO_IPS_CMDLINE
1565 if (ips_is_passthru(SC)) {
1566 ips_copp_wait_item_t *scratch;
1568 /* allocate space for the scribble */
1569 scratch = kmalloc(sizeof(ips_copp_wait_item_t), GFP_ATOMIC);
1571 if (!scratch) {
1572 SC->result = DID_ERROR << 16;
1573 done(SC);
1575 return (0);
1578 scratch->scsi_cmd = SC;
1579 scratch->sem = &sem;
1580 scratch->next = NULL;
1582 ips_putq_copp_tail(&ha->copp_waitlist, scratch);
1584 else
1585 #endif
1586 ips_putq_wait_tail(&ha->scb_waitlist, SC);
1588 IPS_HA_LOCK(cpu_flags);
1589 if ((!test_bit(IPS_IN_INTR, &ha->flags)) &&
1590 (!test_bit(IPS_IN_ABORT, &ha->flags)) &&
1591 (!test_bit(IPS_IN_RESET, &ha->flags))) {
1592 IPS_HA_UNLOCK(cpu_flags);
1593 ips_next(ha, IPS_INTR_IORL);
1594 } else {
1595 IPS_HA_UNLOCK(cpu_flags);
1599 * If this request was a new style IOCTL wait
1600 * for it to finish.
1602 * NOTE: we relinquished the lock above so this should
1603 * not cause contention problems
1605 if (ips_is_passthru(SC) && SC->cmnd[0] == IPS_IOCTL_NEW_COMMAND) {
1606 char *user_area;
1607 char *kern_area;
1608 u32 datasize;
1610 /* free io_request_lock */
1611 spin_unlock_irq(&io_request_lock);
1613 /* wait for the command to finish */
1614 down(&sem);
1616 /* reobtain the lock */
1617 spin_lock_irq(&io_request_lock);
1619 /* command finished -- copy back */
1620 user_area = *((char **) &SC->cmnd[4]);
1621 kern_area = ha->ioctl_data;
1622 datasize = *((u32 *) &SC->cmnd[8]);
1624 if (copy_to_user(user_area, kern_area, datasize) > 0) {
1625 DEBUG_VAR(1, "(%s%d) passthru failed - unable to copy out user data",
1626 ips_name, ha->host_num);
1628 SC->result = DID_ERROR << 16;
1629 SC->scsi_done(SC);
1630 } else {
1631 SC->scsi_done(SC);
1635 return (0);
1638 /****************************************************************************/
1639 /* */
1640 /* Routine Name: ips_biosparam */
1641 /* */
1642 /* Routine Description: */
1643 /* */
1644 /* Set bios geometry for the controller */
1645 /* */
1646 /****************************************************************************/
1648 ips_biosparam(Disk *disk, kdev_t dev, int geom[]) {
1649 ips_ha_t *ha;
1650 int heads;
1651 int sectors;
1652 int cylinders;
1654 METHOD_TRACE("ips_biosparam", 1);
1656 ha = (ips_ha_t *) disk->device->host->hostdata;
1658 if (!ha)
1659 /* ?!?! host adater info invalid */
1660 return (0);
1662 if (!ha->active)
1663 return (0);
1665 if (!ips_read_adapter_status(ha, IPS_INTR_ON))
1666 /* ?!?! Enquiry command failed */
1667 return (0);
1669 if ((disk->capacity > 0x400000) &&
1670 ((ha->enq->ucMiscFlag & 0x8) == 0)) {
1671 heads = IPS_NORM_HEADS;
1672 sectors = IPS_NORM_SECTORS;
1673 } else {
1674 heads = IPS_COMP_HEADS;
1675 sectors = IPS_COMP_SECTORS;
1678 cylinders = disk->capacity / (heads * sectors);
1680 DEBUG_VAR(2, "Geometry: heads: %d, sectors: %d, cylinders: %d",
1681 heads, sectors, cylinders);
1683 geom[0] = heads;
1684 geom[1] = sectors;
1685 geom[2] = cylinders;
1687 return (0);
1690 /****************************************************************************/
1691 /* */
1692 /* Routine Name: ips_select_queue_depth */
1693 /* */
1694 /* Routine Description: */
1695 /* */
1696 /* Select queue depths for the devices on the contoller */
1697 /* */
1698 /****************************************************************************/
1699 static void
1700 ips_select_queue_depth(struct Scsi_Host *host, Scsi_Device *scsi_devs) {
1701 Scsi_Device *device;
1702 ips_ha_t *ha;
1703 int count = 0;
1705 ha = IPS_HA(host);
1707 for (device = scsi_devs; device; device = device->next) {
1708 if (device->host == host) {
1709 if ((device->channel == 0) && (device->type == 0))
1710 count++;
1714 for (device = scsi_devs; device; device = device->next) {
1715 if (device->host == host) {
1716 if ((device->channel == 0) && (device->type == 0))
1717 device->queue_depth = ha->max_cmds / count - 1;
1718 else
1719 device->queue_depth = 2;
1724 /****************************************************************************/
1725 /* */
1726 /* Routine Name: do_ipsintr */
1727 /* */
1728 /* Routine Description: */
1729 /* */
1730 /* Wrapper for the interrupt handler */
1731 /* */
1732 /****************************************************************************/
1733 void
1734 do_ipsintr(int irq, void *dev_id, struct pt_regs *regs) {
1735 ips_ha_t *ha;
1736 u32 cpu_flags;
1738 METHOD_TRACE("do_ipsintr", 2);
1740 ha = (ips_ha_t *) dev_id;
1742 spin_lock_irqsave(&io_request_lock, cpu_flags);
1744 if (test_and_set_bit(IPS_IN_INTR, &ha->flags)) {
1745 spin_unlock_irqrestore(&io_request_lock, cpu_flags);
1747 return ;
1750 if (!ha) {
1751 clear_bit(IPS_IN_INTR, &ha->flags);
1752 spin_unlock_irqrestore(&io_request_lock, cpu_flags);
1754 return;
1757 if (!ha->active) {
1758 clear_bit(IPS_IN_INTR, &ha->flags);
1759 spin_unlock_irqrestore(&io_request_lock, cpu_flags);
1761 return;
1764 (*ha->func.intr)(ha);
1766 clear_bit(IPS_IN_INTR, &ha->flags);
1768 spin_unlock_irqrestore(&io_request_lock, cpu_flags);
1770 /* start the next command */
1771 ips_next(ha, IPS_INTR_ON);
1774 /****************************************************************************/
1775 /* */
1776 /* Routine Name: ips_intr_copperhead */
1777 /* */
1778 /* Routine Description: */
1779 /* */
1780 /* Polling interrupt handler */
1781 /* */
1782 /* ASSUMES interrupts are disabled */
1783 /* */
1784 /****************************************************************************/
1785 void
1786 ips_intr_copperhead(ips_ha_t *ha) {
1787 ips_stat_t *sp;
1788 ips_scb_t *scb;
1789 IPS_STATUS cstatus;
1790 int intrstatus;
1791 u32 cpu_flags;
1793 METHOD_TRACE("ips_intr", 2);
1795 if (!ha)
1796 return;
1798 if (!ha->active)
1799 return;
1801 IPS_HA_LOCK(cpu_flags);
1803 intrstatus = (*ha->func.isintr)(ha);
1805 if (!intrstatus) {
1807 * Unexpected/Shared interrupt
1809 IPS_HA_UNLOCK(cpu_flags);
1811 return;
1814 while (TRUE) {
1815 sp = &ha->sp;
1817 intrstatus = (*ha->func.isintr)(ha);
1819 if (!intrstatus)
1820 break;
1821 else
1822 cstatus.value = (*ha->func.statupd)(ha);
1824 if (cstatus.fields.command_id > (IPS_MAX_CMDS - 1)) {
1825 printk(KERN_WARNING "(%s%d) Spurious interrupt; no ccb.\n",
1826 ips_name, ha->host_num);
1828 continue;
1831 ips_chkstatus(ha, &cstatus);
1832 scb = (ips_scb_t *) sp->scb_addr;
1835 * use the callback function to finish things up
1836 * NOTE: interrupts are OFF for this
1838 IPS_HA_UNLOCK(cpu_flags);
1839 (*scb->callback) (ha, scb);
1840 IPS_HA_LOCK(cpu_flags);
1841 } /* end while */
1843 IPS_HA_UNLOCK(cpu_flags);
1846 /****************************************************************************/
1847 /* */
1848 /* Routine Name: ips_intr_morpheus */
1849 /* */
1850 /* Routine Description: */
1851 /* */
1852 /* Polling interrupt handler */
1853 /* */
1854 /* ASSUMES interrupts are disabled */
1855 /* */
1856 /****************************************************************************/
1857 void
1858 ips_intr_morpheus(ips_ha_t *ha) {
1859 ips_stat_t *sp;
1860 ips_scb_t *scb;
1861 IPS_STATUS cstatus;
1862 int intrstatus;
1863 u32 cpu_flags;
1865 METHOD_TRACE("ips_intr_morpheus", 2);
1867 if (!ha)
1868 return;
1870 if (!ha->active)
1871 return;
1873 IPS_HA_LOCK(cpu_flags);
1875 intrstatus = (*ha->func.isintr)(ha);
1877 if (!intrstatus) {
1879 * Unexpected/Shared interrupt
1881 IPS_HA_UNLOCK(cpu_flags);
1883 return;
1886 while (TRUE) {
1887 sp = &ha->sp;
1889 intrstatus = (*ha->func.isintr)(ha);
1891 if (!intrstatus)
1892 break;
1893 else
1894 cstatus.value = (*ha->func.statupd)(ha);
1896 if (cstatus.value == 0xffffffff)
1897 /* No more to process */
1898 break;
1900 if (cstatus.fields.command_id > (IPS_MAX_CMDS - 1)) {
1901 printk(KERN_WARNING "(%s%d) Spurious interrupt; no ccb.\n",
1902 ips_name, ha->host_num);
1904 continue;
1907 ips_chkstatus(ha, &cstatus);
1908 scb = (ips_scb_t *) sp->scb_addr;
1911 * use the callback function to finish things up
1912 * NOTE: interrupts are OFF for this
1914 IPS_HA_UNLOCK(cpu_flags);
1915 (*scb->callback) (ha, scb);
1916 IPS_HA_LOCK(cpu_flags);
1917 } /* end while */
1919 IPS_HA_UNLOCK(cpu_flags);
1922 /****************************************************************************/
1923 /* */
1924 /* Routine Name: ips_info */
1925 /* */
1926 /* Routine Description: */
1927 /* */
1928 /* Return info about the driver */
1929 /* */
1930 /****************************************************************************/
1931 const char *
1932 ips_info(struct Scsi_Host *SH) {
1933 static char buffer[256];
1934 char *bp;
1935 ips_ha_t *ha;
1937 METHOD_TRACE("ips_info", 1);
1939 ha = IPS_HA(SH);
1941 if (!ha)
1942 return (NULL);
1944 bp = &buffer[0];
1945 memset(bp, 0, sizeof(buffer));
1947 strcpy(bp, "IBM PCI ServeRAID ");
1948 strcat(bp, IPS_VERSION_HIGH);
1949 strcat(bp, IPS_VERSION_LOW);
1951 if (ha->ad_type > 0 &&
1952 ha->ad_type <= MAX_ADAPTER_NAME) {
1953 strcat(bp, " <");
1954 strcat(bp, ips_adapter_name[ha->ad_type-1]);
1955 strcat(bp, ">");
1958 return (bp);
1961 /****************************************************************************/
1962 /* */
1963 /* Routine Name: ips_proc_info */
1964 /* */
1965 /* Routine Description: */
1966 /* */
1967 /* The passthru interface for the driver */
1968 /* */
1969 /****************************************************************************/
1971 ips_proc_info(char *buffer, char **start, off_t offset,
1972 int length, int hostno, int func) {
1973 int i;
1974 int ret;
1975 ips_ha_t *ha = NULL;
1977 METHOD_TRACE("ips_proc_info", 1);
1979 /* Find our host structure */
1980 for (i = 0; i < ips_next_controller; i++) {
1981 if (ips_sh[i] && ips_sh[i]->host_no == hostno) {
1982 ha = (ips_ha_t *) ips_sh[i]->hostdata;
1984 break;
1988 if (!ha)
1989 return (-EINVAL);
1991 if (func) {
1992 /* write */
1993 return (0);
1994 } else {
1995 /* read */
1996 if (start)
1997 *start = buffer;
1999 ret = ips_host_info(ha, buffer, offset, length);
2001 return (ret);
2005 /*--------------------------------------------------------------------------*/
2006 /* Helper Functions */
2007 /*--------------------------------------------------------------------------*/
2009 #ifndef NO_IPS_CMDLINE
2011 /****************************************************************************/
2012 /* */
2013 /* Routine Name: ips_is_passthru */
2014 /* */
2015 /* Routine Description: */
2016 /* */
2017 /* Determine if the specified SCSI command is really a passthru command */
2018 /* */
2019 /****************************************************************************/
2020 static int
2021 ips_is_passthru(Scsi_Cmnd *SC) {
2022 METHOD_TRACE("ips_is_passthru", 1);
2024 if (!SC)
2025 return (0);
2027 if (((SC->cmnd[0] == IPS_IOCTL_COMMAND) || (SC->cmnd[0] == IPS_IOCTL_NEW_COMMAND)) &&
2028 (SC->channel == 0) &&
2029 (SC->target == IPS_ADAPTER_ID) &&
2030 (SC->lun == 0) &&
2031 (SC->request_bufflen) &&
2032 (!SC->use_sg) &&
2033 (((char *) SC->request_buffer)[0] == 'C') &&
2034 (((char *) SC->request_buffer)[1] == 'O') &&
2035 (((char *) SC->request_buffer)[2] == 'P') &&
2036 (((char *) SC->request_buffer)[3] == 'P')) {
2037 return (1);
2038 } else {
2039 return (0);
2043 /****************************************************************************/
2044 /* */
2045 /* Routine Name: ips_make_passthru */
2046 /* */
2047 /* Routine Description: */
2048 /* */
2049 /* Make a passthru command out of the info in the Scsi block */
2050 /* */
2051 /****************************************************************************/
2052 static int
2053 ips_make_passthru(ips_ha_t *ha, Scsi_Cmnd *SC, ips_scb_t *scb) {
2054 ips_passthru_t *pt;
2056 METHOD_TRACE("ips_make_passthru", 1);
2058 if (!SC->request_bufflen || !SC->request_buffer) {
2059 /* no data */
2060 DEBUG_VAR(1, "(%s%d) No passthru structure",
2061 ips_name, ha->host_num);
2063 return (IPS_FAILURE);
2066 if (SC->request_bufflen < sizeof(ips_passthru_t)) {
2067 /* wrong size */
2068 DEBUG_VAR(1, "(%s%d) Passthru structure wrong size",
2069 ips_name, ha->host_num);
2071 return (IPS_FAILURE);
2074 if ((((char *) SC->request_buffer)[0] != 'C') ||
2075 (((char *) SC->request_buffer)[1] != 'O') ||
2076 (((char *) SC->request_buffer)[2] != 'P') ||
2077 (((char *) SC->request_buffer)[3] != 'P')) {
2078 /* signature doesn't match */
2079 DEBUG_VAR(1, "(%s%d) Wrong signature on passthru structure.",
2080 ips_name, ha->host_num);
2082 return (IPS_FAILURE);
2085 pt = (ips_passthru_t *) SC->request_buffer;
2088 * Some notes about the passthru interface used
2090 * IF the scsi op_code == 0x0d then we assume
2091 * that the data came along with/goes with the
2092 * packet we received from the sg driver. In this
2093 * case the CmdBSize field of the pt structure is
2094 * used for the size of the buffer.
2096 * IF the scsi op_code == 0x81 then we assume that
2097 * we will need our own buffer and we will copy the
2098 * data to/from the user buffer passed in the scsi
2099 * command. The data address resides at offset 4
2100 * in the scsi command. The length of the data resides
2101 * at offset 8 in the scsi command.
2104 switch (pt->CoppCmd) {
2105 case IPS_NUMCTRLS:
2106 memcpy(SC->request_buffer + sizeof(ips_passthru_t),
2107 &ips_num_controllers, sizeof(int));
2108 SC->result = DID_OK << 16;
2110 return (IPS_SUCCESS_IMM);
2112 case IPS_CTRLINFO:
2113 memcpy(SC->request_buffer + sizeof(ips_passthru_t),
2114 ha, sizeof(ips_ha_t));
2115 SC->result = DID_OK << 16;
2117 return (IPS_SUCCESS_IMM);
2119 case IPS_COPPUSRCMD:
2120 case IPS_COPPIOCCMD:
2121 if (SC->cmnd[0] == IPS_IOCTL_COMMAND) {
2122 if (SC->request_bufflen < (sizeof(ips_passthru_t) + pt->CmdBSize)) {
2123 /* wrong size */
2124 DEBUG_VAR(1, "(%s%d) Passthru structure wrong size",
2125 ips_name, ha->host_num);
2127 return (IPS_FAILURE);
2130 if (ips_usrcmd(ha, pt, scb))
2131 return (IPS_SUCCESS);
2132 else
2133 return (IPS_FAILURE);
2134 } else if (SC->cmnd[0] == IPS_IOCTL_NEW_COMMAND) {
2135 if (SC->request_bufflen < (sizeof(ips_passthru_t))) {
2136 /* wrong size */
2137 DEBUG_VAR(1, "(%s%d) Passthru structure wrong size",
2138 ips_name, ha->host_num);
2140 return (IPS_FAILURE);
2143 if (ips_newusrcmd(ha, pt, scb))
2144 return (IPS_SUCCESS);
2145 else
2146 return (IPS_FAILURE);
2149 break;
2151 case IPS_FLASHBIOS:
2152 /* we must use the new interface */
2153 if (SC->cmnd[0] != IPS_IOCTL_NEW_COMMAND)
2154 return (IPS_FAILURE);
2156 /* don't flash the BIOS on future cards */
2157 if ((ha->device_id != IPS_COPPERHEAD_DEVICEID) ||
2158 (ha->revision_id > IPS_REVID_TROMBONE64)) {
2159 DEBUG_VAR(1, "(%s%d) flash bios failed - unsupported controller",
2160 ips_name, ha->host_num);
2162 return (IPS_FAILURE);
2166 * Check to make sure we have functions
2167 * to handle the request
2169 if ((!ha->func.programbios) ||
2170 (!ha->func.erasebios) ||
2171 (!ha->func.verifybios))
2172 return (IPS_FAILURE);
2174 /* copy in the size/buffer ptr from the scsi command */
2175 memcpy(&pt->CmdBuffer, &SC->cmnd[4], 4);
2176 memcpy(&pt->CmdBSize, &SC->cmnd[8], 4);
2178 /* must have a buffer */
2179 if ((!pt->CmdBSize) || (!pt->CmdBuffer))
2180 return (IPS_FAILURE);
2182 /* make sure buffer is big enough */
2183 if (pt->CmdBSize > ha->ioctl_datasize) {
2184 void *bigger_struct;
2186 /* try to allocate a bigger struct */
2187 bigger_struct = kmalloc(pt->CmdBSize, GFP_ATOMIC|GFP_DMA);
2188 if (bigger_struct) {
2189 /* free the old memory */
2190 kfree(ha->ioctl_data);
2192 /* use the new memory */
2193 ha->ioctl_data = bigger_struct;
2194 ha->ioctl_datasize = pt->CmdBSize;
2195 } else
2196 return (IPS_FAILURE);
2199 /* copy in the buffer */
2200 if (copy_from_user(ha->ioctl_data, pt->CmdBuffer, pt->CmdBSize) > 0) {
2201 DEBUG_VAR(1, "(%s%d) flash bios failed - unable to copy user buffer",
2202 ips_name, ha->host_num);
2204 return (IPS_FAILURE);
2207 if ((*ha->func.erasebios)(ha)) {
2208 DEBUG_VAR(1, "(%s%d) flash bios failed - unable to erase flash",
2209 ips_name, ha->host_num);
2211 return (IPS_FAILURE);
2214 if ((*ha->func.programbios)(ha, ha->ioctl_data, pt->CmdBSize)) {
2215 DEBUG_VAR(1, "(%s%d) flash bios failed - unable to program flash",
2216 ips_name, ha->host_num);
2218 return (IPS_FAILURE);
2221 if ((*ha->func.verifybios)(ha, ha->ioctl_data, pt->CmdBSize)) {
2222 DEBUG_VAR(1, "(%s%d) flash bios failed - unable to verify flash",
2223 ips_name, ha->host_num);
2225 return (IPS_FAILURE);
2228 return (IPS_SUCCESS_IMM);
2229 } /* end switch */
2231 return (IPS_FAILURE);
2234 /****************************************************************************/
2235 /* */
2236 /* Routine Name: ips_usrcmd */
2237 /* */
2238 /* Routine Description: */
2239 /* */
2240 /* Process a user command and make it ready to send */
2241 /* */
2242 /****************************************************************************/
2243 static int
2244 ips_usrcmd(ips_ha_t *ha, ips_passthru_t *pt, ips_scb_t *scb) {
2245 IPS_SG_LIST *sg_list;
2247 METHOD_TRACE("ips_usrcmd", 1);
2249 if ((!scb) || (!pt) || (!ha))
2250 return (0);
2252 /* Save the S/G list pointer so it doesn't get clobbered */
2253 sg_list = scb->sg_list;
2255 /* copy in the CP */
2256 memcpy(&scb->cmd, &pt->CoppCP.cmd, sizeof(IPS_IOCTL_CMD));
2257 memcpy(&scb->dcdb, &pt->CoppCP.dcdb, sizeof(IPS_DCDB_TABLE));
2259 /* FIX stuff that might be wrong */
2260 scb->sg_list = sg_list;
2261 scb->scb_busaddr = VIRT_TO_BUS(scb);
2262 scb->bus = scb->scsi_cmd->channel;
2263 scb->target_id = scb->scsi_cmd->target;
2264 scb->lun = scb->scsi_cmd->lun;
2265 scb->sg_len = 0;
2266 scb->data_len = 0;
2267 scb->flags = 0;
2268 scb->op_code = 0;
2269 scb->callback = ipsintr_done;
2270 scb->timeout = ips_cmd_timeout;
2271 scb->cmd.basic_io.command_id = IPS_COMMAND_ID(ha, scb);
2273 /* we don't support DCDB/READ/WRITE Scatter Gather */
2274 if ((scb->cmd.basic_io.op_code == IPS_CMD_READ_SG) ||
2275 (scb->cmd.basic_io.op_code == IPS_CMD_WRITE_SG) ||
2276 (scb->cmd.basic_io.op_code == IPS_CMD_DCDB_SG))
2277 return (0);
2279 if (pt->CmdBSize) {
2280 scb->data_busaddr = VIRT_TO_BUS(scb->scsi_cmd->request_buffer + sizeof(ips_passthru_t));
2281 } else {
2282 scb->data_busaddr = 0L;
2285 if (scb->cmd.dcdb.op_code == IPS_CMD_DCDB)
2286 scb->cmd.dcdb.dcdb_address = VIRT_TO_BUS(&scb->dcdb);
2288 if (pt->CmdBSize) {
2289 if (scb->cmd.dcdb.op_code == IPS_CMD_DCDB)
2290 scb->dcdb.buffer_pointer = scb->data_busaddr;
2291 else
2292 scb->cmd.basic_io.sg_addr = scb->data_busaddr;
2295 /* set timeouts */
2296 if (pt->TimeOut) {
2297 scb->timeout = pt->TimeOut;
2299 if (pt->TimeOut <= 10)
2300 scb->dcdb.cmd_attribute |= IPS_TIMEOUT10;
2301 else if (pt->TimeOut <= 60)
2302 scb->dcdb.cmd_attribute |= IPS_TIMEOUT60;
2303 else
2304 scb->dcdb.cmd_attribute |= IPS_TIMEOUT20M;
2307 /* assume success */
2308 scb->scsi_cmd->result = DID_OK << 16;
2310 /* success */
2311 return (1);
2314 /****************************************************************************/
2315 /* */
2316 /* Routine Name: ips_newusrcmd */
2317 /* */
2318 /* Routine Description: */
2319 /* */
2320 /* Process a user command and make it ready to send */
2321 /* */
2322 /****************************************************************************/
2323 static int
2324 ips_newusrcmd(ips_ha_t *ha, ips_passthru_t *pt, ips_scb_t *scb) {
2325 IPS_SG_LIST *sg_list;
2326 char *user_area;
2327 char *kern_area;
2328 u32 datasize;
2330 METHOD_TRACE("ips_usrcmd", 1);
2332 if ((!scb) || (!pt) || (!ha))
2333 return (0);
2335 /* Save the S/G list pointer so it doesn't get clobbered */
2336 sg_list = scb->sg_list;
2338 /* copy in the CP */
2339 memcpy(&scb->cmd, &pt->CoppCP.cmd, sizeof(IPS_IOCTL_CMD));
2340 memcpy(&scb->dcdb, &pt->CoppCP.dcdb, sizeof(IPS_DCDB_TABLE));
2342 /* FIX stuff that might be wrong */
2343 scb->sg_list = sg_list;
2344 scb->scb_busaddr = VIRT_TO_BUS(scb);
2345 scb->bus = scb->scsi_cmd->channel;
2346 scb->target_id = scb->scsi_cmd->target;
2347 scb->lun = scb->scsi_cmd->lun;
2348 scb->sg_len = 0;
2349 scb->data_len = 0;
2350 scb->flags = 0;
2351 scb->op_code = 0;
2352 scb->callback = ipsintr_done;
2353 scb->timeout = ips_cmd_timeout;
2354 scb->cmd.basic_io.command_id = IPS_COMMAND_ID(ha, scb);
2356 /* we don't support DCDB/READ/WRITE Scatter Gather */
2357 if ((scb->cmd.basic_io.op_code == IPS_CMD_READ_SG) ||
2358 (scb->cmd.basic_io.op_code == IPS_CMD_WRITE_SG) ||
2359 (scb->cmd.basic_io.op_code == IPS_CMD_DCDB_SG))
2360 return (0);
2362 if (pt->CmdBSize) {
2363 if (pt->CmdBSize > ha->ioctl_datasize) {
2364 void *bigger_struct;
2366 /* try to allocate a bigger struct */
2367 bigger_struct = kmalloc(pt->CmdBSize, GFP_ATOMIC|GFP_DMA);
2368 if (bigger_struct) {
2369 /* free the old memory */
2370 kfree(ha->ioctl_data);
2372 /* use the new memory */
2373 ha->ioctl_data = bigger_struct;
2374 ha->ioctl_datasize = pt->CmdBSize;
2375 } else
2376 return (0);
2380 scb->data_busaddr = VIRT_TO_BUS(ha->ioctl_data);
2382 /* Attempt to copy in the data */
2383 user_area = *((char **) &scb->scsi_cmd->cmnd[4]);
2384 kern_area = ha->ioctl_data;
2385 datasize = *((u32 *) &scb->scsi_cmd->cmnd[8]);
2387 if (copy_from_user(kern_area, user_area, datasize) > 0) {
2388 DEBUG_VAR(1, "(%s%d) passthru failed - unable to copy in user data",
2389 ips_name, ha->host_num);
2391 return (0);
2394 } else {
2395 scb->data_busaddr = 0L;
2398 if (scb->cmd.dcdb.op_code == IPS_CMD_DCDB)
2399 scb->cmd.dcdb.dcdb_address = VIRT_TO_BUS(&scb->dcdb);
2401 if (pt->CmdBSize) {
2402 if (scb->cmd.dcdb.op_code == IPS_CMD_DCDB)
2403 scb->dcdb.buffer_pointer = scb->data_busaddr;
2404 else
2405 scb->cmd.basic_io.sg_addr = scb->data_busaddr;
2408 /* set timeouts */
2409 if (pt->TimeOut) {
2410 scb->timeout = pt->TimeOut;
2412 if (pt->TimeOut <= 10)
2413 scb->dcdb.cmd_attribute |= IPS_TIMEOUT10;
2414 else if (pt->TimeOut <= 60)
2415 scb->dcdb.cmd_attribute |= IPS_TIMEOUT60;
2416 else
2417 scb->dcdb.cmd_attribute |= IPS_TIMEOUT20M;
2420 /* assume success */
2421 scb->scsi_cmd->result = DID_OK << 16;
2423 /* success */
2424 return (1);
2427 /****************************************************************************/
2428 /* */
2429 /* Routine Name: ips_cleanup_passthru */
2430 /* */
2431 /* Routine Description: */
2432 /* */
2433 /* Cleanup after a passthru command */
2434 /* */
2435 /****************************************************************************/
2436 static void
2437 ips_cleanup_passthru(ips_ha_t *ha, ips_scb_t *scb) {
2438 ips_passthru_t *pt;
2440 METHOD_TRACE("ips_cleanup_passthru", 1);
2442 if ((!scb) || (!scb->scsi_cmd) || (!scb->scsi_cmd->request_buffer)) {
2443 DEBUG_VAR(1, "(%s%d) couldn't cleanup after passthru",
2444 ips_name, ha->host_num);
2446 return ;
2449 pt = (ips_passthru_t *) scb->scsi_cmd->request_buffer;
2451 /* Copy data back to the user */
2452 if (scb->scsi_cmd->cmnd[0] == IPS_IOCTL_COMMAND) {
2453 /* Copy data back to the user */
2454 pt->BasicStatus = scb->basic_status;
2455 pt->ExtendedStatus = scb->extended_status;
2456 } else {
2457 pt->BasicStatus = scb->basic_status;
2458 pt->ExtendedStatus = scb->extended_status;
2459 up(scb->sem);
2463 #endif
2465 /****************************************************************************/
2466 /* */
2467 /* Routine Name: ips_host_info */
2468 /* */
2469 /* Routine Description: */
2470 /* */
2471 /* The passthru interface for the driver */
2472 /* */
2473 /****************************************************************************/
2474 static int
2475 ips_host_info(ips_ha_t *ha, char *ptr, off_t offset, int len) {
2476 IPS_INFOSTR info;
2478 METHOD_TRACE("ips_host_info", 1);
2480 info.buffer = ptr;
2481 info.length = len;
2482 info.offset = offset;
2483 info.pos = 0;
2484 info.localpos = 0;
2486 copy_info(&info, "\nIBM ServeRAID General Information:\n\n");
2488 if ((ha->nvram->signature == IPS_NVRAM_P5_SIG) &&
2489 (ha->nvram->adapter_type != 0))
2490 copy_info(&info, "\tController Type : %s\n", ips_adapter_name[ha->ad_type-1]);
2491 else
2492 copy_info(&info, "\tController Type : Unknown\n");
2494 if (ha->io_addr)
2495 copy_info(&info, "\tIO region : 0x%lx (%d bytes)\n",
2496 ha->io_addr, ha->io_len);
2498 if (ha->mem_addr) {
2499 copy_info(&info, "\tMemory region : 0x%lx (%d bytes)\n",
2500 ha->mem_addr, ha->mem_len);
2501 copy_info(&info, "\tShared memory address : 0x%lx\n", ha->mem_ptr);
2504 copy_info(&info, "\tIRQ number : %d\n", ha->irq);
2506 if (ha->nvram->signature == IPS_NVRAM_P5_SIG)
2507 copy_info(&info, "\tBIOS Version : %c%c%c%c%c%c%c%c\n",
2508 ha->nvram->bios_high[0], ha->nvram->bios_high[1],
2509 ha->nvram->bios_high[2], ha->nvram->bios_high[3],
2510 ha->nvram->bios_low[0], ha->nvram->bios_low[1],
2511 ha->nvram->bios_low[2], ha->nvram->bios_low[3]);
2513 copy_info(&info, "\tFirmware Version : %c%c%c%c%c%c%c%c\n",
2514 ha->enq->CodeBlkVersion[0], ha->enq->CodeBlkVersion[1],
2515 ha->enq->CodeBlkVersion[2], ha->enq->CodeBlkVersion[3],
2516 ha->enq->CodeBlkVersion[4], ha->enq->CodeBlkVersion[5],
2517 ha->enq->CodeBlkVersion[6], ha->enq->CodeBlkVersion[7]);
2519 copy_info(&info, "\tBoot Block Version : %c%c%c%c%c%c%c%c\n",
2520 ha->enq->BootBlkVersion[0], ha->enq->BootBlkVersion[1],
2521 ha->enq->BootBlkVersion[2], ha->enq->BootBlkVersion[3],
2522 ha->enq->BootBlkVersion[4], ha->enq->BootBlkVersion[5],
2523 ha->enq->BootBlkVersion[6], ha->enq->BootBlkVersion[7]);
2525 copy_info(&info, "\tDriver Version : %s%s\n",
2526 IPS_VERSION_HIGH, IPS_VERSION_LOW);
2528 copy_info(&info, "\tMax Physical Devices : %d\n",
2529 ha->enq->ucMaxPhysicalDevices);
2530 copy_info(&info, "\tMax Active Commands : %d\n",
2531 ha->max_cmds);
2532 copy_info(&info, "\tCurrent Queued Commands : %d\n",
2533 ha->scb_waitlist.count);
2534 copy_info(&info, "\tCurrent Active Commands : %d\n",
2535 ha->scb_activelist.count - ha->num_ioctl);
2536 copy_info(&info, "\tCurrent Queued PT Commands : %d\n",
2537 ha->copp_waitlist.count);
2538 copy_info(&info, "\tCurrent Active PT Commands : %d\n",
2539 ha->num_ioctl);
2541 copy_info(&info, "\n");
2543 return (info.localpos);
2546 /****************************************************************************/
2547 /* */
2548 /* Routine Name: copy_mem_info */
2549 /* */
2550 /* Routine Description: */
2551 /* */
2552 /* Copy data into an IPS_INFOSTR structure */
2553 /* */
2554 /****************************************************************************/
2555 static void
2556 copy_mem_info(IPS_INFOSTR *info, char *data, int len) {
2557 METHOD_TRACE("copy_mem_info", 1);
2559 if (info->pos + len < info->offset) {
2560 info->pos += len;
2561 return;
2564 if (info->pos < info->offset) {
2565 data += (info->offset - info->pos);
2566 len -= (info->offset - info->pos);
2567 info->pos += (info->offset - info->pos);
2570 if (info->localpos + len > info->length)
2571 len = info->length - info->localpos;
2573 if (len > 0) {
2574 memcpy(info->buffer + info->localpos, data, len);
2575 info->pos += len;
2576 info->localpos += len;
2580 /****************************************************************************/
2581 /* */
2582 /* Routine Name: copy_info */
2583 /* */
2584 /* Routine Description: */
2585 /* */
2586 /* printf style wrapper for an info structure */
2587 /* */
2588 /****************************************************************************/
2589 static int
2590 copy_info(IPS_INFOSTR *info, char *fmt, ...) {
2591 va_list args;
2592 char buf[128];
2593 int len;
2595 METHOD_TRACE("copy_info", 1);
2597 va_start(args, fmt);
2598 len = vsprintf(buf, fmt, args);
2599 va_end(args);
2601 copy_mem_info(info, buf, len);
2603 return (len);
2606 /****************************************************************************/
2607 /* */
2608 /* Routine Name: ips_hainit */
2609 /* */
2610 /* Routine Description: */
2611 /* */
2612 /* Initialize the controller */
2613 /* */
2614 /* NOTE: Assumes to be called from with a lock */
2615 /* */
2616 /****************************************************************************/
2617 static int
2618 ips_hainit(ips_ha_t *ha) {
2619 int i;
2620 struct timeval tv;
2622 METHOD_TRACE("ips_hainit", 1);
2624 if (!ha)
2625 return (0);
2627 if (ha->func.statinit)
2628 (*ha->func.statinit)(ha);
2630 if (ha->func.enableint)
2631 (*ha->func.enableint)(ha);
2633 /* Send FFDC */
2634 ha->reset_count = 1;
2635 do_gettimeofday(&tv);
2636 ha->last_ffdc = tv.tv_sec;
2637 ips_ffdc_reset(ha, IPS_INTR_IORL);
2639 if (!ips_read_config(ha, IPS_INTR_IORL)) {
2640 printk(KERN_WARNING "(%s%d) unable to read config from controller.\n",
2641 ips_name, ha->host_num);
2643 return (0);
2644 } /* end if */
2646 if (!ips_read_adapter_status(ha, IPS_INTR_IORL)) {
2647 printk(KERN_WARNING "(%s%d) unable to read controller status.\n",
2648 ips_name, ha->host_num);
2650 return (0);
2653 if (!ips_read_subsystem_parameters(ha, IPS_INTR_IORL)) {
2654 printk(KERN_WARNING "(%s%d) unable to read subsystem parameters.\n",
2655 ips_name, ha->host_num);
2657 return (0);
2660 /* write nvram user page 5 */
2661 if (!ips_write_driver_status(ha, IPS_INTR_IORL)) {
2662 printk(KERN_WARNING "(%s%d) unable to write driver info to controller.\n",
2663 ips_name, ha->host_num);
2665 return (0);
2668 /* set limits on SID, LUN, BUS */
2669 ha->ntargets = IPS_MAX_TARGETS + 1;
2670 ha->nlun = 1;
2671 ha->nbus = (ha->enq->ucMaxPhysicalDevices / IPS_MAX_TARGETS) + 1;
2673 switch (ha->conf->logical_drive[0].ucStripeSize) {
2674 case 4:
2675 ha->max_xfer = 0x10000;
2676 break;
2678 case 5:
2679 ha->max_xfer = 0x20000;
2680 break;
2682 case 6:
2683 ha->max_xfer = 0x40000;
2684 break;
2686 case 7:
2687 default:
2688 ha->max_xfer = 0x80000;
2689 break;
2692 /* setup max concurrent commands */
2693 if (ha->subsys->param[4] & 0x1) {
2694 /* Use the new method */
2695 ha->max_cmds = ha->enq->ucConcurrentCmdCount;
2696 } else {
2697 /* use the old method */
2698 switch (ha->conf->logical_drive[0].ucStripeSize) {
2699 case 4:
2700 ha->max_cmds = 32;
2701 break;
2703 case 5:
2704 ha->max_cmds = 16;
2705 break;
2707 case 6:
2708 ha->max_cmds = 8;
2709 break;
2711 case 7:
2712 default:
2713 ha->max_cmds = 4;
2714 break;
2718 /* set controller IDs */
2719 ha->ha_id[0] = IPS_ADAPTER_ID;
2720 for (i = 1; i < ha->nbus; i++) {
2721 ha->ha_id[i] = ha->conf->init_id[i-1] & 0x1f;
2722 ha->dcdb_active[i-1] = 0;
2725 return (1);
2728 /****************************************************************************/
2729 /* */
2730 /* Routine Name: ips_next */
2731 /* */
2732 /* Routine Description: */
2733 /* */
2734 /* Take the next command off the queue and send it to the controller */
2735 /* */
2736 /****************************************************************************/
2737 static void
2738 ips_next(ips_ha_t *ha, int intr) {
2739 ips_scb_t *scb;
2740 Scsi_Cmnd *SC;
2741 Scsi_Cmnd *p;
2742 Scsi_Cmnd *q;
2743 ips_copp_wait_item_t *item;
2744 int ret;
2745 int intr_status;
2746 u32 cpu_flags;
2747 u32 cpu_flags2;
2749 METHOD_TRACE("ips_next", 1);
2751 if (!ha)
2752 return ;
2755 * Block access to the queue function so
2756 * this command won't time out
2758 if (intr == IPS_INTR_ON) {
2759 spin_lock_irqsave(&io_request_lock, cpu_flags2);
2760 intr_status = IPS_INTR_IORL;
2761 } else {
2762 intr_status = intr;
2764 /* Quiet the compiler */
2765 cpu_flags2 = 0;
2768 if (ha->subsys->param[3] & 0x300000) {
2769 struct timeval tv;
2771 do_gettimeofday(&tv);
2773 IPS_HA_LOCK(cpu_flags);
2774 if (tv.tv_sec - ha->last_ffdc > IPS_SECS_8HOURS) {
2775 ha->last_ffdc = tv.tv_sec;
2776 IPS_HA_UNLOCK(cpu_flags);
2777 ips_ffdc_time(ha, intr_status);
2778 } else {
2779 IPS_HA_UNLOCK(cpu_flags);
2783 if (intr == IPS_INTR_ON)
2784 spin_unlock_irqrestore(&io_request_lock, cpu_flags2);
2786 #ifndef NO_IPS_CMDLINE
2788 * Send passthru commands
2789 * These have priority over normal I/O
2790 * but shouldn't affect performance too much
2791 * since we limit the number that can be active
2792 * on the card at any one time
2794 IPS_HA_LOCK(cpu_flags);
2795 IPS_QUEUE_LOCK(&ha->copp_waitlist);
2796 while ((ha->num_ioctl < IPS_MAX_IOCTL) &&
2797 (ha->copp_waitlist.head) &&
2798 (scb = ips_getscb(ha))) {
2800 IPS_QUEUE_UNLOCK(&ha->copp_waitlist);
2801 IPS_HA_UNLOCK(cpu_flags);
2802 item = ips_removeq_copp_head(&ha->copp_waitlist);
2803 scb->scsi_cmd = item->scsi_cmd;
2804 scb->sem = item->sem;
2805 kfree(item);
2807 ret = ips_make_passthru(ha, scb->scsi_cmd, scb);
2809 switch (ret) {
2810 case IPS_FAILURE:
2811 if (scb->scsi_cmd) {
2812 /* raise the semaphore */
2813 if (scb->scsi_cmd->cmnd[0] == IPS_IOCTL_NEW_COMMAND)
2814 up(scb->sem);
2816 scb->scsi_cmd->result = DID_ERROR << 16;
2818 ips_freescb(ha, scb);
2819 break;
2820 case IPS_SUCCESS_IMM:
2821 if (scb->scsi_cmd) {
2822 /* raise the semaphore */
2823 if (scb->scsi_cmd->cmnd[0] == IPS_IOCTL_NEW_COMMAND)
2824 up(scb->sem);
2827 ips_freescb(ha, scb);
2828 break;
2829 default:
2830 break;
2831 } /* end case */
2833 if (ret != IPS_SUCCESS) {
2834 IPS_HA_LOCK(cpu_flags);
2835 IPS_QUEUE_LOCK(&ha->copp_waitlist);
2836 continue;
2839 ret = ips_send_cmd(ha, scb);
2841 if (ret == IPS_SUCCESS) {
2842 ips_putq_scb_head(&ha->scb_activelist, scb);
2843 ha->num_ioctl++;
2846 switch(ret) {
2847 case IPS_FAILURE:
2848 if (scb->scsi_cmd) {
2849 /* raise the semaphore */
2850 if (scb->scsi_cmd->cmnd[0] == IPS_IOCTL_NEW_COMMAND)
2851 up(scb->sem);
2853 scb->scsi_cmd->result = DID_ERROR << 16;
2856 ips_freescb(ha, scb);
2857 break;
2858 case IPS_SUCCESS_IMM:
2859 if (scb->scsi_cmd) {
2860 /* raise the semaphore */
2861 if (scb->scsi_cmd->cmnd[0] == IPS_IOCTL_NEW_COMMAND)
2862 up(scb->sem);
2865 ips_freescb(ha, scb);
2866 break;
2867 default:
2868 break;
2869 } /* end case */
2871 IPS_HA_LOCK(cpu_flags);
2872 IPS_QUEUE_LOCK(&ha->copp_waitlist);
2875 IPS_QUEUE_UNLOCK(&ha->copp_waitlist);
2876 IPS_HA_UNLOCK(cpu_flags);
2877 #endif
2880 * Send "Normal" I/O commands
2882 IPS_HA_LOCK(cpu_flags);
2883 IPS_QUEUE_LOCK(&ha->scb_waitlist);
2884 p = ha->scb_waitlist.head;
2885 IPS_QUEUE_UNLOCK(&ha->scb_waitlist);
2886 while ((p) && (scb = ips_getscb(ha))) {
2887 if ((p->channel > 0) && (ha->dcdb_active[p->channel-1] & (1 << p->target))) {
2888 ips_freescb(ha, scb);
2889 p = (Scsi_Cmnd *) p->host_scribble;
2890 continue;
2893 IPS_HA_UNLOCK(cpu_flags);
2895 q = p;
2896 SC = ips_removeq_wait(&ha->scb_waitlist, q);
2898 SC->result = DID_OK;
2899 SC->host_scribble = NULL;
2901 memset(SC->sense_buffer, 0, sizeof(SC->sense_buffer));
2903 scb->target_id = SC->target;
2904 scb->lun = SC->lun;
2905 scb->bus = SC->channel;
2906 scb->scsi_cmd = SC;
2907 scb->breakup = 0;
2908 scb->data_len = 0;
2909 scb->callback = ipsintr_done;
2910 scb->timeout = ips_cmd_timeout;
2911 memset(&scb->cmd, 0, 16);
2913 /* copy in the CDB */
2914 memcpy(scb->cdb, SC->cmnd, SC->cmd_len);
2916 /* Now handle the data buffer */
2917 if (SC->use_sg) {
2918 struct scatterlist *sg;
2919 int i;
2921 sg = SC->request_buffer;
2923 if (SC->use_sg == 1) {
2924 if (sg[0].length > ha->max_xfer) {
2925 scb->breakup = 1;
2926 scb->data_len = ha->max_xfer;
2927 } else
2928 scb->data_len = sg[0].length;
2930 scb->dcdb.transfer_length = scb->data_len;
2931 scb->data_busaddr = VIRT_TO_BUS(sg[0].address);
2932 scb->sg_len = 0;
2933 } else {
2935 for (i = 0; i < SC->use_sg; i++) {
2936 scb->sg_list[i].address = VIRT_TO_BUS(sg[i].address);
2937 scb->sg_list[i].length = sg[i].length;
2939 if (scb->data_len + sg[i].length > ha->max_xfer) {
2941 * Data Breakup required
2943 scb->breakup = i;
2944 break;
2947 scb->data_len += sg[i].length;
2950 if (!scb->breakup)
2951 scb->sg_len = SC->use_sg;
2952 else
2953 scb->sg_len = scb->breakup;
2955 scb->dcdb.transfer_length = scb->data_len;
2956 scb->data_busaddr = VIRT_TO_BUS(scb->sg_list);
2958 } else {
2959 if (SC->request_bufflen) {
2960 if (SC->request_bufflen > ha->max_xfer) {
2962 * Data breakup required
2964 scb->breakup = 1;
2965 scb->data_len = ha->max_xfer;
2966 } else {
2967 scb->data_len = SC->request_bufflen;
2970 scb->dcdb.transfer_length = scb->data_len;
2971 scb->data_busaddr = VIRT_TO_BUS(SC->request_buffer);
2972 scb->sg_len = 0;
2973 } else {
2974 scb->data_busaddr = 0L;
2975 scb->sg_len = 0;
2976 scb->data_len = 0;
2977 scb->dcdb.transfer_length = 0;
2982 scb->dcdb.cmd_attribute |=
2983 ips_command_direction[scb->scsi_cmd->cmnd[0]];
2985 if (!scb->dcdb.cmd_attribute & 0x3)
2986 scb->dcdb.transfer_length = 0;
2988 if (scb->data_len >= IPS_MAX_XFER) {
2989 scb->dcdb.cmd_attribute |= IPS_TRANSFER64K;
2990 scb->dcdb.transfer_length = 0;
2993 ret = ips_send_cmd(ha, scb);
2995 if (ret == IPS_SUCCESS)
2996 ips_putq_scb_head(&ha->scb_activelist, scb);
2998 switch(ret) {
2999 case IPS_FAILURE:
3000 if (scb->scsi_cmd) {
3001 scb->scsi_cmd->result = DID_ERROR << 16;
3002 scb->scsi_cmd->scsi_done(scb->scsi_cmd);
3005 if (scb->bus)
3006 ha->dcdb_active[scb->bus-1] &= ~(1 << scb->target_id);
3008 ips_freescb(ha, scb);
3009 break;
3010 case IPS_SUCCESS_IMM:
3011 if (scb->scsi_cmd)
3012 scb->scsi_cmd->scsi_done(scb->scsi_cmd);
3014 if (scb->bus)
3015 ha->dcdb_active[scb->bus-1] &= ~(1 << scb->target_id);
3017 ips_freescb(ha, scb);
3018 break;
3019 default:
3020 break;
3021 } /* end case */
3023 p = (Scsi_Cmnd *) p->host_scribble;
3025 IPS_HA_LOCK(cpu_flags);
3026 } /* end while */
3028 IPS_HA_UNLOCK(cpu_flags);
3031 /****************************************************************************/
3032 /* */
3033 /* Routine Name: ips_putq_scb_head */
3034 /* */
3035 /* Routine Description: */
3036 /* */
3037 /* Add an item to the head of the queue */
3038 /* */
3039 /* ASSUMED to be called from within a lock */
3040 /* */
3041 /****************************************************************************/
3042 static inline void
3043 ips_putq_scb_head(ips_scb_queue_t *queue, ips_scb_t *item) {
3044 METHOD_TRACE("ips_putq_scb_head", 1);
3046 if (!item)
3047 return ;
3049 IPS_QUEUE_LOCK(queue);
3051 item->q_next = queue->head;
3052 queue->head = item;
3054 if (!queue->tail)
3055 queue->tail = item;
3057 queue->count++;
3059 IPS_QUEUE_UNLOCK(queue);
3062 /****************************************************************************/
3063 /* */
3064 /* Routine Name: ips_putq_scb_tail */
3065 /* */
3066 /* Routine Description: */
3067 /* */
3068 /* Add an item to the tail of the queue */
3069 /* */
3070 /* ASSUMED to be called from within a lock */
3071 /* */
3072 /****************************************************************************/
3073 static inline void
3074 ips_putq_scb_tail(ips_scb_queue_t *queue, ips_scb_t *item) {
3075 METHOD_TRACE("ips_putq_scb_tail", 1);
3077 if (!item)
3078 return ;
3080 IPS_QUEUE_LOCK(queue);
3082 item->q_next = NULL;
3084 if (queue->tail)
3085 queue->tail->q_next = item;
3087 queue->tail = item;
3089 if (!queue->head)
3090 queue->head = item;
3092 queue->count++;
3094 IPS_QUEUE_UNLOCK(queue);
3097 /****************************************************************************/
3098 /* */
3099 /* Routine Name: ips_removeq_scb_head */
3100 /* */
3101 /* Routine Description: */
3102 /* */
3103 /* Remove the head of the queue */
3104 /* */
3105 /* ASSUMED to be called from within a lock */
3106 /* */
3107 /****************************************************************************/
3108 static inline ips_scb_t *
3109 ips_removeq_scb_head(ips_scb_queue_t *queue) {
3110 ips_scb_t *item;
3112 METHOD_TRACE("ips_removeq_scb_head", 1);
3114 IPS_QUEUE_LOCK(queue);
3116 item = queue->head;
3118 if (!item) {
3119 IPS_QUEUE_UNLOCK(queue);
3121 return (NULL);
3124 queue->head = item->q_next;
3125 item->q_next = NULL;
3127 if (queue->tail == item)
3128 queue->tail = NULL;
3130 queue->count--;
3132 IPS_QUEUE_UNLOCK(queue);
3134 return (item);
3137 /****************************************************************************/
3138 /* */
3139 /* Routine Name: ips_removeq_scb */
3140 /* */
3141 /* Routine Description: */
3142 /* */
3143 /* Remove an item from a queue */
3144 /* */
3145 /* ASSUMED to be called from within a lock */
3146 /* */
3147 /****************************************************************************/
3148 static inline ips_scb_t *
3149 ips_removeq_scb(ips_scb_queue_t *queue, ips_scb_t *item) {
3150 ips_scb_t *p;
3152 METHOD_TRACE("ips_removeq_scb", 1);
3154 if (!item)
3155 return (NULL);
3157 IPS_QUEUE_LOCK(queue);
3159 if (item == queue->head) {
3160 IPS_QUEUE_UNLOCK(queue);
3162 return (ips_removeq_scb_head(queue));
3165 p = queue->head;
3167 while ((p) && (item != p->q_next))
3168 p = p->q_next;
3170 if (p) {
3171 /* found a match */
3172 p->q_next = item->q_next;
3174 if (!item->q_next)
3175 queue->tail = p;
3177 item->q_next = NULL;
3178 queue->count--;
3180 IPS_QUEUE_UNLOCK(queue);
3182 return (item);
3185 IPS_QUEUE_UNLOCK(queue);
3187 return (NULL);
3190 /****************************************************************************/
3191 /* */
3192 /* Routine Name: ips_putq_wait_head */
3193 /* */
3194 /* Routine Description: */
3195 /* */
3196 /* Add an item to the head of the queue */
3197 /* */
3198 /* ASSUMED to be called from within a lock */
3199 /* */
3200 /****************************************************************************/
3201 static inline void
3202 ips_putq_wait_head(ips_wait_queue_t *queue, Scsi_Cmnd *item) {
3203 METHOD_TRACE("ips_putq_wait_head", 1);
3205 if (!item)
3206 return ;
3208 IPS_QUEUE_LOCK(queue);
3210 item->host_scribble = (char *) queue->head;
3211 queue->head = item;
3213 if (!queue->tail)
3214 queue->tail = item;
3216 queue->count++;
3218 IPS_QUEUE_UNLOCK(queue);
3221 /****************************************************************************/
3222 /* */
3223 /* Routine Name: ips_putq_wait_tail */
3224 /* */
3225 /* Routine Description: */
3226 /* */
3227 /* Add an item to the tail of the queue */
3228 /* */
3229 /* ASSUMED to be called from within a lock */
3230 /* */
3231 /****************************************************************************/
3232 static inline void
3233 ips_putq_wait_tail(ips_wait_queue_t *queue, Scsi_Cmnd *item) {
3234 METHOD_TRACE("ips_putq_wait_tail", 1);
3236 if (!item)
3237 return ;
3239 IPS_QUEUE_LOCK(queue);
3241 item->host_scribble = NULL;
3243 if (queue->tail)
3244 queue->tail->host_scribble = (char *)item;
3246 queue->tail = item;
3248 if (!queue->head)
3249 queue->head = item;
3251 queue->count++;
3253 IPS_QUEUE_UNLOCK(queue);
3256 /****************************************************************************/
3257 /* */
3258 /* Routine Name: ips_removeq_wait_head */
3259 /* */
3260 /* Routine Description: */
3261 /* */
3262 /* Remove the head of the queue */
3263 /* */
3264 /* ASSUMED to be called from within a lock */
3265 /* */
3266 /****************************************************************************/
3267 static inline Scsi_Cmnd *
3268 ips_removeq_wait_head(ips_wait_queue_t *queue) {
3269 Scsi_Cmnd *item;
3271 METHOD_TRACE("ips_removeq_wait_head", 1);
3273 IPS_QUEUE_LOCK(queue);
3275 item = queue->head;
3277 if (!item) {
3278 IPS_QUEUE_UNLOCK(queue);
3280 return (NULL);
3283 queue->head = (Scsi_Cmnd *) item->host_scribble;
3284 item->host_scribble = NULL;
3286 if (queue->tail == item)
3287 queue->tail = NULL;
3289 queue->count--;
3291 IPS_QUEUE_UNLOCK(queue);
3293 return (item);
3296 /****************************************************************************/
3297 /* */
3298 /* Routine Name: ips_removeq_wait */
3299 /* */
3300 /* Routine Description: */
3301 /* */
3302 /* Remove an item from a queue */
3303 /* */
3304 /* ASSUMED to be called from within a lock */
3305 /* */
3306 /****************************************************************************/
3307 static inline Scsi_Cmnd *
3308 ips_removeq_wait(ips_wait_queue_t *queue, Scsi_Cmnd *item) {
3309 Scsi_Cmnd *p;
3311 METHOD_TRACE("ips_removeq_wait", 1);
3313 if (!item)
3314 return (NULL);
3316 IPS_QUEUE_LOCK(queue);
3318 if (item == queue->head) {
3319 IPS_QUEUE_UNLOCK(queue);
3321 return (ips_removeq_wait_head(queue));
3324 p = queue->head;
3326 while ((p) && (item != (Scsi_Cmnd *) p->host_scribble))
3327 p = (Scsi_Cmnd *) p->host_scribble;
3329 if (p) {
3330 /* found a match */
3331 p->host_scribble = item->host_scribble;
3333 if (!item->host_scribble)
3334 queue->tail = p;
3336 item->host_scribble = NULL;
3337 queue->count--;
3339 IPS_QUEUE_UNLOCK(queue);
3341 return (item);
3344 IPS_QUEUE_UNLOCK(queue);
3346 return (NULL);
3349 /****************************************************************************/
3350 /* */
3351 /* Routine Name: ips_putq_copp_head */
3352 /* */
3353 /* Routine Description: */
3354 /* */
3355 /* Add an item to the head of the queue */
3356 /* */
3357 /* ASSUMED to be called from within a lock */
3358 /* */
3359 /****************************************************************************/
3360 static inline void
3361 ips_putq_copp_head(ips_copp_queue_t *queue, ips_copp_wait_item_t *item) {
3362 METHOD_TRACE("ips_putq_copp_head", 1);
3364 if (!item)
3365 return ;
3367 IPS_QUEUE_LOCK(queue);
3369 item->next = queue->head;
3370 queue->head = item;
3372 if (!queue->tail)
3373 queue->tail = item;
3375 queue->count++;
3377 IPS_QUEUE_UNLOCK(queue);
3380 /****************************************************************************/
3381 /* */
3382 /* Routine Name: ips_putq_copp_tail */
3383 /* */
3384 /* Routine Description: */
3385 /* */
3386 /* Add an item to the tail of the queue */
3387 /* */
3388 /* ASSUMED to be called from within a lock */
3389 /* */
3390 /****************************************************************************/
3391 static inline void
3392 ips_putq_copp_tail(ips_copp_queue_t *queue, ips_copp_wait_item_t *item) {
3393 METHOD_TRACE("ips_putq_copp_tail", 1);
3395 if (!item)
3396 return ;
3398 IPS_QUEUE_LOCK(queue);
3400 item->next = NULL;
3402 if (queue->tail)
3403 queue->tail->next = item;
3405 queue->tail = item;
3407 if (!queue->head)
3408 queue->head = item;
3410 queue->count++;
3412 IPS_QUEUE_UNLOCK(queue);
3415 /****************************************************************************/
3416 /* */
3417 /* Routine Name: ips_removeq_copp_head */
3418 /* */
3419 /* Routine Description: */
3420 /* */
3421 /* Remove the head of the queue */
3422 /* */
3423 /* ASSUMED to be called from within a lock */
3424 /* */
3425 /****************************************************************************/
3426 static inline ips_copp_wait_item_t *
3427 ips_removeq_copp_head(ips_copp_queue_t *queue) {
3428 ips_copp_wait_item_t *item;
3430 METHOD_TRACE("ips_removeq_copp_head", 1);
3432 IPS_QUEUE_LOCK(queue);
3434 item = queue->head;
3436 if (!item) {
3437 IPS_QUEUE_UNLOCK(queue);
3439 return (NULL);
3442 queue->head = item->next;
3443 item->next = NULL;
3445 if (queue->tail == item)
3446 queue->tail = NULL;
3448 queue->count--;
3450 IPS_QUEUE_UNLOCK(queue);
3452 return (item);
3455 /****************************************************************************/
3456 /* */
3457 /* Routine Name: ips_removeq_copp */
3458 /* */
3459 /* Routine Description: */
3460 /* */
3461 /* Remove an item from a queue */
3462 /* */
3463 /* ASSUMED to be called from within a lock */
3464 /* */
3465 /****************************************************************************/
3466 static inline ips_copp_wait_item_t *
3467 ips_removeq_copp(ips_copp_queue_t *queue, ips_copp_wait_item_t *item) {
3468 ips_copp_wait_item_t *p;
3470 METHOD_TRACE("ips_removeq_copp", 1);
3472 if (!item)
3473 return (NULL);
3475 IPS_QUEUE_LOCK(queue);
3477 if (item == queue->head) {
3478 IPS_QUEUE_UNLOCK(queue);
3480 return (ips_removeq_copp_head(queue));
3483 p = queue->head;
3485 while ((p) && (item != p->next))
3486 p = p->next;
3488 if (p) {
3489 /* found a match */
3490 p->next = item->next;
3492 if (!item->next)
3493 queue->tail = p;
3495 item->next = NULL;
3496 queue->count--;
3498 IPS_QUEUE_UNLOCK(queue);
3500 return (item);
3503 IPS_QUEUE_UNLOCK(queue);
3505 return (NULL);
3508 /****************************************************************************/
3509 /* */
3510 /* Routine Name: ipsintr_blocking */
3511 /* */
3512 /* Routine Description: */
3513 /* */
3514 /* Finalize an interrupt for internal commands */
3515 /* */
3516 /****************************************************************************/
3517 static void
3518 ipsintr_blocking(ips_ha_t *ha, ips_scb_t *scb) {
3519 METHOD_TRACE("ipsintr_blocking", 2);
3521 if ((ha->waitflag == TRUE) &&
3522 (ha->cmd_in_progress == scb->cdb[0])) {
3523 ha->waitflag = FALSE;
3525 return ;
3529 /****************************************************************************/
3530 /* */
3531 /* Routine Name: ipsintr_done */
3532 /* */
3533 /* Routine Description: */
3534 /* */
3535 /* Finalize an interrupt for non-internal commands */
3536 /* */
3537 /****************************************************************************/
3538 static void
3539 ipsintr_done(ips_ha_t *ha, ips_scb_t *scb) {
3540 METHOD_TRACE("ipsintr_done", 2);
3542 if (!scb) {
3543 printk(KERN_WARNING "(%s%d) Spurious interrupt; scb NULL.\n",
3544 ips_name, ha->host_num);
3546 return ;
3549 if (scb->scsi_cmd == NULL) {
3550 /* unexpected interrupt */
3551 printk(KERN_WARNING "(%s%d) Spurious interrupt; scsi_cmd not set.\n",
3552 ips_name, ha->host_num);
3554 return;
3557 ips_done(ha, scb);
3560 /****************************************************************************/
3561 /* */
3562 /* Routine Name: ips_done */
3563 /* */
3564 /* Routine Description: */
3565 /* */
3566 /* Do housekeeping on completed commands */
3567 /* */
3568 /****************************************************************************/
3569 static void
3570 ips_done(ips_ha_t *ha, ips_scb_t *scb) {
3571 int ret;
3572 u32 cpu_flags;
3574 METHOD_TRACE("ips_done", 1);
3576 if (!scb)
3577 return ;
3579 #ifndef NO_IPS_CMDLINE
3580 if ((scb->scsi_cmd) && (ips_is_passthru(scb->scsi_cmd))) {
3581 ips_cleanup_passthru(ha, scb);
3582 IPS_HA_LOCK(cpu_flags);
3583 ha->num_ioctl--;
3584 IPS_HA_UNLOCK(cpu_flags);
3585 } else {
3586 #endif
3588 * Check to see if this command had too much
3589 * data and had to be broke up. If so, queue
3590 * the rest of the data and continue.
3592 if (scb->breakup) {
3593 /* we had a data breakup */
3594 u16 bk_save;
3596 bk_save = scb->breakup;
3597 scb->breakup = 0;
3599 if (scb->scsi_cmd->use_sg) {
3600 /* S/G request */
3601 struct scatterlist *sg;
3602 int i;
3604 sg = scb->scsi_cmd->request_buffer;
3606 if (scb->scsi_cmd->use_sg == 1) {
3607 if (sg[0].length - (bk_save * ha->max_xfer)) {
3608 /* Further breakup required */
3609 scb->data_len = ha->max_xfer;
3610 scb->data_busaddr = VIRT_TO_BUS(sg[0].address + (bk_save * ha->max_xfer));
3611 scb->breakup = bk_save + 1;
3612 } else {
3613 scb->data_len = sg[0].length - (bk_save * ha->max_xfer);
3614 scb->data_busaddr = VIRT_TO_BUS(sg[0].address + (bk_save * ha->max_xfer));
3617 scb->dcdb.transfer_length = scb->data_len;
3618 scb->sg_len = 0;
3619 } else {
3620 scb->data_len = 0;
3622 for (i = bk_save; i < scb->scsi_cmd->use_sg; i++) {
3623 scb->sg_list[i - bk_save].address = VIRT_TO_BUS(sg[i].address);
3624 scb->sg_list[i - bk_save].length = sg[i].length;
3626 if (scb->data_len + sg[i].length > ha->max_xfer) {
3628 * Data Breakup required
3630 scb->breakup = i;
3631 break;
3634 scb->data_len += sg[i].length;
3637 if (!scb->breakup)
3638 scb->sg_len = scb->scsi_cmd->use_sg - bk_save;
3639 else
3640 scb->sg_len = scb->breakup - bk_save;
3642 scb->dcdb.transfer_length = scb->data_len;
3643 scb->data_busaddr = VIRT_TO_BUS(scb->sg_list);
3645 } else {
3646 /* Non S/G Request */
3647 if (scb->scsi_cmd->request_bufflen - (bk_save * ha->max_xfer)) {
3648 /* Further breakup required */
3649 scb->data_len = ha->max_xfer;
3650 scb->data_busaddr = VIRT_TO_BUS(scb->scsi_cmd->request_buffer + (bk_save * ha->max_xfer));
3651 scb->breakup = bk_save + 1;
3652 } else {
3653 scb->data_len = scb->scsi_cmd->request_bufflen - (bk_save * ha->max_xfer);
3654 scb->data_busaddr = VIRT_TO_BUS(scb->scsi_cmd->request_buffer + (bk_save * ha->max_xfer));
3657 scb->dcdb.transfer_length = scb->data_len;
3658 scb->sg_len = 0;
3661 scb->dcdb.cmd_attribute |=
3662 ips_command_direction[scb->scsi_cmd->cmnd[0]];
3664 if (!scb->dcdb.cmd_attribute & 0x3)
3665 scb->dcdb.transfer_length = 0;
3667 if (scb->data_len >= IPS_MAX_XFER) {
3668 scb->dcdb.cmd_attribute |= IPS_TRANSFER64K;
3669 scb->dcdb.transfer_length = 0;
3672 ret = ips_send_cmd(ha, scb);
3674 switch(ret) {
3675 case IPS_FAILURE:
3676 if (scb->scsi_cmd) {
3677 scb->scsi_cmd->result = DID_ERROR << 16;
3678 scb->scsi_cmd->scsi_done(scb->scsi_cmd);
3681 ips_freescb(ha, scb);
3682 break;
3683 case IPS_SUCCESS_IMM:
3684 if (scb->scsi_cmd) {
3685 scb->scsi_cmd->result = DID_ERROR << 16;
3686 scb->scsi_cmd->scsi_done(scb->scsi_cmd);
3689 ips_freescb(ha, scb);
3690 break;
3691 default:
3692 break;
3693 } /* end case */
3695 return ;
3697 #ifndef NO_IPS_CMDLINE
3698 } /* end if passthru */
3699 #endif
3701 if (scb->bus) {
3702 IPS_HA_LOCK(cpu_flags);
3703 ha->dcdb_active[scb->bus-1] &= ~(1 << scb->target_id);
3704 IPS_HA_UNLOCK(cpu_flags);
3707 /* call back to SCSI layer */
3708 if (scb->scsi_cmd && scb->scsi_cmd->cmnd[0] != IPS_IOCTL_NEW_COMMAND)
3709 scb->scsi_cmd->scsi_done(scb->scsi_cmd);
3711 ips_freescb(ha, scb);
3714 /****************************************************************************/
3715 /* */
3716 /* Routine Name: ips_map_status */
3717 /* */
3718 /* Routine Description: */
3719 /* */
3720 /* Map ServeRAID error codes to Linux Error Codes */
3721 /* */
3722 /****************************************************************************/
3723 static int
3724 ips_map_status(ips_ha_t *ha, ips_scb_t *scb, ips_stat_t *sp) {
3725 int errcode;
3726 int device_error;
3728 METHOD_TRACE("ips_map_status", 1);
3730 if (scb->bus) {
3731 DEBUG_VAR(2, "(%s%d) Physical device error (%d %d %d): %x %x, Sense Key: %x, ASC: %x, ASCQ: %x",
3732 ips_name,
3733 ha->host_num,
3734 scb->scsi_cmd->channel,
3735 scb->scsi_cmd->target,
3736 scb->scsi_cmd->lun,
3737 scb->basic_status,
3738 scb->extended_status,
3739 scb->extended_status == IPS_ERR_CKCOND ? scb->dcdb.sense_info[2] & 0xf : 0,
3740 scb->extended_status == IPS_ERR_CKCOND ? scb->dcdb.sense_info[12] : 0,
3741 scb->extended_status == IPS_ERR_CKCOND ? scb->dcdb.sense_info[13] : 0);
3744 /* default driver error */
3745 errcode = DID_ERROR;
3746 device_error = 0;
3748 switch (scb->basic_status & IPS_GSC_STATUS_MASK) {
3749 case IPS_CMD_TIMEOUT:
3750 errcode = DID_TIME_OUT;
3751 break;
3753 case IPS_INVAL_OPCO:
3754 case IPS_INVAL_CMD_BLK:
3755 case IPS_INVAL_PARM_BLK:
3756 case IPS_LD_ERROR:
3757 case IPS_CMD_CMPLT_WERROR:
3758 break;
3760 case IPS_PHYS_DRV_ERROR:
3761 switch (scb->extended_status) {
3762 case IPS_ERR_SEL_TO:
3763 if (scb->bus)
3764 errcode = DID_NO_CONNECT;
3766 break;
3768 case IPS_ERR_OU_RUN:
3769 if ((scb->bus) && (scb->dcdb.transfer_length < scb->data_len)) {
3770 /* Underrun - set default to no error */
3771 errcode = DID_OK;
3773 /* Restrict access to physical DASD */
3774 if ((scb->scsi_cmd->cmnd[0] == INQUIRY) &&
3775 ((((char *) scb->scsi_cmd->buffer)[0] & 0x1f) == TYPE_DISK)) {
3776 /* underflow -- no error */
3777 /* restrict access to physical DASD */
3778 errcode = DID_TIME_OUT;
3779 break;
3781 } else
3782 errcode = DID_ERROR;
3784 break;
3786 case IPS_ERR_RECOVERY:
3787 /* don't fail recovered errors */
3788 if (scb->bus)
3789 errcode = DID_OK;
3791 break;
3793 case IPS_ERR_HOST_RESET:
3794 case IPS_ERR_DEV_RESET:
3795 errcode = DID_RESET;
3796 break;
3798 case IPS_ERR_CKCOND:
3799 if (scb->bus) {
3800 memcpy(scb->scsi_cmd->sense_buffer, scb->dcdb.sense_info,
3801 sizeof(scb->scsi_cmd->sense_buffer));
3803 device_error = 2; /* check condition */
3806 errcode = DID_OK;
3808 break;
3810 default:
3811 errcode = DID_ERROR;
3812 break;
3814 } /* end switch */
3815 } /* end switch */
3817 scb->scsi_cmd->result = device_error | (errcode << 16);
3819 return (1);
3822 /****************************************************************************/
3823 /* */
3824 /* Routine Name: ips_send */
3825 /* */
3826 /* Routine Description: */
3827 /* */
3828 /* Wrapper for ips_send_cmd */
3829 /* */
3830 /****************************************************************************/
3831 static int
3832 ips_send(ips_ha_t *ha, ips_scb_t *scb, ips_scb_callback callback) {
3833 int ret;
3835 METHOD_TRACE("ips_send", 1);
3837 scb->callback = callback;
3839 ret = ips_send_cmd(ha, scb);
3841 return (ret);
3844 /****************************************************************************/
3845 /* */
3846 /* Routine Name: ips_send_wait */
3847 /* */
3848 /* Routine Description: */
3849 /* */
3850 /* Send a command to the controller and wait for it to return */
3851 /* */
3852 /****************************************************************************/
3853 static int
3854 ips_send_wait(ips_ha_t *ha, ips_scb_t *scb, int timeout, int intr) {
3855 int ret;
3857 METHOD_TRACE("ips_send_wait", 1);
3859 ha->waitflag = TRUE;
3860 ha->cmd_in_progress = scb->cdb[0];
3862 ret = ips_send(ha, scb, ipsintr_blocking);
3864 if ((ret == IPS_FAILURE) || (ret == IPS_SUCCESS_IMM))
3865 return (ret);
3867 ret = ips_wait(ha, timeout, intr);
3869 return (ret);
3872 /****************************************************************************/
3873 /* */
3874 /* Routine Name: ips_send_cmd */
3875 /* */
3876 /* Routine Description: */
3877 /* */
3878 /* Map SCSI commands to ServeRAID commands for logical drives */
3879 /* */
3880 /****************************************************************************/
3881 static int
3882 ips_send_cmd(ips_ha_t *ha, ips_scb_t *scb) {
3883 int ret;
3885 METHOD_TRACE("ips_send_cmd", 1);
3887 ret = IPS_SUCCESS;
3889 if (!scb->scsi_cmd) {
3890 /* internal command */
3892 if (scb->bus > 0) {
3893 /* ServeRAID commands can't be issued */
3894 /* to real devices -- fail them */
3895 if ((ha->waitflag == TRUE) &&
3896 (ha->cmd_in_progress == scb->cdb[0])) {
3897 ha->waitflag = FALSE;
3900 return (1);
3902 #ifndef NO_IPS_CMDLINE
3903 } else if ((scb->bus == 0) && (!ips_is_passthru(scb->scsi_cmd))) {
3904 #else
3905 } else if (scb->bus == 0) {
3906 #endif
3907 /* command to logical bus -- interpret */
3908 ret = IPS_SUCCESS_IMM;
3910 switch (scb->scsi_cmd->cmnd[0]) {
3911 case ALLOW_MEDIUM_REMOVAL:
3912 case REZERO_UNIT:
3913 case ERASE:
3914 case WRITE_FILEMARKS:
3915 case SPACE:
3916 scb->scsi_cmd->result = DID_ERROR << 16;
3917 break;
3919 case START_STOP:
3920 scb->scsi_cmd->result = DID_OK << 16;
3922 case TEST_UNIT_READY:
3923 case INQUIRY:
3924 if (scb->target_id == IPS_ADAPTER_ID) {
3926 * Either we have a TUR
3927 * or we have a SCSI inquiry
3929 if (scb->scsi_cmd->cmnd[0] == TEST_UNIT_READY)
3930 scb->scsi_cmd->result = DID_OK << 16;
3932 if (scb->scsi_cmd->cmnd[0] == INQUIRY) {
3933 IPS_INQ_DATA inq;
3935 memset(&inq, 0, sizeof(IPS_INQ_DATA));
3937 inq.DeviceType = TYPE_PROCESSOR;
3938 inq.DeviceTypeQualifier = 0;
3939 inq.RemoveableMedia = 0;
3940 inq.Versions = 0x1; /* SCSI I */
3941 inq.AdditionalLength = 31;
3942 strncpy(inq.VendorId, "IBM ", 8);
3943 strncpy(inq.ProductId, "SERVERAID ", 16);
3944 strncpy(inq.ProductRevisionLevel, "1.00", 4);
3946 memcpy(scb->scsi_cmd->request_buffer, &inq, scb->scsi_cmd->request_bufflen);
3948 scb->scsi_cmd->result = DID_OK << 16;
3950 } else {
3951 scb->cmd.logical_info.op_code = IPS_CMD_GET_LD_INFO;
3952 scb->cmd.logical_info.command_id = IPS_COMMAND_ID(ha, scb);
3953 scb->cmd.logical_info.buffer_addr = VIRT_TO_BUS(&ha->adapt->logical_drive_info);
3954 scb->cmd.logical_info.reserved = 0;
3955 scb->cmd.logical_info.reserved2 = 0;
3956 ret = IPS_SUCCESS;
3959 break;
3961 case REQUEST_SENSE:
3962 ips_reqsen(ha, scb);
3963 scb->scsi_cmd->result = DID_OK << 16;
3964 break;
3966 case READ_6:
3967 case WRITE_6:
3968 if (!scb->sg_len) {
3969 scb->cmd.basic_io.op_code =
3970 (scb->scsi_cmd->cmnd[0] == READ_6) ? IPS_CMD_READ : IPS_CMD_WRITE;
3971 } else {
3972 scb->cmd.basic_io.op_code =
3973 (scb->scsi_cmd->cmnd[0] == READ_6) ? IPS_CMD_READ_SG : IPS_CMD_WRITE_SG;
3976 scb->cmd.basic_io.command_id = IPS_COMMAND_ID(ha, scb);
3977 scb->cmd.basic_io.log_drv = scb->target_id;
3978 scb->cmd.basic_io.sg_count = scb->sg_len;
3979 scb->cmd.basic_io.sg_addr = scb->data_busaddr;
3981 if (scb->cmd.basic_io.lba)
3982 scb->cmd.basic_io.lba += scb->cmd.basic_io.sector_count;
3983 else
3984 scb->cmd.basic_io.lba = (((scb->scsi_cmd->cmnd[1] & 0x1f) << 16) |
3985 (scb->scsi_cmd->cmnd[2] << 8) |
3986 (scb->scsi_cmd->cmnd[3]));
3988 scb->cmd.basic_io.sector_count = scb->data_len / IPS_BLKSIZE;
3990 if (scb->cmd.basic_io.sector_count == 0)
3991 scb->cmd.basic_io.sector_count = 256;
3993 scb->cmd.basic_io.reserved = 0;
3994 ret = IPS_SUCCESS;
3995 break;
3997 case READ_10:
3998 case WRITE_10:
3999 if (!scb->sg_len) {
4000 scb->cmd.basic_io.op_code =
4001 (scb->scsi_cmd->cmnd[0] == READ_10) ? IPS_CMD_READ : IPS_CMD_WRITE;
4002 } else {
4003 scb->cmd.basic_io.op_code =
4004 (scb->scsi_cmd->cmnd[0] == READ_10) ? IPS_CMD_READ_SG : IPS_CMD_WRITE_SG;
4007 scb->cmd.basic_io.command_id = IPS_COMMAND_ID(ha, scb);
4008 scb->cmd.basic_io.log_drv = scb->target_id;
4009 scb->cmd.basic_io.sg_count = scb->sg_len;
4010 scb->cmd.basic_io.sg_addr = scb->data_busaddr;
4012 if (scb->cmd.basic_io.lba)
4013 scb->cmd.basic_io.lba += scb->cmd.basic_io.sector_count;
4014 else
4015 scb->cmd.basic_io.lba = ((scb->scsi_cmd->cmnd[2] << 24) |
4016 (scb->scsi_cmd->cmnd[3] << 16) |
4017 (scb->scsi_cmd->cmnd[4] << 8) |
4018 scb->scsi_cmd->cmnd[5]);
4020 scb->cmd.basic_io.sector_count = scb->data_len / IPS_BLKSIZE;
4022 scb->cmd.basic_io.reserved = 0;
4024 if (scb->cmd.basic_io.sector_count == 0) {
4026 * This is a null condition
4027 * we don't have to do anything
4028 * so just return
4030 scb->scsi_cmd->result = DID_OK << 16;
4031 } else
4032 ret = IPS_SUCCESS;
4034 break;
4036 case RESERVE:
4037 case RELEASE:
4038 scb->scsi_cmd->result = DID_OK << 16;
4039 break;
4041 case MODE_SENSE:
4042 scb->cmd.basic_io.op_code = IPS_CMD_ENQUIRY;
4043 scb->cmd.basic_io.command_id = IPS_COMMAND_ID(ha, scb);
4044 scb->cmd.basic_io.sg_addr = VIRT_TO_BUS(ha->enq);
4045 ret = IPS_SUCCESS;
4046 break;
4048 case READ_CAPACITY:
4049 scb->cmd.logical_info.op_code = IPS_CMD_GET_LD_INFO;
4050 scb->cmd.logical_info.command_id = IPS_COMMAND_ID(ha, scb);
4051 scb->cmd.logical_info.buffer_addr = VIRT_TO_BUS(&ha->adapt->logical_drive_info);
4052 scb->cmd.logical_info.reserved = 0;
4053 scb->cmd.logical_info.reserved2 = 0;
4054 scb->cmd.logical_info.reserved3 = 0;
4055 ret = IPS_SUCCESS;
4056 break;
4058 case SEND_DIAGNOSTIC:
4059 case REASSIGN_BLOCKS:
4060 case FORMAT_UNIT:
4061 case SEEK_10:
4062 case VERIFY:
4063 case READ_DEFECT_DATA:
4064 case READ_BUFFER:
4065 case WRITE_BUFFER:
4066 scb->scsi_cmd->result = DID_OK << 16;
4067 break;
4069 default:
4070 scb->scsi_cmd->result = DID_ERROR << 16;
4071 break;
4072 } /* end switch */
4073 } /* end if */
4075 if (ret == IPS_SUCCESS_IMM)
4076 return (ret);
4078 /* setup DCDB */
4079 if (scb->bus > 0) {
4080 if (!scb->sg_len)
4081 scb->cmd.dcdb.op_code = IPS_CMD_DCDB;
4082 else
4083 scb->cmd.dcdb.op_code = IPS_CMD_DCDB_SG;
4085 ha->dcdb_active[scb->bus-1] |= (1 << scb->target_id);
4086 scb->cmd.dcdb.command_id = IPS_COMMAND_ID(ha, scb);
4087 scb->cmd.dcdb.dcdb_address = VIRT_TO_BUS(&scb->dcdb);
4088 scb->cmd.dcdb.reserved = 0;
4089 scb->cmd.dcdb.reserved2 = 0;
4090 scb->cmd.dcdb.reserved3 = 0;
4092 scb->dcdb.device_address = ((scb->bus - 1) << 4) | scb->target_id;
4093 scb->dcdb.cmd_attribute |= IPS_DISCONNECT_ALLOWED;
4095 if (scb->timeout) {
4096 if (scb->timeout <= 10)
4097 scb->dcdb.cmd_attribute |= IPS_TIMEOUT10;
4098 else if (scb->timeout <= 60)
4099 scb->dcdb.cmd_attribute |= IPS_TIMEOUT60;
4100 else
4101 scb->dcdb.cmd_attribute |= IPS_TIMEOUT20M;
4104 if (!(scb->dcdb.cmd_attribute & IPS_TIMEOUT20M))
4105 scb->dcdb.cmd_attribute |= IPS_TIMEOUT20M;
4107 scb->dcdb.sense_length = sizeof(scb->scsi_cmd->sense_buffer);
4108 scb->dcdb.buffer_pointer = scb->data_busaddr;
4109 scb->dcdb.sg_count = scb->sg_len;
4110 scb->dcdb.cdb_length = scb->scsi_cmd->cmd_len;
4111 memcpy(scb->dcdb.scsi_cdb, scb->scsi_cmd->cmnd, scb->scsi_cmd->cmd_len);
4114 return ((*ha->func.issue)(ha, scb));
4117 /****************************************************************************/
4118 /* */
4119 /* Routine Name: ips_chk_status */
4120 /* */
4121 /* Routine Description: */
4122 /* */
4123 /* Check the status of commands to logical drives */
4124 /* */
4125 /****************************************************************************/
4126 static void
4127 ips_chkstatus(ips_ha_t *ha, IPS_STATUS *pstatus) {
4128 ips_scb_t *scb;
4129 ips_stat_t *sp;
4130 u8 basic_status;
4131 u8 ext_status;
4132 int errcode;
4134 METHOD_TRACE("ips_chkstatus", 1);
4136 scb = &ha->scbs[pstatus->fields.command_id];
4137 scb->basic_status = basic_status = pstatus->fields.basic_status & IPS_BASIC_STATUS_MASK;
4138 scb->extended_status = ext_status = pstatus->fields.extended_status;
4140 sp = &ha->sp;
4141 sp->residue_len = 0;
4142 sp->scb_addr = (u32) scb;
4144 /* Remove the item from the active queue */
4145 ips_removeq_scb(&ha->scb_activelist, scb);
4147 if (!scb->scsi_cmd)
4148 /* internal commands are handled in do_ipsintr */
4149 return ;
4151 DEBUG_VAR(2, "(%s%d) ips_chkstatus: cmd 0x%X id %d (%d %d %d)",
4152 ips_name,
4153 ha->host_num,
4154 scb->cdb[0],
4155 scb->cmd.basic_io.command_id,
4156 scb->bus,
4157 scb->target_id,
4158 scb->lun);
4160 #ifndef NO_IPS_CMDLINE
4161 if ((scb->scsi_cmd) && (ips_is_passthru(scb->scsi_cmd)))
4162 /* passthru - just returns the raw result */
4163 return ;
4164 #endif
4166 errcode = DID_OK;
4168 if (((basic_status & IPS_GSC_STATUS_MASK) == IPS_CMD_SUCCESS) ||
4169 ((basic_status & IPS_GSC_STATUS_MASK) == IPS_CMD_RECOVERED_ERROR)) {
4171 if (scb->bus == 0) {
4172 if ((basic_status & IPS_GSC_STATUS_MASK) == IPS_CMD_RECOVERED_ERROR) {
4173 DEBUG_VAR(1, "(%s%d) Recovered Logical Drive Error OpCode: %x, BSB: %x, ESB: %x",
4174 ips_name, ha->host_num,
4175 scb->cmd.basic_io.op_code, basic_status, ext_status);
4178 switch (scb->scsi_cmd->cmnd[0]) {
4179 case ALLOW_MEDIUM_REMOVAL:
4180 case REZERO_UNIT:
4181 case ERASE:
4182 case WRITE_FILEMARKS:
4183 case SPACE:
4184 errcode = DID_ERROR;
4185 break;
4187 case START_STOP:
4188 break;
4190 case TEST_UNIT_READY:
4191 if (!ips_online(ha, scb)) {
4192 errcode = DID_TIME_OUT;
4194 break;
4196 case INQUIRY:
4197 if (ips_online(ha, scb)) {
4198 ips_inquiry(ha, scb);
4199 } else {
4200 errcode = DID_TIME_OUT;
4202 break;
4204 case REQUEST_SENSE:
4205 ips_reqsen(ha, scb);
4206 break;
4208 case READ_6:
4209 case WRITE_6:
4210 case READ_10:
4211 case WRITE_10:
4212 case RESERVE:
4213 case RELEASE:
4214 break;
4216 case MODE_SENSE:
4217 if (!ips_online(ha, scb) || !ips_msense(ha, scb)) {
4218 errcode = DID_ERROR;
4220 break;
4222 case READ_CAPACITY:
4223 if (ips_online(ha, scb))
4224 ips_rdcap(ha, scb);
4225 else {
4226 errcode = DID_TIME_OUT;
4228 break;
4230 case SEND_DIAGNOSTIC:
4231 case REASSIGN_BLOCKS:
4232 break;
4234 case FORMAT_UNIT:
4235 errcode = DID_ERROR;
4236 break;
4238 case SEEK_10:
4239 case VERIFY:
4240 case READ_DEFECT_DATA:
4241 case READ_BUFFER:
4242 case WRITE_BUFFER:
4243 break;
4245 default:
4246 errcode = DID_ERROR;
4247 } /* end switch */
4249 scb->scsi_cmd->result = errcode << 16;
4250 } else { /* bus == 0 */
4251 /* restrict access to physical drives */
4252 if ((scb->scsi_cmd->cmnd[0] == INQUIRY) &&
4253 ((((char *) scb->scsi_cmd->buffer)[0] & 0x1f) == TYPE_DISK)) {
4255 scb->scsi_cmd->result = DID_TIME_OUT << 16;
4257 } /* else */
4258 } else { /* recovered error / success */
4259 if (scb->bus == 0) {
4260 DEBUG_VAR(1, "(%s%d) Unrecovered Logical Drive Error OpCode: %x, BSB: %x, ESB: %x",
4261 ips_name, ha->host_num,
4262 scb->cmd.basic_io.op_code, basic_status, ext_status);
4265 ips_map_status(ha, scb, sp);
4266 } /* else */
4269 /****************************************************************************/
4270 /* */
4271 /* Routine Name: ips_online */
4272 /* */
4273 /* Routine Description: */
4274 /* */
4275 /* Determine if a logical drive is online */
4276 /* */
4277 /****************************************************************************/
4278 static int
4279 ips_online(ips_ha_t *ha, ips_scb_t *scb) {
4280 METHOD_TRACE("ips_online", 1);
4282 if (scb->target_id >= IPS_MAX_LD)
4283 return (0);
4285 if ((scb->basic_status & IPS_GSC_STATUS_MASK) > 1) {
4286 memset(&ha->adapt->logical_drive_info, 0, sizeof(ha->adapt->logical_drive_info));
4288 return (0);
4291 if (scb->target_id < ha->adapt->logical_drive_info.no_of_log_drive &&
4292 ha->adapt->logical_drive_info.drive_info[scb->target_id].state != IPS_LD_OFFLINE &&
4293 ha->adapt->logical_drive_info.drive_info[scb->target_id].state != IPS_LD_FREE &&
4294 ha->adapt->logical_drive_info.drive_info[scb->target_id].state != IPS_LD_CRS &&
4295 ha->adapt->logical_drive_info.drive_info[scb->target_id].state != IPS_LD_SYS)
4296 return (1);
4297 else
4298 return (0);
4301 /****************************************************************************/
4302 /* */
4303 /* Routine Name: ips_inquiry */
4304 /* */
4305 /* Routine Description: */
4306 /* */
4307 /* Simulate an inquiry command to a logical drive */
4308 /* */
4309 /****************************************************************************/
4310 static int
4311 ips_inquiry(ips_ha_t *ha, ips_scb_t *scb) {
4312 IPS_INQ_DATA inq;
4314 METHOD_TRACE("ips_inquiry", 1);
4316 memset(&inq, 0, sizeof(IPS_INQ_DATA));
4318 inq.DeviceType = TYPE_DISK;
4319 inq.DeviceTypeQualifier = 0;
4320 inq.RemoveableMedia = 0;
4321 inq.Versions = 0x1; /* SCSI I */
4322 inq.AdditionalLength = 31;
4323 strncpy(inq.VendorId, "IBM ", 8);
4324 strncpy(inq.ProductId, "SERVERAID ", 16);
4325 strncpy(inq.ProductRevisionLevel, "1.00", 4);
4327 memcpy(scb->scsi_cmd->request_buffer, &inq, scb->scsi_cmd->request_bufflen);
4329 return (1);
4332 /****************************************************************************/
4333 /* */
4334 /* Routine Name: ips_rdcap */
4335 /* */
4336 /* Routine Description: */
4337 /* */
4338 /* Simulate a read capacity command to a logical drive */
4339 /* */
4340 /****************************************************************************/
4341 static int
4342 ips_rdcap(ips_ha_t *ha, ips_scb_t *scb) {
4343 IPS_CAPACITY *cap;
4345 METHOD_TRACE("ips_rdcap", 1);
4347 if (scb->scsi_cmd->bufflen < 8)
4348 return (0);
4350 cap = (IPS_CAPACITY *) scb->scsi_cmd->request_buffer;
4352 cap->lba = htonl(ha->adapt->logical_drive_info.drive_info[scb->target_id].sector_count - 1);
4353 cap->len = htonl((u32) IPS_BLKSIZE);
4355 return (1);
4358 /****************************************************************************/
4359 /* */
4360 /* Routine Name: ips_msense */
4361 /* */
4362 /* Routine Description: */
4363 /* */
4364 /* Simulate a mode sense command to a logical drive */
4365 /* */
4366 /****************************************************************************/
4367 static int
4368 ips_msense(ips_ha_t *ha, ips_scb_t *scb) {
4369 u16 heads;
4370 u16 sectors;
4371 u32 cylinders;
4372 ips_mdata_t mdata;
4374 METHOD_TRACE("ips_msense", 1);
4376 if (ha->enq->ulDriveSize[scb->target_id] > 0x400000 &&
4377 (ha->enq->ucMiscFlag & 0x8) == 0) {
4378 heads = IPS_NORM_HEADS;
4379 sectors = IPS_NORM_SECTORS;
4380 } else {
4381 heads = IPS_COMP_HEADS;
4382 sectors = IPS_COMP_SECTORS;
4385 cylinders = ha->enq->ulDriveSize[scb->target_id] / (heads * sectors);
4387 mdata.plh.plh_type = 0;
4388 mdata.plh.plh_wp = 0;
4389 mdata.plh.plh_bdl = 8;
4391 switch (scb->scsi_cmd->cmnd[2] & 0x3f) {
4392 case 0x03: /* page 3 */
4393 mdata.pdata.pg3.pg_pc = 0x3;
4394 mdata.pdata.pg3.pg_res1 = 0;
4395 mdata.pdata.pg3.pg_len = sizeof(IPS_DADF);
4396 mdata.plh.plh_len = 3 + mdata.plh.plh_bdl + mdata.pdata.pg3.pg_len;
4397 mdata.pdata.pg3.pg_trk_z = 0;
4398 mdata.pdata.pg3.pg_asec_z = 0;
4399 mdata.pdata.pg3.pg_atrk_z = 0;
4400 mdata.pdata.pg3.pg_atrk_v = 0;
4401 mdata.pdata.pg3.pg_sec_t = htons(sectors);
4402 mdata.pdata.pg3.pg_bytes_s = htons(IPS_BLKSIZE);
4403 mdata.pdata.pg3.pg_intl = htons(1);
4404 mdata.pdata.pg3.pg_trkskew = 0;
4405 mdata.pdata.pg3.pg_cylskew = 0;
4406 mdata.pdata.pg3.pg_res2 = 0;
4407 mdata.pdata.pg3.pg_ins = 0;
4408 mdata.pdata.pg3.pg_surf = 0;
4409 mdata.pdata.pg3.pg_rmb = 0;
4410 mdata.pdata.pg3.pg_hsec = 0;
4411 mdata.pdata.pg3.pg_ssec = 1;
4412 break;
4414 case 0x4:
4415 mdata.pdata.pg4.pg_pc = 0x4;
4416 mdata.pdata.pg4.pg_res1 = 0;
4417 mdata.pdata.pg4.pg_len = sizeof(IPS_RDDG);
4418 mdata.plh.plh_len = 3 + mdata.plh.plh_bdl + mdata.pdata.pg4.pg_len;
4419 mdata.pdata.pg4.pg_cylu = (cylinders >> 8) & 0xffff;
4420 mdata.pdata.pg4.pg_cyll = cylinders & 0xff;
4421 mdata.pdata.pg4.pg_head = heads;
4422 mdata.pdata.pg4.pg_wrpcompu = 0;
4423 mdata.pdata.pg4.pg_wrpcompl = 0;
4424 mdata.pdata.pg4.pg_redwrcur = 0;
4425 mdata.pdata.pg4.pg_drstep = htons(1);
4426 mdata.pdata.pg4.pg_landu = 0;
4427 mdata.pdata.pg4.pg_landl = 0;
4428 mdata.pdata.pg4.pg_res2 = 0;
4429 break;
4430 default:
4431 return (0);
4432 } /* end switch */
4434 memcpy(scb->scsi_cmd->request_buffer, &mdata, scb->scsi_cmd->request_bufflen);
4436 return (1);
4439 /****************************************************************************/
4440 /* */
4441 /* Routine Name: ips_reqsen */
4442 /* */
4443 /* Routine Description: */
4444 /* */
4445 /* Simulate a request sense command to a logical drive */
4446 /* */
4447 /****************************************************************************/
4448 static int
4449 ips_reqsen(ips_ha_t *ha, ips_scb_t *scb) {
4450 char *sp;
4452 METHOD_TRACE("ips_reqsen", 1);
4454 sp = (char *) scb->scsi_cmd->sense_buffer;
4455 memset(sp, 0, sizeof(scb->scsi_cmd->sense_buffer));
4457 sp[0] = 0x70;
4458 sp[3] = NO_SENSE;
4459 sp[7] = 0xe;
4460 sp[12] = NO_SENSE;
4462 return (0);
4465 /****************************************************************************/
4466 /* */
4467 /* Routine Name: ips_free */
4468 /* */
4469 /* Routine Description: */
4470 /* */
4471 /* Free any allocated space for this controller */
4472 /* */
4473 /****************************************************************************/
4474 static void
4475 ips_free(ips_ha_t *ha) {
4476 int i;
4478 METHOD_TRACE("ips_free", 1);
4480 if (ha) {
4481 if (ha->enq) {
4482 kfree(ha->enq);
4483 ha->enq = NULL;
4486 if (ha->conf) {
4487 kfree(ha->conf);
4488 ha->conf = NULL;
4491 if (ha->adapt) {
4492 kfree(ha->adapt);
4493 ha->adapt = NULL;
4496 if (ha->nvram) {
4497 kfree(ha->nvram);
4498 ha->nvram = NULL;
4501 if (ha->subsys) {
4502 kfree(ha->subsys);
4503 ha->subsys = NULL;
4506 if (ha->dummy) {
4507 kfree(ha->dummy);
4508 ha->dummy = NULL;
4511 if (ha->ioctl_data) {
4512 kfree(ha->ioctl_data);
4513 ha->ioctl_data = NULL;
4514 ha->ioctl_datasize = 0;
4517 if (ha->scbs) {
4518 for (i = 0; i < ha->max_cmds; i++) {
4519 if (ha->scbs[i].sg_list)
4520 kfree(ha->scbs[i].sg_list);
4523 kfree(ha->scbs);
4524 ha->scbs = NULL;
4525 } /* end if */
4527 /* free memory mapped (if applicable) */
4528 if (ha->mem_ptr) {
4529 iounmap(ha->ioremap_ptr);
4530 ha->ioremap_ptr = NULL;
4531 ha->mem_ptr = NULL;
4532 ha->mem_addr = 0;
4537 /****************************************************************************/
4538 /* */
4539 /* Routine Name: ips_allocatescbs */
4540 /* */
4541 /* Routine Description: */
4542 /* */
4543 /* Allocate the command blocks */
4544 /* */
4545 /****************************************************************************/
4546 static int
4547 ips_allocatescbs(ips_ha_t *ha) {
4548 ips_scb_t *scb_p;
4549 int i;
4551 METHOD_TRACE("ips_allocatescbs", 1);
4553 /* Allocate memory for the CCBs */
4554 ha->scbs = (ips_scb_t *) kmalloc(ha->max_cmds * sizeof(ips_scb_t), GFP_ATOMIC|GFP_DMA);
4555 if(ha->scbs == NULL)
4556 return 0;
4558 memset(ha->scbs, 0, ha->max_cmds * sizeof(ips_scb_t));
4560 for (i = 0; i < ha->max_cmds; i++) {
4561 scb_p = &ha->scbs[i];
4563 /* allocate S/G list */
4564 scb_p->sg_list = (IPS_SG_LIST *) kmalloc(sizeof(IPS_SG_LIST) * IPS_MAX_SG, GFP_ATOMIC|GFP_DMA);
4566 if (! scb_p->sg_list)
4567 return (0);
4569 /* add to the free list */
4570 if (i < ha->max_cmds - 1) {
4571 scb_p->q_next = ha->scb_freelist;
4572 ha->scb_freelist = scb_p;
4576 /* success */
4577 return (1);
4580 /****************************************************************************/
4581 /* */
4582 /* Routine Name: ips_init_scb */
4583 /* */
4584 /* Routine Description: */
4585 /* */
4586 /* Initialize a CCB to default values */
4587 /* */
4588 /****************************************************************************/
4589 static void
4590 ips_init_scb(ips_ha_t *ha, ips_scb_t *scb) {
4591 IPS_SG_LIST *sg_list;
4593 METHOD_TRACE("ips_init_scb", 1);
4595 if (scb == NULL)
4596 return ;
4598 sg_list = scb->sg_list;
4600 /* zero fill */
4601 memset(scb, 0, sizeof(ips_scb_t));
4602 memset(ha->dummy, 0, sizeof(IPS_IO_CMD));
4604 /* Initialize dummy command bucket */
4605 ha->dummy->op_code = 0xFF;
4606 ha->dummy->ccsar = VIRT_TO_BUS(ha->dummy);
4607 ha->dummy->command_id = IPS_MAX_CMDS;
4609 /* set bus address of scb */
4610 scb->scb_busaddr = VIRT_TO_BUS(scb);
4611 scb->sg_list = sg_list;
4613 /* Neptune Fix */
4614 scb->cmd.basic_io.cccr = IPS_BIT_ILE;
4615 scb->cmd.basic_io.ccsar = VIRT_TO_BUS(ha->dummy);
4618 /****************************************************************************/
4619 /* */
4620 /* Routine Name: ips_get_scb */
4621 /* */
4622 /* Routine Description: */
4623 /* */
4624 /* Initialize a CCB to default values */
4625 /* */
4626 /* ASSUMED to be callled from within a lock */
4627 /* */
4628 /****************************************************************************/
4629 static ips_scb_t *
4630 ips_getscb(ips_ha_t *ha) {
4631 ips_scb_t *scb;
4632 u32 cpu_flags;
4634 METHOD_TRACE("ips_getscb", 1);
4636 IPS_SCB_LOCK(cpu_flags);
4637 if ((scb = ha->scb_freelist) == NULL) {
4638 IPS_SCB_UNLOCK(cpu_flags);
4640 return (NULL);
4643 ha->scb_freelist = scb->q_next;
4644 scb->q_next = NULL;
4646 IPS_SCB_UNLOCK(cpu_flags);
4648 ips_init_scb(ha, scb);
4650 return (scb);
4653 /****************************************************************************/
4654 /* */
4655 /* Routine Name: ips_free_scb */
4656 /* */
4657 /* Routine Description: */
4658 /* */
4659 /* Return an unused CCB back to the free list */
4660 /* */
4661 /* ASSUMED to be called from within a lock */
4662 /* */
4663 /****************************************************************************/
4664 static void
4665 ips_freescb(ips_ha_t *ha, ips_scb_t *scb) {
4666 u32 cpu_flags;
4668 METHOD_TRACE("ips_freescb", 1);
4670 /* check to make sure this is not our "special" scb */
4671 if (IPS_COMMAND_ID(ha, scb) < (ha->max_cmds - 1)) {
4672 IPS_SCB_LOCK(cpu_flags);
4673 scb->q_next = ha->scb_freelist;
4674 ha->scb_freelist = scb;
4675 IPS_SCB_UNLOCK(cpu_flags);
4679 /****************************************************************************/
4680 /* */
4681 /* Routine Name: ips_isinit_copperhead */
4682 /* */
4683 /* Routine Description: */
4684 /* */
4685 /* Reset the controller */
4686 /* */
4687 /****************************************************************************/
4688 static int
4689 ips_isinit_copperhead(ips_ha_t *ha) {
4690 u8 scpr;
4691 u8 isr;
4693 METHOD_TRACE("ips_isinit_copperhead", 1);
4695 isr = inb(ha->io_addr + IPS_REG_HISR);
4696 scpr = inb(ha->io_addr + IPS_REG_SCPR);
4698 if (((isr & IPS_BIT_EI) == 0) && ((scpr & IPS_BIT_EBM) == 0))
4699 return (0);
4700 else
4701 return (1);
4704 /****************************************************************************/
4705 /* */
4706 /* Routine Name: ips_isinit_copperhead_memio */
4707 /* */
4708 /* Routine Description: */
4709 /* */
4710 /* Reset the controller */
4711 /* */
4712 /****************************************************************************/
4713 static int
4714 ips_isinit_copperhead_memio(ips_ha_t *ha) {
4715 u8 isr;
4716 u8 scpr;
4718 METHOD_TRACE("ips_is_init_copperhead_memio", 1);
4720 isr = readb(ha->mem_ptr + IPS_REG_HISR);
4721 scpr = readb(ha->mem_ptr + IPS_REG_SCPR);
4723 if (((isr & IPS_BIT_EI) == 0) && ((scpr & IPS_BIT_EBM) == 0))
4724 return (0);
4725 else
4726 return (1);
4729 /****************************************************************************/
4730 /* */
4731 /* Routine Name: ips_isinit_morpheus */
4732 /* */
4733 /* Routine Description: */
4734 /* */
4735 /* Reset the controller */
4736 /* */
4737 /****************************************************************************/
4738 static int
4739 ips_isinit_morpheus(ips_ha_t *ha) {
4740 u32 post;
4741 u32 bits;
4743 METHOD_TRACE("ips_is_init_morpheus", 1);
4745 post = readl(ha->mem_ptr + IPS_REG_I960_MSG0);
4746 bits = readl(ha->mem_ptr + IPS_REG_I2O_HIR);
4748 if (post == 0)
4749 return (0);
4750 else if (bits & 0x3)
4751 return (0);
4752 else
4753 return (1);
4756 /****************************************************************************/
4757 /* */
4758 /* Routine Name: ips_enable_int_copperhead */
4759 /* */
4760 /* Routine Description: */
4761 /* Turn on interrupts */
4762 /* */
4763 /****************************************************************************/
4764 static void
4765 ips_enable_int_copperhead(ips_ha_t *ha) {
4766 METHOD_TRACE("ips_enable_int_copperhead", 1);
4768 outb(ha->io_addr + IPS_REG_HISR, IPS_BIT_EI);
4771 /****************************************************************************/
4772 /* */
4773 /* Routine Name: ips_enable_int_copperhead_memio */
4774 /* */
4775 /* Routine Description: */
4776 /* Turn on interrupts */
4777 /* */
4778 /****************************************************************************/
4779 static void
4780 ips_enable_int_copperhead_memio(ips_ha_t *ha) {
4781 METHOD_TRACE("ips_enable_int_copperhead_memio", 1);
4783 writeb(IPS_BIT_EI, ha->mem_ptr + IPS_REG_HISR);
4786 /****************************************************************************/
4787 /* */
4788 /* Routine Name: ips_enable_int_morpheus */
4789 /* */
4790 /* Routine Description: */
4791 /* Turn on interrupts */
4792 /* */
4793 /****************************************************************************/
4794 static void
4795 ips_enable_int_morpheus(ips_ha_t *ha) {
4796 u32 Oimr;
4798 METHOD_TRACE("ips_enable_int_morpheus", 1);
4800 Oimr = readl(ha->mem_ptr + IPS_REG_I960_OIMR);
4801 Oimr &= ~0x08;
4802 writel(Oimr, ha->mem_ptr + IPS_REG_I960_OIMR);
4805 /****************************************************************************/
4806 /* */
4807 /* Routine Name: ips_init_copperhead */
4808 /* */
4809 /* Routine Description: */
4810 /* */
4811 /* Initialize a copperhead controller */
4812 /* */
4813 /****************************************************************************/
4814 static int
4815 ips_init_copperhead(ips_ha_t *ha) {
4816 u8 Isr;
4817 u8 Cbsp;
4818 u8 PostByte[IPS_MAX_POST_BYTES];
4819 u8 ConfigByte[IPS_MAX_CONFIG_BYTES];
4820 int i, j;
4822 METHOD_TRACE("ips_init_copperhead", 1);
4824 for (i = 0; i < IPS_MAX_POST_BYTES; i++) {
4825 for (j = 0; j < 45; j++) {
4826 Isr = inb(ha->io_addr + IPS_REG_HISR);
4827 if (Isr & IPS_BIT_GHI)
4828 break;
4830 MDELAY(IPS_ONE_SEC);
4833 if (j >= 45)
4834 /* error occured */
4835 return (0);
4837 PostByte[i] = inb(ha->io_addr + IPS_REG_ISPR);
4838 outb(Isr, ha->io_addr + IPS_REG_HISR);
4841 if (PostByte[0] < IPS_GOOD_POST_STATUS) {
4842 printk(KERN_WARNING "(%s%d) reset controller fails (post status %x %x).\n",
4843 ips_name, ha->host_num, PostByte[0], PostByte[1]);
4845 return (0);
4848 for (i = 0; i < IPS_MAX_CONFIG_BYTES; i++) {
4849 for (j = 0; j < 240; j++) {
4850 Isr = inb(ha->io_addr + IPS_REG_HISR);
4851 if (Isr & IPS_BIT_GHI)
4852 break;
4854 MDELAY(IPS_ONE_SEC); /* 100 msec */
4857 if (j >= 240)
4858 /* error occured */
4859 return (0);
4861 ConfigByte[i] = inb(ha->io_addr + IPS_REG_ISPR);
4862 outb(Isr, ha->io_addr + IPS_REG_HISR);
4865 for (i = 0; i < 240; i++) {
4866 Cbsp = inb(ha->io_addr + IPS_REG_CBSP);
4868 if ((Cbsp & IPS_BIT_OP) == 0)
4869 break;
4871 MDELAY(IPS_ONE_SEC);
4874 if (i >= 240)
4875 /* reset failed */
4876 return (0);
4878 /* setup CCCR */
4879 outw(0x1010, ha->io_addr + IPS_REG_CCCR);
4881 /* Enable busmastering */
4882 outb(IPS_BIT_EBM, ha->io_addr + IPS_REG_SCPR);
4884 if (ha->revision_id == IPS_REVID_TROMBONE64)
4885 /* fix for anaconda64 */
4886 outl(0, ha->io_addr + IPS_REG_NDAE);
4888 /* Enable interrupts */
4889 outb(IPS_BIT_EI, ha->io_addr + IPS_REG_HISR);
4891 return (1);
4894 /****************************************************************************/
4895 /* */
4896 /* Routine Name: ips_init_copperhead_memio */
4897 /* */
4898 /* Routine Description: */
4899 /* */
4900 /* Initialize a copperhead controller with memory mapped I/O */
4901 /* */
4902 /****************************************************************************/
4903 static int
4904 ips_init_copperhead_memio(ips_ha_t *ha) {
4905 u8 Isr;
4906 u8 Cbsp;
4907 u8 PostByte[IPS_MAX_POST_BYTES];
4908 u8 ConfigByte[IPS_MAX_CONFIG_BYTES];
4909 int i, j;
4911 METHOD_TRACE("ips_init_copperhead_memio", 1);
4913 for (i = 0; i < IPS_MAX_POST_BYTES; i++) {
4914 for (j = 0; j < 45; j++) {
4915 Isr = readb(ha->mem_ptr + IPS_REG_HISR);
4916 if (Isr & IPS_BIT_GHI)
4917 break;
4919 MDELAY(IPS_ONE_SEC);
4922 if (j >= 45)
4923 /* error occured */
4924 return (0);
4926 PostByte[i] = readb(ha->mem_ptr + IPS_REG_ISPR);
4927 writeb(Isr, ha->mem_ptr + IPS_REG_HISR);
4930 if (PostByte[0] < IPS_GOOD_POST_STATUS) {
4931 printk(KERN_WARNING "(%s%d) reset controller fails (post status %x %x).\n",
4932 ips_name, ha->host_num, PostByte[0], PostByte[1]);
4934 return (0);
4937 for (i = 0; i < IPS_MAX_CONFIG_BYTES; i++) {
4938 for (j = 0; j < 240; j++) {
4939 Isr = readb(ha->mem_ptr + IPS_REG_HISR);
4940 if (Isr & IPS_BIT_GHI)
4941 break;
4943 MDELAY(IPS_ONE_SEC); /* 100 msec */
4946 if (j >= 240)
4947 /* error occured */
4948 return (0);
4950 ConfigByte[i] = readb(ha->mem_ptr + IPS_REG_ISPR);
4951 writeb(Isr, ha->mem_ptr + IPS_REG_HISR);
4954 for (i = 0; i < 240; i++) {
4955 Cbsp = readb(ha->mem_ptr + IPS_REG_CBSP);
4957 if ((Cbsp & IPS_BIT_OP) == 0)
4958 break;
4960 MDELAY(IPS_ONE_SEC);
4963 if (i >= 240)
4964 /* error occured */
4965 return (0);
4967 /* setup CCCR */
4968 writel(0x1010, ha->mem_ptr + IPS_REG_CCCR);
4970 /* Enable busmastering */
4971 writeb(IPS_BIT_EBM, ha->mem_ptr + IPS_REG_SCPR);
4973 if (ha->revision_id == IPS_REVID_TROMBONE64)
4974 /* fix for anaconda64 */
4975 writel(0, ha->mem_ptr + IPS_REG_NDAE);
4977 /* Enable interrupts */
4978 writeb(IPS_BIT_EI, ha->mem_ptr + IPS_REG_HISR);
4980 /* if we get here then everything went OK */
4981 return (1);
4984 /****************************************************************************/
4985 /* */
4986 /* Routine Name: ips_init_morpheus */
4987 /* */
4988 /* Routine Description: */
4989 /* */
4990 /* Initialize a morpheus controller */
4991 /* */
4992 /****************************************************************************/
4993 static int
4994 ips_init_morpheus(ips_ha_t *ha) {
4995 u32 Post;
4996 u32 Config;
4997 u32 Isr;
4998 u32 Oimr;
4999 int i;
5001 METHOD_TRACE("ips_init_morpheus", 1);
5003 /* Wait up to 45 secs for Post */
5004 for (i = 0; i < 45; i++) {
5005 Isr = readl(ha->mem_ptr + IPS_REG_I2O_HIR);
5007 if (Isr & IPS_BIT_I960_MSG0I)
5008 break;
5010 MDELAY(IPS_ONE_SEC);
5013 if (i >= 45) {
5014 /* error occured */
5015 printk(KERN_WARNING "(%s%d) timeout waiting for post.\n",
5016 ips_name, ha->host_num);
5018 return (0);
5021 Post = readl(ha->mem_ptr + IPS_REG_I960_MSG0);
5023 /* Clear the interrupt bit */
5024 Isr = (u32) IPS_BIT_I960_MSG0I;
5025 writel(Isr, ha->mem_ptr + IPS_REG_I2O_HIR);
5027 if (Post < (IPS_GOOD_POST_STATUS << 8)) {
5028 printk(KERN_WARNING "(%s%d) reset controller fails (post status %x).\n",
5029 ips_name, ha->host_num, Post);
5031 return (0);
5034 /* Wait up to 240 secs for config bytes */
5035 for (i = 0; i < 240; i++) {
5036 Isr = readl(ha->mem_ptr + IPS_REG_I2O_HIR);
5038 if (Isr & IPS_BIT_I960_MSG1I)
5039 break;
5041 MDELAY(IPS_ONE_SEC); /* 100 msec */
5044 if (i >= 240) {
5045 /* error occured */
5046 printk(KERN_WARNING "(%s%d) timeout waiting for config.\n",
5047 ips_name, ha->host_num);
5049 return (0);
5052 Config = readl(ha->mem_ptr + IPS_REG_I960_MSG1);
5054 /* Clear interrupt bit */
5055 Isr = (u32) IPS_BIT_I960_MSG1I;
5056 writel(Isr, ha->mem_ptr + IPS_REG_I2O_HIR);
5058 /* Turn on the interrupts */
5059 Oimr = readl(ha->mem_ptr + IPS_REG_I960_OIMR);
5060 Oimr &= ~0x8;
5061 writel(Oimr, ha->mem_ptr + IPS_REG_I960_OIMR);
5063 /* if we get here then everything went OK */
5064 return (1);
5067 /****************************************************************************/
5068 /* */
5069 /* Routine Name: ips_reset_copperhead */
5070 /* */
5071 /* Routine Description: */
5072 /* */
5073 /* Reset the controller */
5074 /* */
5075 /****************************************************************************/
5076 static int
5077 ips_reset_copperhead(ips_ha_t *ha) {
5078 int reset_counter;
5079 u32 cpu_flags;
5081 METHOD_TRACE("ips_reset_copperhead", 1);
5083 DEBUG_VAR(1, "(%s%d) ips_reset_copperhead: io addr: %x, irq: %d",
5084 ips_name, ha->host_num, ha->io_addr, ha->irq);
5086 IPS_HA_LOCK(cpu_flags);
5088 reset_counter = 0;
5090 while (reset_counter < 2) {
5091 reset_counter++;
5093 outb(IPS_BIT_RST, ha->io_addr + IPS_REG_SCPR);
5094 MDELAY(IPS_ONE_SEC);
5095 outb(0, ha->io_addr + IPS_REG_SCPR);
5096 MDELAY(IPS_ONE_SEC);
5098 if ((*ha->func.init)(ha))
5099 break;
5100 else if (reset_counter >= 2) {
5101 IPS_HA_UNLOCK(cpu_flags);
5103 return (0);
5107 IPS_HA_UNLOCK(cpu_flags);
5109 return (1);
5112 /****************************************************************************/
5113 /* */
5114 /* Routine Name: ips_reset_copperhead_memio */
5115 /* */
5116 /* Routine Description: */
5117 /* */
5118 /* Reset the controller */
5119 /* */
5120 /****************************************************************************/
5121 static int
5122 ips_reset_copperhead_memio(ips_ha_t *ha) {
5123 int reset_counter;
5124 u32 cpu_flags;
5126 METHOD_TRACE("ips_reset_copperhead_memio", 1);
5128 DEBUG_VAR(1, "(%s%d) ips_reset_copperhead_memio: mem addr: %x, irq: %d",
5129 ips_name, ha->host_num, ha->mem_addr, ha->irq);
5131 IPS_HA_LOCK(cpu_flags);
5133 reset_counter = 0;
5135 while (reset_counter < 2) {
5136 reset_counter++;
5138 writeb(IPS_BIT_RST, ha->mem_ptr + IPS_REG_SCPR);
5139 MDELAY(IPS_ONE_SEC);
5140 writeb(0, ha->mem_ptr + IPS_REG_SCPR);
5141 MDELAY(IPS_ONE_SEC);
5143 if ((*ha->func.init)(ha))
5144 break;
5145 else if (reset_counter >= 2) {
5146 IPS_HA_UNLOCK(cpu_flags);
5148 return (0);
5152 IPS_HA_UNLOCK(cpu_flags);
5154 return (1);
5157 /****************************************************************************/
5158 /* */
5159 /* Routine Name: ips_reset_morpheus */
5160 /* */
5161 /* Routine Description: */
5162 /* */
5163 /* Reset the controller */
5164 /* */
5165 /****************************************************************************/
5166 static int
5167 ips_reset_morpheus(ips_ha_t *ha) {
5168 int reset_counter;
5169 u8 junk;
5170 u32 cpu_flags;
5172 METHOD_TRACE("ips_reset_morpheus", 1);
5174 DEBUG_VAR(1, "(%s%d) ips_reset_morpheus: mem addr: %x, irq: %d",
5175 ips_name, ha->host_num, ha->mem_addr, ha->irq);
5177 IPS_HA_LOCK(cpu_flags);
5179 reset_counter = 0;
5181 while (reset_counter < 2) {
5182 reset_counter++;
5184 writel(0x80000000, ha->mem_ptr + IPS_REG_I960_IDR);
5186 /* Delay for 300 msec */
5187 MDELAY(300 * IPS_ONE_MSEC);
5189 /* Do a PCI config read to wait for adapter */
5190 pci_read_config_byte(ha->pcidev, 4, &junk);
5192 if ((*ha->func.init)(ha))
5193 break;
5194 else if (reset_counter >= 2) {
5195 IPS_HA_UNLOCK(cpu_flags);
5197 return (0);
5201 IPS_HA_UNLOCK(cpu_flags);
5203 return (1);
5206 /****************************************************************************/
5207 /* */
5208 /* Routine Name: ips_statinit */
5209 /* */
5210 /* Routine Description: */
5211 /* */
5212 /* Initialize the status queues on the controller */
5213 /* */
5214 /****************************************************************************/
5215 static void
5216 ips_statinit(ips_ha_t *ha) {
5217 u32 phys_status_start;
5219 METHOD_TRACE("ips_statinit", 1);
5221 ha->adapt->p_status_start = ha->adapt->status;
5222 ha->adapt->p_status_end = ha->adapt->status + IPS_MAX_CMDS;
5223 ha->adapt->p_status_tail = ha->adapt->status;
5225 phys_status_start = VIRT_TO_BUS(ha->adapt->status);
5226 outl(phys_status_start, ha->io_addr + IPS_REG_SQSR);
5227 outl(phys_status_start + IPS_STATUS_Q_SIZE, ha->io_addr + IPS_REG_SQER);
5228 outl(phys_status_start + IPS_STATUS_SIZE, ha->io_addr + IPS_REG_SQHR);
5229 outl(phys_status_start, ha->io_addr + IPS_REG_SQTR);
5231 ha->adapt->hw_status_start = phys_status_start;
5232 ha->adapt->hw_status_tail = phys_status_start;
5235 /****************************************************************************/
5236 /* */
5237 /* Routine Name: ips_statinit_memio */
5238 /* */
5239 /* Routine Description: */
5240 /* */
5241 /* Initialize the status queues on the controller */
5242 /* */
5243 /****************************************************************************/
5244 static void
5245 ips_statinit_memio(ips_ha_t *ha) {
5246 u32 phys_status_start;
5248 METHOD_TRACE("ips_statinit_memio", 1);
5250 ha->adapt->p_status_start = ha->adapt->status;
5251 ha->adapt->p_status_end = ha->adapt->status + IPS_MAX_CMDS;
5252 ha->adapt->p_status_tail = ha->adapt->status;
5254 phys_status_start = VIRT_TO_BUS(ha->adapt->status);
5255 writel(phys_status_start, ha->mem_ptr + IPS_REG_SQSR);
5256 writel(phys_status_start + IPS_STATUS_Q_SIZE, ha->mem_ptr + IPS_REG_SQER);
5257 writel(phys_status_start + IPS_STATUS_SIZE, ha->mem_ptr + IPS_REG_SQHR);
5258 writel(phys_status_start, ha->mem_ptr + IPS_REG_SQTR);
5260 ha->adapt->hw_status_start = phys_status_start;
5261 ha->adapt->hw_status_tail = phys_status_start;
5264 /****************************************************************************/
5265 /* */
5266 /* Routine Name: ips_statupd_copperhead */
5267 /* */
5268 /* Routine Description: */
5269 /* */
5270 /* Remove an element from the status queue */
5271 /* */
5272 /****************************************************************************/
5273 static u32
5274 ips_statupd_copperhead(ips_ha_t *ha) {
5275 METHOD_TRACE("ips_statupd_copperhead", 1);
5277 if (ha->adapt->p_status_tail != ha->adapt->p_status_end) {
5278 ha->adapt->p_status_tail++;
5279 ha->adapt->hw_status_tail += sizeof(IPS_STATUS);
5280 } else {
5281 ha->adapt->p_status_tail = ha->adapt->p_status_start;
5282 ha->adapt->hw_status_tail = ha->adapt->hw_status_start;
5285 outl(ha->adapt->hw_status_tail, ha->io_addr + IPS_REG_SQTR);
5287 return (ha->adapt->p_status_tail->value);
5290 /****************************************************************************/
5291 /* */
5292 /* Routine Name: ips_statupd_copperhead_memio */
5293 /* */
5294 /* Routine Description: */
5295 /* */
5296 /* Remove an element from the status queue */
5297 /* */
5298 /****************************************************************************/
5299 static u32
5300 ips_statupd_copperhead_memio(ips_ha_t *ha) {
5301 METHOD_TRACE("ips_statupd_copperhead_memio", 1);
5303 if (ha->adapt->p_status_tail != ha->adapt->p_status_end) {
5304 ha->adapt->p_status_tail++;
5305 ha->adapt->hw_status_tail += sizeof(IPS_STATUS);
5306 } else {
5307 ha->adapt->p_status_tail = ha->adapt->p_status_start;
5308 ha->adapt->hw_status_tail = ha->adapt->hw_status_start;
5311 writel(ha->adapt->hw_status_tail, ha->mem_ptr + IPS_REG_SQTR);
5313 return (ha->adapt->p_status_tail->value);
5316 /****************************************************************************/
5317 /* */
5318 /* Routine Name: ips_statupd_morpheus */
5319 /* */
5320 /* Routine Description: */
5321 /* */
5322 /* Remove an element from the status queue */
5323 /* */
5324 /****************************************************************************/
5325 static u32
5326 ips_statupd_morpheus(ips_ha_t *ha) {
5327 u32 val;
5329 METHOD_TRACE("ips_statupd_morpheus", 1);
5331 val = readl(ha->mem_ptr + IPS_REG_I2O_OUTMSGQ);
5333 return (val);
5336 /****************************************************************************/
5337 /* */
5338 /* Routine Name: ips_issue_copperhead */
5339 /* */
5340 /* Routine Description: */
5341 /* */
5342 /* Send a command down to the controller */
5343 /* */
5344 /****************************************************************************/
5345 static int
5346 ips_issue_copperhead(ips_ha_t *ha, ips_scb_t *scb) {
5347 u32 TimeOut;
5348 u16 val;
5349 u32 cpu_flags;
5351 METHOD_TRACE("ips_issue_copperhead", 1);
5353 if (scb->scsi_cmd) {
5354 DEBUG_VAR(2, "(%s%d) ips_issue: cmd 0x%X id %d (%d %d %d)",
5355 ips_name,
5356 ha->host_num,
5357 scb->cdb[0],
5358 scb->cmd.basic_io.command_id,
5359 scb->bus,
5360 scb->target_id,
5361 scb->lun);
5362 } else {
5363 DEBUG_VAR(2, KERN_NOTICE "(%s%d) ips_issue: logical cmd id %d",
5364 ips_name,
5365 ha->host_num,
5366 scb->cmd.basic_io.command_id);
5369 IPS_HA_LOCK(cpu_flags);
5371 TimeOut = 0;
5373 while ((val = inw(ha->io_addr + IPS_REG_CCCR)) & IPS_BIT_SEM) {
5374 UDELAY(1000);
5376 if (++TimeOut >= IPS_SEM_TIMEOUT) {
5377 if (!(val & IPS_BIT_START_STOP))
5378 break;
5380 printk(KERN_WARNING "(%s%d) ips_issue val [0x%x].\n",
5381 ips_name, ha->host_num, val);
5382 printk(KERN_WARNING "(%s%d) ips_issue semaphore chk timeout.\n",
5383 ips_name, ha->host_num);
5385 IPS_HA_UNLOCK(cpu_flags);
5387 return (IPS_FAILURE);
5388 } /* end if */
5389 } /* end while */
5391 outl(scb->scb_busaddr, ha->io_addr + IPS_REG_CCSAR);
5392 outw(IPS_BIT_START_CMD, ha->io_addr + IPS_REG_CCCR);
5394 IPS_HA_UNLOCK(cpu_flags);
5396 return (IPS_SUCCESS);
5399 /****************************************************************************/
5400 /* */
5401 /* Routine Name: ips_issue_copperhead_memio */
5402 /* */
5403 /* Routine Description: */
5404 /* */
5405 /* Send a command down to the controller */
5406 /* */
5407 /****************************************************************************/
5408 static int
5409 ips_issue_copperhead_memio(ips_ha_t *ha, ips_scb_t *scb) {
5410 u32 TimeOut;
5411 u32 val;
5412 u32 cpu_flags;
5414 METHOD_TRACE("ips_issue_copperhead_memio", 1);
5416 if (scb->scsi_cmd) {
5417 DEBUG_VAR(2, "(%s%d) ips_issue: cmd 0x%X id %d (%d %d %d)",
5418 ips_name,
5419 ha->host_num,
5420 scb->cdb[0],
5421 scb->cmd.basic_io.command_id,
5422 scb->bus,
5423 scb->target_id,
5424 scb->lun);
5425 } else {
5426 DEBUG_VAR(2, "(%s%d) ips_issue: logical cmd id %d",
5427 ips_name,
5428 ha->host_num,
5429 scb->cmd.basic_io.command_id);
5432 IPS_HA_LOCK(cpu_flags);
5434 TimeOut = 0;
5436 while ((val = readl(ha->mem_ptr + IPS_REG_CCCR)) & IPS_BIT_SEM) {
5437 UDELAY(1000);
5439 if (++TimeOut >= IPS_SEM_TIMEOUT) {
5440 if (!(val & IPS_BIT_START_STOP))
5441 break;
5443 printk(KERN_WARNING "(%s%d) ips_issue val [0x%x].\n",
5444 ips_name, ha->host_num, val);
5445 printk(KERN_WARNING "(%s%d) ips_issue semaphore chk timeout.\n",
5446 ips_name, ha->host_num);
5448 IPS_HA_UNLOCK(cpu_flags);
5450 return (IPS_FAILURE);
5451 } /* end if */
5452 } /* end while */
5454 writel(scb->scb_busaddr, ha->mem_ptr + IPS_REG_CCSAR);
5455 writel(IPS_BIT_START_CMD, ha->mem_ptr + IPS_REG_CCCR);
5457 IPS_HA_UNLOCK(cpu_flags);
5459 return (IPS_SUCCESS);
5462 /****************************************************************************/
5463 /* */
5464 /* Routine Name: ips_issue_i2o */
5465 /* */
5466 /* Routine Description: */
5467 /* */
5468 /* Send a command down to the controller */
5469 /* */
5470 /****************************************************************************/
5471 static int
5472 ips_issue_i2o(ips_ha_t *ha, ips_scb_t *scb) {
5473 u32 cpu_flags;
5475 METHOD_TRACE("ips_issue_i2o", 1);
5477 if (scb->scsi_cmd) {
5478 DEBUG_VAR(2, "(%s%d) ips_issue: cmd 0x%X id %d (%d %d %d)",
5479 ips_name,
5480 ha->host_num,
5481 scb->cdb[0],
5482 scb->cmd.basic_io.command_id,
5483 scb->bus,
5484 scb->target_id,
5485 scb->lun);
5486 } else {
5487 DEBUG_VAR(2, "(%s%d) ips_issue: logical cmd id %d",
5488 ips_name,
5489 ha->host_num,
5490 scb->cmd.basic_io.command_id);
5493 IPS_HA_LOCK(cpu_flags);
5495 outl(scb->scb_busaddr, ha->io_addr + IPS_REG_I2O_INMSGQ);
5497 IPS_HA_UNLOCK(cpu_flags);
5499 return (IPS_SUCCESS);
5502 /****************************************************************************/
5503 /* */
5504 /* Routine Name: ips_issue_i2o_memio */
5505 /* */
5506 /* Routine Description: */
5507 /* */
5508 /* Send a command down to the controller */
5509 /* */
5510 /****************************************************************************/
5511 static int
5512 ips_issue_i2o_memio(ips_ha_t *ha, ips_scb_t *scb) {
5513 u32 cpu_flags;
5515 METHOD_TRACE("ips_issue_i2o_memio", 1);
5517 if (scb->scsi_cmd) {
5518 DEBUG_VAR(2, "(%s%d) ips_issue: cmd 0x%X id %d (%d %d %d)",
5519 ips_name,
5520 ha->host_num,
5521 scb->cdb[0],
5522 scb->cmd.basic_io.command_id,
5523 scb->bus,
5524 scb->target_id,
5525 scb->lun);
5526 } else {
5527 DEBUG_VAR(2, "(%s%d) ips_issue: logical cmd id %d",
5528 ips_name,
5529 ha->host_num,
5530 scb->cmd.basic_io.command_id);
5533 IPS_HA_LOCK(cpu_flags);
5535 writel(scb->scb_busaddr, ha->mem_ptr + IPS_REG_I2O_INMSGQ);
5537 IPS_HA_UNLOCK(cpu_flags);
5539 return (IPS_SUCCESS);
5542 /****************************************************************************/
5543 /* */
5544 /* Routine Name: ips_isintr_copperhead */
5545 /* */
5546 /* Routine Description: */
5547 /* */
5548 /* Test to see if an interrupt is for us */
5549 /* */
5550 /****************************************************************************/
5551 static int
5552 ips_isintr_copperhead(ips_ha_t *ha) {
5553 u8 Isr;
5555 METHOD_TRACE("ips_isintr_copperhead", 2);
5557 Isr = inb(ha->io_addr + IPS_REG_HISR);
5559 if (Isr == 0xFF)
5560 /* ?!?! Nothing really there */
5561 return (0);
5563 if (Isr & IPS_BIT_SCE)
5564 return (1);
5565 else if (Isr & (IPS_BIT_SQO | IPS_BIT_GHI)) {
5566 /* status queue overflow or GHI */
5567 /* just clear the interrupt */
5568 outb(Isr, ha->io_addr + IPS_REG_HISR);
5571 return (0);
5574 /****************************************************************************/
5575 /* */
5576 /* Routine Name: ips_isintr_copperhead_memio */
5577 /* */
5578 /* Routine Description: */
5579 /* */
5580 /* Test to see if an interrupt is for us */
5581 /* */
5582 /****************************************************************************/
5583 static int
5584 ips_isintr_copperhead_memio(ips_ha_t *ha) {
5585 u8 Isr;
5587 METHOD_TRACE("ips_isintr_memio", 2);
5589 Isr = readb(ha->mem_ptr + IPS_REG_HISR);
5591 if (Isr == 0xFF)
5592 /* ?!?! Nothing really there */
5593 return (0);
5595 if (Isr & IPS_BIT_SCE)
5596 return (1);
5597 else if (Isr & (IPS_BIT_SQO | IPS_BIT_GHI)) {
5598 /* status queue overflow or GHI */
5599 /* just clear the interrupt */
5600 writeb(Isr, ha->mem_ptr + IPS_REG_HISR);
5603 return (0);
5606 /****************************************************************************/
5607 /* */
5608 /* Routine Name: ips_isintr_morpheus */
5609 /* */
5610 /* Routine Description: */
5611 /* */
5612 /* Test to see if an interrupt is for us */
5613 /* */
5614 /****************************************************************************/
5615 static int
5616 ips_isintr_morpheus(ips_ha_t *ha) {
5617 u32 Isr;
5619 METHOD_TRACE("ips_isintr_morpheus", 2);
5621 Isr = readl(ha->mem_ptr + IPS_REG_I2O_HIR);
5623 if (Isr & IPS_BIT_I2O_OPQI)
5624 return (1);
5625 else
5626 return (0);
5629 /****************************************************************************/
5630 /* */
5631 /* Routine Name: ips_wait */
5632 /* */
5633 /* Routine Description: */
5634 /* */
5635 /* Wait for a command to complete */
5636 /* */
5637 /****************************************************************************/
5638 static int
5639 ips_wait(ips_ha_t *ha, int time, int intr) {
5640 int ret;
5641 u8 done;
5643 METHOD_TRACE("ips_wait", 1);
5645 ret = IPS_FAILURE;
5646 done = FALSE;
5648 time *= IPS_ONE_SEC; /* convert seconds to milliseconds */
5650 while ((time > 0) && (!done)) {
5651 if (intr == IPS_INTR_ON) {
5652 if (ha->waitflag == FALSE) {
5653 ret = IPS_SUCCESS;
5654 done = TRUE;
5655 break;
5657 } else if (intr == IPS_INTR_IORL) {
5658 if (ha->waitflag == FALSE) {
5660 * controller generated an interupt to
5661 * acknowledge completion of the command
5662 * and ips_intr() has serviced the interrupt.
5664 ret = IPS_SUCCESS;
5665 done = TRUE;
5666 break;
5670 * NOTE: we already have the io_request_lock so
5671 * even if we get an interrupt it won't get serviced
5672 * until after we finish.
5675 while (test_and_set_bit(IPS_IN_INTR, &ha->flags))
5676 UDELAY(1000);
5678 (*ha->func.intr)(ha);
5680 clear_bit(IPS_IN_INTR, &ha->flags);
5681 } else if (intr == IPS_INTR_HAL) {
5682 if (ha->waitflag == FALSE) {
5684 * controller generated an interupt to
5685 * acknowledge completion of the command
5686 * and ips_intr() has serviced the interrupt.
5688 ret = IPS_SUCCESS;
5689 done = TRUE;
5690 break;
5694 * NOTE: since we were not called with the iorequest lock
5695 * we must obtain it before we can call the interrupt handler.
5696 * We were called under the HA lock so we can assume that interrupts
5697 * are masked.
5699 spin_lock(&io_request_lock);
5701 while (test_and_set_bit(IPS_IN_INTR, &ha->flags))
5702 UDELAY(1000);
5704 (*ha->func.intr)(ha);
5706 clear_bit(IPS_IN_INTR, &ha->flags);
5708 spin_unlock(&io_request_lock);
5711 UDELAY(1000); /* 1 milisecond */
5712 time--;
5715 return (ret);
5718 /****************************************************************************/
5719 /* */
5720 /* Routine Name: ips_write_driver_status */
5721 /* */
5722 /* Routine Description: */
5723 /* */
5724 /* Write OS/Driver version to Page 5 of the nvram on the controller */
5725 /* */
5726 /****************************************************************************/
5727 static int
5728 ips_write_driver_status(ips_ha_t *ha, int intr) {
5729 METHOD_TRACE("ips_write_driver_status", 1);
5731 if (!ips_readwrite_page5(ha, FALSE, intr)) {
5732 printk(KERN_WARNING "(%s%d) unable to read NVRAM page 5.\n",
5733 ips_name, ha->host_num);
5735 return (0);
5738 /* check to make sure the page has a valid */
5739 /* signature */
5740 if (ha->nvram->signature != IPS_NVRAM_P5_SIG) {
5741 DEBUG_VAR(1, "(%s%d) NVRAM page 5 has an invalid signature: %X.",
5742 ips_name, ha->host_num, ha->nvram->signature);
5744 return (1);
5747 DEBUG_VAR(2, "(%s%d) Ad Type: %d, Ad Slot: %d, BIOS: %c%c%c%c %c%c%c%c.",
5748 ips_name, ha->host_num, ha->nvram->adapter_type, ha->nvram->adapter_slot,
5749 ha->nvram->bios_high[0], ha->nvram->bios_high[1],
5750 ha->nvram->bios_high[2], ha->nvram->bios_high[3],
5751 ha->nvram->bios_low[0], ha->nvram->bios_low[1],
5752 ha->nvram->bios_low[2], ha->nvram->bios_low[3]);
5754 /* save controller type */
5755 ha->ad_type = ha->nvram->adapter_type;
5757 /* change values (as needed) */
5758 ha->nvram->operating_system = IPS_OS_LINUX;
5759 strncpy((char *) ha->nvram->driver_high, IPS_VERSION_HIGH, 4);
5760 strncpy((char *) ha->nvram->driver_low, IPS_VERSION_LOW, 4);
5762 /* now update the page */
5763 if (!ips_readwrite_page5(ha, TRUE, intr)) {
5764 printk(KERN_WARNING "(%s%d) unable to write NVRAM page 5.\n",
5765 ips_name, ha->host_num);
5767 return (0);
5770 return (1);
5773 /****************************************************************************/
5774 /* */
5775 /* Routine Name: ips_read_adapter_status */
5776 /* */
5777 /* Routine Description: */
5778 /* */
5779 /* Do an Inquiry command to the adapter */
5780 /* */
5781 /****************************************************************************/
5782 static int
5783 ips_read_adapter_status(ips_ha_t *ha, int intr) {
5784 ips_scb_t *scb;
5785 int ret;
5787 METHOD_TRACE("ips_read_adapter_status", 1);
5789 scb = &ha->scbs[ha->max_cmds-1];
5791 ips_init_scb(ha, scb);
5793 scb->timeout = ips_cmd_timeout;
5794 scb->cdb[0] = IPS_CMD_ENQUIRY;
5796 scb->cmd.basic_io.op_code = IPS_CMD_ENQUIRY;
5797 scb->cmd.basic_io.command_id = IPS_COMMAND_ID(ha, scb);
5798 scb->cmd.basic_io.sg_count = 0;
5799 scb->cmd.basic_io.sg_addr = VIRT_TO_BUS(ha->enq);
5800 scb->cmd.basic_io.lba = 0;
5801 scb->cmd.basic_io.sector_count = 0;
5802 scb->cmd.basic_io.log_drv = 0;
5803 scb->cmd.basic_io.reserved = 0;
5805 /* send command */
5806 if (((ret = ips_send_wait(ha, scb, ips_cmd_timeout, intr)) == IPS_FAILURE) ||
5807 (ret == IPS_SUCCESS_IMM) ||
5808 ((scb->basic_status & IPS_GSC_STATUS_MASK) > 1))
5809 return (0);
5811 return (1);
5814 /****************************************************************************/
5815 /* */
5816 /* Routine Name: ips_read_subsystem_parameters */
5817 /* */
5818 /* Routine Description: */
5819 /* */
5820 /* Read subsystem parameters from the adapter */
5821 /* */
5822 /****************************************************************************/
5823 static int
5824 ips_read_subsystem_parameters(ips_ha_t *ha, int intr) {
5825 ips_scb_t *scb;
5826 int ret;
5828 METHOD_TRACE("ips_read_subsystem_parameters", 1);
5830 scb = &ha->scbs[ha->max_cmds-1];
5832 ips_init_scb(ha, scb);
5834 scb->timeout = ips_cmd_timeout;
5835 scb->cdb[0] = IPS_CMD_GET_SUBSYS;
5837 scb->cmd.basic_io.op_code = IPS_CMD_GET_SUBSYS;
5838 scb->cmd.basic_io.command_id = IPS_COMMAND_ID(ha, scb);
5839 scb->cmd.basic_io.sg_count = 0;
5840 scb->cmd.basic_io.sg_addr = VIRT_TO_BUS(ha->subsys);
5841 scb->cmd.basic_io.lba = 0;
5842 scb->cmd.basic_io.sector_count = 0;
5843 scb->cmd.basic_io.log_drv = 0;
5844 scb->cmd.basic_io.reserved = 0;
5846 /* send command */
5847 if (((ret = ips_send_wait(ha, scb, ips_cmd_timeout, intr)) == IPS_FAILURE) ||
5848 (ret == IPS_SUCCESS_IMM) ||
5849 ((scb->basic_status & IPS_GSC_STATUS_MASK) > 1))
5850 return (0);
5852 return (1);
5855 /****************************************************************************/
5856 /* */
5857 /* Routine Name: ips_read_config */
5858 /* */
5859 /* Routine Description: */
5860 /* */
5861 /* Read the configuration on the adapter */
5862 /* */
5863 /****************************************************************************/
5864 static int
5865 ips_read_config(ips_ha_t *ha, int intr) {
5866 ips_scb_t *scb;
5867 int i;
5868 int ret;
5870 METHOD_TRACE("ips_read_config", 1);
5872 /* set defaults for initiator IDs */
5873 ha->conf->init_id[0] = IPS_ADAPTER_ID;
5874 for (i = 1; i < 4; i++)
5875 ha->conf->init_id[i] = 7;
5877 scb = &ha->scbs[ha->max_cmds-1];
5879 ips_init_scb(ha, scb);
5881 scb->timeout = ips_cmd_timeout;
5882 scb->cdb[0] = IPS_CMD_READ_CONF;
5884 scb->cmd.basic_io.op_code = IPS_CMD_READ_CONF;
5885 scb->cmd.basic_io.command_id = IPS_COMMAND_ID(ha, scb);
5886 scb->cmd.basic_io.sg_addr = VIRT_TO_BUS(ha->conf);
5888 /* send command */
5889 if (((ret = ips_send_wait(ha, scb, ips_cmd_timeout, intr)) == IPS_FAILURE) ||
5890 (ret == IPS_SUCCESS_IMM) ||
5891 ((scb->basic_status & IPS_GSC_STATUS_MASK) > 1)) {
5893 memset(ha->conf, 0, sizeof(IPS_CONF));
5895 /* reset initiator IDs */
5896 ha->conf->init_id[0] = IPS_ADAPTER_ID;
5897 for (i = 1; i < 4; i++)
5898 ha->conf->init_id[i] = 7;
5900 return (0);
5903 return (1);
5906 /****************************************************************************/
5907 /* */
5908 /* Routine Name: ips_readwrite_page5 */
5909 /* */
5910 /* Routine Description: */
5911 /* */
5912 /* Read nvram page 5 from the adapter */
5913 /* */
5914 /****************************************************************************/
5915 static int
5916 ips_readwrite_page5(ips_ha_t *ha, int write, int intr) {
5917 ips_scb_t *scb;
5918 int ret;
5920 METHOD_TRACE("ips_readwrite_page5", 1);
5922 scb = &ha->scbs[ha->max_cmds-1];
5924 ips_init_scb(ha, scb);
5926 scb->timeout = ips_cmd_timeout;
5927 scb->cdb[0] = IPS_CMD_RW_NVRAM_PAGE;
5929 scb->cmd.nvram.op_code = IPS_CMD_RW_NVRAM_PAGE;
5930 scb->cmd.nvram.command_id = IPS_COMMAND_ID(ha, scb);
5931 scb->cmd.nvram.page = 5;
5932 scb->cmd.nvram.write = write;
5933 scb->cmd.nvram.buffer_addr = VIRT_TO_BUS(ha->nvram);
5934 scb->cmd.nvram.reserved = 0;
5935 scb->cmd.nvram.reserved2 = 0;
5937 /* issue the command */
5938 if (((ret = ips_send_wait(ha, scb, ips_cmd_timeout, intr)) == IPS_FAILURE) ||
5939 (ret == IPS_SUCCESS_IMM) ||
5940 ((scb->basic_status & IPS_GSC_STATUS_MASK) > 1)) {
5942 memset(ha->nvram, 0, sizeof(IPS_NVRAM_P5));
5944 return (0);
5947 return (1);
5950 /****************************************************************************/
5951 /* */
5952 /* Routine Name: ips_clear_adapter */
5953 /* */
5954 /* Routine Description: */
5955 /* */
5956 /* Clear the stripe lock tables */
5957 /* */
5958 /****************************************************************************/
5959 static int
5960 ips_clear_adapter(ips_ha_t *ha, int intr) {
5961 ips_scb_t *scb;
5962 int ret;
5964 METHOD_TRACE("ips_clear_adapter", 1);
5966 scb = &ha->scbs[ha->max_cmds-1];
5968 ips_init_scb(ha, scb);
5970 scb->timeout = ips_reset_timeout;
5971 scb->cdb[0] = IPS_CMD_CONFIG_SYNC;
5973 scb->cmd.config_sync.op_code = IPS_CMD_CONFIG_SYNC;
5974 scb->cmd.config_sync.command_id = IPS_COMMAND_ID(ha, scb);
5975 scb->cmd.config_sync.channel = 0;
5976 scb->cmd.config_sync.source_target = IPS_POCL;
5977 scb->cmd.config_sync.reserved = 0;
5978 scb->cmd.config_sync.reserved2 = 0;
5979 scb->cmd.config_sync.reserved3 = 0;
5981 /* issue command */
5982 if (((ret = ips_send_wait(ha, scb, ips_reset_timeout, intr)) == IPS_FAILURE) ||
5983 (ret == IPS_SUCCESS_IMM) ||
5984 ((scb->basic_status & IPS_GSC_STATUS_MASK) > 1))
5985 return (0);
5987 /* send unlock stripe command */
5988 ips_init_scb(ha, scb);
5990 scb->cdb[0] = IPS_CMD_ERROR_TABLE;
5991 scb->timeout = ips_reset_timeout;
5993 scb->cmd.unlock_stripe.op_code = IPS_CMD_ERROR_TABLE;
5994 scb->cmd.unlock_stripe.command_id = IPS_COMMAND_ID(ha, scb);
5995 scb->cmd.unlock_stripe.log_drv = 0;
5996 scb->cmd.unlock_stripe.control = IPS_CSL;
5997 scb->cmd.unlock_stripe.reserved = 0;
5998 scb->cmd.unlock_stripe.reserved2 = 0;
5999 scb->cmd.unlock_stripe.reserved3 = 0;
6001 /* issue command */
6002 if (((ret = ips_send_wait(ha, scb, ips_cmd_timeout, intr)) == IPS_FAILURE) ||
6003 (ret == IPS_SUCCESS_IMM) ||
6004 ((scb->basic_status & IPS_GSC_STATUS_MASK) > 1))
6005 return (0);
6007 return (1);
6010 /****************************************************************************/
6011 /* */
6012 /* Routine Name: ips_ffdc_reset */
6013 /* */
6014 /* Routine Description: */
6015 /* */
6016 /* FFDC: write reset info */
6017 /* */
6018 /****************************************************************************/
6019 static void
6020 ips_ffdc_reset(ips_ha_t *ha, int intr) {
6021 ips_scb_t *scb;
6023 METHOD_TRACE("ips_ffdc_reset", 1);
6025 scb = &ha->scbs[ha->max_cmds-1];
6027 ips_init_scb(ha, scb);
6029 scb->timeout = ips_cmd_timeout;
6030 scb->cdb[0] = IPS_CMD_FFDC;
6031 scb->cmd.ffdc.op_code = IPS_CMD_FFDC;
6032 scb->cmd.ffdc.command_id = IPS_COMMAND_ID(ha, scb);
6033 scb->cmd.ffdc.reset_count = ha->reset_count;
6034 scb->cmd.ffdc.reset_type = 0x80;
6036 /* convert time to what the card wants */
6037 ips_fix_ffdc_time(ha, scb, ha->last_ffdc);
6039 /* issue command */
6040 ips_send_wait(ha, scb, ips_cmd_timeout, intr);
6043 /****************************************************************************/
6044 /* */
6045 /* Routine Name: ips_ffdc_time */
6046 /* */
6047 /* Routine Description: */
6048 /* */
6049 /* FFDC: write time info */
6050 /* */
6051 /****************************************************************************/
6052 static void
6053 ips_ffdc_time(ips_ha_t *ha, int intr) {
6054 ips_scb_t *scb;
6056 METHOD_TRACE("ips_ffdc_time", 1);
6058 DEBUG_VAR(1, "(%s%d) Sending time update.",
6059 ips_name, ha->host_num);
6061 scb = &ha->scbs[ha->max_cmds-1];
6063 ips_init_scb(ha, scb);
6065 scb->timeout = ips_cmd_timeout;
6066 scb->cdb[0] = IPS_CMD_FFDC;
6067 scb->cmd.ffdc.op_code = IPS_CMD_FFDC;
6068 scb->cmd.ffdc.command_id = IPS_COMMAND_ID(ha, scb);
6069 scb->cmd.ffdc.reset_count = 0;
6070 scb->cmd.ffdc.reset_type = 0x80;
6072 /* convert time to what the card wants */
6073 ips_fix_ffdc_time(ha, scb, ha->last_ffdc);
6075 /* issue command */
6076 ips_send_wait(ha, scb, ips_cmd_timeout, intr);
6079 /****************************************************************************/
6080 /* */
6081 /* Routine Name: ips_fix_ffdc_time */
6082 /* */
6083 /* Routine Description: */
6084 /* Adjust time_t to what the card wants */
6085 /* */
6086 /****************************************************************************/
6087 static void
6088 ips_fix_ffdc_time(ips_ha_t *ha, ips_scb_t *scb, time_t current_time) {
6089 long days;
6090 long rem;
6091 int i;
6092 int year;
6093 int yleap;
6094 int year_lengths[2] = { IPS_DAYS_NORMAL_YEAR, IPS_DAYS_LEAP_YEAR };
6095 int month_lengths[12][2] = { {31, 31},
6096 {28, 29},
6097 {31, 31},
6098 {30, 30},
6099 {31, 31},
6100 {30, 30},
6101 {31, 31},
6102 {31, 31},
6103 {30, 30},
6104 {31, 31},
6105 {30, 30},
6106 {31, 31} };
6108 METHOD_TRACE("ips_fix_ffdc_time", 1);
6110 days = current_time / IPS_SECS_DAY;
6111 rem = current_time % IPS_SECS_DAY;
6113 scb->cmd.ffdc.hour = (rem / IPS_SECS_HOUR);
6114 rem = rem % IPS_SECS_HOUR;
6115 scb->cmd.ffdc.minute = (rem / IPS_SECS_MIN);
6116 scb->cmd.ffdc.second = (rem % IPS_SECS_MIN);
6118 year = IPS_EPOCH_YEAR;
6119 while (days < 0 || days >= year_lengths[yleap = IPS_IS_LEAP_YEAR(year)]) {
6120 int newy;
6122 newy = year + (days / IPS_DAYS_NORMAL_YEAR);
6123 if (days < 0)
6124 --newy;
6125 days -= (newy - year) * IPS_DAYS_NORMAL_YEAR +
6126 IPS_NUM_LEAP_YEARS_THROUGH(newy - 1) -
6127 IPS_NUM_LEAP_YEARS_THROUGH(year - 1);
6128 year = newy;
6131 scb->cmd.ffdc.yearH = year / 100;
6132 scb->cmd.ffdc.yearL = year % 100;
6134 for (i = 0; days >= month_lengths[i][yleap]; ++i)
6135 days -= month_lengths[i][yleap];
6137 scb->cmd.ffdc.month = i + 1;
6138 scb->cmd.ffdc.day = days + 1;
6141 /****************************************************************************
6142 * BIOS Flash Routines *
6143 ****************************************************************************/
6145 /****************************************************************************/
6146 /* */
6147 /* Routine Name: ips_erase_bios */
6148 /* */
6149 /* Routine Description: */
6150 /* Erase the BIOS on the adapter */
6151 /* */
6152 /****************************************************************************/
6153 static int
6154 ips_erase_bios(ips_ha_t *ha) {
6155 int timeout;
6156 u8 status;
6158 METHOD_TRACE("ips_erase_bios", 1);
6160 /* Clear the status register */
6161 outl(0, ha->io_addr + IPS_REG_FLAP);
6162 if (ha->revision_id == IPS_REVID_TROMBONE64)
6163 UDELAY(5); /* 5 us */
6165 outb(0x50, ha->io_addr + IPS_REG_FLDP);
6166 if (ha->revision_id == IPS_REVID_TROMBONE64)
6167 UDELAY(5); /* 5 us */
6169 /* Erase Setup */
6170 outb(0x20, ha->io_addr + IPS_REG_FLDP);
6171 if (ha->revision_id == IPS_REVID_TROMBONE64)
6172 UDELAY(5); /* 5 us */
6174 /* Erase Confirm */
6175 outb(0xD0, ha->io_addr + IPS_REG_FLDP);
6176 if (ha->revision_id == IPS_REVID_TROMBONE64)
6177 UDELAY(5); /* 5 us */
6179 /* Erase Status */
6180 outb(0x70, ha->io_addr + IPS_REG_FLDP);
6181 if (ha->revision_id == IPS_REVID_TROMBONE64)
6182 UDELAY(5); /* 5 us */
6184 timeout = 80000; /* 80 seconds */
6186 while (timeout > 0) {
6187 if (ha->revision_id == IPS_REVID_TROMBONE64) {
6188 outl(0, ha->io_addr + IPS_REG_FLAP);
6189 UDELAY(5); /* 5 us */
6192 status = inb(ha->io_addr + IPS_REG_FLDP);
6194 if (status & 0x80)
6195 break;
6197 MDELAY(1);
6198 timeout--;
6201 /* check for timeout */
6202 if (timeout <= 0) {
6203 /* timeout */
6205 /* try to suspend the erase */
6206 outb(0xB0, ha->io_addr + IPS_REG_FLDP);
6207 if (ha->revision_id == IPS_REVID_TROMBONE64)
6208 UDELAY(5); /* 5 us */
6210 /* wait for 10 seconds */
6211 timeout = 10000;
6212 while (timeout > 0) {
6213 if (ha->revision_id == IPS_REVID_TROMBONE64) {
6214 outl(0, ha->io_addr + IPS_REG_FLAP);
6215 UDELAY(5); /* 5 us */
6218 status = inb(ha->io_addr + IPS_REG_FLDP);
6220 if (status & 0xC0)
6221 break;
6223 MDELAY(1);
6224 timeout--;
6227 return (1);
6230 /* check for valid VPP */
6231 if (status & 0x08)
6232 /* VPP failure */
6233 return (1);
6235 /* check for succesful flash */
6236 if (status & 0x30)
6237 /* sequence error */
6238 return (1);
6240 /* Otherwise, we were successful */
6241 /* clear status */
6242 outb(0x50, ha->io_addr + IPS_REG_FLDP);
6243 if (ha->revision_id == IPS_REVID_TROMBONE64)
6244 UDELAY(5); /* 5 us */
6246 /* enable reads */
6247 outb(0xFF, ha->io_addr + IPS_REG_FLDP);
6248 if (ha->revision_id == IPS_REVID_TROMBONE64)
6249 UDELAY(5); /* 5 us */
6251 return (0);
6254 /****************************************************************************/
6255 /* */
6256 /* Routine Name: ips_erase_bios_memio */
6257 /* */
6258 /* Routine Description: */
6259 /* Erase the BIOS on the adapter */
6260 /* */
6261 /****************************************************************************/
6262 static int
6263 ips_erase_bios_memio(ips_ha_t *ha) {
6264 int timeout;
6265 u8 status;
6267 METHOD_TRACE("ips_erase_bios_memio", 1);
6269 /* Clear the status register */
6270 writel(0, ha->mem_ptr + IPS_REG_FLAP);
6271 if (ha->revision_id == IPS_REVID_TROMBONE64)
6272 UDELAY(5); /* 5 us */
6274 writeb(0x50, ha->mem_ptr + IPS_REG_FLDP);
6275 if (ha->revision_id == IPS_REVID_TROMBONE64)
6276 UDELAY(5); /* 5 us */
6278 /* Erase Setup */
6279 writeb(0x20, ha->mem_ptr + IPS_REG_FLDP);
6280 if (ha->revision_id == IPS_REVID_TROMBONE64)
6281 UDELAY(5); /* 5 us */
6283 /* Erase Confirm */
6284 writeb(0xD0, ha->mem_ptr + IPS_REG_FLDP);
6285 if (ha->revision_id == IPS_REVID_TROMBONE64)
6286 UDELAY(5); /* 5 us */
6288 /* Erase Status */
6289 writeb(0x70, ha->mem_ptr + IPS_REG_FLDP);
6290 if (ha->revision_id == IPS_REVID_TROMBONE64)
6291 UDELAY(5); /* 5 us */
6293 timeout = 80000; /* 80 seconds */
6295 while (timeout > 0) {
6296 if (ha->revision_id == IPS_REVID_TROMBONE64) {
6297 writel(0, ha->mem_ptr + IPS_REG_FLAP);
6298 UDELAY(5); /* 5 us */
6301 status = readb(ha->mem_ptr + IPS_REG_FLDP);
6303 if (status & 0x80)
6304 break;
6306 MDELAY(1);
6307 timeout--;
6310 /* check for timeout */
6311 if (timeout <= 0) {
6312 /* timeout */
6314 /* try to suspend the erase */
6315 writeb(0xB0, ha->mem_ptr + IPS_REG_FLDP);
6316 if (ha->revision_id == IPS_REVID_TROMBONE64)
6317 UDELAY(5); /* 5 us */
6319 /* wait for 10 seconds */
6320 timeout = 10000;
6321 while (timeout > 0) {
6322 if (ha->revision_id == IPS_REVID_TROMBONE64) {
6323 writel(0, ha->mem_ptr + IPS_REG_FLAP);
6324 UDELAY(5); /* 5 us */
6327 status = readb(ha->mem_ptr + IPS_REG_FLDP);
6329 if (status & 0xC0)
6330 break;
6332 MDELAY(1);
6333 timeout--;
6336 return (1);
6339 /* check for valid VPP */
6340 if (status & 0x08)
6341 /* VPP failure */
6342 return (1);
6344 /* check for succesful flash */
6345 if (status & 0x30)
6346 /* sequence error */
6347 return (1);
6349 /* Otherwise, we were successful */
6350 /* clear status */
6351 writeb(0x50, ha->mem_ptr + IPS_REG_FLDP);
6352 if (ha->revision_id == IPS_REVID_TROMBONE64)
6353 UDELAY(5); /* 5 us */
6355 /* enable reads */
6356 writeb(0xFF, ha->mem_ptr + IPS_REG_FLDP);
6357 if (ha->revision_id == IPS_REVID_TROMBONE64)
6358 UDELAY(5); /* 5 us */
6360 return (0);
6363 /****************************************************************************/
6364 /* */
6365 /* Routine Name: ips_program_bios */
6366 /* */
6367 /* Routine Description: */
6368 /* Program the BIOS on the adapter */
6369 /* */
6370 /****************************************************************************/
6371 static int
6372 ips_program_bios(ips_ha_t *ha, char *buffer, int buffersize) {
6373 int i;
6374 int timeout;
6375 u8 status;
6377 METHOD_TRACE("ips_program_bios", 1);
6379 for (i = 0; i < buffersize; i++) {
6380 /* write a byte */
6381 outl(i, ha->io_addr + IPS_REG_FLAP);
6382 if (ha->revision_id == IPS_REVID_TROMBONE64)
6383 UDELAY(5); /* 5 us */
6385 outb(0x40, ha->io_addr + IPS_REG_FLDP);
6386 if (ha->revision_id == IPS_REVID_TROMBONE64)
6387 UDELAY(5); /* 5 us */
6389 outb(buffer[i], ha->io_addr + IPS_REG_FLDP);
6390 if (ha->revision_id == IPS_REVID_TROMBONE64)
6391 UDELAY(5); /* 5 us */
6393 /* wait up to one second */
6394 timeout = 1000;
6395 while (timeout > 0) {
6396 if (ha->revision_id == IPS_REVID_TROMBONE64) {
6397 outl(0, ha->io_addr + IPS_REG_FLAP);
6398 UDELAY(5); /* 5 us */
6401 status = inb(ha->io_addr + IPS_REG_FLDP);
6403 if (status & 0x80)
6404 break;
6406 MDELAY(1);
6407 timeout--;
6410 if (timeout == 0) {
6411 /* timeout error */
6412 outl(0, ha->io_addr + IPS_REG_FLAP);
6413 if (ha->revision_id == IPS_REVID_TROMBONE64)
6414 UDELAY(5); /* 5 us */
6416 outb(0xFF, ha->io_addr + IPS_REG_FLDP);
6417 if (ha->revision_id == IPS_REVID_TROMBONE64)
6418 UDELAY(5); /* 5 us */
6420 return (1);
6423 /* check the status */
6424 if (status & 0x18) {
6425 /* programming error */
6426 outl(0, ha->io_addr + IPS_REG_FLAP);
6427 if (ha->revision_id == IPS_REVID_TROMBONE64)
6428 UDELAY(5); /* 5 us */
6430 outb(0xFF, ha->io_addr + IPS_REG_FLDP);
6431 if (ha->revision_id == IPS_REVID_TROMBONE64)
6432 UDELAY(5); /* 5 us */
6434 return (1);
6436 } /* end for */
6438 /* Enable reading */
6439 outl(0, ha->io_addr + IPS_REG_FLAP);
6440 if (ha->revision_id == IPS_REVID_TROMBONE64)
6441 UDELAY(5); /* 5 us */
6443 outb(0xFF, ha->io_addr + IPS_REG_FLDP);
6444 if (ha->revision_id == IPS_REVID_TROMBONE64)
6445 UDELAY(5); /* 5 us */
6447 return (0);
6450 /****************************************************************************/
6451 /* */
6452 /* Routine Name: ips_program_bios_memio */
6453 /* */
6454 /* Routine Description: */
6455 /* Program the BIOS on the adapter */
6456 /* */
6457 /****************************************************************************/
6458 static int
6459 ips_program_bios_memio(ips_ha_t *ha, char *buffer, int buffersize) {
6460 int i;
6461 int timeout;
6462 u8 status;
6464 METHOD_TRACE("ips_program_bios_memio", 1);
6466 for (i = 0; i < buffersize; i++) {
6467 /* write a byte */
6468 writel(i, ha->mem_ptr + IPS_REG_FLAP);
6469 if (ha->revision_id == IPS_REVID_TROMBONE64)
6470 UDELAY(5); /* 5 us */
6472 writeb(0x40, ha->mem_ptr + IPS_REG_FLDP);
6473 if (ha->revision_id == IPS_REVID_TROMBONE64)
6474 UDELAY(5); /* 5 us */
6476 writeb(buffer[i], ha->mem_ptr + IPS_REG_FLDP);
6477 if (ha->revision_id == IPS_REVID_TROMBONE64)
6478 UDELAY(5); /* 5 us */
6480 /* wait up to one second */
6481 timeout = 1000;
6482 while (timeout > 0) {
6483 if (ha->revision_id == IPS_REVID_TROMBONE64) {
6484 writel(0, ha->mem_ptr + IPS_REG_FLAP);
6485 UDELAY(5); /* 5 us */
6488 status = readb(ha->mem_ptr + IPS_REG_FLDP);
6490 if (status & 0x80)
6491 break;
6493 MDELAY(1);
6494 timeout--;
6497 if (timeout == 0) {
6498 /* timeout error */
6499 writel(0, ha->mem_ptr + IPS_REG_FLAP);
6500 if (ha->revision_id == IPS_REVID_TROMBONE64)
6501 UDELAY(5); /* 5 us */
6503 writeb(0xFF, ha->mem_ptr + IPS_REG_FLDP);
6504 if (ha->revision_id == IPS_REVID_TROMBONE64)
6505 UDELAY(5); /* 5 us */
6507 return (1);
6510 /* check the status */
6511 if (status & 0x18) {
6512 /* programming error */
6513 writel(0, ha->mem_ptr + IPS_REG_FLAP);
6514 if (ha->revision_id == IPS_REVID_TROMBONE64)
6515 UDELAY(5); /* 5 us */
6517 writeb(0xFF, ha->mem_ptr + IPS_REG_FLDP);
6518 if (ha->revision_id == IPS_REVID_TROMBONE64)
6519 UDELAY(5); /* 5 us */
6521 return (1);
6523 } /* end for */
6525 /* Enable reading */
6526 writel(0, ha->mem_ptr + IPS_REG_FLAP);
6527 if (ha->revision_id == IPS_REVID_TROMBONE64)
6528 UDELAY(5); /* 5 us */
6530 writeb(0xFF, ha->mem_ptr + IPS_REG_FLDP);
6531 if (ha->revision_id == IPS_REVID_TROMBONE64)
6532 UDELAY(5); /* 5 us */
6534 return (0);
6537 /****************************************************************************/
6538 /* */
6539 /* Routine Name: ips_verify_bios */
6540 /* */
6541 /* Routine Description: */
6542 /* Verify the BIOS on the adapter */
6543 /* */
6544 /****************************************************************************/
6545 static int
6546 ips_verify_bios(ips_ha_t *ha, char *buffer, int buffersize) {
6547 u8 checksum;
6548 int i;
6550 METHOD_TRACE("ips_verify_bios", 1);
6552 /* test 1st byte */
6553 outl(0, ha->io_addr + IPS_REG_FLAP);
6554 if (ha->revision_id == IPS_REVID_TROMBONE64)
6555 UDELAY(5); /* 5 us */
6557 if (inb(ha->io_addr + IPS_REG_FLDP) != 0x55)
6558 return (1);
6560 outl(1, ha->io_addr + IPS_REG_FLAP);
6561 if (ha->revision_id == IPS_REVID_TROMBONE64)
6562 UDELAY(5); /* 5 us */
6563 if (inb(ha->io_addr + IPS_REG_FLDP) != 0xAA)
6564 return (1);
6566 checksum = 0xff;
6567 for (i = 2; i < buffersize; i++) {
6569 outl(i, ha->io_addr + IPS_REG_FLAP);
6570 if (ha->revision_id == IPS_REVID_TROMBONE64)
6571 UDELAY(5); /* 5 us */
6573 checksum = (u8) checksum + inb(ha->io_addr + IPS_REG_FLDP);
6576 if (checksum != 0)
6577 /* failure */
6578 return (1);
6579 else
6580 /* success */
6581 return (0);
6584 /****************************************************************************/
6585 /* */
6586 /* Routine Name: ips_verify_bios_memio */
6587 /* */
6588 /* Routine Description: */
6589 /* Verify the BIOS on the adapter */
6590 /* */
6591 /****************************************************************************/
6592 static int
6593 ips_verify_bios_memio(ips_ha_t *ha, char *buffer, int buffersize) {
6594 u8 checksum;
6595 int i;
6597 METHOD_TRACE("ips_verify_bios_memio", 1);
6599 /* test 1st byte */
6600 writel(0, ha->mem_ptr + IPS_REG_FLAP);
6601 if (ha->revision_id == IPS_REVID_TROMBONE64)
6602 UDELAY(5); /* 5 us */
6604 if (readb(ha->mem_ptr + IPS_REG_FLDP) != 0x55)
6605 return (1);
6607 writel(1, ha->mem_ptr + IPS_REG_FLAP);
6608 if (ha->revision_id == IPS_REVID_TROMBONE64)
6609 UDELAY(5); /* 5 us */
6610 if (readb(ha->mem_ptr + IPS_REG_FLDP) != 0xAA)
6611 return (1);
6613 checksum = 0xff;
6614 for (i = 2; i < buffersize; i++) {
6616 writel(i, ha->mem_ptr + IPS_REG_FLAP);
6617 if (ha->revision_id == IPS_REVID_TROMBONE64)
6618 UDELAY(5); /* 5 us */
6620 checksum = (u8) checksum + readb(ha->mem_ptr + IPS_REG_FLDP);
6623 if (checksum != 0)
6624 /* failure */
6625 return (1);
6626 else
6627 /* success */
6628 return (0);
6631 static Scsi_Host_Template driver_template = IPS;
6632 #include "scsi_module.c"
6637 * Overrides for Emacs so that we almost follow Linus's tabbing style.
6638 * Emacs will notice this stuff at the end of the file and automatically
6639 * adjust the settings for this buffer only. This must remain at the end
6640 * of the file.
6641 * ---------------------------------------------------------------------------
6642 * Local variables:
6643 * c-indent-level: 2
6644 * c-brace-imaginary-offset: 0
6645 * c-brace-offset: -2
6646 * c-argdecl-indent: 2
6647 * c-label-offset: -2
6648 * c-continued-statement-offset: 2
6649 * c-continued-brace-offset: 0
6650 * indent-tabs-mode: nil
6651 * tab-width: 8
6652 * End: