aboutsummaryrefslogtreecommitdiffstats
path: root/examples/intel/MAX10/runme_postsynth
diff options
context:
space:
mode:
Diffstat (limited to 'examples/intel/MAX10/runme_postsynth')
0 files changed, 0 insertions, 0 deletions
6' href='#n36'>36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143
/******************************************************************************
 * arch/xen/drivers/blkif/backend/interface.c
 * 
 * Block-device interface management.
 * 
 * Copyright (c) 2004, Keir Fraser
 */

#include "common.h"
#include <asm-xen/evtchn.h>

static kmem_cache_t *blkif_cachep;

blkif_t *alloc_blkif(domid_t domid)
{
	blkif_t *blkif;

	blkif = kmem_cache_alloc(blkif_cachep, GFP_KERNEL);
	if (!blkif)
		return ERR_PTR(-ENOMEM);

	memset(blkif, 0, sizeof(*blkif));
	blkif->domid = domid;
	blkif->status = DISCONNECTED;
	spin_lock_init(&blkif->blk_ring_lock);
	atomic_set(&blkif->refcnt, 1);

	return blkif;
}

static int map_frontend_page(blkif_t *blkif, unsigned long shared_page)
{
	struct gnttab_map_grant_ref op;

	op.host_addr = (unsigned long)blkif->blk_ring_area->addr;
	op.flags     = GNTMAP_host_map;
	op.ref       = shared_page;
	op.dom       = blkif->domid;

	lock_vm_area(blkif->blk_ring_area);
	BUG_ON(HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1));
	unlock_vm_area(blkif->blk_ring_area);

	if (op.handle < 0) {
		DPRINTK(" Grant table operation failure !\n");
		return op.handle;
	}

	blkif->shmem_ref    = shared_page;
	blkif->shmem_handle = op.handle;

	return 0;
}

static void unmap_frontend_page(blkif_t *blkif)
{
	struct gnttab_unmap_grant_ref op;

	op.host_addr    = (unsigned long)blkif->blk_ring_area->addr;
	op.handle       = blkif->shmem_handle;
	op.dev_bus_addr = 0;

	lock_vm_area(blkif->blk_ring_area);
	BUG_ON(HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &op, 1));
	unlock_vm_area(blkif->blk_ring_area);
}

int blkif_map(blkif_t *blkif, unsigned long shared_page, unsigned int evtchn)
{
	blkif_sring_t *sring;
	int err;
	evtchn_op_t op = {
		.cmd = EVTCHNOP_bind_interdomain,
		.u.bind_interdomain.remote_dom  = blkif->domid,
		.u.bind_interdomain.remote_port = evtchn };

	if ((blkif->blk_ring_area = alloc_vm_area(PAGE_SIZE)) == NULL)
		return -ENOMEM;

	err = map_frontend_page(blkif, shared_page);
	if (err) {
		free_vm_area(blkif->blk_ring_area);
		return err;
	}

	err = HYPERVISOR_event_channel_op(&op);
	if (err) {
		unmap_frontend_page(blkif);
		free_vm_area(blkif->blk_ring_area);
		return err;
	}

	blkif->evtchn = op.u.bind_interdomain.local_port;

	sring = (blkif_sring_t *)blkif->blk_ring_area->addr;
	SHARED_RING_INIT(sring);
	BACK_RING_INIT(&blkif->blk_ring, sring, PAGE_SIZE);

	blkif->irq = bind_evtchn_to_irqhandler(
		blkif->evtchn, blkif_be_int, 0, "blkif-backend", blkif);

	blkif->status = CONNECTED;

	return 0;
}

static void free_blkif(void *arg)
{
	blkif_t *blkif = (blkif_t *)arg;

	if (blkif->irq)
		unbind_evtchn_from_irqhandler(blkif->irq, blkif);

	if (blkif->blk_ring.sring) {
		unmap_frontend_page(blkif);
		free_vm_area(blkif->blk_ring_area);
		blkif->blk_ring.sring = NULL;
	}

	kmem_cache_free(blkif_cachep, blkif);
}

void free_blkif_callback(blkif_t *blkif)
{
	INIT_WORK(&blkif->free_work, free_blkif, (void *)blkif);
	schedule_work(&blkif->free_work);
}

void __init blkif_interface_init(void)
{
	blkif_cachep = kmem_cache_create(
		"blkif_cache", sizeof(blkif_t), 0, 0, NULL, NULL);
}

/*
 * Local variables:
 *  c-file-style: "linux"
 *  indent-tabs-mode: t
 *  c-indent-level: 8
 *  c-basic-offset: 8
 *  tab-width: 8
 * End:
 */