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