xref: /freebsd/sys/dev/mps/mps_sas_lsi.c (revision 9268022b74279434ed6300244e3f977e56a8ceb5)
1 /*-
2  * Copyright (c) 2011, 2012 LSI Corp.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  *
26  * LSI MPT-Fusion Host Adapter FreeBSD
27  */
28 
29 #include <sys/cdefs.h>
30 __FBSDID("$FreeBSD$");
31 
32 /* Communications core for LSI MPT2 */
33 
34 /* TODO Move headers to mpsvar */
35 #include <sys/types.h>
36 #include <sys/param.h>
37 #include <sys/systm.h>
38 #include <sys/kernel.h>
39 #include <sys/selinfo.h>
40 #include <sys/module.h>
41 #include <sys/bus.h>
42 #include <sys/conf.h>
43 #include <sys/bio.h>
44 #include <sys/malloc.h>
45 #include <sys/uio.h>
46 #include <sys/sysctl.h>
47 #include <sys/endian.h>
48 #include <sys/queue.h>
49 #include <sys/kthread.h>
50 #include <sys/taskqueue.h>
51 #include <sys/sbuf.h>
52 
53 #include <machine/bus.h>
54 #include <machine/resource.h>
55 #include <sys/rman.h>
56 
57 #include <machine/stdarg.h>
58 
59 #include <cam/cam.h>
60 #include <cam/cam_ccb.h>
61 #include <cam/cam_debug.h>
62 #include <cam/cam_sim.h>
63 #include <cam/cam_xpt_sim.h>
64 #include <cam/cam_xpt_periph.h>
65 #include <cam/cam_periph.h>
66 #include <cam/scsi/scsi_all.h>
67 #include <cam/scsi/scsi_message.h>
68 
69 #include <dev/mps/mpi/mpi2_type.h>
70 #include <dev/mps/mpi/mpi2.h>
71 #include <dev/mps/mpi/mpi2_ioc.h>
72 #include <dev/mps/mpi/mpi2_sas.h>
73 #include <dev/mps/mpi/mpi2_cnfg.h>
74 #include <dev/mps/mpi/mpi2_init.h>
75 #include <dev/mps/mpi/mpi2_raid.h>
76 #include <dev/mps/mpi/mpi2_tool.h>
77 #include <dev/mps/mps_ioctl.h>
78 #include <dev/mps/mpsvar.h>
79 #include <dev/mps/mps_table.h>
80 #include <dev/mps/mps_sas.h>
81 
82 /* For Hashed SAS Address creation for SATA Drives */
83 #define MPT2SAS_SN_LEN 20
84 #define MPT2SAS_MN_LEN 40
85 
86 struct mps_fw_event_work {
87 	u16			event;
88 	void			*event_data;
89 	TAILQ_ENTRY(mps_fw_event_work)	ev_link;
90 };
91 
92 union _sata_sas_address {
93 	u8 wwid[8];
94 	struct {
95 		u32 high;
96 		u32 low;
97 	} word;
98 };
99 
100 /*
101  * define the IDENTIFY DEVICE structure
102  */
103 struct _ata_identify_device_data {
104 	u16 reserved1[10];	/* 0-9 */
105 	u16 serial_number[10];	/* 10-19 */
106 	u16 reserved2[7];	/* 20-26 */
107 	u16 model_number[20];	/* 27-46*/
108 	u16 reserved3[209];	/* 47-255*/
109 };
110 static u32 event_count;
111 static void mpssas_fw_work(struct mps_softc *sc,
112     struct mps_fw_event_work *fw_event);
113 static void mpssas_fw_event_free(struct mps_softc *,
114     struct mps_fw_event_work *);
115 static int mpssas_add_device(struct mps_softc *sc, u16 handle, u8 linkrate);
116 static int mpssas_get_sata_identify(struct mps_softc *sc, u16 handle,
117     Mpi2SataPassthroughReply_t *mpi_reply, char *id_buffer, int sz,
118     u32 devinfo);
119 int mpssas_get_sas_address_for_sata_disk(struct mps_softc *sc,
120     u64 *sas_address, u16 handle, u32 device_info);
121 static int mpssas_volume_add(struct mps_softc *sc,
122     u16 handle);
123 static void mpssas_SSU_to_SATA_devices(struct mps_softc *sc);
124 static void mpssas_stop_unit_done(struct cam_periph *periph,
125     union ccb *done_ccb);
126 
127 void
128 mpssas_evt_handler(struct mps_softc *sc, uintptr_t data,
129     MPI2_EVENT_NOTIFICATION_REPLY *event)
130 {
131 	struct mps_fw_event_work *fw_event;
132 	u16 sz;
133 
134 	mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
135 	mps_print_evt_sas(sc, event);
136 	mpssas_record_event(sc, event);
137 
138 	fw_event = malloc(sizeof(struct mps_fw_event_work), M_MPT2,
139 	     M_ZERO|M_NOWAIT);
140 	if (!fw_event) {
141 		printf("%s: allocate failed for fw_event\n", __func__);
142 		return;
143 	}
144 	sz = le16toh(event->EventDataLength) * 4;
145 	fw_event->event_data = malloc(sz, M_MPT2, M_ZERO|M_NOWAIT);
146 	if (!fw_event->event_data) {
147 		printf("%s: allocate failed for event_data\n", __func__);
148 		free(fw_event, M_MPT2);
149 		return;
150 	}
151 
152 	bcopy(event->EventData, fw_event->event_data, sz);
153 	fw_event->event = event->Event;
154 	if ((event->Event == MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST ||
155 	    event->Event == MPI2_EVENT_SAS_ENCL_DEVICE_STATUS_CHANGE ||
156 	    event->Event == MPI2_EVENT_IR_CONFIGURATION_CHANGE_LIST) &&
157 	    sc->track_mapping_events)
158 		sc->pending_map_events++;
159 
160 	/*
161 	 * When wait_for_port_enable flag is set, make sure that all the events
162 	 * are processed. Increment the startup_refcount and decrement it after
163 	 * events are processed.
164 	 */
165 	if ((event->Event == MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST ||
166 	    event->Event == MPI2_EVENT_IR_CONFIGURATION_CHANGE_LIST) &&
167 	    sc->wait_for_port_enable)
168 		mpssas_startup_increment(sc->sassc);
169 
170 	TAILQ_INSERT_TAIL(&sc->sassc->ev_queue, fw_event, ev_link);
171 	taskqueue_enqueue(sc->sassc->ev_tq, &sc->sassc->ev_task);
172 
173 }
174 
175 static void
176 mpssas_fw_event_free(struct mps_softc *sc, struct mps_fw_event_work *fw_event)
177 {
178 
179 	free(fw_event->event_data, M_MPT2);
180 	free(fw_event, M_MPT2);
181 }
182 
183 /**
184  * _mps_fw_work - delayed task for processing firmware events
185  * @sc: per adapter object
186  * @fw_event: The fw_event_work object
187  * Context: user.
188  *
189  * Return nothing.
190  */
191 static void
192 mpssas_fw_work(struct mps_softc *sc, struct mps_fw_event_work *fw_event)
193 {
194 	struct mpssas_softc *sassc;
195 	sassc = sc->sassc;
196 
197 	mps_dprint(sc, MPS_EVENT, "(%d)->(%s) Working on  Event: [%x]\n",
198 			event_count++,__func__,fw_event->event);
199 	switch (fw_event->event) {
200 	case MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST:
201 	{
202 		MPI2_EVENT_DATA_SAS_TOPOLOGY_CHANGE_LIST *data;
203 		MPI2_EVENT_SAS_TOPO_PHY_ENTRY *phy;
204 		int i;
205 
206 		data = (MPI2_EVENT_DATA_SAS_TOPOLOGY_CHANGE_LIST *)
207 		    fw_event->event_data;
208 
209 		mps_mapping_topology_change_event(sc, fw_event->event_data);
210 
211 		for (i = 0; i < data->NumEntries; i++) {
212 			phy = &data->PHY[i];
213 			switch (phy->PhyStatus & MPI2_EVENT_SAS_TOPO_RC_MASK) {
214 			case MPI2_EVENT_SAS_TOPO_RC_TARG_ADDED:
215 				if (mpssas_add_device(sc,
216 				    le16toh(phy->AttachedDevHandle), phy->LinkRate)){
217 					printf("%s: failed to add device with "
218 					    "handle 0x%x\n", __func__,
219 					    le16toh(phy->AttachedDevHandle));
220 					mpssas_prepare_remove(sassc, le16toh(
221 						phy->AttachedDevHandle));
222 				}
223 				break;
224 			case MPI2_EVENT_SAS_TOPO_RC_TARG_NOT_RESPONDING:
225 				mpssas_prepare_remove(sassc,le16toh(
226 					phy->AttachedDevHandle));
227 				break;
228 			case MPI2_EVENT_SAS_TOPO_RC_PHY_CHANGED:
229 			case MPI2_EVENT_SAS_TOPO_RC_NO_CHANGE:
230 			case MPI2_EVENT_SAS_TOPO_RC_DELAY_NOT_RESPONDING:
231 			default:
232 				break;
233 			}
234 		}
235 		/*
236 		 * refcount was incremented for this event in
237 		 * mpssas_evt_handler.  Decrement it here because the event has
238 		 * been processed.
239 		 */
240 		mpssas_startup_decrement(sassc);
241 		break;
242 	}
243 	case MPI2_EVENT_SAS_DISCOVERY:
244 	{
245 		MPI2_EVENT_DATA_SAS_DISCOVERY *data;
246 
247 		data = (MPI2_EVENT_DATA_SAS_DISCOVERY *)fw_event->event_data;
248 
249 		if (data->ReasonCode & MPI2_EVENT_SAS_DISC_RC_STARTED)
250 			mps_dprint(sc, MPS_TRACE,"SAS discovery start event\n");
251 		if (data->ReasonCode & MPI2_EVENT_SAS_DISC_RC_COMPLETED) {
252 			mps_dprint(sc, MPS_TRACE,"SAS discovery stop event\n");
253 			sassc->flags &= ~MPSSAS_IN_DISCOVERY;
254 			mpssas_discovery_end(sassc);
255 		}
256 		break;
257 	}
258 	case MPI2_EVENT_SAS_ENCL_DEVICE_STATUS_CHANGE:
259 	{
260 		Mpi2EventDataSasEnclDevStatusChange_t *data;
261 		data = (Mpi2EventDataSasEnclDevStatusChange_t *)
262 		    fw_event->event_data;
263 		mps_mapping_enclosure_dev_status_change_event(sc,
264 		    fw_event->event_data);
265 		break;
266 	}
267 	case MPI2_EVENT_IR_CONFIGURATION_CHANGE_LIST:
268 	{
269 		Mpi2EventIrConfigElement_t *element;
270 		int i;
271 		u8 foreign_config;
272 		Mpi2EventDataIrConfigChangeList_t *event_data;
273 		struct mpssas_target *targ;
274 		unsigned int id;
275 
276 		event_data = fw_event->event_data;
277 		foreign_config = (le32toh(event_data->Flags) &
278 		    MPI2_EVENT_IR_CHANGE_FLAGS_FOREIGN_CONFIG) ? 1 : 0;
279 
280 		element =
281 		    (Mpi2EventIrConfigElement_t *)&event_data->ConfigElement[0];
282 		id = mps_mapping_get_raid_id_from_handle
283 		    (sc, element->VolDevHandle);
284 
285 		mps_mapping_ir_config_change_event(sc, event_data);
286 
287 		for (i = 0; i < event_data->NumElements; i++, element++) {
288 			switch (element->ReasonCode) {
289 			case MPI2_EVENT_IR_CHANGE_RC_VOLUME_CREATED:
290 			case MPI2_EVENT_IR_CHANGE_RC_ADDED:
291 				if (!foreign_config) {
292 					if (mpssas_volume_add(sc, le16toh(element->VolDevHandle))){
293 						printf("%s: failed to add RAID "
294 						    "volume with handle 0x%x\n",
295 						    __func__, le16toh(element->
296 						    VolDevHandle));
297 					}
298 				}
299 				break;
300 			case MPI2_EVENT_IR_CHANGE_RC_VOLUME_DELETED:
301 			case MPI2_EVENT_IR_CHANGE_RC_REMOVED:
302 				/*
303 				 * Rescan after volume is deleted or removed.
304 				 */
305 				if (!foreign_config) {
306 					if (id == MPS_MAP_BAD_ID) {
307 						printf("%s: could not get ID "
308 						    "for volume with handle "
309 						    "0x%04x\n", __func__,
310 						    le16toh(element->VolDevHandle));
311 						break;
312 					}
313 
314 					targ = &sassc->targets[id];
315 					targ->handle = 0x0;
316 					targ->encl_slot = 0x0;
317 					targ->encl_handle = 0x0;
318 					targ->exp_dev_handle = 0x0;
319 					targ->phy_num = 0x0;
320 					targ->linkrate = 0x0;
321 					mpssas_rescan_target(sc, targ);
322 					printf("RAID target id 0x%x removed\n",
323 					    targ->tid);
324 				}
325 				break;
326 			case MPI2_EVENT_IR_CHANGE_RC_PD_CREATED:
327 			case MPI2_EVENT_IR_CHANGE_RC_HIDE:
328 				/*
329 				 * Phys Disk of a volume has been created.  Hide
330 				 * it from the OS.
331 				 */
332 				targ = mpssas_find_target_by_handle(sassc, 0, element->PhysDiskDevHandle);
333 				if (targ == NULL)
334 					break;
335 
336 				/* Set raid component flags only if it is not WD.
337 				 * OR WrapDrive with WD_HIDE_ALWAYS/WD_HIDE_IF_VOLUME is set in NVRAM
338 				 */
339 				if((!sc->WD_available) ||
340 				((sc->WD_available &&
341 				(sc->WD_hide_expose == MPS_WD_HIDE_ALWAYS)) ||
342 				(sc->WD_valid_config && (sc->WD_hide_expose ==
343 				MPS_WD_HIDE_IF_VOLUME)))) {
344 					targ->flags |= MPS_TARGET_FLAGS_RAID_COMPONENT;
345 				}
346 				mpssas_rescan_target(sc, targ);
347 
348 				break;
349 			case MPI2_EVENT_IR_CHANGE_RC_PD_DELETED:
350 				/*
351 				 * Phys Disk of a volume has been deleted.
352 				 * Expose it to the OS.
353 				 */
354 				if (mpssas_add_device(sc,
355 				    le16toh(element->PhysDiskDevHandle), 0)){
356 					printf("%s: failed to add device with "
357 					    "handle 0x%x\n", __func__,
358 					    le16toh(element->PhysDiskDevHandle));
359 					mpssas_prepare_remove(sassc, le16toh(element->
360 					    PhysDiskDevHandle));
361 				}
362 				break;
363 			}
364 		}
365 		/*
366 		 * refcount was incremented for this event in
367 		 * mpssas_evt_handler.  Decrement it here because the event has
368 		 * been processed.
369 		 */
370 		mpssas_startup_decrement(sassc);
371 		break;
372 	}
373 	case MPI2_EVENT_IR_VOLUME:
374 	{
375 		Mpi2EventDataIrVolume_t *event_data = fw_event->event_data;
376 
377 		/*
378 		 * Informational only.
379 		 */
380 		mps_dprint(sc, MPS_EVENT, "Received IR Volume event:\n");
381 		switch (event_data->ReasonCode) {
382 		case MPI2_EVENT_IR_VOLUME_RC_SETTINGS_CHANGED:
383   			mps_dprint(sc, MPS_EVENT, "   Volume Settings "
384   			    "changed from 0x%x to 0x%x for Volome with "
385  			    "handle 0x%x", le32toh(event_data->PreviousValue),
386  			    le32toh(event_data->NewValue),
387  			    le16toh(event_data->VolDevHandle));
388 			break;
389 		case MPI2_EVENT_IR_VOLUME_RC_STATUS_FLAGS_CHANGED:
390   			mps_dprint(sc, MPS_EVENT, "   Volume Status "
391   			    "changed from 0x%x to 0x%x for Volome with "
392  			    "handle 0x%x", le32toh(event_data->PreviousValue),
393  			    le32toh(event_data->NewValue),
394  			    le16toh(event_data->VolDevHandle));
395 			break;
396 		case MPI2_EVENT_IR_VOLUME_RC_STATE_CHANGED:
397   			mps_dprint(sc, MPS_EVENT, "   Volume State "
398   			    "changed from 0x%x to 0x%x for Volome with "
399  			    "handle 0x%x", le32toh(event_data->PreviousValue),
400  			    le32toh(event_data->NewValue),
401  			    le16toh(event_data->VolDevHandle));
402 				u32 state;
403 				struct mpssas_target *targ;
404 				state = le32toh(event_data->NewValue);
405 				switch (state) {
406 				case MPI2_RAID_VOL_STATE_MISSING:
407 				case MPI2_RAID_VOL_STATE_FAILED:
408 					mpssas_prepare_volume_remove(sassc, event_data->
409 							VolDevHandle);
410 					break;
411 
412 				case MPI2_RAID_VOL_STATE_ONLINE:
413 				case MPI2_RAID_VOL_STATE_DEGRADED:
414 				case MPI2_RAID_VOL_STATE_OPTIMAL:
415 					targ = mpssas_find_target_by_handle(sassc, 0, event_data->VolDevHandle);
416 					if (targ) {
417 						printf("%s %d: Volume handle 0x%x is already added \n",
418 							       	__func__, __LINE__ , event_data->VolDevHandle);
419 						break;
420 					}
421 					if (mpssas_volume_add(sc, le16toh(event_data->VolDevHandle))) {
422 						printf("%s: failed to add RAID "
423 							"volume with handle 0x%x\n",
424 							__func__, le16toh(event_data->
425 							VolDevHandle));
426 					}
427 					break;
428 				default:
429 					break;
430 				}
431 			break;
432 		default:
433 			break;
434 		}
435 		break;
436 	}
437 	case MPI2_EVENT_IR_PHYSICAL_DISK:
438 	{
439 		Mpi2EventDataIrPhysicalDisk_t *event_data =
440 		    fw_event->event_data;
441 		struct mpssas_target *targ;
442 
443 		/*
444 		 * Informational only.
445 		 */
446 		mps_dprint(sc, MPS_EVENT, "Received IR Phys Disk event:\n");
447 		switch (event_data->ReasonCode) {
448 		case MPI2_EVENT_IR_PHYSDISK_RC_SETTINGS_CHANGED:
449   			mps_dprint(sc, MPS_EVENT, "   Phys Disk Settings "
450   			    "changed from 0x%x to 0x%x for Phys Disk Number "
451   			    "%d and handle 0x%x at Enclosure handle 0x%x, Slot "
452  			    "%d", le32toh(event_data->PreviousValue),
453  			    le32toh(event_data->NewValue),
454  				event_data->PhysDiskNum,
455  			    le16toh(event_data->PhysDiskDevHandle),
456  			    le16toh(event_data->EnclosureHandle), le16toh(event_data->Slot));
457 			break;
458 		case MPI2_EVENT_IR_PHYSDISK_RC_STATUS_FLAGS_CHANGED:
459   			mps_dprint(sc, MPS_EVENT, "   Phys Disk Status changed "
460   			    "from 0x%x to 0x%x for Phys Disk Number %d and "
461   			    "handle 0x%x at Enclosure handle 0x%x, Slot %d",
462  				le32toh(event_data->PreviousValue),
463  			    le32toh(event_data->NewValue), event_data->PhysDiskNum,
464  			    le16toh(event_data->PhysDiskDevHandle),
465  			    le16toh(event_data->EnclosureHandle), le16toh(event_data->Slot));
466 			break;
467 		case MPI2_EVENT_IR_PHYSDISK_RC_STATE_CHANGED:
468   			mps_dprint(sc, MPS_EVENT, "   Phys Disk State changed "
469   			    "from 0x%x to 0x%x for Phys Disk Number %d and "
470   			    "handle 0x%x at Enclosure handle 0x%x, Slot %d",
471  				le32toh(event_data->PreviousValue),
472  			    le32toh(event_data->NewValue), event_data->PhysDiskNum,
473  			    le16toh(event_data->PhysDiskDevHandle),
474  			    le16toh(event_data->EnclosureHandle), le16toh(event_data->Slot));
475 			switch (event_data->NewValue) {
476 				case MPI2_RAID_PD_STATE_ONLINE:
477 				case MPI2_RAID_PD_STATE_DEGRADED:
478 				case MPI2_RAID_PD_STATE_REBUILDING:
479 				case MPI2_RAID_PD_STATE_OPTIMAL:
480 				case MPI2_RAID_PD_STATE_HOT_SPARE:
481 					targ = mpssas_find_target_by_handle(sassc, 0,
482 							event_data->PhysDiskDevHandle);
483 					if (targ) {
484 						if(!sc->WD_available) {
485 							targ->flags |= MPS_TARGET_FLAGS_RAID_COMPONENT;
486 							printf("%s %d: Found Target for handle 0x%x.  \n",
487 							__func__, __LINE__ , event_data->PhysDiskDevHandle);
488 						} else if ((sc->WD_available &&
489 							(sc->WD_hide_expose == MPS_WD_HIDE_ALWAYS)) ||
490         						(sc->WD_valid_config && (sc->WD_hide_expose ==
491         						MPS_WD_HIDE_IF_VOLUME))) {
492 							targ->flags |= MPS_TARGET_FLAGS_RAID_COMPONENT;
493 							printf("%s %d: WD: Found Target for handle 0x%x.  \n",
494 							__func__, __LINE__ , event_data->PhysDiskDevHandle);
495 						}
496  					}
497 				break;
498 				case MPI2_RAID_PD_STATE_OFFLINE:
499 				case MPI2_RAID_PD_STATE_NOT_CONFIGURED:
500 				case MPI2_RAID_PD_STATE_NOT_COMPATIBLE:
501 				default:
502 					targ = mpssas_find_target_by_handle(sassc, 0,
503 							event_data->PhysDiskDevHandle);
504 					if (targ) {
505 						targ->flags |= ~MPS_TARGET_FLAGS_RAID_COMPONENT;
506 						printf("%s %d: Found Target for handle 0x%x.  \n",
507 						__func__, __LINE__ , event_data->PhysDiskDevHandle);
508 					}
509 				break;
510 			}
511 		default:
512 			break;
513 		}
514 		break;
515 	}
516 	case MPI2_EVENT_IR_OPERATION_STATUS:
517 	{
518 		Mpi2EventDataIrOperationStatus_t *event_data =
519 		    fw_event->event_data;
520 
521 		/*
522 		 * Informational only.
523 		 */
524 		mps_dprint(sc, MPS_EVENT, "Received IR Op Status event:\n");
525 		mps_dprint(sc, MPS_EVENT, "   RAID Operation of %d is %d "
526 		    "percent complete for Volume with handle 0x%x",
527 		    event_data->RAIDOperation, event_data->PercentComplete,
528 		    le16toh(event_data->VolDevHandle));
529 		break;
530 	}
531 	case MPI2_EVENT_LOG_ENTRY_ADDED:
532 	{
533 		pMpi2EventDataLogEntryAdded_t	logEntry;
534 		uint16_t			logQualifier;
535 		uint8_t				logCode;
536 
537 		logEntry = (pMpi2EventDataLogEntryAdded_t)fw_event->event_data;
538 		logQualifier = logEntry->LogEntryQualifier;
539 
540 		if (logQualifier == MPI2_WD_LOG_ENTRY) {
541 			logCode = logEntry->LogData[0];
542 
543 			switch (logCode) {
544 			case MPI2_WD_SSD_THROTTLING:
545 				printf("WarpDrive Warning: IO Throttling has "
546 				    "occurred in the WarpDrive subsystem. "
547 				    "Check WarpDrive documentation for "
548 				    "additional details\n");
549 				break;
550 			case MPI2_WD_DRIVE_LIFE_WARN:
551 				printf("WarpDrive Warning: Program/Erase "
552 				    "Cycles for the WarpDrive subsystem in "
553 				    "degraded range. Check WarpDrive "
554 				    "documentation for additional details\n");
555 				break;
556 			case MPI2_WD_DRIVE_LIFE_DEAD:
557 				printf("WarpDrive Fatal Error: There are no "
558 				    "Program/Erase Cycles for the WarpDrive "
559 				    "subsystem. The storage device will be in "
560 				    "read-only mode. Check WarpDrive "
561 				    "documentation for additional details\n");
562 				break;
563 			case MPI2_WD_RAIL_MON_FAIL:
564 				printf("WarpDrive Fatal Error: The Backup Rail "
565 				    "Monitor has failed on the WarpDrive "
566 				    "subsystem. Check WarpDrive documentation "
567 				    "for additional details\n");
568 				break;
569 			default:
570 				break;
571 			}
572 		}
573 		break;
574 	}
575 	case MPI2_EVENT_SAS_DEVICE_STATUS_CHANGE:
576 	case MPI2_EVENT_SAS_BROADCAST_PRIMITIVE:
577 	default:
578 		mps_dprint(sc, MPS_TRACE,"Unhandled event 0x%0X\n",
579 		    fw_event->event);
580 		break;
581 
582 	}
583 	mps_dprint(sc, MPS_EVENT, "(%d)->(%s) Event Free: [%x]\n",event_count,__func__, fw_event->event);
584 	mpssas_fw_event_free(sc, fw_event);
585 }
586 
587 void
588 mpssas_firmware_event_work(void *arg, int pending)
589 {
590 	struct mps_fw_event_work *fw_event;
591 	struct mps_softc *sc;
592 
593 	sc = (struct mps_softc *)arg;
594 	mps_lock(sc);
595 	while ((fw_event = TAILQ_FIRST(&sc->sassc->ev_queue)) != NULL) {
596 		TAILQ_REMOVE(&sc->sassc->ev_queue, fw_event, ev_link);
597 		mpssas_fw_work(sc, fw_event);
598 	}
599 	mps_unlock(sc);
600 }
601 
602 static int
603 mpssas_add_device(struct mps_softc *sc, u16 handle, u8 linkrate){
604 	char devstring[80];
605 	struct mpssas_softc *sassc;
606 	struct mpssas_target *targ;
607 	Mpi2ConfigReply_t mpi_reply;
608 	Mpi2SasDevicePage0_t config_page;
609 	uint64_t sas_address, sata_sas_address;
610 	uint64_t parent_sas_address = 0;
611 	u16 ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags);
612 	u32 device_info, parent_devinfo = 0;
613 	unsigned int id;
614 	int ret;
615 	int error = 0;
616 	struct mpssas_lun *lun;
617 
618 	sassc = sc->sassc;
619 	mpssas_startup_increment(sassc);
620 	if ((mps_config_get_sas_device_pg0(sc, &mpi_reply, &config_page,
621 	     MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, handle))) {
622 		printf("%s: error reading SAS device page0\n", __func__);
623 		error = ENXIO;
624 		goto out;
625 	}
626 
627 	device_info = le32toh(config_page.DeviceInfo);
628 
629 	if (((device_info & MPI2_SAS_DEVICE_INFO_SMP_TARGET) == 0)
630 	 && (le16toh(config_page.ParentDevHandle) != 0)) {
631 		Mpi2ConfigReply_t tmp_mpi_reply;
632 		Mpi2SasDevicePage0_t parent_config_page;
633 
634 		if ((mps_config_get_sas_device_pg0(sc, &tmp_mpi_reply,
635 		     &parent_config_page, MPI2_SAS_DEVICE_PGAD_FORM_HANDLE,
636 		     le16toh(config_page.ParentDevHandle)))) {
637 			printf("%s: error reading SAS device %#x page0\n",
638 			       __func__, le16toh(config_page.ParentDevHandle));
639 		} else {
640 			parent_sas_address = parent_config_page.SASAddress.High;
641 			parent_sas_address = (parent_sas_address << 32) |
642 				parent_config_page.SASAddress.Low;
643 			parent_devinfo = le32toh(parent_config_page.DeviceInfo);
644 		}
645 	}
646 	/* TODO Check proper endianess */
647 	sas_address = config_page.SASAddress.High;
648 	sas_address = (sas_address << 32) |
649 	    config_page.SASAddress.Low;
650 
651 	if ((ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE)
652 		    == MPI2_IOCPAGE8_FLAGS_DEVICE_PERSISTENCE_MAPPING) {
653 		if (device_info & MPI2_SAS_DEVICE_INFO_SATA_DEVICE) {
654 			ret = mpssas_get_sas_address_for_sata_disk(sc,
655 			    &sata_sas_address, handle, device_info);
656 			if (!ret)
657 				id = mps_mapping_get_sas_id(sc,
658 				    sata_sas_address, handle);
659 			else
660 				id = mps_mapping_get_sas_id(sc,
661 				    sas_address, handle);
662 		} else
663 			id = mps_mapping_get_sas_id(sc, sas_address,
664 			    handle);
665 	} else
666 		id = mps_mapping_get_sas_id(sc, sas_address, handle);
667 
668 	if (id == MPS_MAP_BAD_ID) {
669 		printf("failure at %s:%d/%s()! Could not get ID for device "
670 		    "with handle 0x%04x\n", __FILE__, __LINE__, __func__,
671 		    handle);
672 		error = ENXIO;
673 		goto out;
674 	}
675 
676 	if (mpssas_check_id(sassc, id) != 0) {
677 		device_printf(sc->mps_dev, "Excluding target id %d\n", id);
678 		error = ENXIO;
679 		goto out;
680 	}
681 
682 	mps_dprint(sc, MPS_MAPPING, "SAS Address from SAS device page0 = %jx\n",
683 	    sas_address);
684 	targ = &sassc->targets[id];
685 	targ->devinfo = device_info;
686 	targ->devname = le32toh(config_page.DeviceName.High);
687 	targ->devname = (targ->devname << 32) |
688 	    le32toh(config_page.DeviceName.Low);
689 	targ->encl_handle = le16toh(config_page.EnclosureHandle);
690 	targ->encl_slot = le16toh(config_page.Slot);
691 	targ->handle = handle;
692 	targ->parent_handle = le16toh(config_page.ParentDevHandle);
693 	targ->sasaddr = mps_to_u64(&config_page.SASAddress);
694 	targ->parent_sasaddr = le64toh(parent_sas_address);
695 	targ->parent_devinfo = parent_devinfo;
696 	targ->tid = id;
697 	targ->linkrate = (linkrate>>4);
698 	targ->flags = 0;
699 	TAILQ_INIT(&targ->commands);
700 	TAILQ_INIT(&targ->timedout_commands);
701 	while(!SLIST_EMPTY(&targ->luns)) {
702 		lun = SLIST_FIRST(&targ->luns);
703 		SLIST_REMOVE_HEAD(&targ->luns, lun_link);
704 		free(lun, M_MPT2);
705 	}
706 	SLIST_INIT(&targ->luns);
707 
708 	mps_describe_devinfo(targ->devinfo, devstring, 80);
709 	mps_dprint(sc, MPS_MAPPING, "Found device <%s> <%s> <0x%04x> <%d/%d>\n", devstring,
710 	    mps_describe_table(mps_linkrate_names, targ->linkrate),
711 	    targ->handle, targ->encl_handle, targ->encl_slot);
712 
713 #if __FreeBSD_version < 1000039
714 	if ((sassc->flags & MPSSAS_IN_STARTUP) == 0)
715 #endif
716 		mpssas_rescan_target(sc, targ);
717 	mps_dprint(sc, MPS_MAPPING, "Target id 0x%x added\n", targ->tid);
718 out:
719 	mpssas_startup_decrement(sassc);
720 	return (error);
721 
722 }
723 
724 int
725 mpssas_get_sas_address_for_sata_disk(struct mps_softc *sc,
726     u64 *sas_address, u16 handle, u32 device_info)
727 {
728 	Mpi2SataPassthroughReply_t mpi_reply;
729 	int i, rc, try_count;
730 	u32 *bufferptr;
731 	union _sata_sas_address hash_address;
732 	struct _ata_identify_device_data ata_identify;
733 	u8 buffer[MPT2SAS_MN_LEN + MPT2SAS_SN_LEN];
734 	u32 ioc_status;
735 	u8 sas_status;
736 
737 	memset(&ata_identify, 0, sizeof(ata_identify));
738 	try_count = 0;
739 	do {
740 		rc = mpssas_get_sata_identify(sc, handle, &mpi_reply,
741 		    (char *)&ata_identify, sizeof(ata_identify), device_info);
742 		try_count++;
743 		ioc_status = le16toh(mpi_reply.IOCStatus)
744 		    & MPI2_IOCSTATUS_MASK;
745 		sas_status = mpi_reply.SASStatus;
746 	} while ((rc == -EAGAIN || ioc_status || sas_status) &&
747 	    (try_count < 5));
748 
749 	if (rc == 0 && !ioc_status && !sas_status) {
750 		mps_dprint(sc, MPS_MAPPING, "%s: got SATA identify successfully "
751 			   "for handle = 0x%x with try_count = %d\n",
752 			   __func__, handle, try_count);
753 	} else {
754 		mps_dprint(sc, MPS_MAPPING, "%s: handle = 0x%x failed\n",
755 			   __func__, handle);
756 		return -1;
757 	}
758 	/* Copy & byteswap the 40 byte model number to a buffer */
759 	for (i = 0; i < MPT2SAS_MN_LEN; i += 2) {
760 		buffer[i] = ((u8 *)ata_identify.model_number)[i + 1];
761 		buffer[i + 1] = ((u8 *)ata_identify.model_number)[i];
762 	}
763 	/* Copy & byteswap the 20 byte serial number to a buffer */
764 	for (i = 0; i < MPT2SAS_SN_LEN; i += 2) {
765 		buffer[MPT2SAS_MN_LEN + i] =
766 			((u8 *)ata_identify.serial_number)[i + 1];
767 		buffer[MPT2SAS_MN_LEN + i + 1] =
768 			((u8 *)ata_identify.serial_number)[i];
769 	}
770 	bufferptr = (u32 *)buffer;
771 	/* There are 60 bytes to hash down to 8. 60 isn't divisible by 8,
772 	 * so loop through the first 56 bytes (7*8),
773 	 * and then add in the last dword.
774 	 */
775 	hash_address.word.low  = 0;
776 	hash_address.word.high = 0;
777 	for (i = 0; (i < ((MPT2SAS_MN_LEN+MPT2SAS_SN_LEN)/8)); i++) {
778 		hash_address.word.low += *bufferptr;
779 		bufferptr++;
780 		hash_address.word.high += *bufferptr;
781 		bufferptr++;
782 	}
783 	/* Add the last dword */
784 	hash_address.word.low += *bufferptr;
785 	/* Make sure the hash doesn't start with 5, because it could clash
786 	 * with a SAS address. Change 5 to a D.
787 	 */
788 	if ((hash_address.word.high & 0x000000F0) == (0x00000050))
789 		hash_address.word.high |= 0x00000080;
790 	*sas_address = (u64)hash_address.wwid[0] << 56 |
791 	    (u64)hash_address.wwid[1] << 48 | (u64)hash_address.wwid[2] << 40 |
792 	    (u64)hash_address.wwid[3] << 32 | (u64)hash_address.wwid[4] << 24 |
793 	    (u64)hash_address.wwid[5] << 16 | (u64)hash_address.wwid[6] <<  8 |
794 	    (u64)hash_address.wwid[7];
795 	return 0;
796 }
797 
798 static int
799 mpssas_get_sata_identify(struct mps_softc *sc, u16 handle,
800     Mpi2SataPassthroughReply_t *mpi_reply, char *id_buffer, int sz, u32 devinfo)
801 {
802 	Mpi2SataPassthroughRequest_t *mpi_request;
803 	Mpi2SataPassthroughReply_t *reply;
804 	struct mps_command *cm;
805 	char *buffer;
806 	int error = 0;
807 
808 	buffer = malloc( sz, M_MPT2, M_NOWAIT | M_ZERO);
809 	if (!buffer)
810 		return ENOMEM;
811 
812 	if ((cm = mps_alloc_command(sc)) == NULL) {
813 		free(buffer, M_MPT2);
814 		return (EBUSY);
815 	}
816 	mpi_request = (MPI2_SATA_PASSTHROUGH_REQUEST *)cm->cm_req;
817 	bzero(mpi_request,sizeof(MPI2_SATA_PASSTHROUGH_REQUEST));
818 	mpi_request->Function = MPI2_FUNCTION_SATA_PASSTHROUGH;
819 	mpi_request->VF_ID = 0;
820 	mpi_request->DevHandle = htole16(handle);
821 	mpi_request->PassthroughFlags = (MPI2_SATA_PT_REQ_PT_FLAGS_PIO |
822 	    MPI2_SATA_PT_REQ_PT_FLAGS_READ);
823 	mpi_request->DataLength = htole32(sz);
824 	mpi_request->CommandFIS[0] = 0x27;
825 	mpi_request->CommandFIS[1] = 0x80;
826 	mpi_request->CommandFIS[2] =  (devinfo &
827 	    MPI2_SAS_DEVICE_INFO_ATAPI_DEVICE) ? 0xA1 : 0xEC;
828 	cm->cm_sge = &mpi_request->SGL;
829 	cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
830 	cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAIN;
831 	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
832 	cm->cm_data = buffer;
833 	cm->cm_length = htole32(sz);
834  	error = mps_wait_command(sc, cm, 60, CAN_SLEEP);
835 	reply = (Mpi2SataPassthroughReply_t *)cm->cm_reply;
836 	if (error || (reply == NULL)) {
837 		/* FIXME */
838  		/*
839  		 * If the request returns an error then we need to do a diag
840  		 * reset
841  		 */
842  		printf("%s: request for page completed with error %d",
843 		    __func__, error);
844 		error = ENXIO;
845 		goto out;
846 	}
847 	bcopy(buffer, id_buffer, sz);
848 	bcopy(reply, mpi_reply, sizeof(Mpi2SataPassthroughReply_t));
849 	if ((le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK) !=
850 	    MPI2_IOCSTATUS_SUCCESS) {
851 		printf("%s: error reading SATA PASSTHRU; iocstatus = 0x%x\n",
852 		    __func__, reply->IOCStatus);
853 		error = ENXIO;
854 		goto out;
855 	}
856 out:
857 	mps_free_command(sc, cm);
858 	free(buffer, M_MPT2);
859 	return (error);
860 }
861 
862 static int
863 mpssas_volume_add(struct mps_softc *sc, u16 handle)
864 {
865 	struct mpssas_softc *sassc;
866 	struct mpssas_target *targ;
867 	u64 wwid;
868 	unsigned int id;
869 	int error = 0;
870 	struct mpssas_lun *lun;
871 
872 	sassc = sc->sassc;
873 	mpssas_startup_increment(sassc);
874 	/* wwid is endian safe */
875 	mps_config_get_volume_wwid(sc, handle, &wwid);
876 	if (!wwid) {
877 		printf("%s: invalid WWID; cannot add volume to mapping table\n",
878 		    __func__);
879 		error = ENXIO;
880 		goto out;
881 	}
882 
883 	id = mps_mapping_get_raid_id(sc, wwid, handle);
884 	if (id == MPS_MAP_BAD_ID) {
885 		printf("%s: could not get ID for volume with handle 0x%04x and "
886 		    "WWID 0x%016llx\n", __func__, handle,
887 		    (unsigned long long)wwid);
888 		error = ENXIO;
889 		goto out;
890 	}
891 
892 	targ = &sassc->targets[id];
893 	targ->tid = id;
894 	targ->handle = handle;
895 	targ->devname = wwid;
896 	TAILQ_INIT(&targ->commands);
897 	TAILQ_INIT(&targ->timedout_commands);
898 	while(!SLIST_EMPTY(&targ->luns)) {
899 		lun = SLIST_FIRST(&targ->luns);
900 		SLIST_REMOVE_HEAD(&targ->luns, lun_link);
901 		free(lun, M_MPT2);
902 	}
903 	SLIST_INIT(&targ->luns);
904 #if __FreeBSD_version < 1000039
905 	if ((sassc->flags & MPSSAS_IN_STARTUP) == 0)
906 #endif
907 		mpssas_rescan_target(sc, targ);
908 	mps_dprint(sc, MPS_MAPPING, "RAID target id %d added (WWID = 0x%jx)\n",
909 	    targ->tid, wwid);
910 out:
911 	mpssas_startup_decrement(sassc);
912 	return (error);
913 }
914 
915 /**
916  * mpssas_SSU_to_SATA_devices
917  * @sc: per adapter object
918  *
919  * Looks through the target list and issues a StartStopUnit SCSI command to each
920  * SATA direct-access device.  This helps to ensure that data corruption is
921  * avoided when the system is being shut down.  This must be called after the IR
922  * System Shutdown RAID Action is sent if in IR mode.
923  *
924  * Return nothing.
925  */
926 static void
927 mpssas_SSU_to_SATA_devices(struct mps_softc *sc)
928 {
929 	struct mpssas_softc *sassc = sc->sassc;
930 	union ccb *ccb;
931 	path_id_t pathid = cam_sim_path(sassc->sim);
932 	target_id_t targetid;
933 	struct mpssas_target *target;
934 	struct mpssas_lun *lun;
935 	char path_str[64];
936 	struct timeval cur_time, start_time;
937 
938 	/*
939 	 * For each LUN of each target, issue a StartStopUnit command to stop
940 	 * the device.
941 	 */
942 	sc->SSU_started = TRUE;
943 	sc->SSU_refcount = 0;
944 	for (targetid = 0; targetid < sc->facts->MaxTargets; targetid++) {
945 		target = &sassc->targets[targetid];
946 		if (target->handle == 0x0) {
947 			continue;
948 		}
949 
950 		SLIST_FOREACH(lun, &target->luns, lun_link) {
951 			ccb = xpt_alloc_ccb_nowait();
952 			if (ccb == NULL) {
953 				mps_dprint(sc, MPS_FAULT, "Unable to alloc CCB "
954 				    "to stop unit.\n");
955 				return;
956 			}
957 
958 			/*
959 			 * The stop_at_shutdown flag will be set if this LUN is
960 			 * a SATA direct-access end device.
961 			 */
962 			if (lun->stop_at_shutdown) {
963 				if (xpt_create_path(&ccb->ccb_h.path,
964 				    xpt_periph, pathid, targetid,
965 				    lun->lun_id) != CAM_REQ_CMP) {
966 					mps_dprint(sc, MPS_FAULT, "Unable to "
967 					    "create LUN path to stop unit.\n");
968 					xpt_free_ccb(ccb);
969 					return;
970 				}
971 				xpt_path_string(ccb->ccb_h.path, path_str,
972 				    sizeof(path_str));
973 
974 				mps_dprint(sc, MPS_INFO, "Sending StopUnit: "
975 				    "path %s handle %d\n", path_str,
976 				    target->handle);
977 
978 				/*
979 				 * Issue a START STOP UNIT command for the LUN.
980 				 * Increment the SSU counter to be used to
981 				 * count the number of required replies.
982 				 */
983 				mps_dprint(sc, MPS_INFO, "Incrementing SSU "
984 				    "count\n");
985 				sc->SSU_refcount++;
986 				ccb->ccb_h.target_id =
987 				    xpt_path_target_id(ccb->ccb_h.path);
988 				ccb->ccb_h.target_lun = lun->lun_id;
989 				ccb->ccb_h.ppriv_ptr1 = sassc;
990 				scsi_start_stop(&ccb->csio,
991 				    /*retries*/0,
992 				    mpssas_stop_unit_done,
993 				    MSG_SIMPLE_Q_TAG,
994 				    /*start*/FALSE,
995 				    /*load/eject*/0,
996 				    /*immediate*/FALSE,
997 				    MPS_SENSE_LEN,
998 				    /*timeout*/10000);
999 				xpt_action(ccb);
1000 			}
1001 		}
1002 	}
1003 
1004 	/*
1005 	 * Wait until all of the SSU commands have completed or time has
1006 	 * expired (60 seconds).  pause for 100ms each time through.  If any
1007 	 * command times out, the target will be reset in the SCSI command
1008 	 * timeout routine.
1009 	 */
1010 	getmicrotime(&start_time);
1011 	while (sc->SSU_refcount) {
1012 		pause("mpswait", hz/10);
1013 
1014 		getmicrotime(&cur_time);
1015 		if ((cur_time.tv_sec - start_time.tv_sec) > 60) {
1016 			mps_dprint(sc, MPS_FAULT, "Time has expired waiting "
1017 			    "for SSU commands to complete.\n");
1018 			break;
1019 		}
1020 	}
1021 }
1022 
1023 static void
1024 mpssas_stop_unit_done(struct cam_periph *periph, union ccb *done_ccb)
1025 {
1026 	struct mpssas_softc *sassc;
1027 	char path_str[64];
1028 
1029 	sassc = (struct mpssas_softc *)done_ccb->ccb_h.ppriv_ptr1;
1030 
1031 	xpt_path_string(done_ccb->ccb_h.path, path_str, sizeof(path_str));
1032 	mps_dprint(sassc->sc, MPS_INFO, "Completing stop unit for %s\n",
1033 	    path_str);
1034 
1035 	if (done_ccb == NULL)
1036 		return;
1037 
1038 	/*
1039 	 * Nothing more to do except free the CCB and path.  If the command
1040 	 * timed out, an abort reset, then target reset will be issued during
1041 	 * the SCSI Command process.
1042 	 */
1043 	xpt_free_path(done_ccb->ccb_h.path);
1044 	xpt_free_ccb(done_ccb);
1045 }
1046 
1047 /**
1048  * mpssas_ir_shutdown - IR shutdown notification
1049  * @sc: per adapter object
1050  *
1051  * Sending RAID Action to alert the Integrated RAID subsystem of the IOC that
1052  * the host system is shutting down.
1053  *
1054  * Return nothing.
1055  */
1056 void
1057 mpssas_ir_shutdown(struct mps_softc *sc)
1058 {
1059 	u16 volume_mapping_flags;
1060 	u16 ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags);
1061 	struct dev_mapping_table *mt_entry;
1062 	u32 start_idx, end_idx;
1063 	unsigned int id, found_volume = 0;
1064 	struct mps_command *cm;
1065 	Mpi2RaidActionRequest_t	*action;
1066 
1067 	mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
1068 
1069 	/* is IR firmware build loaded? */
1070 	if (!sc->ir_firmware)
1071 		goto out;
1072 
1073 	/* are there any volumes?  Look at IR target IDs. */
1074 	// TODO-later, this should be looked up in the RAID config structure
1075 	// when it is implemented.
1076 	volume_mapping_flags = le16toh(sc->ioc_pg8.IRVolumeMappingFlags) &
1077 	    MPI2_IOCPAGE8_IRFLAGS_MASK_VOLUME_MAPPING_MODE;
1078 	if (volume_mapping_flags == MPI2_IOCPAGE8_IRFLAGS_LOW_VOLUME_MAPPING) {
1079 		start_idx = 0;
1080 		if (ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_RESERVED_TARGETID_0)
1081 			start_idx = 1;
1082 	} else
1083 		start_idx = sc->max_devices - sc->max_volumes;
1084 	end_idx = start_idx + sc->max_volumes - 1;
1085 
1086 	for (id = start_idx; id < end_idx; id++) {
1087 		mt_entry = &sc->mapping_table[id];
1088 		if ((mt_entry->physical_id != 0) &&
1089 		    (mt_entry->missing_count == 0)) {
1090 			found_volume = 1;
1091 			break;
1092 		}
1093 	}
1094 
1095 	if (!found_volume)
1096 		goto out;
1097 
1098 	if ((cm = mps_alloc_command(sc)) == NULL) {
1099 		printf("%s: command alloc failed\n", __func__);
1100 		goto out;
1101 	}
1102 
1103 	action = (MPI2_RAID_ACTION_REQUEST *)cm->cm_req;
1104 	action->Function = MPI2_FUNCTION_RAID_ACTION;
1105 	action->Action = MPI2_RAID_ACTION_SYSTEM_SHUTDOWN_INITIATED;
1106 	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1107 	mps_lock(sc);
1108  	mps_wait_command(sc, cm, 5, CAN_SLEEP);
1109 	mps_unlock(sc);
1110 
1111 	/*
1112 	 * Don't check for reply, just leave.
1113 	 */
1114 	if (cm)
1115 		mps_free_command(sc, cm);
1116 
1117 out:
1118 	mpssas_SSU_to_SATA_devices(sc);
1119 }
1120