2 * Copyright (c) 2004-07 Applied Micro Circuits Corporation.
3 * Copyright (c) 2004-05 Vinod Kashyap
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
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.
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
27 * $FreeBSD: head/sys/dev/twa/tw_cl_intr.c 212008 2010-08-30 19:15:04Z delphij $
31 * AMCC'S 3ware driver for 9000 series storage controllers.
33 * Author: Vinod Kashyap
34 * Modifications by: Adam Radford
35 * Modifications by: Manjunath Ranganathaiah
40 * Common Layer interrupt handling functions.
44 #include "tw_osl_share.h"
45 #include "tw_cl_share.h"
46 #include "tw_cl_fwif.h"
47 #include "tw_cl_ioctl.h"
49 #include "tw_cl_externs.h"
50 #include "tw_osl_ioctl.h"
55 * Function name: twa_interrupt
56 * Description: Interrupt handler. Determines the kind of interrupt,
57 * and returns TW_CL_TRUE if it recognizes the interrupt.
59 * Input: ctlr_handle -- controller handle
61 * Return value: TW_CL_TRUE -- interrupt recognized
62 * TW_CL_FALSE-- interrupt not recognized
65 tw_cl_interrupt(struct tw_cl_ctlr_handle
*ctlr_handle
)
67 struct tw_cli_ctlr_context
*ctlr
=
68 (struct tw_cli_ctlr_context
*)(ctlr_handle
->cl_ctlr_ctxt
);
70 TW_INT32 rc
= TW_CL_FALSE
;
72 tw_cli_dbg_printf(10, ctlr_handle
, tw_osl_cur_func(), "entered");
74 /* If we don't have controller context, bail */
79 * Bail If we get an interrupt while resetting, or shutting down.
81 if (ctlr
->reset_in_progress
|| !(ctlr
->active
))
84 /* Read the status register to determine the type of interrupt. */
85 status_reg
= TW_CLI_READ_STATUS_REGISTER(ctlr_handle
);
86 if (tw_cli_check_ctlr_state(ctlr
, status_reg
))
89 /* Clear the interrupt. */
90 if (status_reg
& TWA_STATUS_HOST_INTERRUPT
) {
91 tw_cli_dbg_printf(6, ctlr_handle
, tw_osl_cur_func(),
93 TW_CLI_WRITE_CONTROL_REGISTER(ctlr_handle
,
94 TWA_CONTROL_CLEAR_HOST_INTERRUPT
);
96 if (status_reg
& TWA_STATUS_ATTENTION_INTERRUPT
) {
97 tw_cli_dbg_printf(6, ctlr_handle
, tw_osl_cur_func(),
98 "Attention interrupt");
99 rc
|= TW_CL_TRUE
; /* request for a deferred isr call */
100 tw_cli_process_attn_intr(ctlr
);
101 TW_CLI_WRITE_CONTROL_REGISTER(ctlr_handle
,
102 TWA_CONTROL_CLEAR_ATTENTION_INTERRUPT
);
104 if (status_reg
& TWA_STATUS_COMMAND_INTERRUPT
) {
105 tw_cli_dbg_printf(6, ctlr_handle
, tw_osl_cur_func(),
106 "Command interrupt");
107 rc
|= TW_CL_TRUE
; /* request for a deferred isr call */
108 tw_cli_process_cmd_intr(ctlr
);
109 if ((TW_CL_Q_FIRST_ITEM(&(ctlr
->req_q_head
[TW_CLI_PENDING_Q
]))) == TW_CL_NULL
)
110 TW_CLI_WRITE_CONTROL_REGISTER(ctlr_handle
,
111 TWA_CONTROL_MASK_COMMAND_INTERRUPT
);
113 if (status_reg
& TWA_STATUS_RESPONSE_INTERRUPT
) {
114 tw_cli_dbg_printf(10, ctlr_handle
, tw_osl_cur_func(),
115 "Response interrupt");
116 rc
|= TW_CL_TRUE
; /* request for a deferred isr call */
117 tw_cli_process_resp_intr(ctlr
);
126 * Function name: tw_cli_process_host_intr
127 * Description: This function gets called if we triggered an interrupt.
128 * We don't use it as of now.
130 * Input: ctlr -- ptr to CL internal ctlr context
135 tw_cli_process_host_intr(struct tw_cli_ctlr_context
*ctlr
)
137 tw_cli_dbg_printf(6, ctlr
->ctlr_handle
, tw_osl_cur_func(), "entered");
143 * Function name: tw_cli_process_attn_intr
144 * Description: This function gets called if the fw posted an AEN
145 * (Asynchronous Event Notification). It fetches
146 * all the AEN's that the fw might have posted.
148 * Input: ctlr -- ptr to CL internal ctlr context
153 tw_cli_process_attn_intr(struct tw_cli_ctlr_context
*ctlr
)
157 tw_cli_dbg_printf(6, ctlr
->ctlr_handle
, tw_osl_cur_func(), "entered");
159 if ((error
= tw_cli_get_aen(ctlr
))) {
161 * If the driver is already in the process of retrieveing AEN's,
162 * we will be returned TW_OSL_EBUSY. In this case,
163 * tw_cli_param_callback or tw_cli_aen_callback will eventually
164 * retrieve the AEN this attention interrupt is for. So, we
165 * don't need to print the failure.
167 if (error
!= TW_OSL_EBUSY
)
168 tw_cl_create_event(ctlr
->ctlr_handle
, TW_CL_FALSE
,
169 TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR
,
170 0x1200, 0x1, TW_CL_SEVERITY_ERROR_STRING
,
171 "Failed to fetch AEN",
172 "error = %d", error
);
179 * Function name: tw_cli_process_cmd_intr
180 * Description: This function gets called if we hit a queue full
181 * condition earlier, and the fw is now ready for
182 * new cmds. Submits any pending requests.
184 * Input: ctlr -- ptr to CL internal ctlr context
189 tw_cli_process_cmd_intr(struct tw_cli_ctlr_context
*ctlr
)
191 tw_cli_dbg_printf(6, ctlr
->ctlr_handle
, tw_osl_cur_func(), "entered");
193 /* Start any requests that might be in the pending queue. */
194 tw_cli_submit_pending_queue(ctlr
);
197 * If tw_cli_submit_pending_queue was unsuccessful due to a "cmd queue
198 * full" condition, cmd_intr will already have been unmasked by
199 * tw_cli_submit_cmd. We don't need to do it again... simply return.
206 * Function name: tw_cli_process_resp_intr
207 * Description: Looks for cmd completions from fw; queues cmds completed
208 * by fw into complete queue.
210 * Input: ctlr -- ptr to CL internal ctlr context
212 * Return value: 0 -- no ctlr error
213 * non-zero-- ctlr error
216 tw_cli_process_resp_intr(struct tw_cli_ctlr_context
*ctlr
)
219 struct tw_cli_req_context
*req
;
221 TW_UINT32 status_reg
;
223 tw_cli_dbg_printf(10, ctlr
->ctlr_handle
, tw_osl_cur_func(), "entered");
226 status_reg
= TW_CLI_READ_STATUS_REGISTER(ctlr
->ctlr_handle
);
227 if ((error
= tw_cli_check_ctlr_state(ctlr
, status_reg
)))
229 if (status_reg
& TWA_STATUS_RESPONSE_QUEUE_EMPTY
) {
230 tw_cli_dbg_printf(7, ctlr
->ctlr_handle
,
231 tw_osl_cur_func(), "Response queue empty");
235 /* Response queue is not empty. */
236 resp
= TW_CLI_READ_RESPONSE_QUEUE(ctlr
->ctlr_handle
);
238 req
= &(ctlr
->req_ctxt_buf
[GET_RESP_ID(resp
)]);
241 if (req
->state
!= TW_CLI_REQ_STATE_BUSY
) {
242 tw_cl_create_event(ctlr
->ctlr_handle
, TW_CL_FALSE
,
243 TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR
,
244 0x1201, 0x1, TW_CL_SEVERITY_ERROR_STRING
,
245 "Unposted command completed!!",
246 "request = %p, status = %d",
249 tw_cl_print_ctlr_stats(ctlr
->ctlr_handle
);
250 #endif /* TW_OSL_DEBUG */
255 * Remove the request from the busy queue, mark it as complete,
256 * and enqueue it in the complete queue.
258 tw_cli_req_q_remove_item(req
, TW_CLI_BUSY_Q
);
259 req
->state
= TW_CLI_REQ_STATE_COMPLETE
;
260 tw_cli_req_q_insert_tail(req
, TW_CLI_COMPLETE_Q
);
264 /* Complete this, and other requests in the complete queue. */
265 tw_cli_process_complete_queue(ctlr
);
273 * Function name: tw_cli_submit_pending_queue
274 * Description: Kick starts any requests in the pending queue.
276 * Input: ctlr -- ptr to CL internal ctlr context
278 * Return value: 0 -- all pending requests submitted successfully
279 * non-zero-- otherwise
282 tw_cli_submit_pending_queue(struct tw_cli_ctlr_context
*ctlr
)
284 struct tw_cli_req_context
*req
;
285 TW_INT32 error
= TW_OSL_ESUCCESS
;
287 tw_cli_dbg_printf(3, ctlr
->ctlr_handle
, tw_osl_cur_func(), "entered");
290 * Pull requests off the pending queue, and submit them.
292 while ((req
= tw_cli_req_q_remove_head(ctlr
, TW_CLI_PENDING_Q
)) !=
294 if ((error
= tw_cli_submit_cmd(req
))) {
295 if (error
== TW_OSL_EBUSY
) {
296 tw_cli_dbg_printf(2, ctlr
->ctlr_handle
,
298 "Requeueing pending request");
299 req
->state
= TW_CLI_REQ_STATE_PENDING
;
301 * Queue the request at the head of the pending
302 * queue, and break away, so we don't try to
303 * submit any more requests.
305 tw_cli_req_q_insert_head(req
, TW_CLI_PENDING_Q
);
308 tw_cl_create_event(ctlr
->ctlr_handle
,
310 TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR
,
312 TW_CL_SEVERITY_ERROR_STRING
,
313 "Could not start request "
315 "request = %p, opcode = 0x%x, "
317 GET_OPCODE(req
->cmd_pkt
->
318 command
.cmd_pkt_9k
.res__opcode
),
321 * Set the appropriate error and call the CL
322 * internal callback if there's one. If the
323 * request originator is polling for completion,
324 * he should be checking req->error to
325 * determine that the request did not go
326 * through. The request originators are
327 * responsible for the clean-up.
329 req
->error_code
= error
;
330 req
->state
= TW_CLI_REQ_STATE_COMPLETE
;
331 if (req
->tw_cli_callback
)
332 req
->tw_cli_callback(req
);
333 error
= TW_OSL_ESUCCESS
;
343 * Function name: tw_cli_process_complete_queue
344 * Description: Calls the CL internal callback routine, if any, for
345 * each request in the complete queue.
347 * Input: ctlr -- ptr to CL internal ctlr context
352 tw_cli_process_complete_queue(struct tw_cli_ctlr_context
*ctlr
)
354 struct tw_cli_req_context
*req
;
356 tw_cli_dbg_printf(10, ctlr
->ctlr_handle
, tw_osl_cur_func(), "entered");
359 * Pull commands off the completed list, dispatch them appropriately.
361 while ((req
= tw_cli_req_q_remove_head(ctlr
, TW_CLI_COMPLETE_Q
)) !=
363 /* Call the CL internal callback, if there's one. */
364 if (req
->tw_cli_callback
)
365 req
->tw_cli_callback(req
);
372 * Function name: tw_cli_complete_io
373 * Description: CL internal callback for SCSI/fw passthru requests.
375 * Input: req -- ptr to CL internal request context
380 tw_cli_complete_io(struct tw_cli_req_context
*req
)
382 struct tw_cli_ctlr_context
*ctlr
= req
->ctlr
;
383 struct tw_cl_req_packet
*req_pkt
=
384 (struct tw_cl_req_packet
*)(req
->orig_req
);
386 tw_cli_dbg_printf(8, ctlr
->ctlr_handle
, tw_osl_cur_func(), "entered");
388 req_pkt
->status
= TW_CL_ERR_REQ_SUCCESS
;
389 if (req
->error_code
) {
390 req_pkt
->status
= TW_CL_ERR_REQ_UNABLE_TO_SUBMIT_COMMAND
;
394 if (req
->state
!= TW_CLI_REQ_STATE_COMPLETE
) {
395 tw_cl_create_event(ctlr
->ctlr_handle
, TW_CL_FALSE
,
396 TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR
,
397 0x1203, 0x1, TW_CL_SEVERITY_ERROR_STRING
,
398 "I/O completion on incomplete command!!",
399 "request = %p, status = %d",
402 tw_cl_print_ctlr_stats(ctlr
->ctlr_handle
);
403 #endif /* TW_OSL_DEBUG */
407 if (req
->flags
& TW_CLI_REQ_FLAGS_PASSTHRU
) {
408 /* Copy the command packet back into OSL's space. */
409 tw_osl_memcpy(req_pkt
->gen_req_pkt
.pt_req
.cmd_pkt
, req
->cmd_pkt
,
410 sizeof(struct tw_cl_command_packet
));
412 tw_cli_scsi_complete(req
);
415 req_pkt
->tw_osl_callback(req
->req_handle
);
416 tw_cli_req_q_insert_tail(req
, TW_CLI_FREE_Q
);
422 * Function name: tw_cli_scsi_complete
423 * Description: Completion routine for SCSI requests.
425 * Input: req -- ptr to CL internal request context
430 tw_cli_scsi_complete(struct tw_cli_req_context
*req
)
432 struct tw_cl_req_packet
*req_pkt
=
433 (struct tw_cl_req_packet
*)(req
->orig_req
);
434 struct tw_cl_scsi_req_packet
*scsi_req
=
435 &(req_pkt
->gen_req_pkt
.scsi_req
);
436 struct tw_cl_command_9k
*cmd
=
437 &(req
->cmd_pkt
->command
.cmd_pkt_9k
);
438 struct tw_cl_command_header
*cmd_hdr
;
442 tw_cli_dbg_printf(8, req
->ctlr
->ctlr_handle
, tw_osl_cur_func(),
445 scsi_req
->scsi_status
= cmd
->status
;
449 tw_cli_dbg_printf(1, req
->ctlr
->ctlr_handle
, tw_osl_cur_func(),
450 "req_id = 0x%x, status = 0x%x",
451 GET_REQ_ID(cmd
->lun_l4__req_id
), cmd
->status
);
453 cmd_hdr
= &(req
->cmd_pkt
->cmd_hdr
);
454 error
= cmd_hdr
->status_block
.error
;
455 if ((error
== TWA_ERROR_LOGICAL_UNIT_NOT_SUPPORTED
) ||
456 (error
== TWA_ERROR_UNIT_OFFLINE
)) {
457 if (GET_LUN_L4(cmd
->lun_l4__req_id
))
458 req_pkt
->status
|= TW_CL_ERR_REQ_INVALID_LUN
;
460 req_pkt
->status
|= TW_CL_ERR_REQ_INVALID_TARGET
;
462 tw_cli_dbg_printf(2, req
->ctlr
->ctlr_handle
,
464 "cmd = %x %x %x %x %x %x %x",
465 GET_OPCODE(cmd
->res__opcode
),
466 GET_SGL_OFF(cmd
->res__opcode
),
471 cmd
->lun_h4__sgl_entries
);
473 cdb
= (TW_UINT8
*)(cmd
->cdb
);
474 tw_cli_dbg_printf(2, req
->ctlr
->ctlr_handle
,
476 "cdb = %x %x %x %x %x %x %x %x "
477 "%x %x %x %x %x %x %x %x",
478 cdb
[0], cdb
[1], cdb
[2], cdb
[3],
479 cdb
[4], cdb
[5], cdb
[6], cdb
[7],
480 cdb
[8], cdb
[9], cdb
[10], cdb
[11],
481 cdb
[12], cdb
[13], cdb
[14], cdb
[15]);
485 * Print the error. Firmware doesn't yet support
486 * the 'Mode Sense' cmd. Don't print if the cmd
487 * is 'Mode Sense', and the error is 'Invalid field
490 if (! ((cdb
[0] == 0x1A) && (error
== 0x10D)))
491 tw_cli_create_ctlr_event(req
->ctlr
,
492 TW_CL_MESSAGE_SOURCE_CONTROLLER_ERROR
,
497 if (scsi_req
->sense_data
) {
498 tw_osl_memcpy(scsi_req
->sense_data
, cmd_hdr
->sense_data
,
499 TWA_SENSE_DATA_LENGTH
);
500 scsi_req
->sense_len
= TWA_SENSE_DATA_LENGTH
;
501 req_pkt
->status
|= TW_CL_ERR_REQ_AUTO_SENSE_VALID
;
503 req_pkt
->status
|= TW_CL_ERR_REQ_SCSI_ERROR
;
509 * Function name: tw_cli_param_callback
510 * Description: Callback for get/set_param requests.
512 * Input: req -- ptr to completed request pkt
517 tw_cli_param_callback(struct tw_cli_req_context
*req
)
519 struct tw_cli_ctlr_context
*ctlr
= req
->ctlr
;
520 union tw_cl_command_7k
*cmd
=
521 &(req
->cmd_pkt
->command
.cmd_pkt_7k
);
524 tw_cli_dbg_printf(4, ctlr
->ctlr_handle
, tw_osl_cur_func(), "entered");
527 * If the request was never submitted to the controller, the function
528 * that sets req->error is responsible for calling tw_cl_create_event.
530 if (! req
->error_code
)
531 if (cmd
->param
.status
) {
533 tw_cli_create_ctlr_event(ctlr
,
534 TW_CL_MESSAGE_SOURCE_CONTROLLER_ERROR
,
535 &(req
->cmd_pkt
->cmd_hdr
));
537 tw_cl_create_event(ctlr
->ctlr_handle
, TW_CL_FALSE
,
538 TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR
,
539 0x1204, 0x1, TW_CL_SEVERITY_ERROR_STRING
,
540 "get/set_param failed",
541 "status = %d", cmd
->param
.status
);
544 ctlr
->internal_req_busy
= TW_CL_FALSE
;
545 tw_cli_req_q_insert_tail(req
, TW_CLI_FREE_Q
);
547 if ((ctlr
->get_more_aens
) && (!(ctlr
->reset_in_progress
))) {
548 ctlr
->get_more_aens
= TW_CL_FALSE
;
549 tw_cli_dbg_printf(4, ctlr
->ctlr_handle
, tw_osl_cur_func(),
550 "Fetching more AEN's");
551 if ((error
= tw_cli_get_aen(ctlr
)))
552 tw_cl_create_event(ctlr
->ctlr_handle
, TW_CL_FALSE
,
553 TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR
,
554 0x1205, 0x1, TW_CL_SEVERITY_ERROR_STRING
,
555 "Failed to fetch all AEN's from param_callback",
556 "error = %d", error
);
563 * Function name: tw_cli_aen_callback
564 * Description: Callback for requests to fetch AEN's.
566 * Input: req -- ptr to completed request pkt
571 tw_cli_aen_callback(struct tw_cli_req_context
*req
)
573 struct tw_cli_ctlr_context
*ctlr
= req
->ctlr
;
574 struct tw_cl_command_9k
*cmd
=
575 &(req
->cmd_pkt
->command
.cmd_pkt_9k
);
576 TW_UINT16 aen_code
= TWA_AEN_QUEUE_EMPTY
;
579 tw_cli_dbg_printf(4, ctlr
->ctlr_handle
, tw_osl_cur_func(), "entered");
581 tw_cli_dbg_printf(4, ctlr
->ctlr_handle
, tw_osl_cur_func(),
582 "req_id = 0x%x, req error = %d, status = 0x%x",
583 GET_REQ_ID(cmd
->lun_l4__req_id
), req
->error_code
, cmd
->status
);
586 * If the request was never submitted to the controller, the function
587 * that sets error is responsible for calling tw_cl_create_event.
589 if (!(error
= req
->error_code
))
590 if ((error
= cmd
->status
)) {
592 struct tw_cl_command_header
*cmd_hdr
;
593 cmd_hdr
= (struct tw_cl_command_header
*)
594 (&(req
->cmd_pkt
->cmd_hdr
));
595 tw_cli_create_ctlr_event(ctlr
,
596 TW_CL_MESSAGE_SOURCE_CONTROLLER_ERROR
,
599 tw_cl_create_event(ctlr
->ctlr_handle
, TW_CL_FALSE
,
600 TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR
,
601 0x1206, 0x1, TW_CL_SEVERITY_ERROR_STRING
,
602 "Request Sense failed",
603 "opcode = 0x%x, status = %d",
604 GET_OPCODE(cmd
->res__opcode
), cmd
->status
);
608 ctlr
->internal_req_busy
= TW_CL_FALSE
;
609 tw_cli_req_q_insert_tail(req
, TW_CLI_FREE_Q
);
613 tw_cli_dbg_printf(4, ctlr
->ctlr_handle
, tw_osl_cur_func(),
614 "Request Sense command succeeded");
616 aen_code
= tw_cli_manage_aen(ctlr
, req
);
618 if (aen_code
!= TWA_AEN_SYNC_TIME_WITH_HOST
) {
619 ctlr
->internal_req_busy
= TW_CL_FALSE
;
620 tw_cli_req_q_insert_tail(req
, TW_CLI_FREE_Q
);
621 if (aen_code
!= TWA_AEN_QUEUE_EMPTY
)
622 if ((error
= tw_cli_get_aen(ctlr
)))
623 tw_cl_create_event(ctlr
->ctlr_handle
,
625 TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR
,
627 TW_CL_SEVERITY_ERROR_STRING
,
628 "Failed to fetch all AEN's",
629 "error = %d", error
);
636 * Function name: tw_cli_manage_aen
637 * Description: Handles AEN's.
639 * Input: ctlr -- ptr to CL internal ctlr context
640 * req -- ptr to CL internal request context
645 tw_cli_manage_aen(struct tw_cli_ctlr_context
*ctlr
,
646 struct tw_cli_req_context
*req
)
648 struct tw_cl_command_header
*cmd_hdr
;
654 tw_cli_dbg_printf(4, ctlr
->ctlr_handle
, tw_osl_cur_func(), "entered");
656 cmd_hdr
= (struct tw_cl_command_header
*)(req
->data
);
657 aen_code
= cmd_hdr
->status_block
.error
;
660 case TWA_AEN_SYNC_TIME_WITH_HOST
:
661 tw_cli_dbg_printf(4, ctlr
->ctlr_handle
, tw_osl_cur_func(),
662 "Received AEN_SYNC_TIME");
664 * Free the internal req pkt right here, since
665 * tw_cli_set_param will need it.
667 ctlr
->internal_req_busy
= TW_CL_FALSE
;
668 tw_cli_req_q_insert_tail(req
, TW_CLI_FREE_Q
);
671 * We will use a callback in tw_cli_set_param only when
672 * interrupts are enabled and we can expect our callback
673 * to get called. Setting the get_more_aens
674 * flag will make the callback continue to try to retrieve
677 if (ctlr
->interrupts_enabled
)
678 ctlr
->get_more_aens
= TW_CL_TRUE
;
679 /* Calculate time (in seconds) since last Sunday 12.00 AM. */
680 local_time
= tw_osl_get_local_time();
681 sync_time
= (local_time
- (3 * 86400)) % 604800;
682 if ((error
= tw_cli_set_param(ctlr
, TWA_PARAM_TIME_TABLE
,
683 TWA_PARAM_TIME_SCHED_TIME
, 4,
685 (ctlr
->interrupts_enabled
)
686 ? tw_cli_param_callback
: TW_CL_NULL
)))
687 tw_cl_create_event(ctlr
->ctlr_handle
, TW_CL_FALSE
,
688 TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR
,
689 0x1208, 0x1, TW_CL_SEVERITY_ERROR_STRING
,
690 "Unable to sync time with ctlr",
691 "error = %d", error
);
696 case TWA_AEN_QUEUE_EMPTY
:
697 tw_cli_dbg_printf(4, ctlr
->ctlr_handle
, tw_osl_cur_func(),
703 /* Queue the event. */
705 tw_cli_dbg_printf(4, ctlr
->ctlr_handle
, tw_osl_cur_func(),
707 tw_cli_create_ctlr_event(ctlr
,
708 TW_CL_MESSAGE_SOURCE_CONTROLLER_EVENT
,
718 * Function name: tw_cli_enable_interrupts
719 * Description: Enables interrupts on the controller
721 * Input: ctlr -- ptr to CL internal ctlr context
726 tw_cli_enable_interrupts(struct tw_cli_ctlr_context
*ctlr
)
728 tw_cli_dbg_printf(3, ctlr
->ctlr_handle
, tw_osl_cur_func(), "entered");
730 ctlr
->interrupts_enabled
= TW_CL_TRUE
;
731 TW_CLI_WRITE_CONTROL_REGISTER(ctlr
->ctlr_handle
,
732 TWA_CONTROL_CLEAR_ATTENTION_INTERRUPT
|
733 TWA_CONTROL_UNMASK_RESPONSE_INTERRUPT
|
734 TWA_CONTROL_ENABLE_INTERRUPTS
);
740 * Function name: twa_setup
741 * Description: Disables interrupts on the controller
743 * Input: ctlr -- ptr to CL internal ctlr context
748 tw_cli_disable_interrupts(struct tw_cli_ctlr_context
*ctlr
)
750 tw_cli_dbg_printf(3, ctlr
->ctlr_handle
, tw_osl_cur_func(), "entered");
752 TW_CLI_WRITE_CONTROL_REGISTER(ctlr
->ctlr_handle
,
753 TWA_CONTROL_DISABLE_INTERRUPTS
);
754 ctlr
->interrupts_enabled
= TW_CL_FALSE
;