Deleted Added
full compact
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: head/sys/dev/twa/tw_cl_init.c 169400 2007-05-09 04:16:32Z scottl $
27 * $FreeBSD: head/sys/dev/twa/tw_cl_init.c 172496 2007-10-09 17:43:57Z scottl $
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 */
63TW_INT32
64tw_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) ||
68 (device_id == TW_CL_DEVICE_ID_9K_E)))
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 */
90TW_INT32
91tw_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 */
180TW_INT32
181tw_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 */
248TW_INT32
249tw_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) ||
335 (ctlr->device_id == TW_CL_DEVICE_ID_9K_E))) {
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
390start_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 */
441TW_INT32
442tw_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 */
588TW_INT32
589tw_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
623ret:
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 */
661TW_INT32
662tw_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 |= 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
733out:
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