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