Add in the twa(4) driver. This adds in support for the 3Ware
[dragonfly.git] / sys / dev / raid / twa / twa.c
1 /*-
2  * Copyright (c) 2003-04 3ware, Inc.
3  * Copyright (c) 2000 Michael Smith
4  * Copyright (c) 2000 BSDi
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26  * SUCH DAMAGE.
27  *
28  *      $FreeBSD$
29  * $DragonFly: src/sys/dev/raid/twa/twa.c,v 1.1 2004/04/16 20:13:16 drhodus Exp $
30  */
31
32 /*
33  * 3ware driver for 9000 series storage controllers.
34  *
35  * Author: Vinod Kashyap
36  */
37
38
39 #include "twa_includes.h"
40
41 #ifdef TWA_FLASH_FIRMWARE
42 static int      twa_flash_firmware(struct twa_softc *sc);
43 static int      twa_hard_reset(struct twa_softc *sc);
44 #endif /* TWA_FLASH_FIRMWARE */
45
46 static int      twa_init_ctlr(struct twa_softc *sc);
47 static void     *twa_get_param(struct twa_softc *sc, int table_id,
48                                         int parameter_id, size_t size,
49                                         void (* callback)(struct twa_request *tr));
50 static int      twa_set_param(struct twa_softc *sc, int table_id, int param_id,
51                                         int param_size, void *data,
52                                         void (* callback)(struct twa_request *tr));
53 static int      twa_init_connection(struct twa_softc *sc, u_int16_t message_credits,
54                                 u_int32_t set_features, u_int16_t current_fw_srl,
55                                 u_int16_t current_fw_arch_id, u_int16_t current_fw_branch,
56                                 u_int16_t current_fw_build, u_int16_t *fw_on_ctlr_srl,
57                                 u_int16_t *fw_on_ctlr_arch_id, u_int16_t *fw_on_ctlr_branch,
58                                 u_int16_t *fw_on_ctlr_build, u_int32_t *init_connect_result);
59
60 static int      twa_wait_request(struct twa_request *req, u_int32_t timeout);
61 static int      twa_immediate_request(struct twa_request *req, u_int32_t timeout);
62
63 static int      twa_done(struct twa_softc *sc);
64 static int      twa_drain_pending_queue(struct twa_softc *sc);
65 static void     twa_drain_complete_queue(struct twa_softc *sc);
66 static int      twa_wait_status(struct twa_softc *sc, u_int32_t status, u_int32_t timeout);
67 static int      twa_drain_response_queue(struct twa_softc *sc);
68 static int      twa_check_ctlr_state(struct twa_softc *sc, u_int32_t status_reg);
69 static int      twa_soft_reset(struct twa_softc *sc);
70
71 static void     twa_host_intr(struct twa_softc *sc);
72 static void     twa_attention_intr(struct twa_softc *sc);
73 static void     twa_command_intr(struct twa_softc *sc);
74
75 static int      twa_fetch_aen(struct twa_softc *sc);
76 static void     twa_aen_callback(struct twa_request *tr);
77 static void     twa_enqueue_aen(struct twa_softc *sc, struct twa_command_header *cmd_hdr);
78 static int      twa_drain_aen_queue(struct twa_softc *sc);
79 static int      twa_find_aen(struct twa_softc *sc, u_int16_t aen_code);
80
81 static void     twa_panic(struct twa_softc *sc, int8_t *reason);
82
83 /*
84  * Function name:       twa_setup
85  * Description:         Initializes driver data structures for the controller.
86  *
87  * Input:               sc      -- ptr to per ctlr structure
88  * Output:              None
89  * Return value:        0       -- success
90  *                      non-zero-- failure
91  */
92 int
93 twa_setup(struct twa_softc *sc)
94 {
95         struct twa_event_packet *aen_queue;
96         int                     error = 0;
97         int                     i;
98
99         twa_dbg_dprint_enter(3, sc);
100
101         /* Initialize request queues. */
102         twa_initq_free(sc);
103         twa_initq_busy(sc);
104         twa_initq_pending(sc);
105         twa_initq_complete(sc);
106
107         if (twa_alloc_req_pkts(sc, TWA_Q_LENGTH)) {
108                 twa_printf(sc, "Failed to allocate request packets.\n");
109                 return(ENOMEM);
110         }
111
112         /* Allocate memory for the AEN queue. */
113         if ((aen_queue = malloc(sizeof(struct twa_event_packet) * TWA_Q_LENGTH,
114                                         M_DEVBUF, M_WAITOK)) == NULL) {
115                 /* 
116                  * This should not cause us to return error.  We will only be
117                  * unable to support AEN's.  But then, we will have to check
118                  * time and again to see if we can support AEN's, if we
119                  * continue.  So, we will just return error.
120                  */
121                 twa_printf(sc, "Could not allocate memory for AEN queue.\n");
122                 return(ENOMEM); /* any unfreed memory will be freed by twa_free */
123         }
124         /* Initialize the aen queue. */
125         bzero(aen_queue, sizeof(struct twa_event_packet) * TWA_Q_LENGTH);
126         for (i = 0; i < TWA_Q_LENGTH; i++)
127                 sc->twa_aen_queue[i] = &(aen_queue[i]);
128
129         /*
130          * Disable interrupts from the card.
131          * Interrupts will be enabled back in twa_intrhook.
132          */
133         twa_disable_interrupts(sc);
134
135         /* Initialize the controller. */
136         if ((error = twa_init_ctlr(sc))) {
137                 /* Soft reset the controller, and try one more time. */
138                 twa_printf(sc, "Controller initialization failed. Retrying...\n");
139                 if ((error = twa_soft_reset(sc)))
140                         twa_printf(sc, "Controller soft reset failed.\n");
141                 else
142                         error = twa_init_ctlr(sc);
143         }
144         return(error);
145 }
146
147 #ifdef TWA_FLASH_FIRMWARE
148 /*
149  * Function name:       twa_flash_firmware
150  * Description:         Flashes bundled firmware image onto controller.
151  *
152  * Input:               sc      -- ptr to per ctlr structure
153  * Output:              None
154  * Return value:        0       -- success
155  *                      non-zero-- failure
156  */
157 static int
158 twa_flash_firmware(struct twa_softc *sc)
159 {
160         struct twa_request                      *tr;
161         struct twa_command_download_firmware    *cmd;
162         u_int32_t                               fw_img_chunk_size;
163         u_int32_t                               this_chunk_size = 0;
164         u_int32_t                               remaining_img_size = 0;
165         int                                     error;
166         int                                     i;
167
168         if ((tr = twa_get_request(sc)) == NULL) {
169                 /* No free request packets available.  Can't proceed. */
170                 error = EIO;
171                 goto out;
172         }
173         tr->tr_cmd_pkt_type |= TWA_CMD_PKT_TYPE_INTERNAL;
174         /* Allocate sufficient memory to hold a chunk of the firmware image. */
175         fw_img_chunk_size = ((twa_fw_img_size/NUM_FW_IMAGE_CHUNKS) + 511) & ~511;
176         if ((tr->tr_data = malloc(fw_img_chunk_size, M_DEVBUF, M_WAITOK)) == NULL) {
177                 twa_printf (sc, "Could not allocate memory for firmware image.\n"); 
178                 error = ENOMEM;
179                 goto out;
180         }
181         remaining_img_size = twa_fw_img_size;
182         cmd = &(tr->tr_command->command.cmd_pkt_7k.download_fw);
183
184         for (i = 0; i < NUM_FW_IMAGE_CHUNKS; i++) {
185                 /* Build a cmd pkt for downloading firmware. */
186                 bzero(tr->tr_command, sizeof(struct twa_command_packet));
187
188                 tr->tr_command->cmd_hdr.header_desc.size_header = 128;
189         
190                 cmd->opcode = TWA_OP_DOWNLOAD_FIRMWARE;
191                 cmd->sgl_offset = 2;/* offset in dwords, to the beginning of sg list */
192                 cmd->size = 2;  /* this field will be updated at data map time */
193                 cmd->request_id = tr->tr_request_id;
194                 cmd->unit = 0;
195                 cmd->status = 0;
196                 cmd->flags = 0;
197                 cmd->param = 8; /* prom image */
198
199                 if (i != (NUM_FW_IMAGE_CHUNKS - 1))
200                         this_chunk_size = fw_img_chunk_size;
201                 else     /* last chunk */
202                         this_chunk_size = remaining_img_size;
203         
204                 remaining_img_size -= this_chunk_size;
205                 bcopy(twa_fw_img + (i * fw_img_chunk_size),
206                                         tr->tr_data, this_chunk_size);
207
208                 /*
209                  * The next line will effect only the last chunk.
210                  */
211                 tr->tr_length = (this_chunk_size + 511) & ~511;
212
213                 tr->tr_flags |= TWA_CMD_DATA_OUT;
214
215                 error = twa_immediate_request(tr, TWA_REQUEST_TIMEOUT_PERIOD);
216                 if (error) {
217                         twa_printf(sc, "Firmware flash request could not be posted. error = 0x%x\n",
218                                                                         error);
219                         if (error == ETIMEDOUT)
220                                 return(error); /* clean-up done by twa_immediate_request */
221                         break;
222                 }
223                 error = cmd->status;
224                 if (i != (NUM_FW_IMAGE_CHUNKS - 1)) {
225                         if ((error = tr->tr_command->cmd_hdr.status_block.error) != TWA_ERROR_MORE_DATA) {
226                                 twa_printf(sc, "cmd = 0x%x: ERROR: (0x%02X: 0x%04X): %s: %s\n",
227                                         cmd->opcode,
228                                         TWA_MESSAGE_SOURCE_CONTROLLER_ERROR,
229                                         error,
230                                         twa_find_msg_string(twa_error_table, error),
231                                         tr->tr_command->cmd_hdr.err_specific_desc);
232                                 twa_printf(sc, "Firmware flash request failed. Intermediate error = 0x%x, i = %x\n",
233                                                         cmd->status, i);
234                                 /* Hard reset the controller, so that it doesn't wait for the remaining chunks. */
235                                 twa_hard_reset(sc);
236                                 break;
237                         }
238                 } else   /* last chunk */
239                         if (error) {
240                                 twa_printf(sc, "cmd = 0x%x: ERROR: (0x%02X: 0x%04X): %s: %s\n",
241                                         cmd->opcode,
242                                         TWA_MESSAGE_SOURCE_CONTROLLER_ERROR,
243                                         tr->tr_command->cmd_hdr.status_block.error,
244                                         twa_find_msg_string(twa_error_table,
245                                                 tr->tr_command->cmd_hdr.status_block.error),
246                                         tr->tr_command->cmd_hdr.err_specific_desc);
247                                 twa_printf(sc, "Firmware flash request failed. error = 0x%x\n", error);
248                                 /* Hard reset the controller, so that it doesn't wait for more chunks. */
249                                 twa_hard_reset(sc);
250                         }
251         } /* for */
252
253         if (tr->tr_data)
254                 free(tr->tr_data, M_DEVBUF);
255 out:
256         if (tr)
257                 twa_release_request(tr);
258         return(error);
259 }
260
261
262 /*
263  * Function name:       twa_hard_reset
264  * Description:         Hard reset the controller.
265  *
266  * Input:               sc      -- ptr to per ctlr structure
267  * Output:              None
268  * Return value:        0       -- success
269  *                      non-zero-- failure
270  */
271 static int
272 twa_hard_reset(struct twa_softc *sc)
273 {
274         struct twa_request                      *tr;
275         struct twa_command_reset_firmware       *cmd;
276         int                                     error;
277
278         if ((tr = twa_get_request(sc)) == NULL)
279                 return(EIO);
280         tr->tr_cmd_pkt_type |= TWA_CMD_PKT_TYPE_INTERNAL;
281         /* Build a cmd pkt for sending down the hard reset command. */
282         tr->tr_command->cmd_hdr.header_desc.size_header = 128;
283         
284         cmd = &(tr->tr_command->command.cmd_pkt_7k.reset_fw);
285         cmd->opcode = TWA_OP_RESET_FIRMWARE;
286         cmd->size = 2;  /* this field will be updated at data map time */
287         cmd->request_id = tr->tr_request_id;
288         cmd->unit = 0;
289         cmd->status = 0;
290         cmd->flags = 0;
291         cmd->param = 0; /* don't reload FPGA logic */
292
293         tr->tr_data = NULL;
294         tr->tr_length = 0;
295
296         error = twa_immediate_request(tr, TWA_REQUEST_TIMEOUT_PERIOD);
297         if (error) {
298                 twa_printf(sc, "Hard reset request could not be posted. error = 0x%x\n",
299                                                                 error);
300                 if (error == ETIMEDOUT)
301                         return(error); /* clean-up done by twa_immediate_request */
302                 goto out;
303         }
304         if ((error = cmd->status)) {
305                 twa_printf(sc, "cmd = 0x%x: ERROR: (0x%02X: 0x%04X): %s: %s\n",
306                                         cmd->opcode,
307                                         TWA_MESSAGE_SOURCE_CONTROLLER_ERROR,
308                                         tr->tr_command->cmd_hdr.status_block.error,
309                                         twa_find_msg_string(twa_error_table,
310                                                 tr->tr_command->cmd_hdr.status_block.error),
311                                         tr->tr_command->cmd_hdr.err_specific_desc);
312                 twa_printf(sc, "Hard reset request failed. error = 0x%x\n", error);
313         }
314
315 out:
316         if (tr)
317                 twa_release_request(tr);
318         return(error);
319 }
320
321 #endif /* TWA_FLASH_FIRMWARE */
322
323 /*
324  * Function name:       twa_init_ctlr
325  * Description:         Establishes a logical connection with the controller.
326  *                      If bundled with firmware, determines whether or not
327  *                      to flash firmware, based on arch_id, fw SRL (Spec.
328  *                      Revision Level), branch & build #'s.  Also determines
329  *                      whether or not the driver is compatible with the
330  *                      firmware on the controller, before proceeding to work
331  *                      with it.
332  *
333  * Input:               sc      -- ptr to per ctlr structure
334  * Output:              None
335  * Return value:        0       -- success
336  *                      non-zero-- failure
337  */
338 static int
339 twa_init_ctlr(struct twa_softc *sc)
340 {
341         u_int16_t       fw_on_ctlr_srl = 0;
342         u_int16_t       fw_on_ctlr_arch_id = 0;
343         u_int16_t       fw_on_ctlr_branch = 0;
344         u_int16_t       fw_on_ctlr_build = 0;
345         u_int32_t       init_connect_result = 0;
346         int             error = 0;
347 #ifdef TWA_FLASH_FIRMWARE
348         int8_t          fw_flashed = FALSE;
349         int8_t          fw_flash_failed = FALSE;
350 #endif /* TWA_FLASH_FIRMWARE */
351
352         twa_dbg_dprint_enter(3, sc);
353
354         /* Wait for the controller to become ready. */
355         if (twa_wait_status(sc, TWA_STATUS_MICROCONTROLLER_READY,
356                                         TWA_REQUEST_TIMEOUT_PERIOD)) {
357                 twa_printf(sc, "Microcontroller not ready.\n");
358                 return(ENXIO);
359         }
360         /* Drain the response queue. */
361         if (twa_drain_response_queue(sc)) {
362                 twa_printf(sc, "Can't drain response queue.\n");
363                 return(1);
364         }
365         /* Establish a logical connection with the controller. */
366         if ((error = twa_init_connection(sc, TWA_INIT_MESSAGE_CREDITS,
367                         TWA_EXTENDED_INIT_CONNECT, TWA_CURRENT_FW_SRL,
368                         TWA_9000_ARCH_ID, TWA_CURRENT_FW_BRANCH,
369                         TWA_CURRENT_FW_BUILD, &fw_on_ctlr_srl,
370                         &fw_on_ctlr_arch_id, &fw_on_ctlr_branch,
371                         &fw_on_ctlr_build, &init_connect_result))) {
372                 twa_printf(sc, "Can't initialize connection in current mode.\n");
373                 return(error);
374         }
375
376 #ifdef TWA_FLASH_FIRMWARE
377
378         if ((init_connect_result & TWA_BUNDLED_FW_SAFE_TO_FLASH) &&
379                 (init_connect_result & TWA_CTLR_FW_RECOMMENDS_FLASH)) {
380                 /*
381                  * The bundled firmware is safe to flash, and the firmware
382                  * on the controller recommends a flash.  So, flash!
383                  */
384                 twa_printf(sc, "Flashing bundled firmware...\n");
385                 if ((error = twa_flash_firmware(sc))) {
386                         fw_flash_failed = TRUE;
387                         twa_printf(sc, "Unable to flash bundled firmware.\n");
388                         twa_printf(sc, "Will see if possible to work with firmware on controller...\n");
389                 } else {
390                         twa_printf(sc, "Successfully flashed bundled firmware.\n");
391                         fw_flashed = TRUE;
392                 }
393         }
394
395         if (fw_flashed) {
396                 /* The firmware was flashed.  Have the new image loaded */
397                 error = twa_hard_reset(sc);
398                 if (error)
399                         twa_printf(sc, "Could not reset controller after flash!\n");
400                 else    /* Go through initialization again. */
401                         error = twa_init_ctlr(sc);
402                 /*
403                  * If hard reset of controller failed, we need to return.
404                  * Otherwise, the above recursive call to twa_init_ctlr will
405                  * have completed the rest of the initialization (starting
406                  * from twa_drain_aen_queue below).  Don't do it again.
407                  * Just return.
408                  */
409                 return(error);
410         } else
411 #endif /* TWA_FLASH_FIRMWARE */
412         {
413                 /*
414                  * Either we are not bundled with a firmware image, or
415                  * the bundled firmware is not safe to flash,
416                  * or flash failed for some reason.  See if we can at
417                  * least work with the firmware on the controller in the
418                  * current mode.
419                  */
420                 if (init_connect_result & TWA_CTLR_FW_COMPATIBLE) {
421                         /* Yes, we can.  Make note of the operating mode. */
422                         sc->working_srl = TWA_CURRENT_FW_SRL;
423                         sc->working_branch = TWA_CURRENT_FW_BRANCH;
424                         sc->working_build = TWA_CURRENT_FW_BUILD;
425                 } else {
426                         /*
427                          * No, we can't.  See if we can at least work with
428                          * it in the base mode.  We should never come here
429                          * if firmware has just been flashed.
430                          */
431                         twa_printf(sc, "Driver/Firmware mismatch.  Negotiating for base level...\n");
432                         if ((error = twa_init_connection(sc, TWA_INIT_MESSAGE_CREDITS,
433                                         TWA_EXTENDED_INIT_CONNECT, TWA_BASE_FW_SRL,
434                                         TWA_9000_ARCH_ID, TWA_BASE_FW_BRANCH,
435                                         TWA_BASE_FW_BUILD, &fw_on_ctlr_srl,
436                                         &fw_on_ctlr_arch_id, &fw_on_ctlr_branch,
437                                         &fw_on_ctlr_build, &init_connect_result))) {
438                                 twa_printf(sc, "Can't initialize connection in base mode.\n");
439                                 return(error);
440                         }
441                         if (!(init_connect_result & TWA_CTLR_FW_COMPATIBLE)) {
442                                 /*
443                                  * The firmware on the controller is not even
444                                  * compatible with our base mode.  We cannot
445                                  * work with it.  Bail...
446                                  */
447                                 twa_printf(sc, "Incompatible firmware on controller\n");
448 #ifdef TWA_FLASH_FIRMWARE
449                                 if (fw_flash_failed)
450                                         twa_printf(sc, "...and could not flash bundled firmware.\n");
451                                 else
452                                         twa_printf(sc, "...and bundled firmware not safe to flash.\n");
453 #endif /* TWA_FLASH_FIRMWARE */
454                                 return(1);
455                         }
456                         /* We can work with this firmware, but only in base mode. */
457                         sc->working_srl = TWA_BASE_FW_SRL;
458                         sc->working_branch = TWA_BASE_FW_BRANCH;
459                         sc->working_build = TWA_BASE_FW_BUILD;
460                         sc->twa_operating_mode = TWA_BASE_MODE;
461                 }
462         }
463
464         /* Drain the AEN queue */
465         if (twa_drain_aen_queue(sc)) {
466                 /* 
467                  * We will just print that we couldn't drain the AEN queue.
468                  * There's no need to bail out.
469                  */
470                 twa_printf(sc, "Can't drain AEN queue.\n");
471         }
472
473         /* Set controller state to initialized. */
474         sc->twa_state &= ~TWA_STATE_SHUTDOWN;
475
476         twa_dbg_dprint_exit(3, sc);
477         return(0);
478 }
479
480
481 /*
482  * Function name:       twa_deinit_ctlr
483  * Description:         Close logical connection with the controller.
484  *
485  * Input:               sc      -- ptr to per ctlr structure
486  * Output:              None
487  * Return value:        0       -- success
488  *                      non-zero-- failure
489  */
490 int
491 twa_deinit_ctlr(struct twa_softc *sc)
492 {
493         /*
494          * Mark the controller as shutting down,
495          * and disable any further interrupts.
496          */
497         sc->twa_state |= TWA_STATE_SHUTDOWN;
498         twa_disable_interrupts(sc);
499
500         /* Let the controller know that we are going down. */
501         return(twa_init_connection(sc, TWA_SHUTDOWN_MESSAGE_CREDITS,
502                                         0, 0, 0, 0, 0,
503                                         NULL, NULL, NULL, NULL, NULL));
504 }
505
506
507 /*
508  * Function name:       twa_interrupt
509  * Description:         Interrupt handler.  Determines the kind of interrupt,
510  *                      and calls the appropriate handler.
511  *
512  * Input:               sc      -- ptr to per ctlr structure
513  * Output:              None
514  * Return value:        None
515  */
516 void
517 twa_interrupt(struct twa_softc *sc)
518 {
519         u_int32_t       status_reg;
520
521         twa_dbg_dprint_enter(5, sc);
522
523         /* Collect current interrupt status. */
524         status_reg = TWA_READ_STATUS_REGISTER(sc);
525         if (twa_check_ctlr_state(sc, status_reg))
526                 return;
527
528         /* Dispatch based on the kind of interrupt. */
529         if (status_reg & TWA_STATUS_HOST_INTERRUPT)
530                 twa_host_intr(sc);
531         if (status_reg & TWA_STATUS_ATTENTION_INTERRUPT)
532                 twa_attention_intr(sc);
533         if (status_reg & TWA_STATUS_COMMAND_INTERRUPT)
534                 twa_command_intr(sc);
535         if (status_reg & TWA_STATUS_RESPONSE_INTERRUPT)
536                 twa_done(sc);
537 }
538
539
540 /*
541  * Function name:       twa_ioctl
542  * Description:         ioctl handler.
543  *
544  * Input:               sc      -- ptr to per ctlr structure
545  *                      cmd     -- ioctl cmd
546  *                      buf     -- ptr to buffer in kernel memory, which is
547  *                                 a copy of the input buffer in user-space
548  * Output:              buf     -- ptr to buffer in kernel memory, which will
549  *                                 be copied of the output buffer in user-space
550  * Return value:        0       -- success
551  *                      non-zero-- failure
552  */
553 int
554 twa_ioctl(struct twa_softc *sc, int cmd, void *buf)
555 {
556         struct twa_ioctl_9k     *user_buf = (struct twa_ioctl_9k *)buf;
557         struct twa_event_packet event_buf;
558         int32_t                 event_index;
559         int32_t                 start_index;
560         int                     s;
561         int                     error = 0;
562                 
563         switch (cmd) {
564         case TWA_IOCTL_FIRMWARE_PASS_THROUGH:
565         {
566                 struct twa_command_packet       *cmdpkt;
567                 struct twa_request              *tr;
568                 u_int32_t                       data_buf_size_adjusted;
569
570
571                 twa_dbg_dprint(2, sc, "Firmware PassThru");
572
573                 /* Get a request packet */
574                 while ((tr = twa_get_request(sc)) == NULL)
575                         /*
576                          * No free request packets available.  Sleep until
577                          * one becomes available.
578                          */
579                         tsleep(&(sc->twa_wait_timeout), PPAUSE, "twioctl", hz);
580
581                 /*
582                  * Make sure that the data buffer sent to firmware is a 
583                  * 512 byte multiple in size.
584                  */
585                 data_buf_size_adjusted = (user_buf->twa_drvr_pkt.buffer_length + 511) & ~511;
586                 if ((tr->tr_length = data_buf_size_adjusted)) {
587                         if ((tr->tr_data = malloc(data_buf_size_adjusted, M_DEVBUF, M_WAITOK)) == NULL) {
588                                 twa_printf(sc, "Could not alloc mem for fw_passthru data_buf.\n");
589                                 error = ENOMEM;
590                                 goto fw_passthru_done;
591                         }
592                         /* Copy the payload. */
593                         if ((error = copyin((void *) (user_buf->pdata), 
594                                         (void *) (tr->tr_data),
595                                         user_buf->twa_drvr_pkt.buffer_length)) != 0) {
596                                 twa_printf (sc, "Could not copyin fw_passthru data_buf.\n"); 
597                                 goto fw_passthru_done;
598                         }
599                         tr->tr_flags |= TWA_CMD_DATA_IN | TWA_CMD_DATA_OUT;
600                 }
601                 tr->tr_cmd_pkt_type |= TWA_CMD_PKT_TYPE_IOCTL;
602                 cmdpkt = tr->tr_command;
603
604                 /* Copy the command packet. */
605                 bcopy(&(user_buf->twa_cmd_pkt), cmdpkt,
606                                         sizeof(struct twa_command_packet));
607                 cmdpkt->command.cmd_pkt_7k.generic.request_id = tr->tr_request_id;
608
609                 twa_dbg_dprint(3, sc, "cmd_pkt_7k = %x %x %x %x %x %x %x",
610                                         cmdpkt->command.cmd_pkt_7k.generic.opcode,
611                                         cmdpkt->command.cmd_pkt_7k.generic.sgl_offset,
612                                         cmdpkt->command.cmd_pkt_7k.generic.size,
613                                         cmdpkt->command.cmd_pkt_7k.generic.request_id,
614                                         cmdpkt->command.cmd_pkt_7k.generic.unit,
615                                         cmdpkt->command.cmd_pkt_7k.generic.status,
616                                         cmdpkt->command.cmd_pkt_7k.generic.flags);
617
618                 /* Send down the request, and wait for it to complete. */
619                 if ((error = twa_wait_request(tr, TWA_REQUEST_TIMEOUT_PERIOD))) {
620                         twa_printf(sc, "fw_passthru request failed. error = 0x%x\n", error);
621                         if (error == ETIMEDOUT)
622                                 break; /* clean-up done by twa_wait_request */
623                         goto fw_passthru_done;
624                 }
625
626                 /* Copy the command packet back into user space. */
627                 bcopy(cmdpkt, &(user_buf->twa_cmd_pkt),
628                                         sizeof(struct twa_command_packet));
629         
630                 /* If there was a payload, copy it back too. */
631                 if (tr->tr_length)
632                         error = copyout(tr->tr_data, user_buf->pdata,
633                                         user_buf->twa_drvr_pkt.buffer_length);
634
635 fw_passthru_done:
636                 /* Free resources. */
637                 if (tr->tr_data)
638                         free(tr->tr_data, M_DEVBUF);
639                 if (tr)
640                         twa_release_request(tr);
641                 break;
642         }
643
644
645         case TWA_IOCTL_SCAN_BUS:
646                 /* Request CAM for a bus scan. */
647                 twa_request_bus_scan(sc);
648                 break;
649
650
651         case TWA_IOCTL_GET_FIRST_EVENT:
652                 twa_dbg_dprint(3, sc, "Get First Event");
653
654                 if (sc->twa_aen_queue_wrapped) {
655                         if (sc->twa_aen_queue_overflow) {
656                                 /*
657                                  * The aen queue has wrapped, even before some
658                                  * events have been retrieved.  Let the caller
659                                  * know that he missed out on some AEN's.
660                                  */
661                                 user_buf->twa_drvr_pkt.status = TWA_ERROR_AEN_OVERFLOW;
662                                 sc->twa_aen_queue_overflow = FALSE;
663                         } else
664                                 user_buf->twa_drvr_pkt.status = 0;
665                         event_index = sc->twa_aen_head;
666                 } else {
667                         if (sc->twa_aen_head == sc->twa_aen_tail) {
668                                 user_buf->twa_drvr_pkt.status = TWA_ERROR_AEN_NO_EVENTS;
669                                 break;
670                         }
671                         user_buf->twa_drvr_pkt.status = 0;
672                         event_index = sc->twa_aen_tail; /* = 0 */
673                 }
674                 if ((error = copyout(sc->twa_aen_queue[event_index], user_buf->pdata,
675                                         sizeof(struct twa_event_packet))) != 0)
676                         twa_printf(sc, "get_first: Could not copyout to event_buf. error = %x\n", error);
677                 (sc->twa_aen_queue[event_index])->retrieved = TWA_AEN_RETRIEVED;
678                 break;
679
680
681         case TWA_IOCTL_GET_LAST_EVENT:
682                 twa_dbg_dprint(3, sc, "Get Last Event");
683
684                 if (sc->twa_aen_queue_wrapped) {
685                         if (sc->twa_aen_queue_overflow) {
686                                 /*
687                                  * The aen queue has wrapped, even before some
688                                  * events have been retrieved.  Let the caller
689                                  * know that he missed out on some AEN's.
690                                  */
691                                 user_buf->twa_drvr_pkt.status = TWA_ERROR_AEN_OVERFLOW;
692                                 sc->twa_aen_queue_overflow = FALSE;
693                         } else
694                                 user_buf->twa_drvr_pkt.status = 0;
695                 } else {
696                         if (sc->twa_aen_head == sc->twa_aen_tail) {
697                                 user_buf->twa_drvr_pkt.status = TWA_ERROR_AEN_NO_EVENTS;
698                                 break;
699                         }
700                         user_buf->twa_drvr_pkt.status = 0;
701                 }
702                 event_index = (sc->twa_aen_head - 1 + TWA_Q_LENGTH) % TWA_Q_LENGTH;
703                 if ((error = copyout(sc->twa_aen_queue[event_index], user_buf->pdata,
704                                         sizeof(struct twa_event_packet))) != 0)
705                         twa_printf(sc, "get_last: Could not copyout to event_buf. error = %x\n", error);
706                 (sc->twa_aen_queue[event_index])->retrieved = TWA_AEN_RETRIEVED;
707                 break;
708
709
710         case TWA_IOCTL_GET_NEXT_EVENT:
711                 twa_dbg_dprint(3, sc, "Get Next Event");
712
713                 user_buf->twa_drvr_pkt.status = 0;
714                 if (sc->twa_aen_queue_wrapped) {
715                         twa_dbg_dprint(3, sc, "Get Next Event: wrapped");
716                         if (sc->twa_aen_queue_overflow) {
717                                 /*
718                                  * The aen queue has wrapped, even before some
719                                  * events have been retrieved.  Let the caller
720                                  * know that he missed out on some AEN's.
721                                  */
722                                 twa_dbg_dprint(2, sc, "Get Next Event: overflow");
723                                 user_buf->twa_drvr_pkt.status = TWA_ERROR_AEN_OVERFLOW;
724                                 sc->twa_aen_queue_overflow = FALSE;
725                         }
726                         start_index = sc->twa_aen_head;
727                 } else {
728                         if (sc->twa_aen_head == sc->twa_aen_tail) {
729                                 twa_dbg_dprint(3, sc, "Get Next Event: empty queue");
730                                 user_buf->twa_drvr_pkt.status = TWA_ERROR_AEN_NO_EVENTS;
731                                 break;
732                         }
733                         start_index = sc->twa_aen_tail; /* = 0 */
734                 }
735                 if ((error = copyin(user_buf->pdata, &event_buf,
736                                 sizeof(struct twa_event_packet))) != 0)
737                         twa_printf(sc, "get_next: Could not copyin event_buf.\n");
738
739                 event_index = (start_index + event_buf.sequence_id -
740                                 (sc->twa_aen_queue[start_index])->sequence_id + 1)
741                                 % TWA_Q_LENGTH;
742
743                 twa_dbg_dprint(3, sc, "Get Next Event: si = %x, ei = %x, ebsi = %x, sisi = %x, eisi = %x",
744                                 start_index, event_index, event_buf.sequence_id,
745                                 (sc->twa_aen_queue[start_index])->sequence_id,
746                                 (sc->twa_aen_queue[event_index])->sequence_id);
747
748                 if (! ((sc->twa_aen_queue[event_index])->sequence_id >
749                                                 event_buf.sequence_id)) {
750                         if (user_buf->twa_drvr_pkt.status == TWA_ERROR_AEN_OVERFLOW)
751                                 sc->twa_aen_queue_overflow = TRUE; /* so we report the overflow next time */
752                         user_buf->twa_drvr_pkt.status = TWA_ERROR_AEN_NO_EVENTS;
753                         break;
754                 }
755                 if ((error = copyout(sc->twa_aen_queue[event_index], user_buf->pdata, 
756                                         sizeof(struct twa_event_packet))) != 0)
757                         twa_printf(sc, "get_next: Could not copyout to event_buf. error = %x\n", error);
758
759                 (sc->twa_aen_queue[event_index])->retrieved = TWA_AEN_RETRIEVED;
760                 break;
761
762
763         case TWA_IOCTL_GET_PREVIOUS_EVENT:
764                 twa_dbg_dprint(3, sc, "Get Previous Event");
765
766                 user_buf->twa_drvr_pkt.status = 0;
767                 if (sc->twa_aen_queue_wrapped) {
768                         if (sc->twa_aen_queue_overflow) {
769                                 /*
770                                  * The aen queue has wrapped, even before some
771                                  * events have been retrieved.  Let the caller
772                                  * know that he missed out on some AEN's.
773                                  */
774                                 user_buf->twa_drvr_pkt.status = TWA_ERROR_AEN_OVERFLOW;
775                                 sc->twa_aen_queue_overflow = FALSE;
776                         }
777                         start_index = sc->twa_aen_head;
778                 } else {
779                         if (sc->twa_aen_head == sc->twa_aen_tail) {
780                                 user_buf->twa_drvr_pkt.status = TWA_ERROR_AEN_NO_EVENTS;
781                                 break;
782                         }
783                         start_index = sc->twa_aen_tail; /* = 0 */
784                 }
785                 if ((error = copyin(user_buf->pdata, &event_buf,
786                                 sizeof(struct twa_event_packet))) != 0)
787                         twa_printf(sc, "get_previous: Could not copyin event_buf.\n");
788
789                 event_index = (start_index + event_buf.sequence_id -
790                         (sc->twa_aen_queue[start_index])->sequence_id - 1) % TWA_Q_LENGTH;
791                 if (! ((sc->twa_aen_queue[event_index])->sequence_id < event_buf.sequence_id)) {
792                         if (user_buf->twa_drvr_pkt.status == TWA_ERROR_AEN_OVERFLOW)
793                                 sc->twa_aen_queue_overflow = TRUE; /* so we report the overflow next time */
794                         user_buf->twa_drvr_pkt.status = TWA_ERROR_AEN_NO_EVENTS;
795                         break;
796                 }
797                 if ((error = copyout(sc->twa_aen_queue [event_index], user_buf->pdata,
798                                         sizeof(struct twa_event_packet))) != 0)
799                         twa_printf(sc, "get_previous: Could not copyout to event_buf. error = %x\n", error);
800
801                 (sc->twa_aen_queue[event_index])->retrieved = TWA_AEN_RETRIEVED;
802                 break;
803
804
805         case TWA_IOCTL_GET_LOCK:
806         {
807                 struct twa_lock_packet  twa_lock;
808                 u_int32_t               cur_time;
809
810                 cur_time = time_second - (tz.tz_minuteswest * 60) - 
811                                         (wall_cmos_clock ? adjkerntz : 0);
812                 copyin(user_buf->pdata, &twa_lock,
813                                 sizeof(struct twa_lock_packet));
814                 s = splcam();
815                 if ((sc->twa_ioctl_lock.lock == TWA_LOCK_FREE) ||
816                                 (twa_lock.force_flag) ||
817                                 (cur_time >= sc->twa_ioctl_lock.timeout)) {
818                         twa_dbg_dprint(3, sc, "GET_LOCK: Getting lock!");
819                         sc->twa_ioctl_lock.lock = TWA_LOCK_HELD;
820                         sc->twa_ioctl_lock.timeout = cur_time + (twa_lock.timeout_msec / 1000);
821                         twa_lock.time_remaining_msec = twa_lock.timeout_msec;
822                         user_buf->twa_drvr_pkt.status = 0;
823                 } else {
824                         twa_dbg_dprint(2, sc, "GET_LOCK: Lock already held!");
825                         twa_lock.time_remaining_msec =
826                                 (sc->twa_ioctl_lock.timeout - cur_time) * 1000;
827                         user_buf->twa_drvr_pkt.status =
828                                         TWA_ERROR_IOCTL_LOCK_ALREADY_HELD;
829                 }
830                 splx(s);
831                 copyout(&twa_lock, user_buf->pdata,
832                                 sizeof(struct twa_lock_packet));
833                 break;
834         }
835
836
837         case TWA_IOCTL_RELEASE_LOCK:
838                 s = splcam();
839                 if (sc->twa_ioctl_lock.lock == TWA_LOCK_FREE) {
840                         twa_dbg_dprint(2, sc, "twa_ioctl: RELEASE_LOCK: Lock not held!");
841                         user_buf->twa_drvr_pkt.status = TWA_ERROR_IOCTL_LOCK_NOT_HELD;
842                 } else {
843                         twa_dbg_dprint(3, sc, "RELEASE_LOCK: Releasing lock!");
844                         sc->twa_ioctl_lock.lock = TWA_LOCK_FREE;
845                         user_buf->twa_drvr_pkt.status = 0;
846                 }
847                 splx(s);
848                 break;
849
850
851         case TWA_IOCTL_GET_COMPATIBILITY_INFO:
852         {
853                 struct twa_compatibility_packet comp_pkt;
854
855                 bcopy(TWA_DRIVER_VERSION_STRING, comp_pkt.driver_version,
856                                         sizeof(TWA_DRIVER_VERSION_STRING));
857                 comp_pkt.working_srl = sc->working_srl;
858                 comp_pkt.working_branch = sc->working_branch;
859                 comp_pkt.working_build = sc->working_build;
860                 user_buf->twa_drvr_pkt.status = 0;
861
862                 /* Copy compatibility information to user space. */
863                 copyout(&comp_pkt, user_buf->pdata,
864                                 min(sizeof(struct twa_compatibility_packet),
865                                         user_buf->twa_drvr_pkt.buffer_length));
866                 break;
867         }
868
869         default:        
870                 /* Unknown opcode. */
871                 error = ENOTTY;
872         }
873
874         return(error);
875 }
876
877
878 /*
879  * Function name:       twa_enable_interrupts
880  * Description:         Enables interrupts on the controller
881  *
882  * Input:               sc      -- ptr to per ctlr structure
883  * Output:              None
884  * Return value:        None
885  */
886 void
887 twa_enable_interrupts(struct twa_softc *sc)
888 {
889         sc->twa_state |= TWA_STATE_INTR_ENABLED;
890         TWA_WRITE_CONTROL_REGISTER(sc,
891                 TWA_CONTROL_CLEAR_ATTENTION_INTERRUPT |
892                 TWA_CONTROL_UNMASK_RESPONSE_INTERRUPT |
893                 TWA_CONTROL_ENABLE_INTERRUPTS);
894 }
895
896
897 /*
898  * Function name:       twa_setup
899  * Description:         Disables interrupts on the controller
900  *
901  * Input:               sc      -- ptr to per ctlr structure
902  * Output:              None
903  * Return value:        None
904  */
905 void
906 twa_disable_interrupts(struct twa_softc *sc)
907 {
908         TWA_WRITE_CONTROL_REGISTER(sc, TWA_CONTROL_DISABLE_INTERRUPTS);
909         sc->twa_state &= ~TWA_STATE_INTR_ENABLED;
910 }
911
912
913
914 /*
915  * Function name:       twa_get_param
916  * Description:         Get a firmware parameter.
917  *
918  * Input:               sc              -- ptr to per ctlr structure
919  *                      table_id        -- parameter table #
920  *                      param_id        -- index of the parameter in the table
921  *                      param_size      -- size of the parameter in bytes
922  *                      callback        -- ptr to function, if any, to be called
923  *                                      back on completion; NULL if no callback.
924  * Output:              None
925  * Return value:        ptr to param structure  -- success
926  *                      NULL                    -- failure
927  */
928 static void *
929 twa_get_param(struct twa_softc *sc, int table_id, int param_id,
930                 size_t param_size, void (* callback)(struct twa_request *tr))
931 {
932         struct twa_request      *tr;
933         union twa_command_7k    *cmd;
934         struct twa_param_9k     *param = NULL;
935         int                     error = ENOMEM;
936
937         twa_dbg_dprint_enter(4, sc);
938
939         /* Get a request packet. */
940         if ((tr = twa_get_request(sc)) == NULL)
941                 goto out;
942         tr->tr_cmd_pkt_type |= TWA_CMD_PKT_TYPE_INTERNAL;
943
944         /* Allocate memory to read data into. */
945         if ((param = (struct twa_param_9k *)
946                         malloc(TWA_SECTOR_SIZE, M_DEVBUF, M_NOWAIT)) == NULL)
947                 goto out;
948         bzero(param, sizeof(struct twa_param_9k) - 1 + param_size);
949         tr->tr_data = param;
950         tr->tr_length = TWA_SECTOR_SIZE;
951         tr->tr_flags = TWA_CMD_DATA_IN | TWA_CMD_DATA_OUT;
952
953         /* Build the cmd pkt. */
954         cmd = &(tr->tr_command->command.cmd_pkt_7k);
955
956         tr->tr_command->cmd_hdr.header_desc.size_header = 128;
957         
958         cmd->param.opcode = TWA_OP_GET_PARAM;
959         cmd->param.sgl_offset = 2;
960         cmd->param.size = 2;
961         cmd->param.request_id = tr->tr_request_id;
962         cmd->param.unit = 0;
963         cmd->param.param_count = 1;
964
965         /* Specify which parameter we need. */
966         param->table_id = table_id | TWA_9K_PARAM_DESCRIPTOR;
967         param->parameter_id = param_id;
968         param->parameter_size_bytes = param_size;
969
970         /* Submit the command. */
971         if (callback == NULL) {
972                 /* There's no call back; wait till the command completes. */
973                 error = twa_immediate_request(tr, TWA_REQUEST_TIMEOUT_PERIOD);
974                 if (error == ETIMEDOUT)
975                         return(NULL); /* clean-up done by twa_immediate_request */
976                 if (error)
977                         goto out;
978                 if ((error = cmd->param.status)) {
979                         twa_printf(sc, "cmd = 0x%x: ERROR: (0x%02X: 0x%04X): %s: %s\n",
980                                         cmd->param.opcode,
981                                         TWA_MESSAGE_SOURCE_CONTROLLER_ERROR,
982                                         tr->tr_command->cmd_hdr.status_block.error,
983                                         twa_find_msg_string(twa_error_table,
984                                                 tr->tr_command->cmd_hdr.status_block.error),
985                                         tr->tr_command->cmd_hdr.err_specific_desc);
986                         goto out; /* twa_drain_complete_queue will have done the unmapping */
987                 }
988                 twa_release_request(tr);
989                 return(param);
990         } else {
991                 /* There's a call back.  Simply submit the command. */
992                 tr->tr_callback = callback;
993                 if ((error = twa_map_request(tr))) {
994                         twa_printf(tr->tr_sc, "%s: twa_map_request returned 0x%x\n",
995                                                 __func__, error);
996                         goto out;
997                 }
998                 return(callback);
999         }
1000
1001 out:
1002         twa_printf(sc, "get_param failed. error = 0x%x\n", error);
1003         if (param)
1004                 free(param, M_DEVBUF);
1005         if (tr)
1006                 twa_release_request(tr);
1007         return(NULL);
1008 }
1009
1010
1011 /*
1012  * Function name:       twa_set_param
1013  * Description:         Set a firmware parameter.
1014  *
1015  * Input:               sc              -- ptr to per ctlr structure
1016  *                      table_id        -- parameter table #
1017  *                      param_id        -- index of the parameter in the table
1018  *                      param_size      -- size of the parameter in bytes
1019  *                      callback        -- ptr to function, if any, to be called
1020  *                                      back on completion; NULL if no callback.
1021  * Output:              None
1022  * Return value:        0       -- success
1023  *                      non-zero-- failure
1024  */
1025 static int
1026 twa_set_param(struct twa_softc *sc, int table_id,
1027                         int param_id, int param_size, void *data,
1028                         void (* callback)(struct twa_request *tr))
1029 {
1030         struct twa_request      *tr;
1031         union twa_command_7k    *cmd;
1032         struct twa_param_9k     *param = NULL;
1033         int                     error = ENOMEM;
1034
1035         twa_dbg_dprint_enter(4, sc);
1036
1037         /* Get a request packet. */
1038         if ((tr = twa_get_request(sc)) == NULL)
1039                 goto out;
1040         tr->tr_cmd_pkt_type |= TWA_CMD_PKT_TYPE_INTERNAL;
1041
1042         /* Allocate memory to send data using. */
1043         if ((param = (struct twa_param_9k *)
1044                         malloc(TWA_SECTOR_SIZE, M_DEVBUF, M_NOWAIT)) == NULL)
1045                 goto out;
1046         bzero(param, sizeof(struct twa_param_9k) - 1 + param_size);
1047         tr->tr_data = param;
1048         tr->tr_length = TWA_SECTOR_SIZE;
1049         tr->tr_flags = TWA_CMD_DATA_IN | TWA_CMD_DATA_OUT;
1050
1051         /* Build the cmd pkt. */
1052         cmd = &(tr->tr_command->command.cmd_pkt_7k);
1053
1054         tr->tr_command->cmd_hdr.header_desc.size_header = 128;
1055
1056         cmd->param.opcode = TWA_OP_SET_PARAM;
1057         cmd->param.sgl_offset = 2;
1058         cmd->param.size = 2;
1059         cmd->param.request_id = tr->tr_request_id;
1060         cmd->param.unit = 0;
1061         cmd->param.param_count = 1;
1062
1063         /* Specify which parameter we want to set. */
1064         param->table_id = table_id | TWA_9K_PARAM_DESCRIPTOR;
1065         param->parameter_id = param_id;
1066         param->parameter_size_bytes = param_size;
1067         bcopy(data, param->data, param_size);
1068
1069         /* Submit the command. */
1070         if (callback == NULL) {
1071                 /* There's no call back;  wait till the command completes. */
1072                 error = twa_immediate_request(tr, TWA_REQUEST_TIMEOUT_PERIOD);
1073                 if (error == ETIMEDOUT)
1074                         return(error); /* clean-up done by twa_immediate_request */
1075                 if (error)
1076                         goto out;
1077                 if ((error = cmd->param.status)) {
1078                         twa_printf(sc, "cmd = 0x%x: ERROR: (0x%02X: 0x%04X): %s: %s\n",
1079                                         cmd->param.opcode,
1080                                         TWA_MESSAGE_SOURCE_CONTROLLER_ERROR,
1081                                         tr->tr_command->cmd_hdr.status_block.error,
1082                                         twa_find_msg_string(twa_error_table,
1083                                                 tr->tr_command->cmd_hdr.status_block.error),
1084                                         tr->tr_command->cmd_hdr.err_specific_desc);
1085                         goto out; /* twa_drain_complete_queue will have done the unmapping */
1086                 }
1087                 free(param, M_DEVBUF);
1088                 twa_release_request(tr);
1089                 return(error);
1090         } else {
1091                 /* There's a call back.  Simply submit the command. */
1092                 tr->tr_callback = callback;
1093                 if ((error = twa_map_request(tr))) {
1094                         twa_printf(tr->tr_sc, "%s: twa_map_request returned 0x%x\n",
1095                                                 __func__, error);
1096                         goto out;
1097                 }
1098                 return(0);
1099         }
1100
1101 out:
1102         twa_printf(sc, "set_param failed. error = 0x%x\n", error);
1103         if (param)
1104                 free(param, M_DEVBUF);
1105         if (tr)
1106                 twa_release_request(tr);
1107         return(error);
1108 }
1109
1110
1111 /*
1112  * Function name:       twa_init_connection
1113  * Description:         Send init_connection cmd to firmware
1114  *
1115  * Input:               sc              -- ptr to per ctlr structure
1116  *                      message_credits -- max # of requests that we might send
1117  *                                       down simultaneously.  This will be
1118  *                                       typically set to 256 at init-time or
1119  *                                      after a reset, and to 1 at shutdown-time
1120  *                      set_features    -- indicates if we intend to use 64-bit
1121  *                                      sg, also indicates if we want to do a
1122  *                                      basic or an extended init_connection;
1123  *
1124  * Note: The following input/output parameters are valid, only in case of an
1125  *              extended init_connection:
1126  *
1127  *                      current_fw_srl          -- srl of fw we are bundled
1128  *                                              with, if any; 0 otherwise
1129  *                      current_fw_arch_id      -- arch_id of fw we are bundled
1130  *                                              with, if any; 0 otherwise
1131  *                      current_fw_branch       -- branch # of fw we are bundled
1132  *                                              with, if any; 0 otherwise
1133  *                      current_fw_build        -- build # of fw we are bundled
1134  *                                              with, if any; 0 otherwise
1135  * Output:              fw_on_ctlr_srl          -- srl of fw on ctlr
1136  *                      fw_on_ctlr_arch_id      -- arch_id of fw on ctlr
1137  *                      fw_on_ctlr_branch       -- branch # of fw on ctlr
1138  *                      fw_on_ctlr_build        -- build # of fw on ctlr
1139  *                      init_connect_result     -- result bitmap of fw response
1140  * Return value:        0       -- success
1141  *                      non-zero-- failure
1142  */
1143 static int
1144 twa_init_connection(struct twa_softc *sc, u_int16_t message_credits,
1145                         u_int32_t set_features, u_int16_t current_fw_srl,
1146                         u_int16_t current_fw_arch_id, u_int16_t current_fw_branch,
1147                         u_int16_t current_fw_build, u_int16_t *fw_on_ctlr_srl,
1148                         u_int16_t *fw_on_ctlr_arch_id, u_int16_t *fw_on_ctlr_branch,
1149                         u_int16_t *fw_on_ctlr_build, u_int32_t *init_connect_result)
1150 {
1151         struct twa_request              *tr;
1152         struct twa_command_init_connect *init_connect;
1153         int                             error = 1;
1154     
1155         twa_dbg_dprint_enter(3, sc);
1156
1157         /* Get a request packet. */
1158         if ((tr = twa_get_request(sc)) == NULL)
1159                 goto out;
1160         tr->tr_cmd_pkt_type |= TWA_CMD_PKT_TYPE_INTERNAL;
1161         /* Build the cmd pkt. */
1162         init_connect = &(tr->tr_command->command.cmd_pkt_7k.init_connect);
1163
1164         tr->tr_command->cmd_hdr.header_desc.size_header = 128;
1165
1166         init_connect->opcode = TWA_OP_INIT_CONNECTION;
1167         init_connect->request_id = tr->tr_request_id;
1168         init_connect->message_credits = message_credits;
1169         init_connect->features = set_features;
1170         if (TWA_64BIT_ADDRESSES)
1171                 init_connect->features |= TWA_64BIT_SG_ADDRESSES;
1172         if (set_features & TWA_EXTENDED_INIT_CONNECT) {
1173                 /* Fill in the extra fields needed for an extended init_connect. */
1174                 init_connect->size = 6;
1175                 init_connect->fw_srl = current_fw_srl;
1176                 init_connect->fw_arch_id = current_fw_arch_id;
1177                 init_connect->fw_branch = current_fw_branch;
1178                 init_connect->fw_build = current_fw_build;
1179         } else
1180                 init_connect->size = 3;
1181
1182         /* Submit the command, and wait for it to complete. */
1183         error = twa_immediate_request(tr, TWA_REQUEST_TIMEOUT_PERIOD);
1184         if (error == ETIMEDOUT)
1185                 return(error); /* clean-up done by twa_immediate_request */
1186         if (error)
1187                 goto out;
1188         if ((error = init_connect->status)) {
1189                 twa_printf(sc, "cmd = 0x%x: ERROR: (0x%02X: 0x%04X): %s: %s\n",
1190                                         init_connect->opcode,
1191                                         TWA_MESSAGE_SOURCE_CONTROLLER_ERROR,
1192                                         tr->tr_command->cmd_hdr.status_block.error,
1193                                         twa_find_msg_string(twa_error_table,
1194                                                 tr->tr_command->cmd_hdr.status_block.error),
1195                                         tr->tr_command->cmd_hdr.err_specific_desc);
1196                 goto out; /* twa_drain_complete_queue will have done the unmapping */
1197         }
1198         if (set_features & TWA_EXTENDED_INIT_CONNECT) {
1199                 *fw_on_ctlr_srl = init_connect->fw_srl;
1200                 *fw_on_ctlr_arch_id = init_connect->fw_arch_id;
1201                 *fw_on_ctlr_branch = init_connect->fw_branch;
1202                 *fw_on_ctlr_build = init_connect->fw_build;
1203                 *init_connect_result = init_connect->result;
1204         }
1205         twa_release_request(tr);
1206         return(error);
1207
1208 out:
1209         twa_printf(sc, "init_connection failed. error = 0x%x\n", error);
1210         if (tr)
1211                 twa_release_request(tr);
1212         return(error);
1213 }
1214
1215
1216
1217 /*
1218  * Function name:       twa_wait_request
1219  * Description:         Sends down a firmware cmd, and waits for the completion,
1220  *                      but NOT in a tight loop.
1221  *
1222  * Input:               tr      -- ptr to request pkt
1223  *                      timeout -- max # of seconds to wait before giving up
1224  * Output:              None
1225  * Return value:        0       -- success
1226  *                      non-zero-- failure
1227  */
1228 static int
1229 twa_wait_request(struct twa_request *tr, u_int32_t timeout)
1230 {
1231         time_t  end_time;
1232         int     error;
1233
1234         twa_dbg_dprint_enter(4, tr->tr_sc);
1235
1236         tr->tr_flags |= TWA_CMD_SLEEP_ON_REQUEST;
1237         tr->tr_status = TWA_CMD_BUSY;
1238         if ((error = twa_map_request(tr))) {
1239                 twa_printf(tr->tr_sc, "%s: twa_map_request returned 0x%x\n",
1240                                                 __func__, error);
1241                 return(error);
1242         }
1243
1244         end_time = time_second + timeout;
1245         while (tr->tr_status != TWA_CMD_COMPLETE) {
1246                 if ((error = tr->tr_error))
1247                         return(error);
1248                 if ((error = tsleep(tr, 0, "twawait", timeout * hz)) == 0) {
1249                         error = (tr->tr_status != TWA_CMD_COMPLETE);
1250                         break;
1251                 }
1252                 if (error == EWOULDBLOCK) {
1253                         /* Time out! */
1254                         twa_printf(tr->tr_sc, "%s: Request %p timed out.\n",
1255                                                                 __func__, tr);
1256                         /*
1257                          * We will reset the controller only if the request has
1258                          * already been submitted, so as to not lose the
1259                          * request packet.  If a busy request timed out, the
1260                          * reset will take care of freeing resources.  If a
1261                          * pending request timed out, we will free resources
1262                          * for that request, right here.  So, the caller is
1263                          * expected to NOT cleanup when ETIMEDOUT is returned.
1264                          */
1265                         if (tr->tr_status != TWA_CMD_PENDING)
1266                                 twa_reset(tr->tr_sc);
1267                         else {
1268                                 /* Request was never submitted.  Clean up. */
1269                                 twa_remove_pending(tr);
1270                                 twa_unmap_request(tr);
1271                                 if (tr->tr_data)
1272                                         free(tr->tr_data, M_DEVBUF);
1273                                 twa_release_request(tr);
1274                         }
1275                         return(ETIMEDOUT);
1276                 }
1277                 /* 
1278                  * Either the request got completed, or we were woken up by a
1279                  * signal.  Calculate the new timeout, in case it was the latter.
1280                  */
1281                 timeout = (end_time - time_second);
1282         }
1283         twa_unmap_request(tr);
1284         return(error);
1285 }
1286
1287
1288
1289 /*
1290  * Function name:       twa_immediate_request
1291  * Description:         Sends down a firmware cmd, and waits for the completion
1292  *                      in a tight loop.
1293  *
1294  * Input:               tr      -- ptr to request pkt
1295  *                      timeout -- max # of seconds to wait before giving up
1296  * Output:              None
1297  * Return value:        0       -- success
1298  *                      non-zero-- failure
1299  */
1300 static int
1301 twa_immediate_request(struct twa_request *tr, u_int32_t timeout)
1302 {
1303         time_t  end_time;
1304         int     error = 0;
1305
1306         twa_dbg_dprint_enter(4, tr->tr_sc);
1307
1308         if ((error = twa_map_request(tr))) {
1309                 twa_printf(tr->tr_sc, "%s: twa_map_request returned 0x%x\n",
1310                                                 __func__, error);
1311                 return(error);
1312         }
1313
1314         end_time = time_second + timeout;
1315         do {
1316                 if ((error = tr->tr_error))
1317                         return(error);
1318                 twa_done(tr->tr_sc);
1319                 if ((tr->tr_status != TWA_CMD_BUSY) &&
1320                         (tr->tr_status != TWA_CMD_PENDING)) {
1321                         twa_unmap_request(tr);
1322                         return(tr->tr_status != TWA_CMD_COMPLETE);
1323                 }
1324         } while (time_second <= end_time);
1325
1326         /* Time out! */
1327         twa_printf(tr->tr_sc, "%s: Request %p timed out.\n", __func__, tr);
1328         /*
1329          * We will reset the controller only if the request has
1330          * already been submitted, so as to not lose the
1331          * request packet.  If a busy request timed out, the
1332          * reset will take care of freeing resources.  If a
1333          * pending request timed out, we will free resources
1334          * for that request, right here.  So, the caller is
1335          * expected to NOT cleanup when ETIMEDOUT is returned.
1336          */
1337         if (tr->tr_status != TWA_CMD_PENDING)
1338                 twa_reset(tr->tr_sc);
1339         else {
1340                 /* Request was never submitted.  Clean up. */
1341                 twa_remove_pending(tr);
1342                 twa_unmap_request(tr);
1343                 if (tr->tr_data)
1344                         free(tr->tr_data, M_DEVBUF);
1345                 twa_release_request(tr);
1346         }
1347         return(ETIMEDOUT);
1348 }
1349
1350
1351
1352 /*
1353  * Function name:       twa_complete_io
1354  * Description:         Callback on scsi requests to fw.
1355  *
1356  * Input:               tr      -- ptr to request pkt
1357  * Output:              None
1358  * Return value:        None
1359  */
1360 void
1361 twa_complete_io(struct twa_request *tr)
1362 {
1363         struct twa_softc        *sc = tr->tr_sc;
1364
1365         twa_dbg_dprint_enter(8, sc);
1366
1367         if (tr->tr_status != TWA_CMD_COMPLETE)
1368                 twa_panic(sc, "twa_complete_io on incomplete command");
1369         if (tr->tr_private) /* This is a scsi cmd.  Complete it. */
1370                 twa_scsi_complete(tr);
1371         twa_release_request(tr);
1372 }
1373
1374
1375 /*
1376  * Function name:       twa_reset
1377  * Description:         Soft resets and then initializes the controller;
1378  *                      drains any incomplete requests.
1379  *
1380  * Input:               sc      -- ptr to per ctlr structure
1381  * Output:              None
1382  * Return value:        0       -- success
1383  *                      non-zero-- failure
1384  */
1385 int
1386 twa_reset(struct twa_softc *sc)
1387 {
1388         int     s;
1389         int     error = 0;
1390
1391         twa_dbg_dprint_enter(2, sc);
1392
1393         /*
1394          * Disable interrupts from the controller, and mask any
1395          * accidental entry into our interrupt handler.
1396          */
1397         twa_disable_interrupts(sc);
1398         s = splcam();
1399         
1400         /* Soft reset the controller. */
1401         if ((error = twa_soft_reset(sc))) {
1402                 twa_printf (sc, "Controller reset failed.\n");
1403                 goto out;
1404         }
1405
1406         /* Re-establish logical connection with the controller. */
1407         if ((error = twa_init_connection(sc, TWA_INIT_MESSAGE_CREDITS,
1408                                         0, 0, 0, 0, 0,
1409                                         NULL, NULL, NULL, NULL, NULL))) {
1410                 twa_printf(sc, "Can't initialize connection after reset.\n");
1411                 goto out;
1412         }
1413
1414         twa_printf(sc, "Controller reset done!\n");
1415
1416         /*
1417          * Complete all requests in the complete queue; error back all requests
1418          * in the busy queue.  Any internal requests will be simply freed.
1419          * Re-submit any requests in the pending queue.
1420          */
1421         twa_drain_complete_queue(sc);
1422         twa_drain_busy_queue(sc);
1423
1424 out:
1425         splx(s);
1426         /*
1427          * Enable interrupts, and also clear attention and response interrupts.
1428          */
1429         twa_enable_interrupts(sc);
1430         return(error);
1431 }
1432
1433
1434
1435 /*
1436  * Function name:       twa_soft_reset
1437  * Description:         Does the actual soft reset.
1438  *
1439  * Input:               sc      -- ptr to per ctlr structure
1440  * Output:              None
1441  * Return value:        0       -- success
1442  *                      non-zero-- failure
1443  */
1444 static int
1445 twa_soft_reset(struct twa_softc *sc)
1446 {
1447         u_int32_t       status_reg;
1448
1449         twa_dbg_dprint_enter(1, sc);
1450
1451         twa_printf(sc, "Resetting controller...\n");
1452         TWA_SOFT_RESET(sc);
1453
1454         if (twa_wait_status(sc, TWA_STATUS_MICROCONTROLLER_READY |
1455                                 TWA_STATUS_ATTENTION_INTERRUPT, 30)) {
1456                 twa_printf(sc, "Micro-ctlr not ready/No attn intr after reset.\n");
1457                 return(1);
1458         }
1459         TWA_WRITE_CONTROL_REGISTER(sc, TWA_CONTROL_CLEAR_ATTENTION_INTERRUPT);
1460         if (twa_drain_response_queue(sc)) {
1461                 twa_printf(sc, "Can't drain response queue.\n");
1462                 return(1);
1463         }
1464         if (twa_drain_aen_queue(sc)) {
1465                 twa_printf(sc, "Can't drain AEN queue.\n");
1466                 return(1);
1467         }
1468         if (twa_find_aen(sc, TWA_AEN_SOFT_RESET)) {
1469                 twa_printf(sc, "Reset not reported by controller.\n");
1470                 return(1);
1471         }
1472         status_reg = TWA_READ_STATUS_REGISTER(sc);
1473         if (TWA_STATUS_ERRORS(status_reg) ||
1474                                 twa_check_ctlr_state(sc, status_reg)) {
1475                 twa_printf(sc, "Controller errors detected.\n");
1476                 return(1);
1477         }
1478         return(0);
1479 }
1480
1481
1482
1483 /*
1484  * Function name:       twa_submit_io
1485  * Description:         Wrapper to twa_start.
1486  *
1487  * Input:               tr      -- ptr to request pkt
1488  * Output:              None
1489  * Return value:        0       -- success
1490  *                      non-zero-- failure
1491  */
1492 int
1493 twa_submit_io(struct twa_request *tr)
1494 {
1495         int     error;
1496
1497         if ((error = twa_start(tr))) {
1498                 if (tr->tr_cmd_pkt_type & TWA_CMD_PKT_TYPE_EXTERNAL) {
1499                         if (error == EBUSY)
1500                                 /*
1501                                  * Cmd queue is full.  Freeze the simq to
1502                                  * maintain ccb ordering.  The next ccb that
1503                                  * gets completed will unfreeze the simq.
1504                                  */
1505                                 twa_disallow_new_requests(tr->tr_sc);
1506                         else
1507                                 /* It's a controller error. */
1508                                 twa_printf(tr->tr_sc, "SCSI cmd = 0x%x: ERROR: (0x%02X: 0x%04X)\n",
1509                                         tr->tr_command->command.cmd_pkt_9k.cdb[0],
1510                                         TWA_MESSAGE_SOURCE_CONTROLLER_ERROR,
1511                                         error);
1512                         
1513                         tr->tr_error = error;
1514                         twa_scsi_complete(tr);
1515                 } else {
1516                         if (error == EBUSY)
1517                                 error = 0; /* the request will be in the pending queue */
1518                         else {
1519                                 twa_printf(tr->tr_sc, "cmd = 0x%x: ERROR: (0x%02X: 0x%04X)\n",
1520                                                 (tr->tr_cmd_pkt_type == TWA_CMD_PKT_TYPE_9K) ?
1521                                                 (tr->tr_command->command.cmd_pkt_9k.command.opcode) :
1522                                                 (tr->tr_command->command.cmd_pkt_7k.generic.opcode),
1523                                                 TWA_MESSAGE_SOURCE_CONTROLLER_ERROR,
1524                                                 tr->tr_error);
1525                                 tr->tr_error = error;
1526                         }
1527                 }
1528         }
1529         return(error);
1530 }
1531
1532
1533
1534 /*
1535  * Function name:       twa_start
1536  * Description:         Posts a cmd to firmware.
1537  *
1538  * Input:               tr      -- ptr to request pkt
1539  * Output:              None
1540  * Return value:        0       -- success
1541  *                      non-zero-- failure
1542  */
1543 int
1544 twa_start(struct twa_request *tr)
1545 {
1546         struct twa_softc        *sc = tr->tr_sc;
1547         u_int32_t               status_reg;
1548         int                     s;
1549         int                     error;
1550
1551         twa_dbg_dprint_enter(10, sc);
1552
1553         s = splcam();
1554         /* Check to see if we can post a command. */
1555         status_reg = TWA_READ_STATUS_REGISTER(sc);
1556         if ((error = twa_check_ctlr_state(sc, status_reg)))
1557                 goto out;
1558
1559         if (status_reg & TWA_STATUS_COMMAND_QUEUE_FULL) {
1560                 if ((tr->tr_cmd_pkt_type & TWA_CMD_PKT_TYPE_INTERNAL) ||
1561                         (tr->tr_cmd_pkt_type & TWA_CMD_PKT_TYPE_IOCTL)) {
1562                         if (tr->tr_status != TWA_CMD_PENDING) {
1563                                 twa_dbg_dprint(2, sc, "pending internal/ioctl request");
1564                                 tr->tr_status = TWA_CMD_PENDING;
1565                                 twa_enqueue_pending(tr);
1566                         }
1567                         TWA_WRITE_CONTROL_REGISTER(sc,
1568                                         TWA_CONTROL_UNMASK_COMMAND_INTERRUPT);
1569                 }
1570                 error = EBUSY;
1571         } else {
1572                 /* Cmd queue is not full.  Post the command. */
1573                 TWA_WRITE_COMMAND_QUEUE(sc,
1574                         tr->tr_cmd_phys + sizeof(struct twa_command_header));
1575                 /* Mark the request as currently being processed. */
1576                 tr->tr_status = TWA_CMD_BUSY;
1577                 /* Move the request into the busy queue. */
1578                 twa_enqueue_busy(tr);
1579         }
1580
1581 out:
1582         splx(s);
1583         return(error);
1584 }
1585
1586
1587
1588 /*
1589  * Function name:       twa_done
1590  * Description:         Looks for cmd completions from fw; queues cmds completed
1591  *                      by fw into complete queue.
1592  *
1593  * Input:               sc      -- ptr to per ctlr structure
1594  * Output:              None
1595  * Return value:        0       -- no ctlr error
1596  *                      non-zero-- ctlr error
1597  */
1598 static int
1599 twa_done(struct twa_softc *sc)
1600 {
1601         union twa_response_queue        rq;
1602         struct twa_request              *tr;
1603         int                             s;
1604         int                             error = 0;
1605         u_int32_t                       status_reg;
1606     
1607         twa_dbg_dprint_enter(10, sc);
1608
1609         s = splcam();
1610         for (;;) {
1611                 status_reg = TWA_READ_STATUS_REGISTER(sc);
1612                 if ((error = twa_check_ctlr_state(sc, status_reg)))
1613                         break;
1614                 if (status_reg & TWA_STATUS_RESPONSE_QUEUE_EMPTY)
1615                         break;
1616                 /* Response queue is not empty. */
1617                 rq = TWA_READ_RESPONSE_QUEUE(sc);
1618                 tr = sc->twa_lookup[rq.u.response_id];  /* lookup the request */
1619                 if (tr->tr_status != TWA_CMD_BUSY)
1620                         twa_printf(sc, "ERROR: Unposted command completed!! req = %p; status = %d\n",
1621                                         tr, tr->tr_status);
1622                 tr->tr_status = TWA_CMD_COMPLETE;
1623                 /* Enqueue request in the complete queue. */
1624                 twa_remove_busy(tr);
1625                 twa_enqueue_complete(tr);
1626         }
1627         splx(s);
1628
1629         /* Complete this, and other requests in the complete queue. */
1630         twa_drain_complete_queue(sc);
1631         return(error);
1632 }
1633
1634
1635
1636 /*
1637  * Function name:       twa_drain_pending_queue
1638  * Description:         Kick starts any requests in the pending queue.
1639  *
1640  * Input:               sc      -- ptr to per ctlr structure
1641  * Output:              None
1642  * Return value:        0       -- all pending requests drained
1643  *                      non-zero-- otherwise
1644  */
1645 static int
1646 twa_drain_pending_queue(struct twa_softc *sc)
1647 {
1648         struct twa_request      *tr;
1649         int                     error = 0;
1650     
1651         twa_dbg_dprint_enter(10, sc);
1652         
1653         /*
1654          * Pull requests off the pending queue, and submit them.
1655          */
1656         while ((tr = twa_dequeue_pending(sc)) != NULL) {
1657                 if ((error = twa_start(tr))) {
1658                         if (error == EBUSY) {
1659                                 twa_dbg_dprint(2, sc, "Requeueing pending request");
1660                                 tr->tr_status = TWA_CMD_PENDING;
1661                                 twa_requeue_pending(tr);/* queue at the head */
1662                                 break;
1663                         } else {
1664                                 twa_printf(sc, "%s: twa_start returned 0x%x\n",
1665                                                         __func__, error);
1666                                 if (tr->tr_flags & TWA_CMD_SLEEP_ON_REQUEST)
1667                                         wakeup_one(tr);/* let the caller know it failed */
1668                                 tr->tr_error = error;
1669                                 error = 0;
1670                         }
1671                 }
1672         }
1673         return(error);
1674 }
1675
1676
1677
1678 /*
1679  * Function name:       twa_drain_complete_queue
1680  * Description:         Does unmapping for each request completed by fw,
1681  *                      and lets the request originators know of the completion.
1682  *
1683  * Input:               sc      -- ptr to per ctlr structure
1684  * Output:              None
1685  * Return value:        None
1686  */
1687 static void
1688 twa_drain_complete_queue(struct twa_softc *sc)
1689 {
1690         struct twa_request      *tr;
1691     
1692         twa_dbg_dprint_enter(10, sc);
1693
1694         /*
1695          * Pull commands off the completed list, dispatch them appropriately.
1696          */
1697         while ((tr = twa_dequeue_complete(sc)) != NULL) {
1698                 /* Unmap the command packet, and any associated data buffer. */
1699                 twa_unmap_request(tr);
1700
1701                 /* Call the callback, if there's one. */
1702                 if (tr->tr_callback)
1703                         tr->tr_callback(tr);
1704                 else
1705                         if (tr->tr_flags & TWA_CMD_SLEEP_ON_REQUEST) {
1706                                 /* Wake up the sleeping command originator. */
1707                                 twa_dbg_dprint(7, sc, "Waking up originator of request %p", tr);
1708                                 wakeup_one(tr);
1709                         }
1710         }
1711 }
1712
1713
1714
1715 /*
1716  * Function name:       twa_wait_status
1717  * Description:         Wait for a given status to show up in the fw status register.
1718  *
1719  * Input:               sc      -- ptr to per ctlr structure
1720  *                      status  -- status to look for
1721  *                      timeout -- max # of seconds to wait before giving up
1722  * Output:              None
1723  * Return value:        0       -- success
1724  *                      non-zero-- failure
1725  */
1726 static int
1727 twa_wait_status(struct twa_softc *sc, u_int32_t status, u_int32_t timeout)
1728 {
1729         time_t          end_time;
1730         u_int32_t       status_reg;
1731
1732         twa_dbg_dprint_enter(4, sc);
1733
1734         end_time = time_second + timeout;
1735         do {
1736                 status_reg = TWA_READ_STATUS_REGISTER(sc);
1737                 if ((status_reg & status) == status)/* got the required bit(s)? */
1738                         return(0);
1739                 DELAY(100000);
1740         } while (time_second <= end_time);
1741
1742         return(1);
1743 }
1744
1745
1746
1747 /*
1748  * Function name:       twa_drain_response_queue
1749  * Description:         Drain the response queue.
1750  *
1751  * Input:               sc      -- ptr to per ctlr structure
1752  * Output:              None
1753  * Return value:        0       -- success
1754  *                      non-zero-- failure
1755  */
1756 static int
1757 twa_drain_response_queue(struct twa_softc *sc)
1758 {
1759         union twa_response_queue        rq;
1760         u_int32_t                       status_reg;
1761
1762         twa_dbg_dprint_enter(4, sc);
1763
1764         for (;;) {
1765                 status_reg = TWA_READ_STATUS_REGISTER(sc);
1766                 if (twa_check_ctlr_state(sc, status_reg))
1767                         return(1);
1768                 if (status_reg & TWA_STATUS_RESPONSE_QUEUE_EMPTY)
1769                         return(0); /* no more response queue entries */
1770                 rq = TWA_READ_RESPONSE_QUEUE(sc);
1771         }
1772 }
1773
1774
1775
1776 /*
1777  * Function name:       twa_host_intr
1778  * Description:         This function gets called if we triggered an interrupt.
1779  *                      We don't use it as of now.
1780  *
1781  * Input:               sc      -- ptr to per ctlr structure
1782  * Output:              None
1783  * Return value:        None
1784  */
1785 static void
1786 twa_host_intr(struct twa_softc *sc)
1787 {
1788         twa_dbg_dprint_enter(6, sc);
1789
1790         TWA_WRITE_CONTROL_REGISTER(sc, TWA_CONTROL_CLEAR_HOST_INTERRUPT);
1791 }
1792
1793
1794
1795 /*
1796  * Function name:       twa_attention_intr
1797  * Description:         This function gets called if the fw posted an AEN
1798  *                      (Asynchronous Event Notification).  It fetches
1799  *                      all the AEN's that the fw might have posted.
1800  *
1801  * Input:               sc      -- ptr to per ctlr structure
1802  * Output:              None
1803  * Return value:        None
1804  */
1805 static void
1806 twa_attention_intr(struct twa_softc *sc)
1807 {
1808         int     error;
1809
1810         twa_dbg_dprint_enter(6, sc);
1811
1812         if ((error = twa_fetch_aen(sc)))
1813                 twa_printf(sc, "Fetch AEN failed. error = 0x%x\n", error);
1814         TWA_WRITE_CONTROL_REGISTER(sc, TWA_CONTROL_CLEAR_ATTENTION_INTERRUPT);
1815 }
1816
1817
1818
1819 /*
1820  * Function name:       twa_command_intr
1821  * Description:         This function gets called if we hit a queue full
1822  *                      condition earlier, and the fw is now ready for
1823  *                      new cmds.  Submits any pending requests.
1824  *
1825  * Input:               sc      -- ptr to per ctlr structure
1826  * Output:              None
1827  * Return value:        None
1828  */
1829 static void
1830 twa_command_intr(struct twa_softc *sc)
1831 {
1832         twa_dbg_dprint_enter(6, sc);
1833
1834         /* Start any requests that might be in the pending queue. */
1835         if (! twa_drain_pending_queue(sc))
1836                 TWA_WRITE_CONTROL_REGISTER(sc,
1837                                 TWA_CONTROL_MASK_COMMAND_INTERRUPT);
1838 }
1839
1840
1841
1842 /*
1843  * Function name:       twa_fetch_aen
1844  * Description:         Send down a Request Sense cmd to fw to fetch an AEN.
1845  *
1846  * Input:               sc      -- ptr to per ctlr structure
1847  * Output:              None
1848  * Return value:        0       -- success
1849  *                      non-zero-- failure
1850  */
1851 static int
1852 twa_fetch_aen(struct twa_softc *sc)
1853 {
1854         struct twa_request      *tr;
1855         int                     error = 0;
1856
1857         twa_dbg_dprint_enter(4, sc);
1858
1859         if ((tr = twa_get_request(sc)) == NULL)
1860                 return(EIO);
1861         tr->tr_cmd_pkt_type |= TWA_CMD_PKT_TYPE_INTERNAL;
1862         tr->tr_callback = twa_aen_callback;
1863         if ((error = twa_send_scsi_cmd(tr, 0x03 /* REQUEST_SENSE */))) {
1864                 if (tr->tr_data)
1865                         free(tr->tr_data, M_DEVBUF);
1866                 twa_release_request(tr);
1867         }
1868         return(error);
1869 }
1870
1871
1872
1873 /*
1874  * Function name:       twa_aen_callback
1875  * Description:         Callback for requests to fetch AEN's.
1876  *
1877  * Input:               tr      -- ptr to completed request pkt
1878  * Output:              None
1879  * Return value:        None
1880  */
1881 static void
1882 twa_aen_callback(struct twa_request *tr)
1883 {
1884         struct twa_softc                *sc = tr->tr_sc;
1885         struct twa_command_header       *cmd_hdr = (struct twa_command_header *)(tr->tr_data);
1886         struct twa_command_9k           *cmd = &(tr->tr_command->command.cmd_pkt_9k);
1887         int                             i;
1888
1889         twa_dbg_dprint_enter(4, sc);
1890
1891         twa_dbg_dprint(4, sc, "req_id = 0x%x, status = 0x%x",
1892                                 cmd->request_id,
1893                                 cmd->status);
1894
1895         if (! cmd->status) {
1896                 if ((tr->tr_cmd_pkt_type & TWA_CMD_PKT_TYPE_9K) &&
1897                         (cmd->cdb[0] == 0x3 /* REQUEST_SENSE */))
1898                         twa_enqueue_aen(sc, cmd_hdr);
1899         } else {
1900                 cmd_hdr->err_specific_desc[sizeof(cmd_hdr->err_specific_desc) - 1] = '\0';
1901                 twa_printf(sc, "%s: cmd = 0x%x: ERROR: (0x%02X: 0x%04X): %s: %s\n",
1902                                 __func__, cmd->command.opcode,
1903                                 TWA_MESSAGE_SOURCE_CONTROLLER_ERROR,
1904                                 cmd_hdr->status_block.error,
1905                                 twa_find_msg_string(twa_error_table,
1906                                                 cmd_hdr->status_block.error),
1907                                 cmd_hdr->err_specific_desc);
1908                 twa_dbg_print(2, "sense info: ");
1909                 for (i = 0; i < 18; i++)
1910                         twa_dbg_print(2, "%x\t", tr->tr_command->cmd_hdr.sense_data[i]);
1911                 twa_dbg_print(2, ""); /* print new line */
1912                 for (i = 0; i < 128; i++)
1913                         twa_dbg_print(7, "%x\t", ((int8_t *)(tr->tr_data))[i]);
1914         }
1915
1916         if (tr->tr_data)
1917                 free(tr->tr_data, M_DEVBUF);
1918         twa_release_request(tr);
1919 }
1920
1921
1922
1923 /*
1924  * Function name:       twa_drain_aen_queue
1925  * Description:         Fetches all un-retrieved AEN's posted by fw.
1926  *
1927  * Input:               sc      -- ptr to per ctlr structure
1928  * Output:              None
1929  * Return value:        0       -- success
1930  *                      non-zero-- failure
1931  */
1932 static int
1933 twa_drain_aen_queue(struct twa_softc *sc)
1934 {
1935         struct twa_request              *tr;
1936         struct twa_command_header       *cmd_hdr;
1937         time_t                          end_time;
1938         int                             error = 0;
1939
1940         for (;;) {
1941                 if ((tr = twa_get_request(sc)) == NULL) {
1942                         error = EIO;
1943                         break;
1944                 }
1945                 tr->tr_cmd_pkt_type |= TWA_CMD_PKT_TYPE_INTERNAL;
1946                 tr->tr_callback = NULL;
1947                 if ((error = twa_send_scsi_cmd(tr, 0x03 /* REQUEST_SENSE */))) {
1948                         twa_dbg_dprint(1, sc, "Cannot send command to fetch aen");
1949                         break;
1950                 }
1951
1952                 end_time = time_second + TWA_REQUEST_TIMEOUT_PERIOD;
1953                 do {
1954                         twa_done(tr->tr_sc);
1955                         if (tr->tr_status != TWA_CMD_BUSY)
1956                                 break;
1957                 } while (time_second <= end_time);
1958
1959                 if (tr->tr_status != TWA_CMD_COMPLETE) {
1960                         error = ETIMEDOUT;
1961                         break;
1962                 }
1963
1964                 if ((error = tr->tr_command->command.cmd_pkt_9k.status))
1965                         break;
1966
1967                 cmd_hdr = (struct twa_command_header *)(tr->tr_data);
1968                 if ((cmd_hdr->status_block.error) /* aen_code */
1969                                 == TWA_AEN_QUEUE_EMPTY)
1970                         break;
1971                 twa_enqueue_aen(sc, cmd_hdr);
1972
1973                 free(tr->tr_data, M_DEVBUF);
1974                 twa_release_request(tr);
1975         }
1976
1977         if (tr) {
1978                 if (tr->tr_data)
1979                         free(tr->tr_data, M_DEVBUF);
1980                 twa_release_request(tr);
1981         }
1982         return(error);
1983 }
1984
1985
1986
1987 /*
1988  * Function name:       twa_enqueue_aen
1989  * Description:         Queues AEN's to be supplied to user-space tools on request.
1990  *
1991  * Input:               sc      -- ptr to per ctlr structure
1992  *                      cmd_hdr -- ptr to hdr of fw cmd pkt, from where the AEN
1993  *                                 details can be retrieved.
1994  * Output:              None
1995  * Return value:        None
1996  */
1997 static void
1998 twa_enqueue_aen(struct twa_softc *sc, struct twa_command_header *cmd_hdr)
1999 {
2000         struct twa_event_packet *event;
2001         unsigned short          aen_code;
2002         unsigned long           local_time;
2003         unsigned long           sync_time;
2004         int                     s;
2005
2006         twa_dbg_dprint_enter(4, sc);
2007         s = splcam();
2008         aen_code = cmd_hdr->status_block.error;
2009
2010         switch (aen_code) {
2011         case TWA_AEN_SYNC_TIME_WITH_HOST:
2012                 twa_dbg_dprint(4, sc, "Received AEN_SYNC_TIME");
2013                 /* Calculate time (in seconds) since last Sunday 12.00 AM. */
2014                 local_time = time_second - (tz.tz_minuteswest * 60) -
2015                                         (wall_cmos_clock ? adjkerntz : 0);
2016                 sync_time = (local_time - (3 * 86400)) % 604800;
2017                 if (twa_set_param(sc, TWA_PARAM_TIME_TABLE,
2018                                         TWA_PARAM_TIME_SchedulerTime, 4,
2019                                         &sync_time, twa_aen_callback))
2020                         twa_printf(sc, "Unable to sync time with ctlr!\n");
2021                 break;
2022
2023         case TWA_AEN_QUEUE_EMPTY:
2024                 twa_dbg_dprint(4, sc, "AEN queue empty");
2025                 break;
2026
2027         default:
2028                 /* Queue the event. */
2029                 event = sc->twa_aen_queue[sc->twa_aen_head];
2030                 if (event->retrieved == TWA_AEN_NOT_RETRIEVED)
2031                         sc->twa_aen_queue_overflow = TRUE;
2032                 event->severity = cmd_hdr->status_block.substatus_block.severity;
2033                 local_time = time_second - (tz.tz_minuteswest * 60) -
2034                                         (wall_cmos_clock ? adjkerntz : 0);
2035                 event->time_stamp_sec = local_time;
2036                 event->aen_code = aen_code;
2037                 event->retrieved = TWA_AEN_NOT_RETRIEVED;
2038                 event->sequence_id = ++(sc->twa_current_sequence_id);
2039                 cmd_hdr->err_specific_desc[sizeof(cmd_hdr->err_specific_desc) - 1] = '\0';
2040                 event->parameter_len = strlen(cmd_hdr->err_specific_desc);
2041                 bcopy(cmd_hdr->err_specific_desc, event->parameter_data,
2042                                         event->parameter_len);
2043
2044                 twa_dbg_dprint(4, sc, "event = %x %x %x %x %x %x %x\n %s",
2045                                 event->sequence_id,
2046                                 event->time_stamp_sec,
2047                                 event->aen_code,
2048                                 event->severity,
2049                                 event->retrieved,
2050                                 event->repeat_count,
2051                                 event->parameter_len,
2052                                 event->parameter_data);
2053
2054                 twa_dbg_dprint(4, sc, "cmd_hdr = %x %lx %x %x %x %x %x\n %s",
2055                                 sc->twa_current_sequence_id,
2056                                 local_time,
2057                                 cmd_hdr->status_block.error,
2058                                 cmd_hdr->status_block.substatus_block.severity,
2059                                 TWA_AEN_NOT_RETRIEVED,
2060                                 0,
2061                                 strlen(cmd_hdr->err_specific_desc),
2062                                 cmd_hdr->err_specific_desc);
2063
2064                 /* Print the event. */
2065                 if (event->severity < TWA_AEN_SEVERITY_DEBUG)
2066                         twa_printf(sc,  "%s: (0x%02X: 0x%04X): %s: %s\n",
2067                                         twa_aen_severity_table[event->severity],
2068                                         TWA_MESSAGE_SOURCE_CONTROLLER_EVENT,
2069                                         aen_code,
2070                                         twa_find_msg_string(twa_aen_table, aen_code),
2071                                         event->parameter_data);
2072
2073                 if ((sc->twa_aen_head + 1) == TWA_Q_LENGTH)
2074                         sc->twa_aen_queue_wrapped = TRUE;
2075                 sc->twa_aen_head = (sc->twa_aen_head + 1) % TWA_Q_LENGTH;
2076                 break;
2077         } /* switch */
2078         splx(s);
2079 }
2080
2081
2082
2083 /*
2084  * Function name:       twa_find_aen
2085  * Description:         Reports whether a given AEN ever occurred.
2086  *
2087  * Input:               sc      -- ptr to per ctlr structure
2088  *                      aen_code-- AEN to look for
2089  * Output:              None
2090  * Return value:        0       -- success
2091  *                      non-zero-- failure
2092  */
2093 static int
2094 twa_find_aen(struct twa_softc *sc, u_int16_t aen_code)
2095 {
2096         u_int32_t       last_index;
2097         int             s;
2098         int             i;
2099
2100         s = splcam();
2101
2102         if (sc->twa_aen_queue_wrapped)
2103                 last_index = sc->twa_aen_head;
2104         else
2105                 last_index = 0;
2106
2107         i = sc->twa_aen_head;
2108         do {
2109                 i = (i + TWA_Q_LENGTH - 1) % TWA_Q_LENGTH;
2110                 if ((sc->twa_aen_queue[i])->aen_code == aen_code) {
2111                         splx(s);
2112                         return(0);
2113                 }
2114         } while (i != last_index);
2115
2116         splx(s);
2117         return(1);
2118 }
2119
2120
2121
2122 /*
2123  * Function name:       twa_find_msg_string
2124  * Description:         Looks up a given table, and returns the message string
2125  *                      corresponding to a given code (error code or AEN code).
2126  *
2127  * Input:               sc      -- ptr to per ctlr structure
2128  *                      code    -- code, the message string corresponding to
2129  *                                 which is to be returned.
2130  * Output:              None
2131  * Return value:        ptr to corresponding msg string -- success
2132  *                      NULL                            -- failure
2133  */
2134 char *
2135 twa_find_msg_string(struct twa_message *table, u_int16_t code)
2136 {
2137         int     i;
2138
2139         for (i = 0; table[i].message != NULL; i++)
2140                 if (table[i].code == code)
2141                         return(table[i].message);
2142
2143         return(table[i].message);
2144 }
2145
2146
2147
2148 /*
2149  * Function name:       twa_get_request
2150  * Description:         Gets a request pkt from the free queue.
2151  *
2152  * Input:               sc      -- ptr to per ctlr structure
2153  * Output:              None
2154  * Return value:        ptr to request pkt      -- success
2155  *                      NULL                    -- failure
2156  */
2157 struct twa_request *
2158 twa_get_request(struct twa_softc *sc)
2159 {
2160         struct twa_request      *tr;
2161
2162         twa_dbg_dprint_enter(4, sc);
2163
2164         /* Get a free request packet. */
2165         tr = twa_dequeue_free(sc);
2166
2167         /* Initialize some fields to their defaults. */
2168         if (tr) {
2169                 tr->tr_data = NULL;
2170                 tr->tr_real_data = NULL;
2171                 tr->tr_length = 0;
2172                 tr->tr_real_length = 0;
2173                 tr->tr_status = TWA_CMD_SETUP;/* command is in setup phase */
2174                 tr->tr_flags = 0;
2175                 tr->tr_error = 0;
2176                 tr->tr_private = NULL;
2177                 tr->tr_callback = NULL;
2178                 tr->tr_cmd_pkt_type = 0;
2179
2180                 /*
2181                  * Look at the status field in the command packet to see how
2182                  * it completed the last time it was used, and zero out only
2183                  * the portions that might have changed.  Note that we don't
2184                  * care to zero out the sglist.
2185                  */
2186                 if (tr->tr_command->command.cmd_pkt_9k.status)
2187                         bzero(tr->tr_command,
2188                                 sizeof(struct twa_command_header) + 28 /* max bytes before sglist */);
2189                 else
2190                         bzero(&(tr->tr_command->command), 28 /* max bytes before sglist */);
2191         }
2192         return(tr);
2193 }
2194
2195
2196
2197 /*
2198  * Function name:       twa_release_request
2199  * Description:         Puts a request pkt into the free queue.
2200  *
2201  * Input:               tr      -- ptr to request pkt to be freed
2202  * Output:              None
2203  * Return value:        None
2204  */
2205 void
2206 twa_release_request(struct twa_request *tr)
2207 {
2208         twa_dbg_dprint_enter(4, tr->tr_sc);
2209
2210         twa_enqueue_free(tr);
2211 }
2212
2213
2214
2215 /*
2216  * Function name:       twa_describe_controller
2217  * Description:         Describes the controller, in terms of its fw version,
2218  *                      BIOS version etc.
2219  *
2220  * Input:               sc      -- ptr to per ctlr structure
2221  * Output:              None
2222  * Return value:        None
2223  */
2224 void
2225 twa_describe_controller(struct twa_softc *sc)
2226 {
2227         struct twa_param_9k     *p[6];
2228         u_int8_t                num_ports = 0;
2229
2230         twa_dbg_dprint_enter(2, sc);
2231
2232         /* Get the port count. */
2233         p[0] = twa_get_param(sc, TWA_PARAM_CONTROLLER_TABLE,
2234                                 TWA_PARAM_CONTROLLER_PORT_COUNT, 1, NULL);
2235         if (p[0]) {
2236                 num_ports = *(u_int8_t *)(p[0]->data);
2237                 free(p[0], M_DEVBUF);
2238         }
2239
2240         /* Get the firmware and BIOS versions. */
2241         p[0] = twa_get_param(sc, TWA_PARAM_VERSION_TABLE,
2242                                 TWA_PARAM_VERSION_FW, 16, NULL);
2243         p[1] = twa_get_param(sc, TWA_PARAM_VERSION_TABLE,
2244                                 TWA_PARAM_VERSION_BIOS, 16, NULL);
2245
2246         twa_printf(sc, "%d ports, Firmware %.16s, BIOS %.16s\n",
2247                         num_ports, p[0]?(p[0]->data):NULL, p[1]?(p[1]->data):NULL);
2248         if (bootverbose) {
2249                 /* Get more versions. */
2250                 p[2] = twa_get_param(sc, TWA_PARAM_VERSION_TABLE,
2251                                         TWA_PARAM_VERSION_MONITOR, 16, NULL);
2252                 p[3] = twa_get_param(sc, TWA_PARAM_VERSION_TABLE,
2253                                         TWA_PARAM_VERSION_PCBA, 8, NULL);
2254                 p[4] = twa_get_param(sc, TWA_PARAM_VERSION_TABLE,
2255                                         TWA_PARAM_VERSION_ATA, 8, NULL);
2256                 p[5] = twa_get_param(sc, TWA_PARAM_VERSION_TABLE,
2257                                         TWA_PARAM_VERSION_PCI, 8, NULL);
2258
2259                 twa_printf(sc, "Monitor %.16s, PCB %.8s, Achip %.8s, Pchip %.8s\n",
2260                                 p[2]?(p[2]->data):NULL, p[3]?(p[3]->data):NULL,
2261                                 p[4]?(p[4]->data):NULL, p[5]?(p[5]->data):NULL);
2262
2263                 if (p[2])
2264                         free(p[2], M_DEVBUF);
2265                 if (p[3])
2266                         free(p[3], M_DEVBUF);
2267                 if (p[4])
2268                         free(p[4], M_DEVBUF);
2269                 if (p[5])
2270                         free(p[5], M_DEVBUF);
2271         }
2272         if (p[0])
2273                 free(p[0], M_DEVBUF);
2274         if (p[1])
2275                 free(p[1], M_DEVBUF);
2276 }
2277
2278
2279
2280 /*
2281  * Function name:       twa_check_ctlr_state
2282  * Description:         Makes sure that the fw status register reports a
2283  *                      proper status.
2284  *
2285  * Input:               sc              -- ptr to per ctlr structure
2286  *                      status_reg      -- value in the status register
2287  * Output:              None
2288  * Return value:        0       -- no errors
2289  *                      non-zero-- errors
2290  */
2291 static int
2292 twa_check_ctlr_state(struct twa_softc *sc, u_int32_t status_reg)
2293 {
2294         int             result = 0;
2295         static time_t   last_warning[2] = {0, 0};
2296
2297         /* Check if the 'micro-controller ready' bit is not set. */
2298         if ((status_reg & TWA_STATUS_EXPECTED_BITS) !=
2299                                 TWA_STATUS_EXPECTED_BITS) {
2300                 if (time_second > (last_warning[0] + 5)) {
2301                         twa_printf(sc, "Missing expected status bit(s) %b\n",
2302                                         ~status_reg & TWA_STATUS_EXPECTED_BITS,
2303                                         TWA_STATUS_BITS_DESCRIPTION);
2304                         last_warning[0] = time_second;
2305                 }
2306                 result = 1;
2307         }
2308
2309         /* Check if any error bits are set. */
2310         if ((status_reg & TWA_STATUS_UNEXPECTED_BITS) != 0) {
2311                 if (time_second > (last_warning[1] + 5)) {
2312                         twa_printf(sc, "Unexpected status bit(s) %b\n",
2313                                         status_reg & TWA_STATUS_UNEXPECTED_BITS,
2314                                         TWA_STATUS_BITS_DESCRIPTION);
2315                         last_warning[1] = time_second;
2316                 }
2317                 if (status_reg & TWA_STATUS_PCI_PARITY_ERROR_INTERRUPT) {
2318                         twa_printf(sc, "PCI parity error: clearing... Re-seat/move/replace card.\n");
2319                         TWA_WRITE_CONTROL_REGISTER(sc, TWA_CONTROL_CLEAR_PARITY_ERROR);
2320                         twa_write_pci_config(sc, TWA_PCI_CONFIG_CLEAR_PARITY_ERROR, 2);
2321                 }
2322                 if (status_reg & TWA_STATUS_PCI_ABORT_INTERRUPT) {
2323                         twa_printf(sc, "PCI abort: clearing...\n");
2324                         TWA_WRITE_CONTROL_REGISTER(sc, TWA_CONTROL_CLEAR_PCI_ABORT);
2325                         twa_write_pci_config(sc, TWA_PCI_CONFIG_CLEAR_PCI_ABORT, 2);
2326                 }
2327                 if (status_reg & TWA_STATUS_QUEUE_ERROR_INTERRUPT) {
2328                         twa_printf(sc, "Controller queue error: clearing...\n");
2329                         TWA_WRITE_CONTROL_REGISTER(sc, TWA_CONTROL_CLEAR_PCI_ABORT);
2330                 }
2331                 if (status_reg & TWA_STATUS_SBUF_WRITE_ERROR) {
2332                         twa_printf(sc, "SBUF write error: clearing...\n");
2333                         TWA_WRITE_CONTROL_REGISTER(sc, TWA_CONTROL_CLEAR_SBUF_WRITE_ERROR);
2334                 }
2335                 if (status_reg & TWA_STATUS_MICROCONTROLLER_ERROR) {
2336                         twa_printf(sc, "Micro-controller error!\n");
2337                         result = 1;
2338                 }
2339         }
2340         return(result);
2341 }       
2342
2343
2344
2345 /*
2346  * Function name:       twa_print_controller
2347  * Description:         Prints the current status of the controller.
2348  *
2349  * Input:               sc      -- ptr to per ctlr structure
2350  * Output:              None
2351  * Return value:        None
2352  */
2353 void
2354 twa_print_controller(struct twa_softc *sc)
2355 {
2356         u_int32_t       status_reg;
2357
2358         /* Print current controller details. */
2359         status_reg = TWA_READ_STATUS_REGISTER(sc);
2360         twa_printf(sc, "status   %b\n", status_reg, TWA_STATUS_BITS_DESCRIPTION);
2361 #ifdef TWA_DEBUG
2362         twa_printf(sc, "q type    current  max\n");
2363         twa_printf(sc, "free      %04d     %04d\n",
2364                 sc->twa_qstats[TWAQ_FREE].q_length, sc->twa_qstats[TWAQ_FREE].q_max);
2365         twa_printf(sc, "busy      %04d     %04d\n",
2366                 sc->twa_qstats[TWAQ_BUSY].q_length, sc->twa_qstats[TWAQ_BUSY].q_max);
2367         twa_printf(sc, "pending   %04d     %04d\n",
2368                 sc->twa_qstats[TWAQ_PENDING].q_length, sc->twa_qstats[TWAQ_PENDING].q_max);
2369         twa_printf(sc, "complete  %04d     %04d\n",
2370                 sc->twa_qstats[TWAQ_COMPLETE].q_length, sc->twa_qstats[TWAQ_COMPLETE].q_max);
2371 #endif /* TWA_DEBUG */
2372         twa_printf(sc, "AEN queue head %d  tail %d\n",
2373                         sc->twa_aen_head, sc->twa_aen_tail);
2374 }       
2375
2376
2377
2378 /*
2379  * Function name:       twa_panic
2380  * Description:         Called when something is seriously wrong with the ctlr.
2381  *                      Hits the debugger if the debugger is turned on, else
2382  *                      resets the ctlr.
2383  *
2384  * Input:               sc      -- ptr to per ctlr structure
2385  *                      reason  -- string describing what went wrong
2386  * Output:              None
2387  * Return value:        None
2388  */
2389 static void
2390 twa_panic(struct twa_softc *sc, int8_t *reason)
2391 {
2392         twa_print_controller(sc);
2393 #ifdef TWA_DEBUG
2394         panic(reason);
2395 #else
2396         twa_printf(sc, "twa_panic: RESETTING CONTROLLER...\n");
2397         twa_reset(sc);
2398 #endif
2399 }
2400