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