FreeBSD/sys/dev/mps/mps_sas_lsi.c
/**
 * mpssas_SSU_to_SATA_devices 
 * @sc: per adapter object
 *
 * Looks through the target list and issues a StartStopUnit SCSI command to each
 * SATA direct-access device.  This helps to ensure that data corruption is
 * avoided when the system is being shut down.  This must be called after the IR
 * System Shutdown RAID Action is sent if in IR mode.
 *
 * Return nothing.
 */
mpssas_SSU_to_SATA_devices
@sc: per adapter object

Looks through the target list and issues a StartStopUnit SCSI command to each
SATA direct-access device.  This helps to ensure that data corruption is
avoided when the system is being shut down.  This must be called after the IR
System Shutdown RAID Action is sent if in IR mode.

Return nothing.
mpssas_SSU_to_SATA_devices @sc : per adapter object Looks through the target list and issues a StartStopUnit SCSI command to each SATA direct - access device . This helps to ensure that data corruption is avoided when the system is being shut down . This must be called after the IR System Shutdown RAID Action is sent if in IR mode . Return nothing .
static void
mpssas_SSU_to_SATA_devices(struct mps_softc *sc)
{
	struct mpssas_softc *sassc = sc->sassc;
	union ccb *ccb;
	path_id_t pathid = cam_sim_path(sassc->sim);
	target_id_t targetid;
	struct mpssas_target *target;
	char path_str[64];
	struct timeval cur_time, start_time;
	sc->SSU_started = TRUE;
	sc->SSU_refcount = 0;
	for (targetid = 0; targetid < sc->facts->MaxTargets; targetid++) {
		target = &sassc->targets[targetid];
		if (target->handle == 0x0) {
			continue;
		}
		ccb = xpt_alloc_ccb_nowait();
		if (ccb == NULL) {
			mps_dprint(sc, MPS_FAULT, "Unable to alloc CCB to stop "
			    "unit.\n");
			return;
		}
		if (target->stop_at_shutdown) {
			if (xpt_create_path(&ccb->ccb_h.path,
			    xpt_periph, pathid, targetid,
			    CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
				mps_dprint(sc, MPS_FAULT, "Unable to create "
				    "LUN path to stop unit.\n");
				xpt_free_ccb(ccb);
				return;
			}
			xpt_path_string(ccb->ccb_h.path, path_str,
			    sizeof(path_str));
			mps_dprint(sc, MPS_INFO, "Sending StopUnit: path %s "
			    "handle %d\n", path_str, target->handle);
			mps_dprint(sc, MPS_INFO, "Incrementing SSU count\n");
			sc->SSU_refcount++;
			ccb->ccb_h.target_id =
			    xpt_path_target_id(ccb->ccb_h.path);
			ccb->ccb_h.ppriv_ptr1 = sassc;
			scsi_start_stop(&ccb->csio,
			    0,
			    mpssas_stop_unit_done,
			    MSG_SIMPLE_Q_TAG,
			    FALSE,
			    0,
			    FALSE,
			    MPS_SENSE_LEN,
			    10000);
			xpt_action(ccb);
		}
	}
	getmicrotime(&start_time);
	while (sc->SSU_refcount) {
		pause("mpswait", hz/10);
		getmicrotime(&cur_time);
		if ((cur_time.tv_sec - start_time.tv_sec) > 60) {
			mps_dprint(sc, MPS_FAULT, "Time has expired waiting "
			    "for SSU commands to complete.\n");
			break;
		}
	}
}
static void mpssas_SSU_to_SATA_devices ( struct mps_softc * sc ) { struct mpssas_softc * sassc = sc -> sassc ; union ccb * ccb ; path_id_t pathid = cam_sim_path ( sassc -> sim ) ; target_id_t targetid ; struct mpssas_target * target ; char path_str [ 64 ] ; struct timeval cur_time , start_time ; sc -> SSU_started = TRUE ; sc -> SSU_refcount = 0 ; for ( targetid = 0 ; targetid < sc -> facts -> MaxTargets ; targetid ++ ) { target = & sassc -> targets [ targetid ] ; if ( target -> handle == 0x0 ) { continue ; } ccb = xpt_alloc_ccb_nowait ( ) ; if ( ccb == NULL ) { mps_dprint ( sc , MPS_FAULT , " " " \n " ) ; return ; } if ( target -> stop_at_shutdown ) { if ( xpt_create_path ( & ccb -> ccb_h . path , xpt_periph , pathid , targetid , CAM_LUN_WILDCARD ) != CAM_REQ_CMP ) { mps_dprint ( sc , MPS_FAULT , " " " \n " ) ; xpt_free_ccb ( ccb ) ; return ; } xpt_path_string ( ccb -> ccb_h . path , path_str , sizeof ( path_str ) ) ; mps_dprint ( sc , MPS_INFO , " " " \n " , path_str , target -> handle ) ; mps_dprint ( sc , MPS_INFO , " \n " ) ; sc -> SSU_refcount ++ ; ccb -> ccb_h . target_id = xpt_path_target_id ( ccb -> ccb_h . path ) ; ccb -> ccb_h . ppriv_ptr1 = sassc ; scsi_start_stop ( & ccb -> csio , 0 , mpssas_stop_unit_done , MSG_SIMPLE_Q_TAG , FALSE , 0 , FALSE , MPS_SENSE_LEN , 10000 ) ; xpt_action ( ccb ) ; } } getmicrotime ( & start_time ) ; while ( sc -> SSU_refcount ) { pause ( " " , hz / 10 ) ; getmicrotime ( & cur_time ) ; if ( ( cur_time . tv_sec - start_time . tv_sec ) > 60 ) { mps_dprint ( sc , MPS_FAULT , " " " \n " ) ; break ; } } }
mpssas_SSU_to_SATA_devices
 @sc: per adapter object
mpssas_SSU_to_SATA_devices @sc : per adapter object
/*
	 * For each target, issue a StartStopUnit command to stop the device.
	 */ /*
		 * The stop_at_shutdown flag will be set if this device is
		 * a SATA direct-access end device.
		 */ /*
			 * Issue a START STOP UNIT command for the target.
			 * Increment the SSU counter to be used to count the
			 * number of required replies.
			 */ /*retries*/ /*start*/ /*load/eject*/ /*immediate*/ /*timeout*/ /*
	 * Wait until all of the SSU commands have completed or time has
	 * expired (60 seconds).  Pause for 100ms each time through.  If any
	 * command times out, the target will be reset in the SCSI command
	 * timeout routine.
	 */