FreeBSD/sys/dev/xen/blkback/blkback.c
/**
 * Map shared memory ring into domain local address space, initialize
 * ring control structures, and bind an interrupt to the event channel
 * used to notify us of ring changes.
 *
 * \param xbb  Per-instance xbb configuration structure.
 */
Map shared memory ring into domain local address space, initialize
ring control structures, and bind an interrupt to the event channel
used to notify us of ring changes.

\param xbb  Per-instance xbb configuration structure.
Map shared memory ring into domain local address space initialize ring control structures and bind an interrupt to the event channel used to notify us of ring changes . \ param xbb Per - instance xbb configuration structure .
static int
xbb_connect_ring(struct xbb_softc *xbb)
{
	struct gnttab_map_grant_ref  gnts[XBB_MAX_RING_PAGES];
	struct gnttab_map_grant_ref *gnt;
	u_int			     ring_idx;
	int			     error;
	if ((xbb->flags & XBBF_RING_CONNECTED) != 0)
		return (0);
	xbb->ring_config.va = xbb->kva
			    + (xbb->kva_size
			     - (xbb->ring_config.ring_pages * PAGE_SIZE));
	xbb->ring_config.gnt_addr = xbb->gnt_base_addr
				  + (xbb->kva_size
				   - (xbb->ring_config.ring_pages * PAGE_SIZE));
	for (ring_idx = 0, gnt = gnts;
	     ring_idx < xbb->ring_config.ring_pages;
	     ring_idx++, gnt++) {
		gnt->host_addr = xbb->ring_config.gnt_addr
			       + (ring_idx * PAGE_SIZE);
		gnt->flags     = GNTMAP_host_map;
		gnt->ref       = xbb->ring_config.ring_ref[ring_idx];
		gnt->dom       = xbb->otherend_id;
	}
	error = HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, gnts,
					  xbb->ring_config.ring_pages);
	if (error)
		panic("blkback: Ring page grant table op failed (%d)", error);
	for (ring_idx = 0, gnt = gnts;
	     ring_idx < xbb->ring_config.ring_pages;
	     ring_idx++, gnt++) {
		if (gnt->status != 0) {
			xbb->ring_config.va = 0;
			xenbus_dev_fatal(xbb->dev, EACCES,
					 "Ring shared page mapping failed. "
					 "Status %d.", gnt->status);
			return (EACCES);
		}
		xbb->ring_config.handle[ring_idx]   = gnt->handle;
		xbb->ring_config.bus_addr[ring_idx] = gnt->dev_bus_addr;
	}
	switch (xbb->abi) {
	case BLKIF_PROTOCOL_NATIVE:
	{
		blkif_sring_t *sring;
		sring = (blkif_sring_t *)xbb->ring_config.va;
		BACK_RING_INIT(&xbb->rings.native, sring,
			       xbb->ring_config.ring_pages * PAGE_SIZE);
		break;
	}
	case BLKIF_PROTOCOL_X86_32:
	{
		blkif_x86_32_sring_t *sring_x86_32;
		sring_x86_32 = (blkif_x86_32_sring_t *)xbb->ring_config.va;
		BACK_RING_INIT(&xbb->rings.x86_32, sring_x86_32,
			       xbb->ring_config.ring_pages * PAGE_SIZE);
		break;
	}
	case BLKIF_PROTOCOL_X86_64:
	{
		blkif_x86_64_sring_t *sring_x86_64;
		sring_x86_64 = (blkif_x86_64_sring_t *)xbb->ring_config.va;
		BACK_RING_INIT(&xbb->rings.x86_64, sring_x86_64,
			       xbb->ring_config.ring_pages * PAGE_SIZE);
		break;
	}
	default:
		panic("Unexpected blkif protocol ABI.");
	}
	xbb->flags |= XBBF_RING_CONNECTED;
	error = xen_intr_bind_remote_port(xbb->dev,
					  xbb->otherend_id,
					  xbb->ring_config.evtchn,
					  xbb_filter,
					  NULL,
					  xbb,
					  INTR_TYPE_BIO | INTR_MPSAFE,
					  &xbb->xen_intr_handle);
	if (error) {
		(void)xbb_disconnect(xbb);
		xenbus_dev_fatal(xbb->dev, error, "binding event channel");
		return (error);
	}
	DPRINTF("rings connected!\n");
	return 0;
}
static int xbb_connect_ring ( struct xbb_softc * xbb ) { struct gnttab_map_grant_ref gnts [ XBB_MAX_RING_PAGES ] ; struct gnttab_map_grant_ref * gnt ; u_int ring_idx ; int error ; if ( ( xbb -> flags & XBBF_RING_CONNECTED ) != 0 ) return ( 0 ) ; xbb -> ring_config . va = xbb -> kva + ( xbb -> kva_size - ( xbb -> ring_config . ring_pages * PAGE_SIZE ) ) ; xbb -> ring_config . gnt_addr = xbb -> gnt_base_addr + ( xbb -> kva_size - ( xbb -> ring_config . ring_pages * PAGE_SIZE ) ) ; for ( ring_idx = 0 , gnt = gnts ; ring_idx < xbb -> ring_config . ring_pages ; ring_idx ++ , gnt ++ ) { gnt -> host_addr = xbb -> ring_config . gnt_addr + ( ring_idx * PAGE_SIZE ) ; gnt -> flags = GNTMAP_host_map ; gnt -> ref = xbb -> ring_config . ring_ref [ ring_idx ] ; gnt -> dom = xbb -> otherend_id ; } error = HYPERVISOR_grant_table_op ( GNTTABOP_map_grant_ref , gnts , xbb -> ring_config . ring_pages ) ; if ( error ) panic ( " " , error ) ; for ( ring_idx = 0 , gnt = gnts ; ring_idx < xbb -> ring_config . ring_pages ; ring_idx ++ , gnt ++ ) { if ( gnt -> status != 0 ) { xbb -> ring_config . va = 0 ; xenbus_dev_fatal ( xbb -> dev , EACCES , " " " " , gnt -> status ) ; return ( EACCES ) ; } xbb -> ring_config . handle [ ring_idx ] = gnt -> handle ; xbb -> ring_config . bus_addr [ ring_idx ] = gnt -> dev_bus_addr ; } switch ( xbb -> abi ) { case BLKIF_PROTOCOL_NATIVE : { blkif_sring_t * sring ; sring = ( blkif_sring_t * ) xbb -> ring_config . va ; BACK_RING_INIT ( & xbb -> rings . native , sring , xbb -> ring_config . ring_pages * PAGE_SIZE ) ; break ; } case BLKIF_PROTOCOL_X86_32 : { blkif_x86_32_sring_t * sring_x86_32 ; sring_x86_32 = ( blkif_x86_32_sring_t * ) xbb -> ring_config . va ; BACK_RING_INIT ( & xbb -> rings . x86_32 , sring_x86_32 , xbb -> ring_config . ring_pages * PAGE_SIZE ) ; break ; } case BLKIF_PROTOCOL_X86_64 : { blkif_x86_64_sring_t * sring_x86_64 ; sring_x86_64 = ( blkif_x86_64_sring_t * ) xbb -> ring_config . va ; BACK_RING_INIT ( & xbb -> rings . x86_64 , sring_x86_64 , xbb -> ring_config . ring_pages * PAGE_SIZE ) ; break ; } default : panic ( " " ) ; } xbb -> flags |= XBBF_RING_CONNECTED ; error = xen_intr_bind_remote_port ( xbb -> dev , xbb -> otherend_id , xbb -> ring_config . evtchn , xbb_filter , NULL , xbb , INTR_TYPE_BIO | INTR_MPSAFE , & xbb -> xen_intr_handle ) ; if ( error ) { ( void ) xbb_disconnect ( xbb ) ; xenbus_dev_fatal ( xbb -> dev , error , " " ) ; return ( error ) ; } DPRINTF ( " \n " ) ; return 0 ; }
Map shared memory ring into domain local address space, initialize
 ring control structures, and bind an interrupt to the event channel
 used to notify us of ring changes.
Map shared memory ring into domain local address space initialize ring control structures and bind an interrupt to the event channel used to notify us of ring changes .
/*
	 * Kva for our ring is at the tail of the region of kva allocated
	 * by xbb_alloc_communication_mem().
	 */ /* Initialize the ring based on ABI. */ /*ithread_handler*/ /*arg*/