]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/dev/twa/tw_cl_init.c
OpenZFS: MFV 2.0-rc3-gfc5966
[FreeBSD/FreeBSD.git] / sys / dev / twa / tw_cl_init.c
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3  *
4  * Copyright (c) 2004-07 Applied Micro Circuits Corporation.
5  * Copyright (c) 2004-05 Vinod Kashyap
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  *
29  *      $FreeBSD$
30  */
31
32 /*
33  * AMCC'S 3ware driver for 9000 series storage controllers.
34  *
35  * Author: Vinod Kashyap
36  * Modifications by: Adam Radford
37  * Modifications by: Manjunath Ranganathaiah
38  */
39
40 /*
41  * Common Layer initialization functions.
42  */
43
44 #include "tw_osl_share.h"
45 #include "tw_cl_share.h"
46 #include "tw_cl_fwif.h"
47 #include "tw_cl_ioctl.h"
48 #include "tw_cl.h"
49 #include "tw_cl_externs.h"
50 #include "tw_osl_ioctl.h"
51
52 /*
53  * Function name:       tw_cl_ctlr_supported
54  * Description:         Determines if a controller is supported.
55  *
56  * Input:               vendor_id -- vendor id of the controller
57  *                      device_id -- device id of the controller
58  * Output:              None
59  * Return value:        TW_CL_TRUE-- controller supported
60  *                      TW_CL_FALSE-- controller not supported
61  */
62 TW_INT32
63 tw_cl_ctlr_supported(TW_INT32 vendor_id, TW_INT32 device_id)
64 {
65         if ((vendor_id == TW_CL_VENDOR_ID) &&
66                 ((device_id == TW_CL_DEVICE_ID_9K) ||
67                  (device_id == TW_CL_DEVICE_ID_9K_X) ||
68                  (device_id == TW_CL_DEVICE_ID_9K_E) ||
69                  (device_id == TW_CL_DEVICE_ID_9K_SA)))
70                 return(TW_CL_TRUE);
71         return(TW_CL_FALSE);
72 }
73
74 /*
75  * Function name:       tw_cl_get_pci_bar_info
76  * Description:         Returns PCI BAR info.
77  *
78  * Input:               device_id -- device id of the controller
79  *                      bar_type -- type of PCI BAR in question
80  * Output:              bar_num -- PCI BAR number corresponding to bar_type
81  *                      bar0_offset -- byte offset from BAR 0 (0x10 in
82  *                                      PCI config space)
83  *                      bar_size -- size, in bytes, of the BAR in question
84  * Return value:        0 -- success
85  *                      non-zero -- failure
86  */
87 TW_INT32
88 tw_cl_get_pci_bar_info(TW_INT32 device_id, TW_INT32 bar_type,
89         TW_INT32 *bar_num, TW_INT32 *bar0_offset, TW_INT32 *bar_size)
90 {
91         TW_INT32        error = TW_OSL_ESUCCESS;
92
93         switch(device_id) {
94         case TW_CL_DEVICE_ID_9K:
95                 switch(bar_type) {
96                 case TW_CL_BAR_TYPE_IO:
97                         *bar_num = 0;
98                         *bar0_offset = 0;
99                         *bar_size = 4;
100                         break;
101
102                 case TW_CL_BAR_TYPE_MEM:
103                         *bar_num = 1;
104                         *bar0_offset = 0x4;
105                         *bar_size = 8;
106                         break;
107
108                 case TW_CL_BAR_TYPE_SBUF:
109                         *bar_num = 2;
110                         *bar0_offset = 0xC;
111                         *bar_size = 8;
112                         break;
113                 }
114                 break;
115
116         case TW_CL_DEVICE_ID_9K_X:
117         case TW_CL_DEVICE_ID_9K_E:
118         case TW_CL_DEVICE_ID_9K_SA:
119                 switch(bar_type) {
120                 case TW_CL_BAR_TYPE_IO:
121                         *bar_num = 2;
122                         *bar0_offset = 0x10;
123                         *bar_size = 4;
124                         break;
125
126                 case TW_CL_BAR_TYPE_MEM:
127                         *bar_num = 1;
128                         *bar0_offset = 0x8;
129                         *bar_size = 8;
130                         break;
131
132                 case TW_CL_BAR_TYPE_SBUF:
133                         *bar_num = 0;
134                         *bar0_offset = 0;
135                         *bar_size = 8;
136                         break;
137                 }
138                 break;
139
140         default:
141                 error = TW_OSL_ENOTTY;
142                 break;
143         }
144
145         return(error);
146 }
147
148 /*
149  * Function name:       tw_cl_get_mem_requirements
150  * Description:         Provides info about Common Layer requirements for a
151  *                      controller, given the controller type (in 'flags').
152  * Input:               ctlr_handle -- controller handle
153  *                      flags -- more info passed by the OS Layer
154  *                      device_id -- device id of the controller
155  *                      max_simult_reqs -- maximum # of simultaneous
156  *                                      requests that the OS Layer expects
157  *                                      the Common Layer to support
158  *                      max_aens -- maximun # of AEN's needed to be supported
159  * Output:              alignment -- alignment needed for all DMA'able
160  *                                      buffers
161  *                      sg_size_factor -- every SG element should have a size
162  *                                      that's a multiple of this number
163  *                      non_dma_mem_size -- # of bytes of memory needed for
164  *                                      non-DMA purposes
165  *                      dma_mem_size -- # of bytes of DMA'able memory needed
166  *                      per_req_dma_mem_size -- # of bytes of DMA'able memory
167  *                                      needed per request, if applicable
168  *                      per_req_non_dma_mem_size -- # of bytes of memory needed
169  *                                      per request for non-DMA purposes,
170  *                                      if applicable
171  * Output:              None
172  * Return value:        0       -- success
173  *                      non-zero-- failure
174  */
175 TW_INT32
176 tw_cl_get_mem_requirements(struct tw_cl_ctlr_handle *ctlr_handle,
177         TW_UINT32 flags, TW_INT32 device_id, TW_INT32 max_simult_reqs,
178         TW_INT32 max_aens, TW_UINT32 *alignment, TW_UINT32 *sg_size_factor,
179         TW_UINT32 *non_dma_mem_size, TW_UINT32 *dma_mem_size
180         )
181 {
182         if (device_id == 0)
183                 device_id = TW_CL_DEVICE_ID_9K;
184
185         if (max_simult_reqs > TW_CL_MAX_SIMULTANEOUS_REQUESTS) {
186                 tw_cl_create_event(ctlr_handle, TW_CL_FALSE,
187                         TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR,
188                         0x1000, 0x1, TW_CL_SEVERITY_ERROR_STRING,
189                         "Too many simultaneous requests to support!",
190                         "requested = %d, supported = %d, error = %d\n",
191                         max_simult_reqs, TW_CL_MAX_SIMULTANEOUS_REQUESTS,
192                         TW_OSL_EBIG);
193                 return(TW_OSL_EBIG);
194         }
195
196         *alignment = TWA_ALIGNMENT(device_id);
197         *sg_size_factor = TWA_SG_ELEMENT_SIZE_FACTOR(device_id);
198
199         /*
200          * Total non-DMA memory needed is the sum total of memory needed for
201          * the controller context, request packets (including the 1 needed for
202          * CL internal requests), and event packets.
203          */
204
205         *non_dma_mem_size = sizeof(struct tw_cli_ctlr_context) +
206                 (sizeof(struct tw_cli_req_context) * max_simult_reqs) +
207                 (sizeof(struct tw_cl_event_packet) * max_aens);
208
209         /*
210          * Total DMA'able memory needed is the sum total of memory needed for
211          * all command packets (including the 1 needed for CL internal
212          * requests), and memory needed to hold the payload for internal
213          * requests.
214          */
215
216         *dma_mem_size = (sizeof(struct tw_cl_command_packet) *
217                 (max_simult_reqs)) + (TW_CLI_SECTOR_SIZE);
218
219         return(0);
220 }
221
222 /*
223  * Function name:       tw_cl_init_ctlr
224  * Description:         Initializes driver data structures for the controller.
225  *
226  * Input:               ctlr_handle -- controller handle
227  *                      flags -- more info passed by the OS Layer
228  *                      device_id -- device id of the controller
229  *                      max_simult_reqs -- maximum # of simultaneous requests
230  *                                      that the OS Layer expects the Common
231  *                                      Layer to support
232  *                      max_aens -- maximun # of AEN's needed to be supported
233  *                      non_dma_mem -- ptr to allocated non-DMA memory
234  *                      dma_mem -- ptr to allocated DMA'able memory
235  *                      dma_mem_phys -- physical address of dma_mem
236  * Output:              None
237  * Return value:        0       -- success
238  *                      non-zero-- failure
239  */
240 TW_INT32
241 tw_cl_init_ctlr(struct tw_cl_ctlr_handle *ctlr_handle, TW_UINT32 flags,
242         TW_INT32 device_id, TW_INT32 max_simult_reqs, TW_INT32 max_aens,
243         TW_VOID *non_dma_mem, TW_VOID *dma_mem, TW_UINT64 dma_mem_phys
244         )
245 {
246         struct tw_cli_ctlr_context      *ctlr;
247         struct tw_cli_req_context       *req;
248         TW_UINT8                        *free_non_dma_mem;
249         TW_INT32                        error = TW_OSL_ESUCCESS;
250         TW_INT32                        i;
251
252         tw_cli_dbg_printf(3, ctlr_handle, tw_osl_cur_func(), "entered");
253
254         if (flags & TW_CL_START_CTLR_ONLY) {
255                 ctlr = (struct tw_cli_ctlr_context *)
256                         (ctlr_handle->cl_ctlr_ctxt);
257                 goto start_ctlr;
258         }
259
260         if (max_simult_reqs > TW_CL_MAX_SIMULTANEOUS_REQUESTS) {
261                 tw_cl_create_event(ctlr_handle, TW_CL_FALSE,
262                         TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR,
263                         0x1000, 0x1, TW_CL_SEVERITY_ERROR_STRING,
264                         "Too many simultaneous requests to support!",
265                         "requested = %d, supported = %d, error = %d\n",
266                         max_simult_reqs, TW_CL_MAX_SIMULTANEOUS_REQUESTS,
267                         TW_OSL_EBIG);
268                 return(TW_OSL_EBIG);
269         }
270
271         if ((non_dma_mem == TW_CL_NULL) || (dma_mem == TW_CL_NULL)
272                 ) {
273                 tw_cl_create_event(ctlr_handle, TW_CL_FALSE,
274                         TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR,
275                         0x1001, 0x1, TW_CL_SEVERITY_ERROR_STRING,
276                         "Insufficient memory for Common Layer's internal usage",
277                         "error = %d\n", TW_OSL_ENOMEM);
278                 return(TW_OSL_ENOMEM);
279         }
280
281         tw_osl_memzero(non_dma_mem, sizeof(struct tw_cli_ctlr_context) +
282                 (sizeof(struct tw_cli_req_context) * max_simult_reqs) +
283                 (sizeof(struct tw_cl_event_packet) * max_aens));
284
285         tw_osl_memzero(dma_mem,
286                 (sizeof(struct tw_cl_command_packet) *
287                 max_simult_reqs) +
288                 TW_CLI_SECTOR_SIZE);
289
290         free_non_dma_mem = (TW_UINT8 *)non_dma_mem;
291
292         ctlr = (struct tw_cli_ctlr_context *)free_non_dma_mem;
293         free_non_dma_mem += sizeof(struct tw_cli_ctlr_context);
294
295         ctlr_handle->cl_ctlr_ctxt = ctlr;
296         ctlr->ctlr_handle = ctlr_handle;
297
298         ctlr->device_id = (TW_UINT32)device_id;
299         ctlr->arch_id = TWA_ARCH_ID(device_id);
300         ctlr->flags = flags;
301         ctlr->sg_size_factor = TWA_SG_ELEMENT_SIZE_FACTOR(device_id);
302         ctlr->max_simult_reqs = max_simult_reqs;
303         ctlr->max_aens_supported = max_aens;
304
305         /* Initialize queues of CL internal request context packets. */
306         tw_cli_req_q_init(ctlr, TW_CLI_FREE_Q);
307         tw_cli_req_q_init(ctlr, TW_CLI_BUSY_Q);
308         tw_cli_req_q_init(ctlr, TW_CLI_PENDING_Q);
309         tw_cli_req_q_init(ctlr, TW_CLI_COMPLETE_Q);
310         tw_cli_req_q_init(ctlr, TW_CLI_RESET_Q);
311
312         /* Initialize all locks used by CL. */
313         ctlr->gen_lock = &(ctlr->gen_lock_handle);
314         tw_osl_init_lock(ctlr_handle, "tw_cl_gen_lock", ctlr->gen_lock);
315         ctlr->io_lock = &(ctlr->io_lock_handle);
316         tw_osl_init_lock(ctlr_handle, "tw_cl_io_lock", ctlr->io_lock);
317
318         /* Initialize CL internal request context packets. */
319         ctlr->req_ctxt_buf = (struct tw_cli_req_context *)free_non_dma_mem;
320         free_non_dma_mem += (sizeof(struct tw_cli_req_context) *
321                 max_simult_reqs);
322
323         ctlr->cmd_pkt_buf = (struct tw_cl_command_packet *)dma_mem;
324         ctlr->cmd_pkt_phys = dma_mem_phys;
325
326         ctlr->internal_req_data = (TW_UINT8 *)
327                 (ctlr->cmd_pkt_buf +
328                 max_simult_reqs);
329         ctlr->internal_req_data_phys = ctlr->cmd_pkt_phys +
330                 (sizeof(struct tw_cl_command_packet) *
331                 max_simult_reqs);
332
333         for (i = 0; i < max_simult_reqs; i++) {
334                 req = &(ctlr->req_ctxt_buf[i]);
335
336                 req->cmd_pkt = &(ctlr->cmd_pkt_buf[i]);
337                 req->cmd_pkt_phys = ctlr->cmd_pkt_phys +
338                         (i * sizeof(struct tw_cl_command_packet));
339
340                 req->request_id = i;
341                 req->ctlr = ctlr;
342
343                 /* Insert request into the free queue. */
344                 tw_cli_req_q_insert_tail(req, TW_CLI_FREE_Q);
345         }
346
347         /* Initialize the AEN queue. */
348         ctlr->aen_queue = (struct tw_cl_event_packet *)free_non_dma_mem;
349
350 start_ctlr:
351         /*
352          * Disable interrupts.  Interrupts will be enabled in tw_cli_start_ctlr
353          * (only) if initialization succeeded.
354          */
355         tw_cli_disable_interrupts(ctlr);
356
357         /* Initialize the controller. */
358         if ((error = tw_cli_start_ctlr(ctlr))) {
359                 /* Soft reset the controller, and try one more time. */
360                 tw_cl_create_event(ctlr_handle, TW_CL_FALSE,
361                         TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR,
362                         0x1002, 0x1, TW_CL_SEVERITY_ERROR_STRING,
363                         "Controller initialization failed. Retrying...",
364                         "error = %d\n", error);
365                 if ((error = tw_cli_soft_reset(ctlr))) {
366                         tw_cl_create_event(ctlr_handle, TW_CL_FALSE,
367                                 TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR,
368                                 0x1003, 0x1, TW_CL_SEVERITY_ERROR_STRING,
369                                 "Controller soft reset failed",
370                                 "error = %d\n", error);
371                         return(error);
372                 } else if ((error = tw_cli_start_ctlr(ctlr))) {
373                         tw_cl_create_event(ctlr_handle, TW_CL_FALSE,
374                                 TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR,
375                                 0x1004, 0x1, TW_CL_SEVERITY_ERROR_STRING,
376                                 "Controller initialization retry failed",
377                                 "error = %d\n", error);
378                         return(error);
379                 }
380         }
381         /* Notify some info about the controller to the OSL. */
382         tw_cli_notify_ctlr_info(ctlr);
383
384         /* Mark the controller active. */
385         ctlr->active = TW_CL_TRUE;
386         return(error);
387 }
388
389 /*
390  * Function name:       tw_cli_start_ctlr
391  * Description:         Establishes a logical connection with the controller.
392  *                      Determines whether or not the driver is compatible 
393  *                      with the firmware on the controller, before proceeding
394  *                      to work with it.
395  *
396  * Input:               ctlr    -- ptr to per ctlr structure
397  * Output:              None
398  * Return value:        0       -- success
399  *                      non-zero-- failure
400  */
401 TW_INT32
402 tw_cli_start_ctlr(struct tw_cli_ctlr_context *ctlr)
403 {
404         TW_UINT16       fw_on_ctlr_srl = 0;
405         TW_UINT16       fw_on_ctlr_arch_id = 0;
406         TW_UINT16       fw_on_ctlr_branch = 0;
407         TW_UINT16       fw_on_ctlr_build = 0;
408         TW_UINT32       init_connect_result = 0;
409         TW_INT32        error = TW_OSL_ESUCCESS;
410
411         tw_cli_dbg_printf(3, ctlr->ctlr_handle, tw_osl_cur_func(), "entered");
412
413         /* Wait for the controller to become ready. */
414         if ((error = tw_cli_poll_status(ctlr,
415                         TWA_STATUS_MICROCONTROLLER_READY,
416                         TW_CLI_REQUEST_TIMEOUT_PERIOD))) {
417                 tw_cl_create_event(ctlr->ctlr_handle, TW_CL_FALSE,
418                         TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR,
419                         0x1009, 0x1, TW_CL_SEVERITY_ERROR_STRING,
420                         "Microcontroller not ready",
421                         "error = %d", error);
422                 return(error);
423         }
424         /* Drain the response queue. */
425         if ((error = tw_cli_drain_response_queue(ctlr))) {
426                 tw_cl_create_event(ctlr->ctlr_handle, TW_CL_FALSE,
427                         TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR,
428                         0x100A, 0x1, TW_CL_SEVERITY_ERROR_STRING,
429                         "Can't drain response queue",
430                         "error = %d", error);
431                 return(error);
432         }
433         /* Establish a logical connection with the controller. */
434         if ((error = tw_cli_init_connection(ctlr,
435                         (TW_UINT16)(ctlr->max_simult_reqs),
436                         TWA_EXTENDED_INIT_CONNECT, TWA_CURRENT_FW_SRL,
437                         (TW_UINT16)(ctlr->arch_id),
438                         TWA_CURRENT_FW_BRANCH(ctlr->arch_id),
439                         TWA_CURRENT_FW_BUILD(ctlr->arch_id),
440                         &fw_on_ctlr_srl, &fw_on_ctlr_arch_id,
441                         &fw_on_ctlr_branch, &fw_on_ctlr_build,
442                         &init_connect_result))) {
443                 tw_cl_create_event(ctlr->ctlr_handle, TW_CL_FALSE,
444                         TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR,
445                         0x100B, 0x2, TW_CL_SEVERITY_WARNING_STRING,
446                         "Can't initialize connection in current mode",
447                         "error = %d", error);
448                 return(error);
449         }
450         {
451                  /* See if we can at least work with the firmware on the
452                  * controller in the current mode.
453                  */
454                 if (init_connect_result & TWA_CTLR_FW_COMPATIBLE) {
455                         /* Yes, we can.  Make note of the operating mode. */
456                         if (init_connect_result & TWA_CTLR_FW_SAME_OR_NEWER) {
457                                 ctlr->working_srl = TWA_CURRENT_FW_SRL;
458                                 ctlr->working_branch =
459                                         TWA_CURRENT_FW_BRANCH(ctlr->arch_id);
460                                 ctlr->working_build =
461                                         TWA_CURRENT_FW_BUILD(ctlr->arch_id);
462                         } else {
463                                 ctlr->working_srl = fw_on_ctlr_srl;
464                                 ctlr->working_branch = fw_on_ctlr_branch;
465                                 ctlr->working_build = fw_on_ctlr_build;
466                         }
467                 } else {
468                         /*
469                          * No, we can't.  See if we can at least work with
470                          * it in the base mode.
471                          */
472                         tw_cl_create_event(ctlr->ctlr_handle, TW_CL_FALSE,
473                                 TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR,
474                                 0x1010, 0x2, TW_CL_SEVERITY_WARNING_STRING,
475                                 "Driver/Firmware mismatch. "
476                                 "Negotiating for base level...",
477                                 " ");
478                         if ((error = tw_cli_init_connection(ctlr,
479                                         (TW_UINT16)(ctlr->max_simult_reqs),
480                                         TWA_EXTENDED_INIT_CONNECT,
481                                         TWA_BASE_FW_SRL,
482                                         (TW_UINT16)(ctlr->arch_id),
483                                         TWA_BASE_FW_BRANCH, TWA_BASE_FW_BUILD,
484                                         &fw_on_ctlr_srl, &fw_on_ctlr_arch_id,
485                                         &fw_on_ctlr_branch, &fw_on_ctlr_build,
486                                         &init_connect_result))) {
487                                 tw_cl_create_event(ctlr->ctlr_handle,
488                                         TW_CL_FALSE,
489                                         TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR,
490                                         0x1011, 0x1,
491                                         TW_CL_SEVERITY_ERROR_STRING,
492                                         "Can't initialize connection in "
493                                         "base mode",
494                                         " ");
495                                 return(error);
496                         }
497                         if (!(init_connect_result & TWA_CTLR_FW_COMPATIBLE)) {
498                                 /*
499                                  * The firmware on the controller is not even
500                                  * compatible with our base mode.  We cannot
501                                  * work with it.  Bail...
502                                  */
503                                 return(1);
504                         }
505                         /*
506                          * We can work with this firmware, but only in
507                          * base mode.
508                          */
509                         ctlr->working_srl = TWA_BASE_FW_SRL;
510                         ctlr->working_branch = TWA_BASE_FW_BRANCH;
511                         ctlr->working_build = TWA_BASE_FW_BUILD;
512                         ctlr->operating_mode = TWA_BASE_MODE;
513                 }
514                 ctlr->fw_on_ctlr_srl = fw_on_ctlr_srl;
515                 ctlr->fw_on_ctlr_branch = fw_on_ctlr_branch;
516                 ctlr->fw_on_ctlr_build = fw_on_ctlr_build;
517         }
518
519         /* Drain the AEN queue */
520         if ((error = tw_cli_drain_aen_queue(ctlr)))
521                 /* 
522                  * We will just print that we couldn't drain the AEN queue.
523                  * There's no need to bail out.
524                  */
525                 tw_cl_create_event(ctlr->ctlr_handle, TW_CL_FALSE,
526                         TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR,
527                         0x1014, 0x2, TW_CL_SEVERITY_WARNING_STRING,
528                         "Can't drain AEN queue",
529                         "error = %d", error);
530
531         /* Enable interrupts. */
532         tw_cli_enable_interrupts(ctlr);
533
534         return(TW_OSL_ESUCCESS);
535 }
536
537 /*
538  * Function name:       tw_cl_shutdown_ctlr
539  * Description:         Closes logical connection with the controller.
540  *
541  * Input:               ctlr    -- ptr to per ctlr structure
542  *                      flags   -- more info passed by the OS Layer
543  * Output:              None
544  * Return value:        0       -- success
545  *                      non-zero-- failure
546  */
547 TW_INT32
548 tw_cl_shutdown_ctlr(struct tw_cl_ctlr_handle *ctlr_handle, TW_UINT32 flags)
549 {
550         struct tw_cli_ctlr_context      *ctlr =
551                 (struct tw_cli_ctlr_context *)(ctlr_handle->cl_ctlr_ctxt);
552         TW_INT32                        error;
553
554         tw_cli_dbg_printf(3, ctlr_handle, tw_osl_cur_func(), "entered");
555         /*
556          * Mark the controller as inactive, disable any further interrupts,
557          * and notify the controller that we are going down.
558          */
559         ctlr->active = TW_CL_FALSE;
560
561         tw_cli_disable_interrupts(ctlr);
562
563         /* Let the controller know that we are going down. */
564         if ((error = tw_cli_init_connection(ctlr, TWA_SHUTDOWN_MESSAGE_CREDITS,
565                         0, 0, 0, 0, 0, TW_CL_NULL, TW_CL_NULL, TW_CL_NULL,
566                         TW_CL_NULL, TW_CL_NULL)))
567                 tw_cl_create_event(ctlr_handle, TW_CL_FALSE,
568                         TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR,
569                         0x1015, 0x1, TW_CL_SEVERITY_ERROR_STRING,
570                         "Can't close connection with controller",
571                         "error = %d", error);
572
573         if (flags & TW_CL_STOP_CTLR_ONLY)
574                 goto ret;
575
576         /* Destroy all locks used by CL. */
577         tw_osl_destroy_lock(ctlr_handle, ctlr->gen_lock);
578         tw_osl_destroy_lock(ctlr_handle, ctlr->io_lock);
579
580 ret:
581         return(error);
582 }
583
584 /*
585  * Function name:       tw_cli_init_connection
586  * Description:         Sends init_connection cmd to firmware
587  *
588  * Input:               ctlr            -- ptr to per ctlr structure
589  *                      message_credits -- max # of requests that we might send
590  *                                       down simultaneously.  This will be
591  *                                       typically set to 256 at init-time or
592  *                                      after a reset, and to 1 at shutdown-time
593  *                      set_features    -- indicates if we intend to use 64-bit
594  *                                      sg, also indicates if we want to do a
595  *                                      basic or an extended init_connection;
596  *
597  * Note: The following input/output parameters are valid, only in case of an
598  *              extended init_connection:
599  *
600  *                      current_fw_srl          -- srl of fw we are bundled
601  *                                              with, if any; 0 otherwise
602  *                      current_fw_arch_id      -- arch_id of fw we are bundled
603  *                                              with, if any; 0 otherwise
604  *                      current_fw_branch       -- branch # of fw we are bundled
605  *                                              with, if any; 0 otherwise
606  *                      current_fw_build        -- build # of fw we are bundled
607  *                                              with, if any; 0 otherwise
608  * Output:              fw_on_ctlr_srl          -- srl of fw on ctlr
609  *                      fw_on_ctlr_arch_id      -- arch_id of fw on ctlr
610  *                      fw_on_ctlr_branch       -- branch # of fw on ctlr
611  *                      fw_on_ctlr_build        -- build # of fw on ctlr
612  *                      init_connect_result     -- result bitmap of fw response
613  * Return value:        0       -- success
614  *                      non-zero-- failure
615  */
616 TW_INT32
617 tw_cli_init_connection(struct tw_cli_ctlr_context *ctlr,
618         TW_UINT16 message_credits, TW_UINT32 set_features,
619         TW_UINT16 current_fw_srl, TW_UINT16 current_fw_arch_id,
620         TW_UINT16 current_fw_branch, TW_UINT16 current_fw_build,
621         TW_UINT16 *fw_on_ctlr_srl, TW_UINT16 *fw_on_ctlr_arch_id,
622         TW_UINT16 *fw_on_ctlr_branch, TW_UINT16 *fw_on_ctlr_build,
623         TW_UINT32 *init_connect_result)
624 {
625         struct tw_cli_req_context               *req;
626         struct tw_cl_command_init_connect       *init_connect;
627         TW_INT32                                error = TW_OSL_EBUSY;
628     
629         tw_cli_dbg_printf(3, ctlr->ctlr_handle, tw_osl_cur_func(), "entered");
630
631         /* Get a request packet. */
632         if ((req = tw_cli_get_request(ctlr
633                 )) == TW_CL_NULL)
634                 goto out;
635
636         req->flags |= TW_CLI_REQ_FLAGS_INTERNAL;
637
638         /* Build the cmd pkt. */
639         init_connect = &(req->cmd_pkt->command.cmd_pkt_7k.init_connect);
640
641         req->cmd_pkt->cmd_hdr.header_desc.size_header = 128;
642
643         init_connect->res1__opcode =
644                 BUILD_RES__OPCODE(0, TWA_FW_CMD_INIT_CONNECTION);
645         init_connect->request_id =
646                 (TW_UINT8)(TW_CL_SWAP16(req->request_id));
647         init_connect->message_credits = TW_CL_SWAP16(message_credits);
648         init_connect->features = TW_CL_SWAP32(set_features);
649         if (ctlr->flags & TW_CL_64BIT_ADDRESSES)
650                 init_connect->features |= TW_CL_SWAP32(TWA_64BIT_SG_ADDRESSES);
651         if (set_features & TWA_EXTENDED_INIT_CONNECT) {
652                 /*
653                  * Fill in the extra fields needed for an extended
654                  * init_connect.
655                  */
656                 init_connect->size = 6;
657                 init_connect->fw_srl = TW_CL_SWAP16(current_fw_srl);
658                 init_connect->fw_arch_id = TW_CL_SWAP16(current_fw_arch_id);
659                 init_connect->fw_branch = TW_CL_SWAP16(current_fw_branch);
660                 init_connect->fw_build = TW_CL_SWAP16(current_fw_build);
661         } else
662                 init_connect->size = 3;
663
664         /* Submit the command, and wait for it to complete. */
665         error = tw_cli_submit_and_poll_request(req,
666                 TW_CLI_REQUEST_TIMEOUT_PERIOD);
667         if (error)
668                 goto out;
669         if ((error = init_connect->status)) {
670 #if       0
671                 tw_cli_create_ctlr_event(ctlr,
672                         TW_CL_MESSAGE_SOURCE_CONTROLLER_ERROR,
673                         &(req->cmd_pkt->cmd_hdr));
674 #endif // 0
675                 goto out;
676         }
677         if (set_features & TWA_EXTENDED_INIT_CONNECT) {
678                 *fw_on_ctlr_srl = TW_CL_SWAP16(init_connect->fw_srl);
679                 *fw_on_ctlr_arch_id = TW_CL_SWAP16(init_connect->fw_arch_id);
680                 *fw_on_ctlr_branch = TW_CL_SWAP16(init_connect->fw_branch);
681                 *fw_on_ctlr_build = TW_CL_SWAP16(init_connect->fw_build);
682                 *init_connect_result = TW_CL_SWAP32(init_connect->result);
683         }
684         tw_cli_req_q_insert_tail(req, TW_CLI_FREE_Q);
685         return(error);
686
687 out:
688         tw_cl_create_event(ctlr->ctlr_handle, TW_CL_FALSE,
689                 TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR,
690                 0x1016, 0x1, TW_CL_SEVERITY_ERROR_STRING,
691                 "init_connection failed",
692                 "error = %d", error);
693         if (req)
694                 tw_cli_req_q_insert_tail(req, TW_CLI_FREE_Q);
695         return(error);
696 }