83 /* 84 * Synchronize access between writes to command and control registers 85 * in 64-bit environments, on G66. 86 */ 87 if (ctlr->state & TW_CLI_CTLR_STATE_G66_WORKAROUND_NEEDED) 88 tw_osl_get_lock(ctlr_handle, ctlr->io_lock); 89 90 /* Read the status register to determine the type of interrupt. */ 91 status_reg = TW_CLI_READ_STATUS_REGISTER(ctlr_handle); 92 if (tw_cli_check_ctlr_state(ctlr, status_reg)) 93 goto out_unlock; 94 95 /* Clear the interrupt. */ 96 if (status_reg & TWA_STATUS_HOST_INTERRUPT) { 97 tw_cli_dbg_printf(6, ctlr_handle, tw_osl_cur_func(), 98 "Host interrupt"); 99 TW_CLI_WRITE_CONTROL_REGISTER(ctlr_handle, 100 TWA_CONTROL_CLEAR_HOST_INTERRUPT); 101 ctlr->host_intr_pending = 0; /* we don't use this */ 102 rc |= TW_CL_FALSE; /* don't request for a deferred isr call */ 103 } 104 if (status_reg & TWA_STATUS_ATTENTION_INTERRUPT) { 105 tw_cli_dbg_printf(6, ctlr_handle, tw_osl_cur_func(), 106 "Attention interrupt"); 107 TW_CLI_WRITE_CONTROL_REGISTER(ctlr_handle, 108 TWA_CONTROL_CLEAR_ATTENTION_INTERRUPT); 109 ctlr->attn_intr_pending = 1; 110 rc |= TW_CL_TRUE; /* request for a deferred isr call */ 111 } 112 if (status_reg & TWA_STATUS_COMMAND_INTERRUPT) { 113 tw_cli_dbg_printf(6, ctlr_handle, tw_osl_cur_func(), 114 "Command interrupt"); 115 TW_CLI_WRITE_CONTROL_REGISTER(ctlr_handle, 116 TWA_CONTROL_MASK_COMMAND_INTERRUPT); 117 ctlr->cmd_intr_pending = 1; 118 rc |= TW_CL_TRUE; /* request for a deferred isr call */ 119 } 120 if (status_reg & TWA_STATUS_RESPONSE_INTERRUPT) { 121 tw_cli_dbg_printf(10, ctlr_handle, tw_osl_cur_func(), 122 "Response interrupt"); 123 TW_CLI_WRITE_CONTROL_REGISTER(ctlr_handle, 124 TWA_CONTROL_MASK_RESPONSE_INTERRUPT); 125 ctlr->resp_intr_pending = 1; 126 rc |= TW_CL_TRUE; /* request for a deferred isr call */ 127 } 128out_unlock: 129 if (ctlr->state & TW_CLI_CTLR_STATE_G66_WORKAROUND_NEEDED) 130 tw_osl_free_lock(ctlr_handle, ctlr->io_lock); 131out: 132 return(rc); 133} 134 135 136 137/* 138 * Function name: tw_cl_deferred_interrupt 139 * Description: Deferred interrupt handler. Does most of the processing 140 * related to an interrupt. 141 * 142 * Input: ctlr_handle -- controller handle 143 * Output: None 144 * Return value: None 145 */ 146TW_VOID 147tw_cl_deferred_interrupt(struct tw_cl_ctlr_handle *ctlr_handle) 148{ 149 struct tw_cli_ctlr_context *ctlr = 150 (struct tw_cli_ctlr_context *)(ctlr_handle->cl_ctlr_ctxt); 151 152 tw_cli_dbg_printf(10, ctlr_handle, tw_osl_cur_func(), "entered"); 153 154 /* Dispatch based on the kind of interrupt. */ 155 if (ctlr->host_intr_pending) { 156 tw_cli_dbg_printf(6, ctlr_handle, tw_osl_cur_func(), 157 "Processing Host interrupt"); 158 ctlr->host_intr_pending = 0; 159 tw_cli_process_host_intr(ctlr); 160 } 161 if (ctlr->attn_intr_pending) { 162 tw_cli_dbg_printf(6, ctlr_handle, tw_osl_cur_func(), 163 "Processing Attention interrupt"); 164 ctlr->attn_intr_pending = 0; 165 tw_cli_process_attn_intr(ctlr); 166 } 167 if (ctlr->cmd_intr_pending) { 168 tw_cli_dbg_printf(6, ctlr_handle, tw_osl_cur_func(), 169 "Processing Command interrupt"); 170 ctlr->cmd_intr_pending = 0; 171 tw_cli_process_cmd_intr(ctlr); 172 } 173 if (ctlr->resp_intr_pending) { 174 tw_cli_dbg_printf(10, ctlr_handle, tw_osl_cur_func(), 175 "Processing Response interrupt"); 176 ctlr->resp_intr_pending = 0; 177 tw_cli_process_resp_intr(ctlr); 178 } 179} 180 181 182 183/* 184 * Function name: tw_cli_process_host_intr 185 * Description: This function gets called if we triggered an interrupt. 186 * We don't use it as of now. 187 * 188 * Input: ctlr -- ptr to CL internal ctlr context 189 * Output: None 190 * Return value: None 191 */ 192TW_VOID 193tw_cli_process_host_intr(struct tw_cli_ctlr_context *ctlr) 194{ 195 tw_cli_dbg_printf(6, ctlr->ctlr_handle, tw_osl_cur_func(), "entered"); 196} 197 198 199 200/* 201 * Function name: tw_cli_process_attn_intr 202 * Description: This function gets called if the fw posted an AEN 203 * (Asynchronous Event Notification). It fetches 204 * all the AEN's that the fw might have posted. 205 * 206 * Input: ctlr -- ptr to CL internal ctlr context 207 * Output: None 208 * Return value: None 209 */ 210TW_VOID 211tw_cli_process_attn_intr(struct tw_cli_ctlr_context *ctlr) 212{ 213 TW_INT32 error; 214 215 tw_cli_dbg_printf(6, ctlr->ctlr_handle, tw_osl_cur_func(), "entered"); 216 217 if ((error = tw_cli_get_aen(ctlr))) { 218 /* 219 * If the driver is already in the process of retrieveing AEN's, 220 * we will be returned TW_OSL_EBUSY. In this case, 221 * tw_cli_param_callback or tw_cli_aen_callback will eventually 222 * retrieve the AEN this attention interrupt is for. So, we 223 * don't need to print the failure. 224 */ 225 if (error != TW_OSL_EBUSY) 226 tw_cl_create_event(ctlr->ctlr_handle, TW_CL_FALSE, 227 TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR, 228 0x1200, 0x1, TW_CL_SEVERITY_ERROR_STRING, 229 "Failed to fetch AEN", 230 "error = %d", error); 231 } 232} 233 234 235 236/* 237 * Function name: tw_cli_process_cmd_intr 238 * Description: This function gets called if we hit a queue full 239 * condition earlier, and the fw is now ready for 240 * new cmds. Submits any pending requests. 241 * 242 * Input: ctlr -- ptr to CL internal ctlr context 243 * Output: None 244 * Return value: None 245 */ 246TW_VOID 247tw_cli_process_cmd_intr(struct tw_cli_ctlr_context *ctlr) 248{ 249 tw_cli_dbg_printf(6, ctlr->ctlr_handle, tw_osl_cur_func(), "entered"); 250 251 /* 252 * Let the OS Layer submit any requests in its pending queue, 253 * if it has one. 254 */ 255 tw_osl_ctlr_ready(ctlr->ctlr_handle); 256 257 /* Start any requests that might be in the pending queue. */ 258 tw_cli_submit_pending_queue(ctlr); 259 260 /* 261 * If tw_cli_submit_pending_queue was unsuccessful due to a "cmd queue 262 * full" condition, cmd_intr will already have been unmasked by 263 * tw_cli_submit_cmd. We don't need to do it again... simply return. 264 */ 265} 266 267 268 269/* 270 * Function name: tw_cli_process_resp_intr 271 * Description: Looks for cmd completions from fw; queues cmds completed 272 * by fw into complete queue. 273 * 274 * Input: ctlr -- ptr to CL internal ctlr context 275 * Output: None 276 * Return value: 0 -- no ctlr error 277 * non-zero-- ctlr error 278 */ 279TW_INT32 280tw_cli_process_resp_intr(struct tw_cli_ctlr_context *ctlr) 281{ 282 TW_UINT32 resp; 283 struct tw_cli_req_context *req; 284 TW_INT32 error; 285 TW_UINT32 status_reg; 286 287 tw_cli_dbg_printf(10, ctlr->ctlr_handle, tw_osl_cur_func(), "entered"); 288 289 /* Serialize access to the controller response queue. */ 290 tw_osl_get_lock(ctlr->ctlr_handle, ctlr->intr_lock); 291 292 for (;;) { 293 status_reg = TW_CLI_READ_STATUS_REGISTER(ctlr->ctlr_handle); 294 if ((error = tw_cli_check_ctlr_state(ctlr, status_reg))) 295 break; 296 if (status_reg & TWA_STATUS_RESPONSE_QUEUE_EMPTY) { 297 tw_cli_dbg_printf(7, ctlr->ctlr_handle, 298 tw_osl_cur_func(), "Response queue empty"); 299 break; 300 } 301 302 /* Response queue is not empty. */ 303 resp = TW_CLI_READ_RESPONSE_QUEUE(ctlr->ctlr_handle); 304 { 305 req = &(ctlr->req_ctxt_buf[GET_RESP_ID(resp)]); 306 } 307 308 if (req->state != TW_CLI_REQ_STATE_BUSY) { 309 tw_cl_create_event(ctlr->ctlr_handle, TW_CL_FALSE, 310 TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR, 311 0x1201, 0x1, TW_CL_SEVERITY_ERROR_STRING, 312 "Unposted command completed!!", 313 "request = %p, status = %d", 314 req, req->state); 315#ifdef TW_OSL_DEBUG 316 tw_cl_print_ctlr_stats(ctlr->ctlr_handle); 317#endif /* TW_OSL_DEBUG */ 318 tw_osl_free_lock(ctlr->ctlr_handle, ctlr->intr_lock); 319 tw_cl_reset_ctlr(ctlr->ctlr_handle); 320 return(TW_OSL_EIO); 321 } 322 323 /* 324 * Remove the request from the busy queue, mark it as complete, 325 * and enqueue it in the complete queue. 326 */ 327 tw_cli_req_q_remove_item(req, TW_CLI_BUSY_Q); 328 req->state = TW_CLI_REQ_STATE_COMPLETE; 329 tw_cli_req_q_insert_tail(req, TW_CLI_COMPLETE_Q); 330 331 } 332 333 /* Unmask the response interrupt. */ 334 TW_CLI_WRITE_CONTROL_REGISTER(ctlr->ctlr_handle, 335 TWA_CONTROL_UNMASK_RESPONSE_INTERRUPT); 336 337 tw_osl_free_lock(ctlr->ctlr_handle, ctlr->intr_lock); 338 339 /* Complete this, and other requests in the complete queue. */ 340 tw_cli_process_complete_queue(ctlr); 341 342 return(error); 343} 344 345 346 347/* 348 * Function name: tw_cli_submit_pending_queue 349 * Description: Kick starts any requests in the pending queue. 350 * 351 * Input: ctlr -- ptr to CL internal ctlr context 352 * Output: None 353 * Return value: 0 -- all pending requests submitted successfully 354 * non-zero-- otherwise 355 */ 356TW_INT32 357tw_cli_submit_pending_queue(struct tw_cli_ctlr_context *ctlr) 358{ 359 struct tw_cli_req_context *req; 360 TW_INT32 error = TW_OSL_ESUCCESS; 361 362 tw_cli_dbg_printf(3, ctlr->ctlr_handle, tw_osl_cur_func(), "entered"); 363 364 /* 365 * Pull requests off the pending queue, and submit them. 366 */ 367 while ((req = tw_cli_req_q_remove_head(ctlr, TW_CLI_PENDING_Q)) != 368 TW_CL_NULL) { 369 if ((error = tw_cli_submit_cmd(req))) { 370 if (error == TW_OSL_EBUSY) { 371 tw_cli_dbg_printf(2, ctlr->ctlr_handle, 372 tw_osl_cur_func(), 373 "Requeueing pending request"); 374 req->state = TW_CLI_REQ_STATE_PENDING; 375 /* 376 * Queue the request at the head of the pending 377 * queue, and break away, so we don't try to 378 * submit any more requests. 379 */ 380 tw_cli_req_q_insert_head(req, TW_CLI_PENDING_Q); 381 break; 382 } else { 383 tw_cl_create_event(ctlr->ctlr_handle, 384 TW_CL_FALSE, 385 TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR, 386 0x1202, 0x1, 387 TW_CL_SEVERITY_ERROR_STRING, 388 "Could not start request " 389 "in pending queue", 390 "request = %p, opcode = 0x%x, " 391 "error = %d", req, 392 GET_OPCODE(req->cmd_pkt-> 393 command.cmd_pkt_9k.res__opcode), 394 error); 395 /* 396 * Set the appropriate error and call the CL 397 * internal callback if there's one. If the 398 * request originator is polling for completion, 399 * he should be checking req->error to 400 * determine that the request did not go 401 * through. The request originators are 402 * responsible for the clean-up. 403 */ 404 req->error_code = error; 405 req->state = TW_CLI_REQ_STATE_COMPLETE; 406 if (req->tw_cli_callback) 407 req->tw_cli_callback(req); 408 error = TW_OSL_ESUCCESS; 409 } 410 } 411 } 412 return(error); 413} 414 415 416 417/* 418 * Function name: tw_cli_process_complete_queue 419 * Description: Calls the CL internal callback routine, if any, for 420 * each request in the complete queue. 421 * 422 * Input: ctlr -- ptr to CL internal ctlr context 423 * Output: None 424 * Return value: None 425 */ 426TW_VOID 427tw_cli_process_complete_queue(struct tw_cli_ctlr_context *ctlr) 428{ 429 struct tw_cli_req_context *req; 430 431 tw_cli_dbg_printf(10, ctlr->ctlr_handle, tw_osl_cur_func(), "entered"); 432 433 /* 434 * Pull commands off the completed list, dispatch them appropriately. 435 */ 436 while ((req = tw_cli_req_q_remove_head(ctlr, TW_CLI_COMPLETE_Q)) != 437 TW_CL_NULL) { 438 /* Call the CL internal callback, if there's one. */ 439 if (req->tw_cli_callback) 440 req->tw_cli_callback(req); 441 } 442} 443 444 445 446/* 447 * Function name: tw_cli_complete_io 448 * Description: CL internal callback for SCSI/fw passthru requests. 449 * 450 * Input: req -- ptr to CL internal request context 451 * Output: None 452 * Return value: None 453 */ 454TW_VOID 455tw_cli_complete_io(struct tw_cli_req_context *req) 456{ 457 struct tw_cli_ctlr_context *ctlr = req->ctlr; 458 struct tw_cl_req_packet *req_pkt = 459 (struct tw_cl_req_packet *)(req->orig_req); 460 461 tw_cli_dbg_printf(8, ctlr->ctlr_handle, tw_osl_cur_func(), "entered"); 462 463 req_pkt->status = TW_CL_ERR_REQ_SUCCESS; 464 if (req->error_code) { 465 req_pkt->status = TW_CL_ERR_REQ_UNABLE_TO_SUBMIT_COMMAND; 466 goto out; 467 } 468 469 if (req->state != TW_CLI_REQ_STATE_COMPLETE) { 470 tw_cl_create_event(ctlr->ctlr_handle, TW_CL_FALSE, 471 TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR, 472 0x1203, 0x1, TW_CL_SEVERITY_ERROR_STRING, 473 "I/O completion on incomplete command!!", 474 "request = %p, status = %d", 475 req, req->state); 476#ifdef TW_OSL_DEBUG 477 tw_cl_print_ctlr_stats(ctlr->ctlr_handle); 478#endif /* TW_OSL_DEBUG */ 479 tw_cl_reset_ctlr(ctlr->ctlr_handle); 480 req_pkt->status = TW_CL_ERR_REQ_BUS_RESET; 481 goto out; 482 } 483 484 if (req->flags & TW_CLI_REQ_FLAGS_PASSTHRU) { 485 /* Copy the command packet back into OSL's space. */ 486 tw_osl_memcpy(req_pkt->gen_req_pkt.pt_req.cmd_pkt, req->cmd_pkt, 487 sizeof(struct tw_cl_command_packet)); 488 } else 489 tw_cli_scsi_complete(req); 490 491out: 492 req_pkt->tw_osl_callback(req->req_handle); 493 tw_cli_req_q_insert_tail(req, TW_CLI_FREE_Q); 494} 495 496 497 498/* 499 * Function name: tw_cli_scsi_complete 500 * Description: Completion routine for SCSI requests. 501 * 502 * Input: req -- ptr to CL internal request context 503 * Output: None 504 * Return value: None 505 */ 506TW_VOID 507tw_cli_scsi_complete(struct tw_cli_req_context *req) 508{ 509 struct tw_cl_req_packet *req_pkt = 510 (struct tw_cl_req_packet *)(req->orig_req); 511 struct tw_cl_scsi_req_packet *scsi_req = 512 &(req_pkt->gen_req_pkt.scsi_req); 513 struct tw_cl_command_9k *cmd = 514 &(req->cmd_pkt->command.cmd_pkt_9k); 515 struct tw_cl_command_header *cmd_hdr; 516 TW_UINT16 error; 517 TW_UINT8 *cdb; 518 519 tw_cli_dbg_printf(8, req->ctlr->ctlr_handle, tw_osl_cur_func(), 520 "entered"); 521 522 scsi_req->scsi_status = cmd->status; 523 if (! cmd->status) 524 return; 525 526 tw_cli_dbg_printf(1, req->ctlr->ctlr_handle, tw_osl_cur_func(), 527 "req_id = 0x%x, status = 0x%x", 528 GET_REQ_ID(cmd->lun_l4__req_id), cmd->status); 529 530 cmd_hdr = &(req->cmd_pkt->cmd_hdr); 531 error = cmd_hdr->status_block.error; 532 if ((error == TWA_ERROR_LOGICAL_UNIT_NOT_SUPPORTED) || 533 (error == TWA_ERROR_UNIT_OFFLINE)) { 534 if (GET_LUN_L4(cmd->lun_l4__req_id)) 535 req_pkt->status |= TW_CL_ERR_REQ_INVALID_LUN; 536 else 537 req_pkt->status |= TW_CL_ERR_REQ_INVALID_TARGET; 538 } else { 539 tw_cli_dbg_printf(2, req->ctlr->ctlr_handle, 540 tw_osl_cur_func(), 541 "cmd = %x %x %x %x %x %x %x", 542 GET_OPCODE(cmd->res__opcode), 543 GET_SGL_OFF(cmd->res__opcode), 544 cmd->unit, 545 cmd->lun_l4__req_id, 546 cmd->status, 547 cmd->sgl_offset, 548 cmd->lun_h4__sgl_entries); 549 550 cdb = (TW_UINT8 *)(cmd->cdb); 551 tw_cli_dbg_printf(2, req->ctlr->ctlr_handle, 552 tw_osl_cur_func(), 553 "cdb = %x %x %x %x %x %x %x %x " 554 "%x %x %x %x %x %x %x %x", 555 cdb[0], cdb[1], cdb[2], cdb[3], 556 cdb[4], cdb[5], cdb[6], cdb[7], 557 cdb[8], cdb[9], cdb[10], cdb[11], 558 cdb[12], cdb[13], cdb[14], cdb[15]); 559 560 /* 561 * Print the error. Firmware doesn't yet support 562 * the 'Mode Sense' cmd. Don't print if the cmd 563 * is 'Mode Sense', and the error is 'Invalid field 564 * in CDB'. 565 */ 566 if (! ((cdb[0] == 0x1A) && (error == 0x10D))) 567 tw_cli_create_ctlr_event(req->ctlr, 568 TW_CL_MESSAGE_SOURCE_CONTROLLER_ERROR, 569 cmd_hdr); 570 } 571 572 if (scsi_req->sense_data) { 573 tw_osl_memcpy(scsi_req->sense_data, cmd_hdr->sense_data, 574 TWA_SENSE_DATA_LENGTH); 575 scsi_req->sense_len = TWA_SENSE_DATA_LENGTH; 576 req_pkt->status |= TW_CL_ERR_REQ_AUTO_SENSE_VALID; 577 } 578 req_pkt->status |= TW_CL_ERR_REQ_SCSI_ERROR; 579} 580 581 582 583/* 584 * Function name: tw_cli_param_callback 585 * Description: Callback for get/set_param requests. 586 * 587 * Input: req -- ptr to completed request pkt 588 * Output: None 589 * Return value: None 590 */ 591TW_VOID 592tw_cli_param_callback(struct tw_cli_req_context *req) 593{ 594 struct tw_cli_ctlr_context *ctlr = req->ctlr; 595 union tw_cl_command_7k *cmd = 596 &(req->cmd_pkt->command.cmd_pkt_7k); 597 TW_INT32 error; 598 599 tw_cli_dbg_printf(4, ctlr->ctlr_handle, tw_osl_cur_func(), "entered"); 600 601 /* 602 * If the request was never submitted to the controller, the function 603 * that sets req->error is responsible for calling tw_cl_create_event. 604 */ 605 if (! req->error_code) 606 if (cmd->param.status) { 607 tw_cli_create_ctlr_event(ctlr, 608 TW_CL_MESSAGE_SOURCE_CONTROLLER_ERROR, 609 &(req->cmd_pkt->cmd_hdr)); 610 tw_cl_create_event(ctlr->ctlr_handle, TW_CL_FALSE, 611 TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR, 612 0x1204, 0x1, TW_CL_SEVERITY_ERROR_STRING, 613 "get/set_param failed", 614 "status = %d", cmd->param.status); 615 } 616 617 ctlr->state &= ~TW_CLI_CTLR_STATE_INTERNAL_REQ_BUSY; 618 tw_cli_req_q_insert_tail(req, TW_CLI_FREE_Q); 619 620 if ((ctlr->state & TW_CLI_CTLR_STATE_GET_MORE_AENS) && 621 (!(ctlr->state & TW_CLI_CTLR_STATE_RESET_IN_PROGRESS))) { 622 ctlr->state &= ~TW_CLI_CTLR_STATE_GET_MORE_AENS; 623 tw_cli_dbg_printf(4, ctlr->ctlr_handle, tw_osl_cur_func(), 624 "Fetching more AEN's"); 625 if ((error = tw_cli_get_aen(ctlr))) 626 tw_cl_create_event(ctlr->ctlr_handle, TW_CL_FALSE, 627 TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR, 628 0x1205, 0x1, TW_CL_SEVERITY_ERROR_STRING, 629 "Failed to fetch all AEN's from param_callback", 630 "error = %d", error); 631 } 632} 633 634 635 636/* 637 * Function name: tw_cli_aen_callback 638 * Description: Callback for requests to fetch AEN's. 639 * 640 * Input: req -- ptr to completed request pkt 641 * Output: None 642 * Return value: None 643 */ 644TW_VOID 645tw_cli_aen_callback(struct tw_cli_req_context *req) 646{ 647 struct tw_cli_ctlr_context *ctlr = req->ctlr; 648 struct tw_cl_command_header *cmd_hdr; 649 struct tw_cl_command_9k *cmd = 650 &(req->cmd_pkt->command.cmd_pkt_9k); 651 TW_UINT16 aen_code = TWA_AEN_QUEUE_EMPTY; 652 TW_INT32 error; 653 654 tw_cli_dbg_printf(4, ctlr->ctlr_handle, tw_osl_cur_func(), "entered"); 655 656 tw_cli_dbg_printf(4, ctlr->ctlr_handle, tw_osl_cur_func(), 657 "req_id = 0x%x, req error = %d, status = 0x%x", 658 GET_REQ_ID(cmd->lun_l4__req_id), req->error_code, cmd->status); 659 660 /* 661 * If the request was never submitted to the controller, the function 662 * that sets error is responsible for calling tw_cl_create_event. 663 */ 664 if (!(error = req->error_code)) 665 if ((error = cmd->status)) { 666 cmd_hdr = (struct tw_cl_command_header *) 667 (&(req->cmd_pkt->cmd_hdr)); 668 tw_cli_create_ctlr_event(ctlr, 669 TW_CL_MESSAGE_SOURCE_CONTROLLER_ERROR, 670 cmd_hdr); 671 tw_cl_create_event(ctlr->ctlr_handle, TW_CL_FALSE, 672 TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR, 673 0x1206, 0x1, TW_CL_SEVERITY_ERROR_STRING, 674 "Request Sense failed", 675 "opcode = 0x%x, status = %d", 676 GET_OPCODE(cmd->res__opcode), cmd->status); 677 } 678 679 if (error) { 680 ctlr->state &= ~TW_CLI_CTLR_STATE_INTERNAL_REQ_BUSY; 681 tw_cli_req_q_insert_tail(req, TW_CLI_FREE_Q); 682 return; 683 } 684 685 tw_cli_dbg_printf(4, ctlr->ctlr_handle, tw_osl_cur_func(), 686 "Request Sense command succeeded"); 687 688 aen_code = tw_cli_manage_aen(ctlr, req); 689 690 if (aen_code != TWA_AEN_SYNC_TIME_WITH_HOST) { 691 ctlr->state &= ~TW_CLI_CTLR_STATE_INTERNAL_REQ_BUSY; 692 tw_cli_req_q_insert_tail(req, TW_CLI_FREE_Q); 693 if (aen_code != TWA_AEN_QUEUE_EMPTY) 694 if ((error = tw_cli_get_aen(ctlr))) 695 tw_cl_create_event(ctlr->ctlr_handle, 696 TW_CL_FALSE, 697 TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR, 698 0x1207, 0x1, 699 TW_CL_SEVERITY_ERROR_STRING, 700 "Failed to fetch all AEN's", 701 "error = %d", error); 702 } 703} 704 705 706 707/* 708 * Function name: tw_cli_manage_aen 709 * Description: Handles AEN's. 710 * 711 * Input: ctlr -- ptr to CL internal ctlr context 712 * req -- ptr to CL internal request context 713 * Output: None 714 * Return value: None 715 */ 716TW_UINT16 717tw_cli_manage_aen(struct tw_cli_ctlr_context *ctlr, 718 struct tw_cli_req_context *req) 719{ 720 struct tw_cl_command_header *cmd_hdr; 721 TW_UINT16 aen_code; 722 TW_TIME local_time; 723 TW_TIME sync_time; 724 TW_UINT32 error; 725 726 tw_cli_dbg_printf(4, ctlr->ctlr_handle, tw_osl_cur_func(), "entered"); 727 728 cmd_hdr = (struct tw_cl_command_header *)(req->data); 729 aen_code = cmd_hdr->status_block.error; 730 731 switch (aen_code) { 732 case TWA_AEN_SYNC_TIME_WITH_HOST: 733 tw_cli_dbg_printf(4, ctlr->ctlr_handle, tw_osl_cur_func(), 734 "Received AEN_SYNC_TIME"); 735 /* 736 * Free the internal req pkt right here, since 737 * tw_cli_set_param will need it. 738 */ 739 ctlr->state &= ~TW_CLI_CTLR_STATE_INTERNAL_REQ_BUSY; 740 tw_cli_req_q_insert_tail(req, TW_CLI_FREE_Q); 741 742 /* 743 * We will use a callback in tw_cli_set_param only when 744 * interrupts are enabled and we can expect our callback 745 * to get called. Setting the TW_CLI_CTLR_STATE_GET_MORE_AENS 746 * flag will make the callback continue to try to retrieve 747 * more AEN's. 748 */ 749 if (ctlr->state & TW_CLI_CTLR_STATE_INTR_ENABLED) 750 ctlr->state |= TW_CLI_CTLR_STATE_GET_MORE_AENS; 751 /* Calculate time (in seconds) since last Sunday 12.00 AM. */ 752 local_time = tw_osl_get_local_time(); 753 sync_time = (local_time - (3 * 86400)) % 604800; 754 if ((error = tw_cli_set_param(ctlr, TWA_PARAM_TIME_TABLE, 755 TWA_PARAM_TIME_SCHED_TIME, 4, 756 &sync_time, 757 (ctlr->state & TW_CLI_CTLR_STATE_INTR_ENABLED) 758 ? tw_cli_param_callback : TW_CL_NULL))) 759 tw_cl_create_event(ctlr->ctlr_handle, TW_CL_FALSE, 760 TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR, 761 0x1208, 0x1, TW_CL_SEVERITY_ERROR_STRING, 762 "Unable to sync time with ctlr", 763 "error = %d", error); 764 765 break; 766 767 768 case TWA_AEN_QUEUE_EMPTY: 769 tw_cli_dbg_printf(4, ctlr->ctlr_handle, tw_osl_cur_func(), 770 "AEN queue empty"); 771 break; 772 773 774 default: 775 /* Queue the event. */ 776 777 tw_cli_dbg_printf(4, ctlr->ctlr_handle, tw_osl_cur_func(), 778 "Queueing AEN"); 779 tw_cli_create_ctlr_event(ctlr, 780 TW_CL_MESSAGE_SOURCE_CONTROLLER_EVENT, 781 cmd_hdr); 782 break; 783 } /* switch */ 784 return(aen_code); 785} 786 787 788 789/* 790 * Function name: tw_cli_enable_interrupts 791 * Description: Enables interrupts on the controller 792 * 793 * Input: ctlr -- ptr to CL internal ctlr context 794 * Output: None 795 * Return value: None 796 */ 797TW_VOID 798tw_cli_enable_interrupts(struct tw_cli_ctlr_context *ctlr) 799{ 800 tw_cli_dbg_printf(3, ctlr->ctlr_handle, tw_osl_cur_func(), "entered"); 801 802 ctlr->state |= TW_CLI_CTLR_STATE_INTR_ENABLED; 803 TW_CLI_WRITE_CONTROL_REGISTER(ctlr->ctlr_handle, 804 TWA_CONTROL_CLEAR_ATTENTION_INTERRUPT | 805 TWA_CONTROL_UNMASK_RESPONSE_INTERRUPT | 806 TWA_CONTROL_ENABLE_INTERRUPTS); 807} 808 809 810 811/* 812 * Function name: twa_setup 813 * Description: Disables interrupts on the controller 814 * 815 * Input: ctlr -- ptr to CL internal ctlr context 816 * Output: None 817 * Return value: None 818 */ 819TW_VOID 820tw_cli_disable_interrupts(struct tw_cli_ctlr_context *ctlr) 821{ 822 tw_cli_dbg_printf(3, ctlr->ctlr_handle, tw_osl_cur_func(), "entered"); 823 824 TW_CLI_WRITE_CONTROL_REGISTER(ctlr->ctlr_handle, 825 TWA_CONTROL_DISABLE_INTERRUPTS); 826 ctlr->state &= ~TW_CLI_CTLR_STATE_INTR_ENABLED; 827} 828
|