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