FreeBSD/sys/cam/cam_xpt.c
/*
 * A sim structure, listing the SIM entry points and instance
 * identification info is passed to xpt_bus_register to hook the SIM
 * into the CAM framework.  xpt_bus_register creates a cam_eb entry
 * for this new bus and places it in the array of busses and assigns
 * it a path_id.  The path_id may be influenced by "hard wiring"
 * information specified by the user.  Once interrupt services are
 * available, the bus will be probed.
 */
A sim structure, listing the SIM entry points and instance
identification info is passed to xpt_bus_register to hook the SIM
into the CAM framework.  xpt_bus_register creates a cam_eb entry
for this new bus and places it in the array of busses and assigns
it a path_id.  The path_id may be influenced by "hard wiring"
information specified by the user.  Once interrupt services are
available, the bus will be probed.
A sim structure listing the SIM entry points and instance identification info is passed to xpt_bus_register to hook the SIM into the CAM framework . xpt_bus_register creates a cam_eb entry for this new bus and places it in the array of busses and assigns it a path_id . The path_id may be influenced by " hard wiring " information specified by the user . Once interrupt services are available the bus will be probed .
int32_t
xpt_bus_register(struct cam_sim *sim, device_t parent, u_int32_t bus)
{
	struct cam_eb *new_bus;
	struct cam_eb *old_bus;
	struct ccb_pathinq cpi;
	struct cam_path *path;
	cam_status status;
	mtx_assert(sim->mtx, MA_OWNED);
	sim->bus_id = bus;
	new_bus = (struct cam_eb *)malloc(sizeof(*new_bus),
					  M_CAMXPT, M_NOWAIT|M_ZERO);
	if (new_bus == NULL) {
		return (CAM_RESRC_UNAVAIL);
	}
	mtx_init(&new_bus->eb_mtx, "CAM bus lock", NULL, MTX_DEF);
	TAILQ_INIT(&new_bus->et_entries);
	cam_sim_hold(sim);
	new_bus->sim = sim;
	timevalclear(&new_bus->last_reset);
	new_bus->flags = 0;
	new_bus->refcount = 1;	
	new_bus->generation = 0;
	xpt_lock_buses();
	sim->path_id = new_bus->path_id =
	    xptpathid(sim->sim_name, sim->unit_number, sim->bus_id);
	old_bus = TAILQ_FIRST(&xsoftc.xpt_busses);
	while (old_bus != NULL
	    && old_bus->path_id < new_bus->path_id)
		old_bus = TAILQ_NEXT(old_bus, links);
	if (old_bus != NULL)
		TAILQ_INSERT_BEFORE(old_bus, new_bus, links);
	else
		TAILQ_INSERT_TAIL(&xsoftc.xpt_busses, new_bus, links);
	xsoftc.bus_generation++;
	xpt_unlock_buses();
	new_bus->xport = &xport_default;
	status = xpt_create_path(&path, NULL, sim->path_id,
				  CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD);
	if (status != CAM_REQ_CMP) {
		xpt_release_bus(new_bus);
		free(path, M_CAMXPT);
		return (CAM_RESRC_UNAVAIL);
	}
	xpt_setup_ccb(&cpi.ccb_h, path, CAM_PRIORITY_NORMAL);
	cpi.ccb_h.func_code = XPT_PATH_INQ;
	xpt_action((union ccb *)&cpi);
	if (cpi.ccb_h.status == CAM_REQ_CMP) {
		switch (cpi.transport) {
		case XPORT_SPI:
		case XPORT_SAS:
		case XPORT_FC:
		case XPORT_USB:
		case XPORT_ISCSI:
		case XPORT_SRP:
		case XPORT_PPB:
			new_bus->xport = scsi_get_xport();
			break;
		case XPORT_ATA:
		case XPORT_SATA:
			new_bus->xport = ata_get_xport();
			break;
		default:
			new_bus->xport = &xport_default;
			break;
		}
	}
	if (sim->path_id != CAM_XPT_PATH_ID) {
		xpt_async(AC_PATH_REGISTERED, path, &cpi);
		if ((cpi.hba_misc & PIM_NOSCAN) == 0) {
			union	ccb *scan_ccb;
			scan_ccb = xpt_alloc_ccb_nowait();
			if (scan_ccb != NULL) {
				scan_ccb->ccb_h.path = path;
				scan_ccb->ccb_h.func_code = XPT_SCAN_BUS;
				scan_ccb->crcn.flags = 0;
				xpt_rescan(scan_ccb);
			} else {
				xpt_print(path,
					  "Can't allocate CCB to scan bus\n");
				xpt_free_path(path);
			}
		} else
			xpt_free_path(path);
	} else
		xpt_free_path(path);
	return (CAM_SUCCESS);
}
int32_t xpt_bus_register ( struct cam_sim * sim , device_t parent , u_int32_t bus ) { struct cam_eb * new_bus ; struct cam_eb * old_bus ; struct ccb_pathinq cpi ; struct cam_path * path ; cam_status status ; mtx_assert ( sim -> mtx , MA_OWNED ) ; sim -> bus_id = bus ; new_bus = ( struct cam_eb * ) malloc ( sizeof ( * new_bus ) , M_CAMXPT , M_NOWAIT | M_ZERO ) ; if ( new_bus == NULL ) { return ( CAM_RESRC_UNAVAIL ) ; } mtx_init ( & new_bus -> eb_mtx , " " , NULL , MTX_DEF ) ; TAILQ_INIT ( & new_bus -> et_entries ) ; cam_sim_hold ( sim ) ; new_bus -> sim = sim ; timevalclear ( & new_bus -> last_reset ) ; new_bus -> flags = 0 ; new_bus -> refcount = 1 ; new_bus -> generation = 0 ; xpt_lock_buses ( ) ; sim -> path_id = new_bus -> path_id = xptpathid ( sim -> sim_name , sim -> unit_number , sim -> bus_id ) ; old_bus = TAILQ_FIRST ( & xsoftc . xpt_busses ) ; while ( old_bus != NULL && old_bus -> path_id < new_bus -> path_id ) old_bus = TAILQ_NEXT ( old_bus , links ) ; if ( old_bus != NULL ) TAILQ_INSERT_BEFORE ( old_bus , new_bus , links ) ; else TAILQ_INSERT_TAIL ( & xsoftc . xpt_busses , new_bus , links ) ; xsoftc . bus_generation ++ ; xpt_unlock_buses ( ) ; new_bus -> xport = & xport_default ; status = xpt_create_path ( & path , NULL , sim -> path_id , CAM_TARGET_WILDCARD , CAM_LUN_WILDCARD ) ; if ( status != CAM_REQ_CMP ) { xpt_release_bus ( new_bus ) ; free ( path , M_CAMXPT ) ; return ( CAM_RESRC_UNAVAIL ) ; } xpt_setup_ccb ( & cpi . ccb_h , path , CAM_PRIORITY_NORMAL ) ; cpi . ccb_h . func_code = XPT_PATH_INQ ; xpt_action ( ( union ccb * ) & cpi ) ; if ( cpi . ccb_h . status == CAM_REQ_CMP ) { switch ( cpi . transport ) { case XPORT_SPI : case XPORT_SAS : case XPORT_FC : case XPORT_USB : case XPORT_ISCSI : case XPORT_SRP : case XPORT_PPB : new_bus -> xport = scsi_get_xport ( ) ; break ; case XPORT_ATA : case XPORT_SATA : new_bus -> xport = ata_get_xport ( ) ; break ; default : new_bus -> xport = & xport_default ; break ; } } if ( sim -> path_id != CAM_XPT_PATH_ID ) { xpt_async ( AC_PATH_REGISTERED , path , & cpi ) ; if ( ( cpi . hba_misc & PIM_NOSCAN ) == 0 ) { union ccb * scan_ccb ; scan_ccb = xpt_alloc_ccb_nowait ( ) ; if ( scan_ccb != NULL ) { scan_ccb -> ccb_h . path = path ; scan_ccb -> ccb_h . func_code = XPT_SCAN_BUS ; scan_ccb -> crcn . flags = 0 ; xpt_rescan ( scan_ccb ) ; } else { xpt_print ( path , " \n " ) ; xpt_free_path ( path ) ; } } else xpt_free_path ( path ) ; } else xpt_free_path ( path ) ; return ( CAM_SUCCESS ) ; }
A sim structure, listing the SIM entry points and instance
 identification info is passed to xpt_bus_register to hook the SIM
 into the CAM framework.
A sim structure listing the SIM entry points and instance identification info is passed to xpt_bus_register to hook the SIM into the CAM framework .
/* Couldn't satisfy request */ /* Held until a bus_deregister event */ /*
	 * Set a default transport so that a PATH_INQ can be issued to
	 * the SIM.  This will then allow for probing and attaching of
	 * a more appropriate transport.
	 */ /*periph*/ /* Notify interested parties */ /* Initiate bus rescan. */