1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 /* 28 * Copyright (c) 2000 to 2009, LSI Corporation. 29 * All rights reserved. 30 * 31 * Redistribution and use in source and binary forms of all code within 32 * this file that is exclusively owned by LSI, with or without 33 * modification, is permitted provided that, in addition to the CDDL 1.0 34 * License requirements, the following conditions are met: 35 * 36 * Neither the name of the author nor the names of its contributors may be 37 * used to endorse or promote products derived from this software without 38 * specific prior written permission. 39 * 40 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 41 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 42 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 43 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 44 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 45 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 46 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 47 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 48 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 49 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 50 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 51 * DAMAGE. 52 */ 53 54 /* 55 * mptsas_init - This file contains all the functions used to initialize 56 * MPT2.0 based hardware. 57 */ 58 59 #if defined(lint) || defined(DEBUG) 60 #define MPTSAS_DEBUG 61 #endif 62 63 /* 64 * standard header files 65 */ 66 #include <sys/note.h> 67 #include <sys/scsi/scsi.h> 68 69 #pragma pack(1) 70 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2_type.h> 71 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2.h> 72 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2_cnfg.h> 73 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2_init.h> 74 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2_ioc.h> 75 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2_tool.h> 76 #pragma pack() 77 /* 78 * private header files. 79 */ 80 #include <sys/scsi/adapters/mpt_sas/mptsas_var.h> 81 82 static int mptsas_ioc_do_get_facts(mptsas_t *mpt, caddr_t memp, int var, 83 ddi_acc_handle_t accessp); 84 static int mptsas_ioc_do_get_facts_reply(mptsas_t *mpt, caddr_t memp, int var, 85 ddi_acc_handle_t accessp); 86 static int mptsas_ioc_do_get_port_facts(mptsas_t *mpt, caddr_t memp, int var, 87 ddi_acc_handle_t accessp); 88 static int mptsas_ioc_do_get_port_facts_reply(mptsas_t *mpt, caddr_t memp, 89 int var, ddi_acc_handle_t accessp); 90 static int mptsas_ioc_do_enable_port(mptsas_t *mpt, caddr_t memp, int var, 91 ddi_acc_handle_t accessp); 92 static int mptsas_ioc_do_enable_port_reply(mptsas_t *mpt, caddr_t memp, int var, 93 ddi_acc_handle_t accessp); 94 static int mptsas_ioc_do_enable_event_notification(mptsas_t *mpt, caddr_t memp, 95 int var, ddi_acc_handle_t accessp); 96 static int mptsas_ioc_do_enable_event_notification_reply(mptsas_t *mpt, 97 caddr_t memp, int var, ddi_acc_handle_t accessp); 98 static int mptsas_do_ioc_init(mptsas_t *mpt, caddr_t memp, int var, 99 ddi_acc_handle_t accessp); 100 static int mptsas_do_ioc_init_reply(mptsas_t *mpt, caddr_t memp, int var, 101 ddi_acc_handle_t accessp); 102 103 static const char * 104 mptsas_product_type_string(mptsas_t *mpt) 105 { 106 switch (mpt->m_productid & MPI2_FW_HEADER_PID_PROD_MASK) { 107 108 case MPI2_FW_HEADER_PID_PROD_A: 109 return ("A"); 110 default: 111 return ("?"); 112 } 113 } 114 115 int 116 mptsas_ioc_get_facts(mptsas_t *mpt) 117 { 118 /* 119 * Send get facts messages 120 */ 121 if (mptsas_do_dma(mpt, sizeof (MPI2_IOC_FACTS_REQUEST), NULL, 122 mptsas_ioc_do_get_facts)) { 123 return (DDI_FAILURE); 124 } 125 126 /* 127 * Get facts reply messages 128 */ 129 if (mptsas_do_dma(mpt, sizeof (MPI2_IOC_FACTS_REPLY), NULL, 130 mptsas_ioc_do_get_facts_reply)) { 131 return (DDI_FAILURE); 132 } 133 134 return (DDI_SUCCESS); 135 } 136 137 static int 138 mptsas_ioc_do_get_facts(mptsas_t *mpt, caddr_t memp, int var, 139 ddi_acc_handle_t accessp) 140 { 141 #ifndef __lock_lint 142 _NOTE(ARGUNUSED(var)) 143 #endif 144 pMpi2IOCFactsRequest_t facts; 145 int numbytes; 146 147 bzero(memp, sizeof (*facts)); 148 facts = (void *)memp; 149 ddi_put8(accessp, &facts->Function, MPI2_FUNCTION_IOC_FACTS); 150 numbytes = sizeof (*facts); 151 152 /* 153 * Post message via handshake 154 */ 155 if (mptsas_send_handshake_msg(mpt, memp, numbytes, accessp)) { 156 return (DDI_FAILURE); 157 } 158 159 return (DDI_SUCCESS); 160 } 161 162 static int 163 mptsas_ioc_do_get_facts_reply(mptsas_t *mpt, caddr_t memp, int var, 164 ddi_acc_handle_t accessp) 165 { 166 #ifndef __lock_lint 167 _NOTE(ARGUNUSED(var)) 168 #endif 169 170 pMpi2IOCFactsReply_t factsreply; 171 int numbytes; 172 uint_t iocstatus; 173 char buf[32]; 174 uint16_t numReplyFrames; 175 uint16_t queueSize, queueDiff; 176 int simple_sge_main; 177 int simple_sge_next; 178 uint32_t capabilities; 179 180 bzero(memp, sizeof (*factsreply)); 181 factsreply = (void *)memp; 182 numbytes = sizeof (*factsreply); 183 184 /* 185 * get ioc facts reply message 186 */ 187 if (mptsas_get_handshake_msg(mpt, memp, numbytes, accessp)) { 188 return (DDI_FAILURE); 189 } 190 191 if (iocstatus = ddi_get16(accessp, &factsreply->IOCStatus)) { 192 mptsas_log(mpt, CE_WARN, "mptsas_ioc_do_get_facts_reply: " 193 "IOCStatus=0x%x, IOCLogInfo=0x%x", iocstatus, 194 ddi_get32(accessp, &factsreply->IOCLogInfo)); 195 return (DDI_FAILURE); 196 } 197 198 /* 199 * store key values from reply to mpt structure 200 */ 201 mpt->m_fwversion = ddi_get32(accessp, &factsreply->FWVersion.Word); 202 mpt->m_productid = ddi_get16(accessp, &factsreply->ProductID); 203 204 205 (void) sprintf(buf, "%u.%u.%u.%u", 206 ddi_get8(accessp, &factsreply->FWVersion.Struct.Major), 207 ddi_get8(accessp, &factsreply->FWVersion.Struct.Minor), 208 ddi_get8(accessp, &factsreply->FWVersion.Struct.Unit), 209 ddi_get8(accessp, &factsreply->FWVersion.Struct.Dev)); 210 mptsas_log(mpt, CE_NOTE, "?mpt%d Firmware version v%s (%s)\n", 211 mpt->m_instance, buf, mptsas_product_type_string(mpt)); 212 (void) ddi_prop_update_string(DDI_DEV_T_NONE, mpt->m_dip, 213 "firmware-version", buf); 214 215 /* 216 * Set up request info. 217 */ 218 mpt->m_max_requests = ddi_get16(accessp, 219 &factsreply->RequestCredit) - 1; 220 mpt->m_req_frame_size = ddi_get16(accessp, 221 &factsreply->IOCRequestFrameSize) * 4; 222 223 /* 224 * Size of reply free queue should be the number of requests 225 * plus some additional for events (32). Make sure number of 226 * reply frames is not a multiple of 16 so that the queue sizes 227 * are calculated correctly later to be a multiple of 16. 228 */ 229 mpt->m_reply_frame_size = ddi_get8(accessp, 230 &factsreply->ReplyFrameSize) * 4; 231 numReplyFrames = mpt->m_max_requests + 32; 232 if (!(numReplyFrames % 16)) { 233 numReplyFrames--; 234 } 235 mpt->m_max_replies = numReplyFrames; 236 queueSize = numReplyFrames; 237 queueSize += 16 - (queueSize % 16); 238 mpt->m_free_queue_depth = queueSize; 239 240 /* 241 * Size of reply descriptor post queue should be the number of 242 * request frames + the number of reply frames + 1 and needs to 243 * be a multiple of 16. This size can be no larger than 244 * MaxReplyDescriptorPostQueueDepth from IOCFacts. If the 245 * calculated queue size is larger than allowed, subtract a 246 * multiple of 16 from m_max_requests, m_max_replies, and 247 * m_reply_free_depth. 248 */ 249 queueSize = mpt->m_max_requests + numReplyFrames + 1; 250 if (queueSize % 16) { 251 queueSize += 16 - (queueSize % 16); 252 } 253 mpt->m_post_queue_depth = ddi_get16(accessp, 254 &factsreply->MaxReplyDescriptorPostQueueDepth); 255 if (queueSize > mpt->m_post_queue_depth) { 256 queueDiff = queueSize - mpt->m_post_queue_depth; 257 if (queueDiff % 16) { 258 queueDiff += 16 - (queueDiff % 16); 259 } 260 mpt->m_max_requests -= queueDiff; 261 mpt->m_max_replies -= queueDiff; 262 mpt->m_free_queue_depth -= queueDiff; 263 queueSize -= queueDiff; 264 } 265 mpt->m_post_queue_depth = queueSize; 266 267 /* 268 * Set up max chain depth. 269 */ 270 mpt->m_max_chain_depth = ddi_get8(accessp, 271 &factsreply->MaxChainDepth); 272 mpt->m_ioc_capabilities = ddi_get32(accessp, 273 &factsreply->IOCCapabilities); 274 275 /* 276 * Calculate max frames per request based on DMA S/G length. 277 */ 278 simple_sge_main = MPTSAS_MAX_FRAME_SGES64(mpt) - 1; 279 simple_sge_next = mpt->m_req_frame_size / 280 sizeof (MPI2_SGE_SIMPLE64) - 1; 281 282 mpt->m_max_request_frames = (MPTSAS_MAX_DMA_SEGS - 283 simple_sge_main) / simple_sge_next + 1; 284 if (((MPTSAS_MAX_DMA_SEGS - simple_sge_main) % 285 simple_sge_next) > 1) { 286 mpt->m_max_request_frames++; 287 } 288 289 /* 290 * Check if controller supports FW diag buffers and set flag to enable 291 * each type. 292 */ 293 capabilities = ddi_get32(accessp, &factsreply->IOCCapabilities); 294 if (capabilities & MPI2_IOCFACTS_CAPABILITY_DIAG_TRACE_BUFFER) { 295 mpt->m_fw_diag_buffer_list[MPI2_DIAG_BUF_TYPE_TRACE].enabled = 296 TRUE; 297 } 298 if (capabilities & MPI2_IOCFACTS_CAPABILITY_SNAPSHOT_BUFFER) { 299 mpt->m_fw_diag_buffer_list[MPI2_DIAG_BUF_TYPE_SNAPSHOT]. 300 enabled = TRUE; 301 } 302 if (capabilities & MPI2_IOCFACTS_CAPABILITY_EXTENDED_BUFFER) { 303 mpt->m_fw_diag_buffer_list[MPI2_DIAG_BUF_TYPE_EXTENDED]. 304 enabled = TRUE; 305 } 306 307 /* 308 * Check if controller supports replaying events when issuing Message 309 * Unit Reset and set flag to enable MUR. 310 */ 311 if (capabilities & MPI2_IOCFACTS_CAPABILITY_EVENT_REPLAY) { 312 mpt->m_event_replay = TRUE; 313 } 314 315 /* 316 * Check if controller supports IR. 317 */ 318 if (capabilities & MPI2_IOCFACTS_CAPABILITY_INTEGRATED_RAID) { 319 mpt->m_ir_capable = TRUE; 320 } 321 322 return (DDI_SUCCESS); 323 } 324 325 int 326 mptsas_ioc_get_port_facts(mptsas_t *mpt, int port) 327 { 328 /* 329 * Send get port facts message 330 */ 331 if (mptsas_do_dma(mpt, sizeof (MPI2_PORT_FACTS_REQUEST), port, 332 mptsas_ioc_do_get_port_facts)) { 333 return (DDI_FAILURE); 334 } 335 336 /* 337 * Get port facts reply message 338 */ 339 if (mptsas_do_dma(mpt, sizeof (MPI2_PORT_FACTS_REPLY), port, 340 mptsas_ioc_do_get_port_facts_reply)) { 341 return (DDI_FAILURE); 342 } 343 344 return (DDI_SUCCESS); 345 } 346 347 static int 348 mptsas_ioc_do_get_port_facts(mptsas_t *mpt, caddr_t memp, int var, 349 ddi_acc_handle_t accessp) 350 { 351 pMpi2PortFactsRequest_t facts; 352 int numbytes; 353 354 bzero(memp, sizeof (*facts)); 355 facts = (void *)memp; 356 ddi_put8(accessp, &facts->Function, MPI2_FUNCTION_PORT_FACTS); 357 ddi_put8(accessp, &facts->PortNumber, var); 358 numbytes = sizeof (*facts); 359 360 /* 361 * Send port facts message via handshake 362 */ 363 if (mptsas_send_handshake_msg(mpt, memp, numbytes, accessp)) { 364 return (DDI_FAILURE); 365 } 366 367 return (DDI_SUCCESS); 368 } 369 370 static int 371 mptsas_ioc_do_get_port_facts_reply(mptsas_t *mpt, caddr_t memp, int var, 372 ddi_acc_handle_t accessp) 373 { 374 #ifndef __lock_lint 375 _NOTE(ARGUNUSED(var)) 376 #endif 377 pMpi2PortFactsReply_t factsreply; 378 int numbytes; 379 uint_t iocstatus; 380 381 bzero(memp, sizeof (*factsreply)); 382 factsreply = (void *)memp; 383 numbytes = sizeof (*factsreply); 384 385 /* 386 * Get port facts reply message via handshake 387 */ 388 if (mptsas_get_handshake_msg(mpt, memp, numbytes, accessp)) { 389 return (DDI_FAILURE); 390 } 391 392 if (iocstatus = ddi_get16(accessp, &factsreply->IOCStatus)) { 393 mptsas_log(mpt, CE_WARN, "mptsas_ioc_do_get_port_facts_reply: " 394 "IOCStatus=0x%x, IOCLogInfo=0x%x", iocstatus, 395 ddi_get32(accessp, &factsreply->IOCLogInfo)); 396 return (DDI_FAILURE); 397 } 398 399 return (DDI_SUCCESS); 400 } 401 402 int 403 mptsas_ioc_enable_port(mptsas_t *mpt) 404 { 405 /* 406 * Send enable port message 407 */ 408 if (mptsas_do_dma(mpt, sizeof (MPI2_PORT_ENABLE_REQUEST), 0, 409 mptsas_ioc_do_enable_port)) { 410 return (DDI_FAILURE); 411 } 412 413 /* 414 * Get enable port reply message 415 */ 416 if (mptsas_do_dma(mpt, sizeof (MPI2_PORT_ENABLE_REPLY), 0, 417 mptsas_ioc_do_enable_port_reply)) { 418 return (DDI_FAILURE); 419 } 420 421 return (DDI_SUCCESS); 422 } 423 424 static int 425 mptsas_ioc_do_enable_port(mptsas_t *mpt, caddr_t memp, int var, 426 ddi_acc_handle_t accessp) 427 { 428 #ifndef __lock_lint 429 _NOTE(ARGUNUSED(var)) 430 #endif 431 pMpi2PortEnableRequest_t enable; 432 int numbytes; 433 434 bzero(memp, sizeof (*enable)); 435 enable = (void *)memp; 436 ddi_put8(accessp, &enable->Function, MPI2_FUNCTION_PORT_ENABLE); 437 numbytes = sizeof (*enable); 438 439 /* 440 * Send message via handshake 441 */ 442 if (mptsas_send_handshake_msg(mpt, memp, numbytes, accessp)) { 443 return (DDI_FAILURE); 444 } 445 446 return (DDI_SUCCESS); 447 } 448 449 static int 450 mptsas_ioc_do_enable_port_reply(mptsas_t *mpt, caddr_t memp, int var, 451 ddi_acc_handle_t accessp) 452 { 453 #ifndef __lock_lint 454 _NOTE(ARGUNUSED(var)) 455 #endif 456 457 int numbytes; 458 uint_t iocstatus; 459 pMpi2PortEnableReply_t portreply; 460 461 numbytes = sizeof (MPI2_PORT_ENABLE_REPLY); 462 bzero(memp, numbytes); 463 portreply = (void *)memp; 464 465 /* 466 * Get message via handshake 467 */ 468 if (mptsas_get_handshake_msg(mpt, memp, numbytes, accessp)) { 469 return (DDI_FAILURE); 470 } 471 472 if (iocstatus = ddi_get16(accessp, &portreply->IOCStatus)) { 473 mptsas_log(mpt, CE_WARN, "mptsas_ioc_do_enable_port_reply: " 474 "IOCStatus=0x%x, IOCLogInfo=0x%x", iocstatus, 475 ddi_get32(accessp, &portreply->IOCLogInfo)); 476 return (DDI_FAILURE); 477 } 478 479 return (DDI_SUCCESS); 480 } 481 482 int 483 mptsas_ioc_enable_event_notification(mptsas_t *mpt) 484 { 485 ASSERT(mutex_owned(&mpt->m_mutex)); 486 487 /* 488 * Send enable event notification message 489 */ 490 if (mptsas_do_dma(mpt, sizeof (MPI2_EVENT_NOTIFICATION_REQUEST), NULL, 491 mptsas_ioc_do_enable_event_notification)) { 492 return (DDI_FAILURE); 493 } 494 495 /* 496 * Get enable event reply message 497 */ 498 if (mptsas_do_dma(mpt, sizeof (MPI2_EVENT_NOTIFICATION_REPLY), NULL, 499 mptsas_ioc_do_enable_event_notification_reply)) { 500 return (DDI_FAILURE); 501 } 502 503 return (DDI_SUCCESS); 504 } 505 506 static int 507 mptsas_ioc_do_enable_event_notification(mptsas_t *mpt, caddr_t memp, int var, 508 ddi_acc_handle_t accessp) 509 { 510 #ifndef __lock_lint 511 _NOTE(ARGUNUSED(var)) 512 #endif 513 514 pMpi2EventNotificationRequest_t event; 515 int numbytes; 516 517 bzero(memp, sizeof (*event)); 518 event = (void *)memp; 519 ddi_put8(accessp, &event->Function, MPI2_FUNCTION_EVENT_NOTIFICATION); 520 numbytes = sizeof (*event); 521 522 /* 523 * Send message via handshake 524 */ 525 if (mptsas_send_handshake_msg(mpt, memp, numbytes, accessp)) { 526 return (DDI_FAILURE); 527 } 528 529 return (DDI_SUCCESS); 530 } 531 532 static int 533 mptsas_ioc_do_enable_event_notification_reply(mptsas_t *mpt, caddr_t memp, 534 int var, ddi_acc_handle_t accessp) 535 { 536 #ifndef __lock_lint 537 _NOTE(ARGUNUSED(var)) 538 #endif 539 int numbytes; 540 uint_t iocstatus; 541 pMpi2EventNotificationReply_t eventsreply; 542 543 numbytes = sizeof (MPI2_EVENT_NOTIFICATION_REPLY); 544 bzero(memp, numbytes); 545 eventsreply = (void *)memp; 546 547 /* 548 * Get message via handshake 549 */ 550 if (mptsas_get_handshake_msg(mpt, memp, numbytes, accessp)) { 551 return (DDI_FAILURE); 552 } 553 554 if (iocstatus = ddi_get16(accessp, &eventsreply->IOCStatus)) { 555 mptsas_log(mpt, CE_WARN, 556 "mptsas_ioc_do_enable_event_notification_reply: " 557 "IOCStatus=0x%x, IOCLogInfo=0x%x", iocstatus, 558 ddi_get32(accessp, &eventsreply->IOCLogInfo)); 559 return (DDI_FAILURE); 560 } 561 562 return (DDI_SUCCESS); 563 } 564 565 int 566 mptsas_ioc_init(mptsas_t *mpt) 567 { 568 /* 569 * Send ioc init message 570 */ 571 if (mptsas_do_dma(mpt, sizeof (MPI2_IOC_INIT_REQUEST), NULL, 572 mptsas_do_ioc_init)) { 573 return (DDI_FAILURE); 574 } 575 576 /* 577 * Get ioc init reply message 578 */ 579 if (mptsas_do_dma(mpt, sizeof (MPI2_IOC_INIT_REPLY), NULL, 580 mptsas_do_ioc_init_reply)) { 581 return (DDI_FAILURE); 582 } 583 584 return (DDI_SUCCESS); 585 } 586 587 static int 588 mptsas_do_ioc_init(mptsas_t *mpt, caddr_t memp, int var, 589 ddi_acc_handle_t accessp) 590 { 591 #ifndef __lock_lint 592 _NOTE(ARGUNUSED(var)) 593 #endif 594 595 pMpi2IOCInitRequest_t init; 596 int numbytes; 597 timespec_t time; 598 uint64_t mSec; 599 600 bzero(memp, sizeof (*init)); 601 init = (void *)memp; 602 ddi_put8(accessp, &init->Function, MPI2_FUNCTION_IOC_INIT); 603 ddi_put8(accessp, &init->WhoInit, MPI2_WHOINIT_HOST_DRIVER); 604 ddi_put16(accessp, &init->MsgVersion, MPI2_VERSION); 605 ddi_put16(accessp, &init->HeaderVersion, MPI2_HEADER_VERSION); 606 ddi_put16(accessp, &init->SystemRequestFrameSize, 607 mpt->m_req_frame_size / 4); 608 ddi_put16(accessp, &init->ReplyDescriptorPostQueueDepth, 609 mpt->m_post_queue_depth); 610 ddi_put16(accessp, &init->ReplyFreeQueueDepth, 611 mpt->m_free_queue_depth); 612 613 /* 614 * These addresses are set using the DMA cookie addresses from when the 615 * memory was allocated. Sense buffer hi address should be 0. 616 */ 617 ddi_put32(accessp, &init->SenseBufferAddressHigh, 0); 618 ddi_put32(accessp, &init->SystemReplyAddressHigh, 619 (uint32_t)(mpt->m_reply_frame_dma_addr >> 32)); 620 ddi_put32(accessp, &init->SystemRequestFrameBaseAddress.High, 621 (uint32_t)(mpt->m_req_frame_dma_addr >> 32)); 622 ddi_put32(accessp, &init->SystemRequestFrameBaseAddress.Low, 623 (uint32_t)mpt->m_req_frame_dma_addr); 624 ddi_put32(accessp, &init->ReplyDescriptorPostQueueAddress.High, 625 (uint32_t)(mpt->m_post_queue_dma_addr >> 32)); 626 ddi_put32(accessp, &init->ReplyDescriptorPostQueueAddress.Low, 627 (uint32_t)mpt->m_post_queue_dma_addr); 628 ddi_put32(accessp, &init->ReplyFreeQueueAddress.High, 629 (uint32_t)(mpt->m_free_queue_dma_addr >> 32)); 630 ddi_put32(accessp, &init->ReplyFreeQueueAddress.Low, 631 (uint32_t)mpt->m_free_queue_dma_addr); 632 633 /* 634 * Fill in the timestamp with the number of milliseconds since midnight 635 * of January 1, 1970 UT (Greenwich Mean Time). Time is returned in 636 * seconds and nanoseconds. Translate both to milliseconds and add 637 * them together to get total milliseconds. 638 */ 639 gethrestime(&time); 640 mSec = time.tv_sec * MILLISEC; 641 mSec += (time.tv_nsec / MICROSEC); 642 ddi_put32(accessp, &init->TimeStamp.High, (uint32_t)(mSec >> 32)); 643 ddi_put32(accessp, &init->TimeStamp.Low, (uint32_t)mSec); 644 645 numbytes = sizeof (*init); 646 647 /* 648 * Post message via handshake 649 */ 650 if (mptsas_send_handshake_msg(mpt, memp, numbytes, accessp)) { 651 return (DDI_FAILURE); 652 } 653 654 return (DDI_SUCCESS); 655 } 656 657 static int 658 mptsas_do_ioc_init_reply(mptsas_t *mpt, caddr_t memp, int var, 659 ddi_acc_handle_t accessp) 660 { 661 #ifndef __lock_lint 662 _NOTE(ARGUNUSED(var)) 663 #endif 664 665 pMpi2IOCInitReply_t initreply; 666 int numbytes; 667 uint_t iocstatus; 668 669 numbytes = sizeof (MPI2_IOC_INIT_REPLY); 670 bzero(memp, numbytes); 671 initreply = (void *)memp; 672 673 /* 674 * Get reply message via handshake 675 */ 676 if (mptsas_get_handshake_msg(mpt, memp, numbytes, accessp)) { 677 return (DDI_FAILURE); 678 } 679 680 if (iocstatus = ddi_get16(accessp, &initreply->IOCStatus)) { 681 mptsas_log(mpt, CE_WARN, "mptsas_do_ioc_init_reply: " 682 "IOCStatus=0x%x, IOCLogInfo=0x%x", iocstatus, 683 ddi_get32(accessp, &initreply->IOCLogInfo)); 684 return (DDI_FAILURE); 685 } 686 687 if ((ddi_get32(mpt->m_datap, &mpt->m_reg->Doorbell)) & 688 MPI2_IOC_STATE_OPERATIONAL) { 689 mptsas_log(mpt, CE_NOTE, 690 "?mpt%d: IOC Operational.\n", mpt->m_instance); 691 } else { 692 return (DDI_FAILURE); 693 } 694 695 return (DDI_SUCCESS); 696 }