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