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 default: 141 return ("?"); 142 } 143 } 144 145 int 146 mptsas_ioc_get_facts(mptsas_t *mpt) 147 { 148 /* 149 * Send get facts messages 150 */ 151 if (mptsas_do_dma(mpt, sizeof (MPI2_IOC_FACTS_REQUEST), NULL, 152 mptsas_ioc_do_get_facts)) { 153 return (DDI_FAILURE); 154 } 155 156 /* 157 * Get facts reply messages 158 */ 159 if (mptsas_do_dma(mpt, sizeof (MPI2_IOC_FACTS_REPLY), NULL, 160 mptsas_ioc_do_get_facts_reply)) { 161 return (DDI_FAILURE); 162 } 163 164 return (DDI_SUCCESS); 165 } 166 167 static int 168 mptsas_ioc_do_get_facts(mptsas_t *mpt, caddr_t memp, int var, 169 ddi_acc_handle_t accessp) 170 { 171 #ifndef __lock_lint 172 _NOTE(ARGUNUSED(var)) 173 #endif 174 pMpi2IOCFactsRequest_t facts; 175 int numbytes; 176 177 bzero(memp, sizeof (*facts)); 178 facts = (void *)memp; 179 ddi_put8(accessp, &facts->Function, MPI2_FUNCTION_IOC_FACTS); 180 numbytes = sizeof (*facts); 181 182 /* 183 * Post message via handshake 184 */ 185 if (mptsas_send_handshake_msg(mpt, memp, numbytes, accessp)) { 186 return (DDI_FAILURE); 187 } 188 189 return (DDI_SUCCESS); 190 } 191 192 static int 193 mptsas_ioc_do_get_facts_reply(mptsas_t *mpt, caddr_t memp, int var, 194 ddi_acc_handle_t accessp) 195 { 196 #ifndef __lock_lint 197 _NOTE(ARGUNUSED(var)) 198 #endif 199 200 pMpi2IOCFactsReply_t factsreply; 201 int numbytes; 202 uint_t iocstatus; 203 char buf[32]; 204 uint16_t numReplyFrames; 205 uint16_t queueSize, queueDiff; 206 int simple_sge_main; 207 int simple_sge_next; 208 uint32_t capabilities; 209 uint16_t msgversion; 210 211 bzero(memp, sizeof (*factsreply)); 212 factsreply = (void *)memp; 213 numbytes = sizeof (*factsreply); 214 215 /* 216 * get ioc facts reply message 217 */ 218 if (mptsas_get_handshake_msg(mpt, memp, numbytes, accessp)) { 219 return (DDI_FAILURE); 220 } 221 222 if (iocstatus = ddi_get16(accessp, &factsreply->IOCStatus)) { 223 mptsas_log(mpt, CE_WARN, "mptsas_ioc_do_get_facts_reply: " 224 "IOCStatus=0x%x, IOCLogInfo=0x%x", iocstatus, 225 ddi_get32(accessp, &factsreply->IOCLogInfo)); 226 return (DDI_FAILURE); 227 } 228 229 /* 230 * store key values from reply to mpt structure 231 */ 232 mpt->m_fwversion = ddi_get32(accessp, &factsreply->FWVersion.Word); 233 mpt->m_productid = ddi_get16(accessp, &factsreply->ProductID); 234 235 236 (void) sprintf(buf, "%u.%u.%u.%u", 237 ddi_get8(accessp, &factsreply->FWVersion.Struct.Major), 238 ddi_get8(accessp, &factsreply->FWVersion.Struct.Minor), 239 ddi_get8(accessp, &factsreply->FWVersion.Struct.Unit), 240 ddi_get8(accessp, &factsreply->FWVersion.Struct.Dev)); 241 mptsas_log(mpt, CE_NOTE, "?MPT Firmware version v%s (%s)\n", 242 buf, mptsas_devid_type_string(mpt)); 243 (void) ddi_prop_update_string(DDI_DEV_T_NONE, mpt->m_dip, 244 "firmware-version", buf); 245 246 /* 247 * Set up request info. 248 */ 249 mpt->m_max_requests = ddi_get16(accessp, 250 &factsreply->RequestCredit) - 1; 251 mpt->m_req_frame_size = ddi_get16(accessp, 252 &factsreply->IOCRequestFrameSize) * 4; 253 254 /* 255 * Size of reply free queue should be the number of requests 256 * plus some additional for events (32). Make sure number of 257 * reply frames is not a multiple of 16 so that the queue sizes 258 * are calculated correctly later to be a multiple of 16. 259 */ 260 mpt->m_reply_frame_size = ddi_get8(accessp, 261 &factsreply->ReplyFrameSize) * 4; 262 numReplyFrames = mpt->m_max_requests + 32; 263 if (!(numReplyFrames % 16)) { 264 numReplyFrames--; 265 } 266 mpt->m_max_replies = numReplyFrames; 267 queueSize = numReplyFrames; 268 queueSize += 16 - (queueSize % 16); 269 mpt->m_free_queue_depth = queueSize; 270 271 /* 272 * Size of reply descriptor post queue should be the number of 273 * request frames + the number of reply frames + 1 and needs to 274 * be a multiple of 16. This size can be no larger than 275 * MaxReplyDescriptorPostQueueDepth from IOCFacts. If the 276 * calculated queue size is larger than allowed, subtract a 277 * multiple of 16 from m_max_requests, m_max_replies, and 278 * m_reply_free_depth. 279 */ 280 queueSize = mpt->m_max_requests + numReplyFrames + 1; 281 if (queueSize % 16) { 282 queueSize += 16 - (queueSize % 16); 283 } 284 mpt->m_post_queue_depth = ddi_get16(accessp, 285 &factsreply->MaxReplyDescriptorPostQueueDepth); 286 if (queueSize > mpt->m_post_queue_depth) { 287 queueDiff = queueSize - mpt->m_post_queue_depth; 288 if (queueDiff % 16) { 289 queueDiff += 16 - (queueDiff % 16); 290 } 291 mpt->m_max_requests -= queueDiff; 292 mpt->m_max_replies -= queueDiff; 293 mpt->m_free_queue_depth -= queueDiff; 294 queueSize -= queueDiff; 295 } 296 mpt->m_post_queue_depth = queueSize; 297 298 /* 299 * Set up max chain depth. 300 */ 301 mpt->m_max_chain_depth = ddi_get8(accessp, 302 &factsreply->MaxChainDepth); 303 mpt->m_ioc_capabilities = ddi_get32(accessp, 304 &factsreply->IOCCapabilities); 305 306 /* 307 * Set flag to check for SAS3 support. 308 */ 309 msgversion = ddi_get16(accessp, &factsreply->MsgVersion); 310 if (msgversion >= MPI2_VERSION_02_05) { 311 mptsas_log(mpt, CE_NOTE, "?mpt_sas%d SAS 3 Supported\n", 312 mpt->m_instance); 313 mpt->m_MPI25 = TRUE; 314 } else { 315 mptsas_log(mpt, CE_NOTE, "?mpt_sas%d MPI Version 0x%x\n", 316 mpt->m_instance, msgversion); 317 } 318 319 /* 320 * Calculate max frames per request based on DMA S/G length. 321 */ 322 simple_sge_main = MPTSAS_MAX_FRAME_SGES64(mpt) - 1; 323 simple_sge_next = mpt->m_req_frame_size / MPTSAS_SGE_SIZE(mpt) - 1; 324 325 mpt->m_max_request_frames = (MPTSAS_MAX_DMA_SEGS - 326 simple_sge_main) / simple_sge_next + 1; 327 if (((MPTSAS_MAX_DMA_SEGS - simple_sge_main) % 328 simple_sge_next) > 1) { 329 mpt->m_max_request_frames++; 330 } 331 332 /* 333 * Check if controller supports FW diag buffers and set flag to enable 334 * each type. 335 */ 336 capabilities = ddi_get32(accessp, &factsreply->IOCCapabilities); 337 if (capabilities & MPI2_IOCFACTS_CAPABILITY_DIAG_TRACE_BUFFER) { 338 mpt->m_fw_diag_buffer_list[MPI2_DIAG_BUF_TYPE_TRACE].enabled = 339 TRUE; 340 } 341 if (capabilities & MPI2_IOCFACTS_CAPABILITY_SNAPSHOT_BUFFER) { 342 mpt->m_fw_diag_buffer_list[MPI2_DIAG_BUF_TYPE_SNAPSHOT]. 343 enabled = TRUE; 344 } 345 if (capabilities & MPI2_IOCFACTS_CAPABILITY_EXTENDED_BUFFER) { 346 mpt->m_fw_diag_buffer_list[MPI2_DIAG_BUF_TYPE_EXTENDED]. 347 enabled = TRUE; 348 } 349 350 /* 351 * Check if controller supports replaying events when issuing Message 352 * Unit Reset and set flag to enable MUR. 353 */ 354 if (capabilities & MPI2_IOCFACTS_CAPABILITY_EVENT_REPLAY) { 355 mpt->m_event_replay = TRUE; 356 } 357 358 /* 359 * Check if controller supports IR. 360 */ 361 if (capabilities & MPI2_IOCFACTS_CAPABILITY_INTEGRATED_RAID) { 362 mpt->m_ir_capable = TRUE; 363 } 364 365 return (DDI_SUCCESS); 366 } 367 368 int 369 mptsas_ioc_get_port_facts(mptsas_t *mpt, int port) 370 { 371 /* 372 * Send get port facts message 373 */ 374 if (mptsas_do_dma(mpt, sizeof (MPI2_PORT_FACTS_REQUEST), port, 375 mptsas_ioc_do_get_port_facts)) { 376 return (DDI_FAILURE); 377 } 378 379 /* 380 * Get port facts reply message 381 */ 382 if (mptsas_do_dma(mpt, sizeof (MPI2_PORT_FACTS_REPLY), port, 383 mptsas_ioc_do_get_port_facts_reply)) { 384 return (DDI_FAILURE); 385 } 386 387 return (DDI_SUCCESS); 388 } 389 390 static int 391 mptsas_ioc_do_get_port_facts(mptsas_t *mpt, caddr_t memp, int var, 392 ddi_acc_handle_t accessp) 393 { 394 pMpi2PortFactsRequest_t facts; 395 int numbytes; 396 397 bzero(memp, sizeof (*facts)); 398 facts = (void *)memp; 399 ddi_put8(accessp, &facts->Function, MPI2_FUNCTION_PORT_FACTS); 400 ddi_put8(accessp, &facts->PortNumber, var); 401 numbytes = sizeof (*facts); 402 403 /* 404 * Send port facts message via handshake 405 */ 406 if (mptsas_send_handshake_msg(mpt, memp, numbytes, accessp)) { 407 return (DDI_FAILURE); 408 } 409 410 return (DDI_SUCCESS); 411 } 412 413 static int 414 mptsas_ioc_do_get_port_facts_reply(mptsas_t *mpt, caddr_t memp, int var, 415 ddi_acc_handle_t accessp) 416 { 417 #ifndef __lock_lint 418 _NOTE(ARGUNUSED(var)) 419 #endif 420 pMpi2PortFactsReply_t factsreply; 421 int numbytes; 422 uint_t iocstatus; 423 424 bzero(memp, sizeof (*factsreply)); 425 factsreply = (void *)memp; 426 numbytes = sizeof (*factsreply); 427 428 /* 429 * Get port facts reply message via handshake 430 */ 431 if (mptsas_get_handshake_msg(mpt, memp, numbytes, accessp)) { 432 return (DDI_FAILURE); 433 } 434 435 if (iocstatus = ddi_get16(accessp, &factsreply->IOCStatus)) { 436 mptsas_log(mpt, CE_WARN, "mptsas_ioc_do_get_port_facts_reply: " 437 "IOCStatus=0x%x, IOCLogInfo=0x%x", iocstatus, 438 ddi_get32(accessp, &factsreply->IOCLogInfo)); 439 return (DDI_FAILURE); 440 } 441 442 return (DDI_SUCCESS); 443 } 444 445 int 446 mptsas_ioc_enable_port(mptsas_t *mpt) 447 { 448 /* 449 * Send enable port message 450 */ 451 if (mptsas_do_dma(mpt, sizeof (MPI2_PORT_ENABLE_REQUEST), 0, 452 mptsas_ioc_do_enable_port)) { 453 return (DDI_FAILURE); 454 } 455 456 /* 457 * Get enable port reply message 458 */ 459 if (mptsas_do_dma(mpt, sizeof (MPI2_PORT_ENABLE_REPLY), 0, 460 mptsas_ioc_do_enable_port_reply)) { 461 return (DDI_FAILURE); 462 } 463 464 return (DDI_SUCCESS); 465 } 466 467 static int 468 mptsas_ioc_do_enable_port(mptsas_t *mpt, caddr_t memp, int var, 469 ddi_acc_handle_t accessp) 470 { 471 #ifndef __lock_lint 472 _NOTE(ARGUNUSED(var)) 473 #endif 474 pMpi2PortEnableRequest_t enable; 475 int numbytes; 476 477 bzero(memp, sizeof (*enable)); 478 enable = (void *)memp; 479 ddi_put8(accessp, &enable->Function, MPI2_FUNCTION_PORT_ENABLE); 480 numbytes = sizeof (*enable); 481 482 /* 483 * Send message via handshake 484 */ 485 if (mptsas_send_handshake_msg(mpt, memp, numbytes, accessp)) { 486 return (DDI_FAILURE); 487 } 488 489 return (DDI_SUCCESS); 490 } 491 492 static int 493 mptsas_ioc_do_enable_port_reply(mptsas_t *mpt, caddr_t memp, int var, 494 ddi_acc_handle_t accessp) 495 { 496 #ifndef __lock_lint 497 _NOTE(ARGUNUSED(var)) 498 #endif 499 500 int numbytes; 501 uint_t iocstatus; 502 pMpi2PortEnableReply_t portreply; 503 504 numbytes = sizeof (MPI2_PORT_ENABLE_REPLY); 505 bzero(memp, numbytes); 506 portreply = (void *)memp; 507 508 /* 509 * Get message via handshake 510 */ 511 if (mptsas_get_handshake_msg(mpt, memp, numbytes, accessp)) { 512 return (DDI_FAILURE); 513 } 514 515 if (iocstatus = ddi_get16(accessp, &portreply->IOCStatus)) { 516 mptsas_log(mpt, CE_WARN, "mptsas_ioc_do_enable_port_reply: " 517 "IOCStatus=0x%x, IOCLogInfo=0x%x", iocstatus, 518 ddi_get32(accessp, &portreply->IOCLogInfo)); 519 return (DDI_FAILURE); 520 } 521 522 return (DDI_SUCCESS); 523 } 524 525 int 526 mptsas_ioc_enable_event_notification(mptsas_t *mpt) 527 { 528 ASSERT(mutex_owned(&mpt->m_mutex)); 529 530 /* 531 * Send enable event notification message 532 */ 533 if (mptsas_do_dma(mpt, sizeof (MPI2_EVENT_NOTIFICATION_REQUEST), NULL, 534 mptsas_ioc_do_enable_event_notification)) { 535 return (DDI_FAILURE); 536 } 537 538 /* 539 * Get enable event reply message 540 */ 541 if (mptsas_do_dma(mpt, sizeof (MPI2_EVENT_NOTIFICATION_REPLY), NULL, 542 mptsas_ioc_do_enable_event_notification_reply)) { 543 return (DDI_FAILURE); 544 } 545 546 return (DDI_SUCCESS); 547 } 548 549 static int 550 mptsas_ioc_do_enable_event_notification(mptsas_t *mpt, caddr_t memp, int var, 551 ddi_acc_handle_t accessp) 552 { 553 #ifndef __lock_lint 554 _NOTE(ARGUNUSED(var)) 555 #endif 556 557 pMpi2EventNotificationRequest_t event; 558 int numbytes; 559 560 bzero(memp, sizeof (*event)); 561 event = (void *)memp; 562 ddi_put8(accessp, &event->Function, MPI2_FUNCTION_EVENT_NOTIFICATION); 563 numbytes = sizeof (*event); 564 565 /* 566 * Send message via handshake 567 */ 568 if (mptsas_send_handshake_msg(mpt, memp, numbytes, accessp)) { 569 return (DDI_FAILURE); 570 } 571 572 return (DDI_SUCCESS); 573 } 574 575 static int 576 mptsas_ioc_do_enable_event_notification_reply(mptsas_t *mpt, caddr_t memp, 577 int var, ddi_acc_handle_t accessp) 578 { 579 #ifndef __lock_lint 580 _NOTE(ARGUNUSED(var)) 581 #endif 582 int numbytes; 583 uint_t iocstatus; 584 pMpi2EventNotificationReply_t eventsreply; 585 586 numbytes = sizeof (MPI2_EVENT_NOTIFICATION_REPLY); 587 bzero(memp, numbytes); 588 eventsreply = (void *)memp; 589 590 /* 591 * Get message via handshake 592 */ 593 if (mptsas_get_handshake_msg(mpt, memp, numbytes, accessp)) { 594 return (DDI_FAILURE); 595 } 596 597 if (iocstatus = ddi_get16(accessp, &eventsreply->IOCStatus)) { 598 mptsas_log(mpt, CE_WARN, 599 "mptsas_ioc_do_enable_event_notification_reply: " 600 "IOCStatus=0x%x, IOCLogInfo=0x%x", iocstatus, 601 ddi_get32(accessp, &eventsreply->IOCLogInfo)); 602 return (DDI_FAILURE); 603 } 604 605 return (DDI_SUCCESS); 606 } 607 608 int 609 mptsas_ioc_init(mptsas_t *mpt) 610 { 611 /* 612 * Send ioc init message 613 */ 614 if (mptsas_do_dma(mpt, sizeof (MPI2_IOC_INIT_REQUEST), NULL, 615 mptsas_do_ioc_init)) { 616 return (DDI_FAILURE); 617 } 618 619 /* 620 * Get ioc init reply message 621 */ 622 if (mptsas_do_dma(mpt, sizeof (MPI2_IOC_INIT_REPLY), NULL, 623 mptsas_do_ioc_init_reply)) { 624 return (DDI_FAILURE); 625 } 626 627 return (DDI_SUCCESS); 628 } 629 630 static int 631 mptsas_do_ioc_init(mptsas_t *mpt, caddr_t memp, int var, 632 ddi_acc_handle_t accessp) 633 { 634 #ifndef __lock_lint 635 _NOTE(ARGUNUSED(var)) 636 #endif 637 638 pMpi2IOCInitRequest_t init; 639 int numbytes; 640 timespec_t time; 641 uint64_t mSec; 642 643 bzero(memp, sizeof (*init)); 644 init = (void *)memp; 645 ddi_put8(accessp, &init->Function, MPI2_FUNCTION_IOC_INIT); 646 ddi_put8(accessp, &init->WhoInit, MPI2_WHOINIT_HOST_DRIVER); 647 ddi_put16(accessp, &init->MsgVersion, MPI2_VERSION); 648 ddi_put16(accessp, &init->HeaderVersion, MPI2_HEADER_VERSION); 649 ddi_put16(accessp, &init->SystemRequestFrameSize, 650 mpt->m_req_frame_size / 4); 651 ddi_put16(accessp, &init->ReplyDescriptorPostQueueDepth, 652 mpt->m_post_queue_depth); 653 ddi_put16(accessp, &init->ReplyFreeQueueDepth, 654 mpt->m_free_queue_depth); 655 656 /* 657 * These addresses are set using the DMA cookie addresses from when the 658 * memory was allocated. Sense buffer hi address should be 0. 659 */ 660 ddi_put32(accessp, &init->SenseBufferAddressHigh, 661 (uint32_t)(mpt->m_req_sense_dma_addr >> 32)); 662 ddi_put32(accessp, &init->SystemReplyAddressHigh, 663 (uint32_t)(mpt->m_reply_frame_dma_addr >> 32)); 664 ddi_put32(accessp, &init->SystemRequestFrameBaseAddress.High, 665 (uint32_t)(mpt->m_req_frame_dma_addr >> 32)); 666 ddi_put32(accessp, &init->SystemRequestFrameBaseAddress.Low, 667 (uint32_t)mpt->m_req_frame_dma_addr); 668 ddi_put32(accessp, &init->ReplyDescriptorPostQueueAddress.High, 669 (uint32_t)(mpt->m_post_queue_dma_addr >> 32)); 670 ddi_put32(accessp, &init->ReplyDescriptorPostQueueAddress.Low, 671 (uint32_t)mpt->m_post_queue_dma_addr); 672 ddi_put32(accessp, &init->ReplyFreeQueueAddress.High, 673 (uint32_t)(mpt->m_free_queue_dma_addr >> 32)); 674 ddi_put32(accessp, &init->ReplyFreeQueueAddress.Low, 675 (uint32_t)mpt->m_free_queue_dma_addr); 676 677 /* 678 * Fill in the timestamp with the number of milliseconds since midnight 679 * of January 1, 1970 UT (Greenwich Mean Time). Time is returned in 680 * seconds and nanoseconds. Translate both to milliseconds and add 681 * them together to get total milliseconds. 682 */ 683 gethrestime(&time); 684 mSec = time.tv_sec * MILLISEC; 685 mSec += (time.tv_nsec / MICROSEC); 686 ddi_put32(accessp, &init->TimeStamp.High, (uint32_t)(mSec >> 32)); 687 ddi_put32(accessp, &init->TimeStamp.Low, (uint32_t)mSec); 688 689 numbytes = sizeof (*init); 690 691 /* 692 * Post message via handshake 693 */ 694 if (mptsas_send_handshake_msg(mpt, memp, numbytes, accessp)) { 695 return (DDI_FAILURE); 696 } 697 698 return (DDI_SUCCESS); 699 } 700 701 static int 702 mptsas_do_ioc_init_reply(mptsas_t *mpt, caddr_t memp, int var, 703 ddi_acc_handle_t accessp) 704 { 705 #ifndef __lock_lint 706 _NOTE(ARGUNUSED(var)) 707 #endif 708 709 pMpi2IOCInitReply_t initreply; 710 int numbytes; 711 uint_t iocstatus; 712 713 numbytes = sizeof (MPI2_IOC_INIT_REPLY); 714 bzero(memp, numbytes); 715 initreply = (void *)memp; 716 717 /* 718 * Get reply message via handshake 719 */ 720 if (mptsas_get_handshake_msg(mpt, memp, numbytes, accessp)) { 721 return (DDI_FAILURE); 722 } 723 724 if (iocstatus = ddi_get16(accessp, &initreply->IOCStatus)) { 725 mptsas_log(mpt, CE_WARN, "mptsas_do_ioc_init_reply: " 726 "IOCStatus=0x%x, IOCLogInfo=0x%x", iocstatus, 727 ddi_get32(accessp, &initreply->IOCLogInfo)); 728 return (DDI_FAILURE); 729 } 730 731 if ((ddi_get32(mpt->m_datap, &mpt->m_reg->Doorbell)) & 732 MPI2_IOC_STATE_OPERATIONAL) { 733 mptsas_log(mpt, CE_NOTE, 734 "?mpt%d: IOC Operational.\n", mpt->m_instance); 735 } else { 736 return (DDI_FAILURE); 737 } 738 739 return (DDI_SUCCESS); 740 } 741