xref: /dragonfly/sys/dev/raid/mps/mps_sas_lsi.c (revision 25a2db75)
1 /*-
2  * Copyright (c) 2011 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  * $FreeBSD: src/sys/dev/mps/mps_sas_lsi.c,v 1.1 2012/01/26 18:17:21 ken Exp $
29  */
30 
31 /* Communications core for LSI MPT2 */
32 
33 /* TODO Move headers to mpsvar */
34 #include <sys/types.h>
35 #include <sys/param.h>
36 #include <sys/systm.h>
37 #include <sys/kernel.h>
38 #include <sys/module.h>
39 #include <sys/bus.h>
40 #include <sys/conf.h>
41 #include <sys/eventhandler.h>
42 #include <sys/bio.h>
43 #include <sys/malloc.h>
44 #include <sys/uio.h>
45 #include <sys/sysctl.h>
46 #include <sys/endian.h>
47 #include <sys/queue.h>
48 #include <sys/kthread.h>
49 #include <sys/taskqueue.h>
50 #include <sys/sbuf.h>
51 
52 #include <sys/rman.h>
53 
54 #include <machine/stdarg.h>
55 
56 #include <bus/cam/cam.h>
57 #include <bus/cam/cam_ccb.h>
58 #include <bus/cam/cam_debug.h>
59 #include <bus/cam/cam_sim.h>
60 #include <bus/cam/cam_xpt_sim.h>
61 #include <bus/cam/cam_xpt_periph.h>
62 #include <bus/cam/cam_periph.h>
63 #include <bus/cam/scsi/scsi_all.h>
64 #include <bus/cam/scsi/scsi_message.h>
65 
66 #include <dev/raid/mps/mpi/mpi2_type.h>
67 #include <dev/raid/mps/mpi/mpi2.h>
68 #include <dev/raid/mps/mpi/mpi2_ioc.h>
69 #include <dev/raid/mps/mpi/mpi2_sas.h>
70 #include <dev/raid/mps/mpi/mpi2_cnfg.h>
71 #include <dev/raid/mps/mpi/mpi2_init.h>
72 #include <dev/raid/mps/mpi/mpi2_raid.h>
73 #include <dev/raid/mps/mpi/mpi2_tool.h>
74 #include <dev/raid/mps/mps_ioctl.h>
75 #include <dev/raid/mps/mpsvar.h>
76 #include <dev/raid/mps/mps_table.h>
77 #include <dev/raid/mps/mps_sas.h>
78 
79 /* For Hashed SAS Address creation for SATA Drives */
80 #define MPT2SAS_SN_LEN 20
81 #define MPT2SAS_MN_LEN 40
82 
83 struct mps_fw_event_work {
84 	u16			event;
85 	void			*event_data;
86 	TAILQ_ENTRY(mps_fw_event_work)	ev_link;
87 };
88 
89 union _sata_sas_address {
90 	u8 wwid[8];
91 	struct {
92 		u32 high;
93 		u32 low;
94 	} word;
95 };
96 
97 /*
98  * define the IDENTIFY DEVICE structure
99  */
100 struct _ata_identify_device_data {
101 	u16 reserved1[10];	/* 0-9 */
102 	u16 serial_number[10];	/* 10-19 */
103 	u16 reserved2[7];	/* 20-26 */
104 	u16 model_number[20];	/* 27-46*/
105 	u16 reserved3[209];	/* 47-255*/
106 };
107 
108 static void mpssas_fw_work(struct mps_softc *sc,
109     struct mps_fw_event_work *fw_event);
110 static void mpssas_fw_event_free(struct mps_softc *,
111     struct mps_fw_event_work *);
112 static int mpssas_add_device(struct mps_softc *sc, u16 handle, u8 linkrate);
113 static int mpssas_get_sata_identify(struct mps_softc *sc, u16 handle,
114     Mpi2SataPassthroughReply_t *mpi_reply, char *id_buffer, int sz,
115     u32 devinfo);
116 int mpssas_get_sas_address_for_sata_disk(struct mps_softc *sc,
117     u64 *sas_address, u16 handle, u32 device_info);
118 static int mpssas_volume_add(struct mps_softc *sc,
119     Mpi2EventIrConfigElement_t *element);
120 
121 void
122 mpssas_evt_handler(struct mps_softc *sc, uintptr_t data,
123     MPI2_EVENT_NOTIFICATION_REPLY *event)
124 {
125 	struct mps_fw_event_work *fw_event;
126 	u16 sz;
127 
128 	mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
129 	mps_print_evt_sas(sc, event);
130 	mpssas_record_event(sc, event);
131 
132 	fw_event = kmalloc(sizeof(struct mps_fw_event_work), M_MPT2,
133 	     M_ZERO|M_INTWAIT);
134 	if (!fw_event) {
135 		kprintf("%s: allocate failed for fw_event\n", __func__);
136 		return;
137 	}
138 	sz = le16toh(event->EventDataLength) * 4;
139 	fw_event->event_data = kmalloc(sz, M_MPT2, M_ZERO|M_INTWAIT);
140 	if (!fw_event->event_data) {
141 		kprintf("%s: allocate failed for event_data\n", __func__);
142 		kfree(fw_event, M_MPT2);
143 		return;
144 	}
145 
146 	bcopy(event->EventData, fw_event->event_data, sz);
147 	fw_event->event = event->Event;
148 	if ((event->Event == MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST ||
149 	    event->Event == MPI2_EVENT_SAS_ENCL_DEVICE_STATUS_CHANGE ||
150 	    event->Event == MPI2_EVENT_IR_CONFIGURATION_CHANGE_LIST) &&
151 	    sc->track_mapping_events)
152 		sc->pending_map_events++;
153 
154 	/*
155 	 * When wait_for_port_enable flag is set, make sure that all the events
156 	 * are processed. Increment the startup_refcount and decrement it after
157 	 * events are processed.
158 	 */
159 	if ((event->Event == MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST ||
160 	    event->Event == MPI2_EVENT_IR_CONFIGURATION_CHANGE_LIST) &&
161 	    sc->wait_for_port_enable)
162 		mpssas_startup_increment(sc->sassc);
163 
164 	TAILQ_INSERT_TAIL(&sc->sassc->ev_queue, fw_event, ev_link);
165 	taskqueue_enqueue(sc->sassc->ev_tq, &sc->sassc->ev_task);
166 
167 }
168 
169 static void
170 mpssas_fw_event_free(struct mps_softc *sc, struct mps_fw_event_work *fw_event)
171 {
172 
173 	kfree(fw_event->event_data, M_MPT2);
174 	kfree(fw_event, M_MPT2);
175 }
176 
177 /**
178  * _mps_fw_work - delayed task for processing firmware events
179  * @sc: per adapter object
180  * @fw_event: The fw_event_work object
181  * Context: user.
182  *
183  * Return nothing.
184  */
185 static void
186 mpssas_fw_work(struct mps_softc *sc, struct mps_fw_event_work *fw_event)
187 {
188 	struct mpssas_softc *sassc;
189 	sassc = sc->sassc;
190 
191 	switch (fw_event->event) {
192 	case MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST:
193 	{
194 		MPI2_EVENT_DATA_SAS_TOPOLOGY_CHANGE_LIST *data;
195 		MPI2_EVENT_SAS_TOPO_PHY_ENTRY *phy;
196 		int i;
197 
198 		data = (MPI2_EVENT_DATA_SAS_TOPOLOGY_CHANGE_LIST *)
199 		    fw_event->event_data;
200 
201 		mps_mapping_topology_change_event(sc, fw_event->event_data);
202 
203 		for (i = 0; i < data->NumEntries; i++) {
204 			phy = &data->PHY[i];
205 			switch (phy->PhyStatus & MPI2_EVENT_SAS_TOPO_RC_MASK) {
206 			case MPI2_EVENT_SAS_TOPO_RC_TARG_ADDED:
207 				if (mpssas_add_device(sc,
208 				    phy->AttachedDevHandle, phy->LinkRate)){
209 					kprintf("%s: failed to add device with "
210 					    "handle 0x%x\n", __func__,
211 					    phy->AttachedDevHandle);
212 					mpssas_prepare_remove(sassc, phy->
213 					    AttachedDevHandle);
214 				}
215 				break;
216 			case MPI2_EVENT_SAS_TOPO_RC_TARG_NOT_RESPONDING:
217 				mpssas_prepare_remove(sassc, phy->
218 				    AttachedDevHandle);
219 				break;
220 			case MPI2_EVENT_SAS_TOPO_RC_PHY_CHANGED:
221 			case MPI2_EVENT_SAS_TOPO_RC_NO_CHANGE:
222 			case MPI2_EVENT_SAS_TOPO_RC_DELAY_NOT_RESPONDING:
223 			default:
224 				break;
225 			}
226 		}
227 		/*
228 		 * refcount was incremented for this event in
229 		 * mpssas_evt_handler.  Decrement it here because the event has
230 		 * been processed.
231 		 */
232 		mpssas_startup_decrement(sassc);
233 		break;
234 	}
235 	case MPI2_EVENT_SAS_DISCOVERY:
236 	{
237 		MPI2_EVENT_DATA_SAS_DISCOVERY *data;
238 
239 		data = (MPI2_EVENT_DATA_SAS_DISCOVERY *)fw_event->event_data;
240 
241 		if (data->ReasonCode & MPI2_EVENT_SAS_DISC_RC_STARTED)
242 			mps_dprint(sc, MPS_TRACE,"SAS discovery start event\n");
243 		if (data->ReasonCode & MPI2_EVENT_SAS_DISC_RC_COMPLETED) {
244 			mps_dprint(sc, MPS_TRACE,"SAS discovery stop event\n");
245 			sassc->flags &= ~MPSSAS_IN_DISCOVERY;
246 			mpssas_discovery_end(sassc);
247 		}
248 		break;
249 	}
250 	case MPI2_EVENT_SAS_ENCL_DEVICE_STATUS_CHANGE:
251 	{
252 		Mpi2EventDataSasEnclDevStatusChange_t *data;
253 		data = (Mpi2EventDataSasEnclDevStatusChange_t *)
254 		    fw_event->event_data;
255 		mps_mapping_enclosure_dev_status_change_event(sc, data);
256 		break;
257 	}
258 	case MPI2_EVENT_IR_CONFIGURATION_CHANGE_LIST:
259 	{
260 		Mpi2EventIrConfigElement_t *element;
261 		int i;
262 		u8 foreign_config;
263 		Mpi2EventDataIrConfigChangeList_t *event_data;
264 		struct mpssas_target *targ;
265 		unsigned int id;
266 
267 		event_data = fw_event->event_data;
268 		foreign_config = (le32toh(event_data->Flags) &
269 		    MPI2_EVENT_IR_CHANGE_FLAGS_FOREIGN_CONFIG) ? 1 : 0;
270 
271 		element =
272 		    (Mpi2EventIrConfigElement_t *)&event_data->ConfigElement[0];
273 		id = mps_mapping_get_raid_id_from_handle
274 		    (sc, element->VolDevHandle);
275 
276 		mps_mapping_ir_config_change_event(sc, event_data);
277 
278 		for (i = 0; i < event_data->NumElements; i++, element++) {
279 			switch (element->ReasonCode) {
280 			case MPI2_EVENT_IR_CHANGE_RC_VOLUME_CREATED:
281 			case MPI2_EVENT_IR_CHANGE_RC_ADDED:
282 				if (!foreign_config) {
283 					if (mpssas_volume_add(sc, element)) {
284 						kprintf("%s: failed to add RAID "
285 						    "volume with handle 0x%x\n",
286 						    __func__, le16toh(element->
287 						    VolDevHandle));
288 					}
289 				}
290 				break;
291 			case MPI2_EVENT_IR_CHANGE_RC_VOLUME_DELETED:
292 			case MPI2_EVENT_IR_CHANGE_RC_REMOVED:
293 				/*
294 				 * Rescan after volume is deleted or removed.
295 				 */
296 				if (!foreign_config) {
297 					if (id == MPS_MAP_BAD_ID) {
298 						kprintf("%s: could not get ID "
299 						    "for volume with handle "
300 						    "0x%04x\n", __func__,
301 						    element->VolDevHandle);
302 						break;
303 					}
304 
305 					targ = &sassc->targets[id];
306 					targ->handle = 0x0;
307 					targ->encl_slot = 0x0;
308 					targ->encl_handle = 0x0;
309 					targ->exp_dev_handle = 0x0;
310 					targ->phy_num = 0x0;
311 					targ->linkrate = 0x0;
312 					mpssas_rescan_target(sc, targ);
313 					kprintf("RAID target id 0x%x removed\n",
314 					    targ->tid);
315 				}
316 				break;
317 			case MPI2_EVENT_IR_CHANGE_RC_PD_CREATED:
318 				/*
319 				 * Phys Disk of a volume has been created.  Hide
320 				 * it from the OS.
321 				 */
322 				mpssas_prepare_remove(sassc, element->
323 				    PhysDiskDevHandle);
324 				break;
325 			case MPI2_EVENT_IR_CHANGE_RC_PD_DELETED:
326 				/*
327 				 * Phys Disk of a volume has been deleted.
328 				 * Expose it to the OS.
329 				 */
330 				if (mpssas_add_device(sc,
331 				    element->PhysDiskDevHandle, 0)){
332 					kprintf("%s: failed to add device with "
333 					    "handle 0x%x\n", __func__,
334 					    element->PhysDiskDevHandle);
335 					mpssas_prepare_remove(sassc, element->
336 					    PhysDiskDevHandle);
337 				}
338 				break;
339 			}
340 		}
341 		/*
342 		 * refcount was incremented for this event in
343 		 * mpssas_evt_handler.  Decrement it here because the event has
344 		 * been processed.
345 		 */
346 		mpssas_startup_decrement(sassc);
347 		break;
348 	}
349 	case MPI2_EVENT_IR_VOLUME:
350 	{
351 		Mpi2EventDataIrVolume_t *event_data = fw_event->event_data;
352 
353 		/*
354 		 * Informational only.
355 		 */
356 		mps_dprint(sc, MPS_INFO, "Received IR Volume event:\n");
357 		switch (event_data->ReasonCode) {
358 		case MPI2_EVENT_IR_VOLUME_RC_SETTINGS_CHANGED:
359 			mps_dprint(sc, MPS_INFO, "   Volume Settings "
360 			    "changed from 0x%x to 0x%x for Volome with "
361 			    "handle 0x%x", event_data->PreviousValue,
362 			    event_data->NewValue,
363 			    event_data->VolDevHandle);
364 			break;
365 		case MPI2_EVENT_IR_VOLUME_RC_STATUS_FLAGS_CHANGED:
366 			mps_dprint(sc, MPS_INFO, "   Volume Status "
367 			    "changed from 0x%x to 0x%x for Volome with "
368 			    "handle 0x%x", event_data->PreviousValue,
369 			    event_data->NewValue,
370 			    event_data->VolDevHandle);
371 			break;
372 		case MPI2_EVENT_IR_VOLUME_RC_STATE_CHANGED:
373 			mps_dprint(sc, MPS_INFO, "   Volume State "
374 			    "changed from 0x%x to 0x%x for Volome with "
375 			    "handle 0x%x", event_data->PreviousValue,
376 			    event_data->NewValue,
377 			    event_data->VolDevHandle);
378 			break;
379 		default:
380 			break;
381 		}
382 		break;
383 	}
384 	case MPI2_EVENT_IR_PHYSICAL_DISK:
385 	{
386 		Mpi2EventDataIrPhysicalDisk_t *event_data =
387 		    fw_event->event_data;
388 
389 		/*
390 		 * Informational only.
391 		 */
392 		mps_dprint(sc, MPS_INFO, "Received IR Phys Disk event:\n");
393 		switch (event_data->ReasonCode) {
394 		case MPI2_EVENT_IR_PHYSDISK_RC_SETTINGS_CHANGED:
395 			mps_dprint(sc, MPS_INFO, "   Phys Disk Settings "
396 			    "changed from 0x%x to 0x%x for Phys Disk Number "
397 			    "%d and handle 0x%x at Enclosure handle 0x%x, Slot "
398 			    "%d", event_data->PreviousValue,
399 			    event_data->NewValue, event_data->PhysDiskNum,
400 			    event_data->PhysDiskDevHandle,
401 			    event_data->EnclosureHandle, event_data->Slot);
402 			break;
403 		case MPI2_EVENT_IR_PHYSDISK_RC_STATUS_FLAGS_CHANGED:
404 			mps_dprint(sc, MPS_INFO, "   Phys Disk Status changed "
405 			    "from 0x%x to 0x%x for Phys Disk Number %d and "
406 			    "handle 0x%x at Enclosure handle 0x%x, Slot %d",
407 			    event_data->PreviousValue, event_data->NewValue,
408 			    event_data->PhysDiskNum,
409 			    event_data->PhysDiskDevHandle,
410 			    event_data->EnclosureHandle, event_data->Slot);
411 			break;
412 		case MPI2_EVENT_IR_PHYSDISK_RC_STATE_CHANGED:
413 			mps_dprint(sc, MPS_INFO, "   Phys Disk State changed "
414 			    "from 0x%x to 0x%x for Phys Disk Number %d and "
415 			    "handle 0x%x at Enclosure handle 0x%x, Slot %d",
416 			    event_data->PreviousValue, event_data->NewValue,
417 			    event_data->PhysDiskNum,
418 			    event_data->PhysDiskDevHandle,
419 			    event_data->EnclosureHandle, event_data->Slot);
420 			break;
421 		default:
422 			break;
423 		}
424 		break;
425 	}
426 	case MPI2_EVENT_IR_OPERATION_STATUS:
427 	{
428 		Mpi2EventDataIrOperationStatus_t *event_data =
429 		    fw_event->event_data;
430 
431 		/*
432 		 * Informational only.
433 		 */
434 		mps_dprint(sc, MPS_INFO, "Received IR Op Status event:\n");
435 		mps_dprint(sc, MPS_INFO, "   RAID Operation of %d is %d "
436 		    "percent complete for Volume with handle 0x%x",
437 		    event_data->RAIDOperation, event_data->PercentComplete,
438 		    event_data->VolDevHandle);
439 		break;
440 	}
441 	case MPI2_EVENT_LOG_ENTRY_ADDED:
442 	{
443 		pMpi2EventDataLogEntryAdded_t	logEntry;
444 		uint16_t			logQualifier;
445 		uint8_t				logCode;
446 
447 		logEntry = (pMpi2EventDataLogEntryAdded_t)fw_event->event_data;
448 		logQualifier = logEntry->LogEntryQualifier;
449 
450 		if (logQualifier == MPI2_WD_LOG_ENTRY) {
451 			logCode = logEntry->LogData[0];
452 
453 			switch (logCode) {
454 			case MPI2_WD_SSD_THROTTLING:
455 				kprintf("WarpDrive Warning: IO Throttling has "
456 				    "occurred in the WarpDrive subsystem. "
457 				    "Check WarpDrive documentation for "
458 				    "additional details\n");
459 				break;
460 			case MPI2_WD_DRIVE_LIFE_WARN:
461 				kprintf("WarpDrive Warning: Program/Erase "
462 				    "Cycles for the WarpDrive subsystem in "
463 				    "degraded range. Check WarpDrive "
464 				    "documentation for additional details\n");
465 				break;
466 			case MPI2_WD_DRIVE_LIFE_DEAD:
467 				kprintf("WarpDrive Fatal Error: There are no "
468 				    "Program/Erase Cycles for the WarpDrive "
469 				    "subsystem. The storage device will be in "
470 				    "read-only mode. Check WarpDrive "
471 				    "documentation for additional details\n");
472 				break;
473 			case MPI2_WD_RAIL_MON_FAIL:
474 				kprintf("WarpDrive Fatal Error: The Backup Rail "
475 				    "Monitor has failed on the WarpDrive "
476 				    "subsystem. Check WarpDrive documentation "
477 				    "for additional details\n");
478 				break;
479 			default:
480 				break;
481 			}
482 		}
483 		break;
484 	}
485 	case MPI2_EVENT_SAS_DEVICE_STATUS_CHANGE:
486 	case MPI2_EVENT_SAS_BROADCAST_PRIMITIVE:
487 	default:
488 		mps_dprint(sc, MPS_TRACE,"Unhandled event 0x%0X\n",
489 		    fw_event->event);
490 		break;
491 
492 	}
493 	mpssas_fw_event_free(sc, fw_event);
494 }
495 
496 void
497 mpssas_firmware_event_work(void *arg, int pending)
498 {
499 	struct mps_fw_event_work *fw_event;
500 	struct mps_softc *sc;
501 
502 	sc = (struct mps_softc *)arg;
503 	mps_lock(sc);
504 	while ((fw_event = TAILQ_FIRST(&sc->sassc->ev_queue)) != NULL) {
505 		TAILQ_REMOVE(&sc->sassc->ev_queue, fw_event, ev_link);
506 		mpssas_fw_work(sc, fw_event);
507 	}
508 	mps_unlock(sc);
509 }
510 
511 static int
512 mpssas_add_device(struct mps_softc *sc, u16 handle, u8 linkrate){
513 	char devstring[80];
514 	struct mpssas_softc *sassc;
515 	struct mpssas_target *targ;
516 	Mpi2ConfigReply_t mpi_reply;
517 	Mpi2SasDevicePage0_t config_page;
518 	uint64_t sas_address, sata_sas_address;
519 	uint64_t parent_sas_address = 0;
520 	u16 ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags);
521 	u32 device_info, parent_devinfo = 0;
522 	unsigned int id;
523 	int ret;
524 	int error = 0;
525 
526 	sassc = sc->sassc;
527 	mpssas_startup_increment(sassc);
528 	if ((mps_config_get_sas_device_pg0(sc, &mpi_reply, &config_page,
529 	     MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, handle))) {
530 		kprintf("%s: error reading SAS device page0\n", __func__);
531 		error = ENXIO;
532 		goto out;
533 	}
534 
535 	device_info = le32toh(config_page.DeviceInfo);
536 
537 	if (((device_info & MPI2_SAS_DEVICE_INFO_SMP_TARGET) == 0)
538 	 && (config_page.ParentDevHandle != 0)) {
539 		Mpi2ConfigReply_t tmp_mpi_reply;
540 		Mpi2SasDevicePage0_t parent_config_page;
541 
542 		if ((mps_config_get_sas_device_pg0(sc, &tmp_mpi_reply,
543 		     &parent_config_page, MPI2_SAS_DEVICE_PGAD_FORM_HANDLE,
544 		     le16toh(config_page.ParentDevHandle)))) {
545 			kprintf("%s: error reading SAS device %#x page0\n",
546 			       __func__, le16toh(config_page.ParentDevHandle));
547 		} else {
548 			parent_sas_address = parent_config_page.SASAddress.High;
549 			parent_sas_address = (parent_sas_address << 32) |
550 				parent_config_page.SASAddress.Low;
551 			parent_devinfo = le32toh(parent_config_page.DeviceInfo);
552 		}
553 	}
554 	/* TODO Check proper endianess */
555 	sas_address = config_page.SASAddress.High;
556 	sas_address = (sas_address << 32) |
557 	    config_page.SASAddress.Low;
558 
559 	if ((ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE)
560 		    == MPI2_IOCPAGE8_FLAGS_DEVICE_PERSISTENCE_MAPPING) {
561 		if (device_info & MPI2_SAS_DEVICE_INFO_SATA_DEVICE) {
562 			ret = mpssas_get_sas_address_for_sata_disk(sc,
563 			    &sata_sas_address, handle, device_info);
564 			if (!ret)
565 				id = mps_mapping_get_sas_id(sc,
566 				    sata_sas_address, handle);
567 			else
568 				id = mps_mapping_get_sas_id(sc,
569 				    sas_address, handle);
570 		} else
571 			id = mps_mapping_get_sas_id(sc, sas_address,
572 			    handle);
573 	} else
574 		id = mps_mapping_get_sas_id(sc, sas_address, handle);
575 
576 	if (id == MPS_MAP_BAD_ID) {
577 		kprintf("failure at %s:%d/%s()! Could not get ID for device "
578 		    "with handle 0x%04x\n", __FILE__, __LINE__, __func__,
579 		    handle);
580 		error = ENXIO;
581 		goto out;
582 	}
583 	mps_vprintf(sc, "SAS Address from SAS device page0 = %jx\n",
584 	    sas_address);
585 	targ = &sassc->targets[id];
586 	targ->devinfo = device_info;
587 	targ->devname = le32toh(config_page.DeviceName.High);
588 	targ->devname = (targ->devname << 32) |
589 	    le32toh(config_page.DeviceName.Low);
590 	targ->encl_handle = le16toh(config_page.EnclosureHandle);
591 	targ->encl_slot = le16toh(config_page.Slot);
592 	targ->handle = handle;
593 	targ->parent_handle = le16toh(config_page.ParentDevHandle);
594 	targ->sasaddr = mps_to_u64(&config_page.SASAddress);
595 	targ->parent_sasaddr = le64toh(parent_sas_address);
596 	targ->parent_devinfo = parent_devinfo;
597 	targ->tid = id;
598 	targ->linkrate = (linkrate>>4);
599 	targ->flags = 0;
600 	TAILQ_INIT(&targ->commands);
601 	TAILQ_INIT(&targ->timedout_commands);
602 	SLIST_INIT(&targ->luns);
603 	mps_describe_devinfo(targ->devinfo, devstring, 80);
604 	mps_vprintf(sc, "Found device <%s> <%s> <0x%04x> <%d/%d>\n", devstring,
605 	    mps_describe_table(mps_linkrate_names, targ->linkrate),
606 	    targ->handle, targ->encl_handle, targ->encl_slot);
607 	if ((sassc->flags & MPSSAS_IN_STARTUP) == 0)
608 		mpssas_rescan_target(sc, targ);
609 	mps_vprintf(sc, "Target id 0x%x added\n", targ->tid);
610 out:
611 	mpssas_startup_decrement(sassc);
612 	return (error);
613 
614 }
615 
616 int
617 mpssas_get_sas_address_for_sata_disk(struct mps_softc *sc,
618     u64 *sas_address, u16 handle, u32 device_info)
619 {
620 	Mpi2SataPassthroughReply_t mpi_reply;
621 	int i, rc, try_count;
622 	u32 *bufferptr;
623 	union _sata_sas_address hash_address;
624 	struct _ata_identify_device_data ata_identify;
625 	u8 buffer[MPT2SAS_MN_LEN + MPT2SAS_SN_LEN];
626 	u32 ioc_status;
627 	u8 sas_status;
628 
629 	memset(&ata_identify, 0, sizeof(ata_identify));
630 	try_count = 0;
631 	do {
632 		rc = mpssas_get_sata_identify(sc, handle, &mpi_reply,
633 		    (char *)&ata_identify, sizeof(ata_identify), device_info);
634 		try_count++;
635 		ioc_status = le16toh(mpi_reply.IOCStatus)
636 		    & MPI2_IOCSTATUS_MASK;
637 		sas_status = mpi_reply.SASStatus;
638 	} while ((rc == -EAGAIN || ioc_status || sas_status) &&
639 	    (try_count < 5));
640 
641 	if (rc == 0 && !ioc_status && !sas_status) {
642 		mps_dprint(sc, MPS_INFO, "%s: got SATA identify successfully "
643 			   "for handle = 0x%x with try_count = %d\n",
644 			   __func__, handle, try_count);
645 	} else {
646 		mps_dprint(sc, MPS_INFO, "%s: handle = 0x%x failed\n",
647 			   __func__, handle);
648 		return -1;
649 	}
650 	/* Copy & byteswap the 40 byte model number to a buffer */
651 	for (i = 0; i < MPT2SAS_MN_LEN; i += 2) {
652 		buffer[i] = ((u8 *)ata_identify.model_number)[i + 1];
653 		buffer[i + 1] = ((u8 *)ata_identify.model_number)[i];
654 	}
655 	/* Copy & byteswap the 20 byte serial number to a buffer */
656 	for (i = 0; i < MPT2SAS_SN_LEN; i += 2) {
657 		buffer[MPT2SAS_MN_LEN + i] =
658 			((u8 *)ata_identify.serial_number)[i + 1];
659 		buffer[MPT2SAS_MN_LEN + i + 1] =
660 			((u8 *)ata_identify.serial_number)[i];
661 	}
662 	bufferptr = (u32 *)buffer;
663 	/* There are 60 bytes to hash down to 8. 60 isn't divisible by 8,
664 	 * so loop through the first 56 bytes (7*8),
665 	 * and then add in the last dword.
666 	 */
667 	hash_address.word.low  = 0;
668 	hash_address.word.high = 0;
669 	for (i = 0; (i < ((MPT2SAS_MN_LEN+MPT2SAS_SN_LEN)/8)); i++) {
670 		hash_address.word.low += *bufferptr;
671 		bufferptr++;
672 		hash_address.word.high += *bufferptr;
673 		bufferptr++;
674 	}
675 	/* Add the last dword */
676 	hash_address.word.low += *bufferptr;
677 	/* Make sure the hash doesn't start with 5, because it could clash
678 	 * with a SAS address. Change 5 to a D.
679 	 */
680 	if ((hash_address.word.high & 0x000000F0) == (0x00000050))
681 		hash_address.word.high |= 0x00000080;
682 	*sas_address = (u64)hash_address.wwid[0] << 56 |
683 	    (u64)hash_address.wwid[1] << 48 | (u64)hash_address.wwid[2] << 40 |
684 	    (u64)hash_address.wwid[3] << 32 | (u64)hash_address.wwid[4] << 24 |
685 	    (u64)hash_address.wwid[5] << 16 | (u64)hash_address.wwid[6] <<  8 |
686 	    (u64)hash_address.wwid[7];
687 	return 0;
688 }
689 
690 static int
691 mpssas_get_sata_identify(struct mps_softc *sc, u16 handle,
692     Mpi2SataPassthroughReply_t *mpi_reply, char *id_buffer, int sz, u32 devinfo)
693 {
694 	Mpi2SataPassthroughRequest_t *mpi_request;
695 	Mpi2SataPassthroughReply_t *reply;
696 	struct mps_command *cm;
697 	char *buffer;
698 	int error = 0;
699 
700 	buffer = kmalloc( sz, M_MPT2, M_INTWAIT | M_ZERO);
701 	if (!buffer)
702 		return ENOMEM;
703 
704 	if ((cm = mps_alloc_command(sc)) == NULL) {
705 		kfree(buffer, M_MPT2);
706 		return (EBUSY);
707 	}
708 	mpi_request = (MPI2_SATA_PASSTHROUGH_REQUEST *)cm->cm_req;
709 	bzero(mpi_request,sizeof(MPI2_SATA_PASSTHROUGH_REQUEST));
710 	mpi_request->Function = MPI2_FUNCTION_SATA_PASSTHROUGH;
711 	mpi_request->VF_ID = 0;
712 	mpi_request->DevHandle = htole16(handle);
713 	mpi_request->PassthroughFlags = (MPI2_SATA_PT_REQ_PT_FLAGS_PIO |
714 	    MPI2_SATA_PT_REQ_PT_FLAGS_READ);
715 	mpi_request->DataLength = htole32(sz);
716 	mpi_request->CommandFIS[0] = 0x27;
717 	mpi_request->CommandFIS[1] = 0x80;
718 	mpi_request->CommandFIS[2] =  (devinfo &
719 	    MPI2_SAS_DEVICE_INFO_ATAPI_DEVICE) ? 0xA1 : 0xEC;
720 	cm->cm_sge = &mpi_request->SGL;
721 	cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
722 	cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAIN;
723 	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
724 	cm->cm_data = buffer;
725 	cm->cm_length = htole32(sz);
726 	error = mps_request_polled(sc, cm);
727 	reply = (Mpi2SataPassthroughReply_t *)cm->cm_reply;
728 	if (error || (reply == NULL)) {
729 		/* FIXME */
730 		/* If the poll returns error then we need to do diag reset */
731 		kprintf("%s: poll for page completed with error %d",
732 		    __func__, error);
733 		error = ENXIO;
734 		goto out;
735 	}
736 	bcopy(buffer, id_buffer, sz);
737 	bcopy(reply, mpi_reply, sizeof(Mpi2SataPassthroughReply_t));
738 	if ((reply->IOCStatus & MPI2_IOCSTATUS_MASK) !=
739 	    MPI2_IOCSTATUS_SUCCESS) {
740 		kprintf("%s: error reading SATA PASSTHRU; iocstatus = 0x%x\n",
741 		    __func__, reply->IOCStatus);
742 		error = ENXIO;
743 		goto out;
744 	}
745 out:
746 	mps_free_command(sc, cm);
747 	kfree(buffer, M_MPT2);
748 	return (error);
749 }
750 
751 static int
752 mpssas_volume_add(struct mps_softc *sc, Mpi2EventIrConfigElement_t *element)
753 {
754 	struct mpssas_softc *sassc;
755 	struct mpssas_target *targ;
756 	u64 wwid;
757 	u16 handle = le16toh(element->VolDevHandle);
758 	unsigned int id;
759 	int error = 0;
760 
761 	sassc = sc->sassc;
762 	mpssas_startup_increment(sassc);
763 	mps_config_get_volume_wwid(sc, handle, &wwid);
764 	if (!wwid) {
765 		kprintf("%s: invalid WWID; cannot add volume to mapping table\n",
766 		    __func__);
767 		error = ENXIO;
768 		goto out;
769 	}
770 
771 	id = mps_mapping_get_raid_id(sc, wwid, handle);
772 	if (id == MPS_MAP_BAD_ID) {
773 		kprintf("%s: could not get ID for volume with handle 0x%04x and "
774 		    "WWID 0x%016llx\n", __func__, handle,
775 		    (unsigned long long)wwid);
776 		error = ENXIO;
777 		goto out;
778 	}
779 
780 	targ = &sassc->targets[id];
781 	targ->tid = id;
782 	targ->handle = handle;
783 	targ->devname = wwid;
784 	TAILQ_INIT(&targ->commands);
785 	TAILQ_INIT(&targ->timedout_commands);
786 	SLIST_INIT(&targ->luns);
787 	if ((sassc->flags & MPSSAS_IN_STARTUP) == 0)
788 		mpssas_rescan_target(sc, targ);
789 	mps_dprint(sc, MPS_INFO, "RAID target id %d added (WWID = 0x%jx)\n",
790 	    targ->tid, wwid);
791 out:
792 	mpssas_startup_decrement(sassc);
793 	return (error);
794 }
795 
796 /**
797  * mpssas_ir_shutdown - IR shutdown notification
798  * @sc: per adapter object
799  *
800  * Sending RAID Action to alert the Integrated RAID subsystem of the IOC that
801  * the host system is shutting down.
802  *
803  * Return nothing.
804  */
805 void
806 mpssas_ir_shutdown(struct mps_softc *sc)
807 {
808 	u16 volume_mapping_flags;
809 	u16 ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags);
810 	struct dev_mapping_table *mt_entry;
811 	u32 start_idx, end_idx;
812 	unsigned int id, found_volume = 0;
813 	struct mps_command *cm;
814 	Mpi2RaidActionRequest_t	*action;
815 
816 	mps_lock(sc);
817 
818 	mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
819 
820 	/* is IR firmware build loaded? */
821 	if (!sc->ir_firmware)
822 		goto back;
823 
824 	/* are there any volumes?  Look at IR target IDs. */
825 	// TODO-later, this should be looked up in the RAID config structure
826 	// when it is implemented.
827 	volume_mapping_flags = le16toh(sc->ioc_pg8.IRVolumeMappingFlags) &
828 	    MPI2_IOCPAGE8_IRFLAGS_MASK_VOLUME_MAPPING_MODE;
829 	if (volume_mapping_flags == MPI2_IOCPAGE8_IRFLAGS_LOW_VOLUME_MAPPING) {
830 		start_idx = 0;
831 		if (ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_RESERVED_TARGETID_0)
832 			start_idx = 1;
833 	} else
834 		start_idx = sc->max_devices - sc->max_volumes;
835 	end_idx = start_idx + sc->max_volumes - 1;
836 
837 	for (id = start_idx; id < end_idx; id++) {
838 		mt_entry = &sc->mapping_table[id];
839 		if ((mt_entry->physical_id != 0) &&
840 		    (mt_entry->missing_count == 0)) {
841 			found_volume = 1;
842 			break;
843 		}
844 	}
845 
846 	if (!found_volume)
847 		goto back;
848 
849 	if ((cm = mps_alloc_command(sc)) == NULL) {
850 		kprintf("%s: command alloc failed\n", __func__);
851 		goto back;
852 	}
853 
854 	action = (MPI2_RAID_ACTION_REQUEST *)cm->cm_req;
855 	action->Function = MPI2_FUNCTION_RAID_ACTION;
856 	action->Action = MPI2_RAID_ACTION_SYSTEM_SHUTDOWN_INITIATED;
857 	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
858 	mps_request_polled(sc, cm);
859 
860 	/*
861 	 * Don't check for reply, just leave.
862 	 */
863 	if (cm)
864 		mps_free_command(sc, cm);
865 
866 back:
867 	mps_unlock(sc);
868 }
869