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