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