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: src/sys/dev/twa/tw_cl_intr.c,v 1.5 2010/06/09 21:40:38 delphij Exp $
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 */
251 tw_cl_reset_ctlr(ctlr->ctlr_handle);
256 * Remove the request from the busy queue, mark it as complete,
257 * and enqueue it in the complete queue.
259 tw_cli_req_q_remove_item(req, TW_CLI_BUSY_Q);
260 req->state = TW_CLI_REQ_STATE_COMPLETE;
261 tw_cli_req_q_insert_tail(req, TW_CLI_COMPLETE_Q);
265 /* Complete this, and other requests in the complete queue. */
266 tw_cli_process_complete_queue(ctlr);
274 * Function name: tw_cli_submit_pending_queue
275 * Description: Kick starts any requests in the pending queue.
277 * Input: ctlr -- ptr to CL internal ctlr context
279 * Return value: 0 -- all pending requests submitted successfully
280 * non-zero-- otherwise
283 tw_cli_submit_pending_queue(struct tw_cli_ctlr_context *ctlr)
285 struct tw_cli_req_context *req;
286 TW_INT32 error = TW_OSL_ESUCCESS;
288 tw_cli_dbg_printf(3, ctlr->ctlr_handle, tw_osl_cur_func(), "entered");
291 * Pull requests off the pending queue, and submit them.
293 while ((req = tw_cli_req_q_remove_head(ctlr, TW_CLI_PENDING_Q)) !=
295 if ((error = tw_cli_submit_cmd(req))) {
296 if (error == TW_OSL_EBUSY) {
297 tw_cli_dbg_printf(2, ctlr->ctlr_handle,
299 "Requeueing pending request");
300 req->state = TW_CLI_REQ_STATE_PENDING;
302 * Queue the request at the head of the pending
303 * queue, and break away, so we don't try to
304 * submit any more requests.
306 tw_cli_req_q_insert_head(req, TW_CLI_PENDING_Q);
309 tw_cl_create_event(ctlr->ctlr_handle,
311 TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR,
313 TW_CL_SEVERITY_ERROR_STRING,
314 "Could not start request "
316 "request = %p, opcode = 0x%x, "
318 GET_OPCODE(req->cmd_pkt->
319 command.cmd_pkt_9k.res__opcode),
322 * Set the appropriate error and call the CL
323 * internal callback if there's one. If the
324 * request originator is polling for completion,
325 * he should be checking req->error to
326 * determine that the request did not go
327 * through. The request originators are
328 * responsible for the clean-up.
330 req->error_code = error;
331 req->state = TW_CLI_REQ_STATE_COMPLETE;
332 if (req->tw_cli_callback)
333 req->tw_cli_callback(req);
334 error = TW_OSL_ESUCCESS;
344 * Function name: tw_cli_process_complete_queue
345 * Description: Calls the CL internal callback routine, if any, for
346 * each request in the complete queue.
348 * Input: ctlr -- ptr to CL internal ctlr context
353 tw_cli_process_complete_queue(struct tw_cli_ctlr_context *ctlr)
355 struct tw_cli_req_context *req;
357 tw_cli_dbg_printf(10, ctlr->ctlr_handle, tw_osl_cur_func(), "entered");
360 * Pull commands off the completed list, dispatch them appropriately.
362 while ((req = tw_cli_req_q_remove_head(ctlr, TW_CLI_COMPLETE_Q)) !=
364 /* Call the CL internal callback, if there's one. */
365 if (req->tw_cli_callback)
366 req->tw_cli_callback(req);
373 * Function name: tw_cli_complete_io
374 * Description: CL internal callback for SCSI/fw passthru requests.
376 * Input: req -- ptr to CL internal request context
381 tw_cli_complete_io(struct tw_cli_req_context *req)
383 struct tw_cli_ctlr_context *ctlr = req->ctlr;
384 struct tw_cl_req_packet *req_pkt =
385 (struct tw_cl_req_packet *)(req->orig_req);
387 tw_cli_dbg_printf(8, ctlr->ctlr_handle, tw_osl_cur_func(), "entered");
389 req_pkt->status = TW_CL_ERR_REQ_SUCCESS;
390 if (req->error_code) {
391 req_pkt->status = TW_CL_ERR_REQ_UNABLE_TO_SUBMIT_COMMAND;
395 if (req->state != TW_CLI_REQ_STATE_COMPLETE) {
396 tw_cl_create_event(ctlr->ctlr_handle, TW_CL_FALSE,
397 TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR,
398 0x1203, 0x1, TW_CL_SEVERITY_ERROR_STRING,
399 "I/O completion on incomplete command!!",
400 "request = %p, status = %d",
403 tw_cl_print_ctlr_stats(ctlr->ctlr_handle);
404 #endif /* TW_OSL_DEBUG */
405 tw_cl_reset_ctlr(ctlr->ctlr_handle);
406 req_pkt->status = TW_CL_ERR_REQ_BUS_RESET;
410 if (req->flags & TW_CLI_REQ_FLAGS_PASSTHRU) {
411 /* Copy the command packet back into OSL's space. */
412 tw_osl_memcpy(req_pkt->gen_req_pkt.pt_req.cmd_pkt, req->cmd_pkt,
413 sizeof(struct tw_cl_command_packet));
415 tw_cli_scsi_complete(req);
418 req_pkt->tw_osl_callback(req->req_handle);
419 tw_cli_req_q_insert_tail(req, TW_CLI_FREE_Q);
425 * Function name: tw_cli_scsi_complete
426 * Description: Completion routine for SCSI requests.
428 * Input: req -- ptr to CL internal request context
433 tw_cli_scsi_complete(struct tw_cli_req_context *req)
435 struct tw_cl_req_packet *req_pkt =
436 (struct tw_cl_req_packet *)(req->orig_req);
437 struct tw_cl_scsi_req_packet *scsi_req =
438 &(req_pkt->gen_req_pkt.scsi_req);
439 struct tw_cl_command_9k *cmd =
440 &(req->cmd_pkt->command.cmd_pkt_9k);
441 struct tw_cl_command_header *cmd_hdr;
445 tw_cli_dbg_printf(8, req->ctlr->ctlr_handle, tw_osl_cur_func(),
448 scsi_req->scsi_status = cmd->status;
452 tw_cli_dbg_printf(1, req->ctlr->ctlr_handle, tw_osl_cur_func(),
453 "req_id = 0x%x, status = 0x%x",
454 GET_REQ_ID(cmd->lun_l4__req_id), cmd->status);
456 cmd_hdr = &(req->cmd_pkt->cmd_hdr);
457 error = cmd_hdr->status_block.error;
458 if ((error == TWA_ERROR_LOGICAL_UNIT_NOT_SUPPORTED) ||
459 (error == TWA_ERROR_UNIT_OFFLINE)) {
460 if (GET_LUN_L4(cmd->lun_l4__req_id))
461 req_pkt->status |= TW_CL_ERR_REQ_INVALID_LUN;
463 req_pkt->status |= TW_CL_ERR_REQ_INVALID_TARGET;
465 tw_cli_dbg_printf(2, req->ctlr->ctlr_handle,
467 "cmd = %x %x %x %x %x %x %x",
468 GET_OPCODE(cmd->res__opcode),
469 GET_SGL_OFF(cmd->res__opcode),
474 cmd->lun_h4__sgl_entries);
476 cdb = (TW_UINT8 *)(cmd->cdb);
477 tw_cli_dbg_printf(2, req->ctlr->ctlr_handle,
479 "cdb = %x %x %x %x %x %x %x %x "
480 "%x %x %x %x %x %x %x %x",
481 cdb[0], cdb[1], cdb[2], cdb[3],
482 cdb[4], cdb[5], cdb[6], cdb[7],
483 cdb[8], cdb[9], cdb[10], cdb[11],
484 cdb[12], cdb[13], cdb[14], cdb[15]);
487 * Print the error. Firmware doesn't yet support
488 * the 'Mode Sense' cmd. Don't print if the cmd
489 * is 'Mode Sense', and the error is 'Invalid field
492 if (! ((cdb[0] == 0x1A) && (error == 0x10D)))
493 tw_cli_create_ctlr_event(req->ctlr,
494 TW_CL_MESSAGE_SOURCE_CONTROLLER_ERROR,
498 if (scsi_req->sense_data) {
499 tw_osl_memcpy(scsi_req->sense_data, cmd_hdr->sense_data,
500 TWA_SENSE_DATA_LENGTH);
501 scsi_req->sense_len = TWA_SENSE_DATA_LENGTH;
502 req_pkt->status |= TW_CL_ERR_REQ_AUTO_SENSE_VALID;
504 req_pkt->status |= TW_CL_ERR_REQ_SCSI_ERROR;
510 * Function name: tw_cli_param_callback
511 * Description: Callback for get/set_param requests.
513 * Input: req -- ptr to completed request pkt
518 tw_cli_param_callback(struct tw_cli_req_context *req)
520 struct tw_cli_ctlr_context *ctlr = req->ctlr;
521 union tw_cl_command_7k *cmd =
522 &(req->cmd_pkt->command.cmd_pkt_7k);
525 tw_cli_dbg_printf(4, ctlr->ctlr_handle, tw_osl_cur_func(), "entered");
528 * If the request was never submitted to the controller, the function
529 * that sets req->error is responsible for calling tw_cl_create_event.
531 if (! req->error_code)
532 if (cmd->param.status) {
533 tw_cli_create_ctlr_event(ctlr,
534 TW_CL_MESSAGE_SOURCE_CONTROLLER_ERROR,
535 &(req->cmd_pkt->cmd_hdr));
536 tw_cl_create_event(ctlr->ctlr_handle, TW_CL_FALSE,
537 TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR,
538 0x1204, 0x1, TW_CL_SEVERITY_ERROR_STRING,
539 "get/set_param failed",
540 "status = %d", cmd->param.status);
543 ctlr->internal_req_busy = TW_CL_FALSE;
544 tw_cli_req_q_insert_tail(req, TW_CLI_FREE_Q);
546 if ((ctlr->get_more_aens) && (!(ctlr->reset_in_progress))) {
547 ctlr->get_more_aens = TW_CL_FALSE;
548 tw_cli_dbg_printf(4, ctlr->ctlr_handle, tw_osl_cur_func(),
549 "Fetching more AEN's");
550 if ((error = tw_cli_get_aen(ctlr)))
551 tw_cl_create_event(ctlr->ctlr_handle, TW_CL_FALSE,
552 TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR,
553 0x1205, 0x1, TW_CL_SEVERITY_ERROR_STRING,
554 "Failed to fetch all AEN's from param_callback",
555 "error = %d", error);
562 * Function name: tw_cli_aen_callback
563 * Description: Callback for requests to fetch AEN's.
565 * Input: req -- ptr to completed request pkt
570 tw_cli_aen_callback(struct tw_cli_req_context *req)
572 struct tw_cli_ctlr_context *ctlr = req->ctlr;
573 struct tw_cl_command_header *cmd_hdr;
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)) {
591 cmd_hdr = (struct tw_cl_command_header *)
592 (&(req->cmd_pkt->cmd_hdr));
593 tw_cli_create_ctlr_event(ctlr,
594 TW_CL_MESSAGE_SOURCE_CONTROLLER_ERROR,
596 tw_cl_create_event(ctlr->ctlr_handle, TW_CL_FALSE,
597 TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR,
598 0x1206, 0x1, TW_CL_SEVERITY_ERROR_STRING,
599 "Request Sense failed",
600 "opcode = 0x%x, status = %d",
601 GET_OPCODE(cmd->res__opcode), cmd->status);
605 ctlr->internal_req_busy = TW_CL_FALSE;
606 tw_cli_req_q_insert_tail(req, TW_CLI_FREE_Q);
610 tw_cli_dbg_printf(4, ctlr->ctlr_handle, tw_osl_cur_func(),
611 "Request Sense command succeeded");
613 aen_code = tw_cli_manage_aen(ctlr, req);
615 if (aen_code != TWA_AEN_SYNC_TIME_WITH_HOST) {
616 ctlr->internal_req_busy = TW_CL_FALSE;
617 tw_cli_req_q_insert_tail(req, TW_CLI_FREE_Q);
618 if (aen_code != TWA_AEN_QUEUE_EMPTY)
619 if ((error = tw_cli_get_aen(ctlr)))
620 tw_cl_create_event(ctlr->ctlr_handle,
622 TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR,
624 TW_CL_SEVERITY_ERROR_STRING,
625 "Failed to fetch all AEN's",
626 "error = %d", error);
633 * Function name: tw_cli_manage_aen
634 * Description: Handles AEN's.
636 * Input: ctlr -- ptr to CL internal ctlr context
637 * req -- ptr to CL internal request context
642 tw_cli_manage_aen(struct tw_cli_ctlr_context *ctlr,
643 struct tw_cli_req_context *req)
645 struct tw_cl_command_header *cmd_hdr;
651 tw_cli_dbg_printf(4, ctlr->ctlr_handle, tw_osl_cur_func(), "entered");
653 cmd_hdr = (struct tw_cl_command_header *)(req->data);
654 aen_code = cmd_hdr->status_block.error;
657 case TWA_AEN_SYNC_TIME_WITH_HOST:
658 tw_cli_dbg_printf(4, ctlr->ctlr_handle, tw_osl_cur_func(),
659 "Received AEN_SYNC_TIME");
661 * Free the internal req pkt right here, since
662 * tw_cli_set_param will need it.
664 ctlr->internal_req_busy = TW_CL_FALSE;
665 tw_cli_req_q_insert_tail(req, TW_CLI_FREE_Q);
668 * We will use a callback in tw_cli_set_param only when
669 * interrupts are enabled and we can expect our callback
670 * to get called. Setting the get_more_aens
671 * flag will make the callback continue to try to retrieve
674 if (ctlr->interrupts_enabled)
675 ctlr->get_more_aens = TW_CL_TRUE;
676 /* Calculate time (in seconds) since last Sunday 12.00 AM. */
677 local_time = tw_osl_get_local_time();
678 sync_time = (local_time - (3 * 86400)) % 604800;
679 if ((error = tw_cli_set_param(ctlr, TWA_PARAM_TIME_TABLE,
680 TWA_PARAM_TIME_SCHED_TIME, 4,
682 (ctlr->interrupts_enabled)
683 ? tw_cli_param_callback : TW_CL_NULL)))
684 tw_cl_create_event(ctlr->ctlr_handle, TW_CL_FALSE,
685 TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR,
686 0x1208, 0x1, TW_CL_SEVERITY_ERROR_STRING,
687 "Unable to sync time with ctlr",
688 "error = %d", error);
693 case TWA_AEN_QUEUE_EMPTY:
694 tw_cli_dbg_printf(4, ctlr->ctlr_handle, tw_osl_cur_func(),
700 /* Queue the event. */
702 tw_cli_dbg_printf(4, ctlr->ctlr_handle, tw_osl_cur_func(),
704 tw_cli_create_ctlr_event(ctlr,
705 TW_CL_MESSAGE_SOURCE_CONTROLLER_EVENT,
715 * Function name: tw_cli_enable_interrupts
716 * Description: Enables interrupts on the controller
718 * Input: ctlr -- ptr to CL internal ctlr context
723 tw_cli_enable_interrupts(struct tw_cli_ctlr_context *ctlr)
725 tw_cli_dbg_printf(3, ctlr->ctlr_handle, tw_osl_cur_func(), "entered");
727 ctlr->interrupts_enabled = TW_CL_TRUE;
728 TW_CLI_WRITE_CONTROL_REGISTER(ctlr->ctlr_handle,
729 TWA_CONTROL_CLEAR_ATTENTION_INTERRUPT |
730 TWA_CONTROL_UNMASK_RESPONSE_INTERRUPT |
731 TWA_CONTROL_ENABLE_INTERRUPTS);
737 * Function name: twa_setup
738 * Description: Disables interrupts on the controller
740 * Input: ctlr -- ptr to CL internal ctlr context
745 tw_cli_disable_interrupts(struct tw_cli_ctlr_context *ctlr)
747 tw_cli_dbg_printf(3, ctlr->ctlr_handle, tw_osl_cur_func(), "entered");
749 TW_CLI_WRITE_CONTROL_REGISTER(ctlr->ctlr_handle,
750 TWA_CONTROL_DISABLE_INTERRUPTS);
751 ctlr->interrupts_enabled = TW_CL_FALSE;