#include "../xen/xen.h" /****************************************************************************** * blkif.h * * Unified block-device I/O interface for Xen guest OSes. * * Copyright (c) 2003-2004, Keir Fraser */ #ifndef __SHARED_BLKIF_H__ #define __SHARED_BLKIF_H__ #define BLKIF_OP_READ 0 #define BLKIF_OP_WRITE 1 #define BLKIF_OP_PROBE 2 /* NB. Ring size must be small enough for sizeof(blkif_ring_t) <= PAGE_SIZE. */ #define BLKIF_RING_SIZE 64 /* * Maximum scatter/gather segments per request. * This is carefully chosen so that sizeof(blkif_ring_t) <= PAGE_SIZE. * NB. This could be 12 if the ring indexes weren't stored in the same page. */ #define BLKIF_MAX_SEGMENTS_PER_REQUEST 11 typedef struct { u8 operation; /* 0: BLKIF_OP_??? */ u8 nr_segments; /* 1: number of segments */ blkif_vdev_t device; /* 2: only for read/write requests */ unsigned long id; /* 4: private guest value, echoed in resp */ blkif_sector_t sector_number; /* start sector idx on disk (r/w only) */ /* @f_a_s[2:0]=last_sect ; @f_a_s[5:3]=first_sect ; @f_a_s[:12]=frame. */ /* @first_sect: first sector in frame to transfer (inclusive). */ /* @last_sect: last sector in frame to transfer (inclusive). */ /* @frame: machine page frame number. */ unsigned long frame_and_sects[BLKIF_MAX_SEGMENTS_PER_REQUEST]; } PACKED blkif_request_t; #define blkif_first_sect(_fas) (((_fas)>>3)&7) #define blkif_last_sect(_fas) ((_fas)&7) typedef struct { unsigned long id; /* copied from request */ u8 operation; /* copied from request */ s16 status; /* BLKIF_RSP_??? */ } PACKED blkif_response_t; #define BLKIF_RSP_ERROR -1 /* non-specific 'error' */ #define BLKIF_RSP_OKAY 0 /* non-specific 'okay' */ /* * We use a special capitalised type name because it is _essential_ that all * arithmetic on indexes is done on an integer type of the correct size. */ typedef u32 BLKIF_RING_IDX; /* * Ring indexes are 'free running'. That is, they are not stored modulo the * size of the ring buffer. The following macro converts a free-running counter * into a value that can directly index a ring-buffer array. */ #define MASK_BLKIF_IDX(_i) ((_i)&(BLKIF_RING_SIZE-1)) typedef struct { BLKIF_RING_IDX req_prod; /* 0: Request producer. Updated by front-end. */ BLKIF_RING_IDX resp_prod; /* 4: Response producer. Updated by back-end. */ union { /* 8 */ blkif_request_t req; blkif_response_t resp; } PACKED ring[BLKIF_RING_SIZE]; } PACKED blkif_ring_t; /* * BLKIF_OP_PROBE: * The request format for a probe request is constrained as follows: * @operation == BLKIF_OP_PROBE * @nr_segments == size of probe buffer in pages * @device == unused (zero) * @id == any value (echoed in response message) * @sector_num == unused (zero) * @frame_and_sects == list of page-sized buffers. * (i.e., @first_sect == 0, @last_sect == 7). * * The response is a list of vdisk_t elements copied into the out-of-band * probe buffer. On success the response status field contains the number * of vdisk_t elements. */ /* XXX SMH: Type values below are chosen to match ide_xxx in Linux ide.h. */ #define VDISK_TYPE_FLOPPY 0x00 #define VDISK_TYPE_TAPE 0x01 #define VDISK_TYPE_CDROM 0x05 #define VDISK_TYPE_OPTICAL 0x07 #define VDISK_TYPE_DISK 0x20 #define VDISK_TYPE_MASK 0x3F #define VDISK_TYPE(_x) ((_x) & VDISK_TYPE_MASK) /* The top two bits of the type field encode various flags. */ #define VDISK_FLAG_RO 0x40 #define VDISK_FLAG_VIRT 0x80 #define VDISK_READONLY(_x) ((_x) & VDISK_FLAG_RO) #define VDISK_VIRTUAL(_x) ((_x) & VDISK_FLAG_VIRT) typedef struct { blkif_sector_t capacity; /* 0: Size in terms of 512-byte sectors. */ blkif_vdev_t device; /* 8: Device number (opaque 16 bit value). */ u16 info; /* 10: Device type and flags (VDISK_*). */ } PACKED vdisk_t; /* 12 bytes */ #endif /* __SHARED_BLKIF_H__ */ /****************************************************************************** * arch/xen/drivers/blkif/backend/common.h */ #ifndef __BLKIF__BACKEND__COMMON_H__ #define __BLKIF__BACKEND__COMMON_H__ typedef struct blkif_st { Ref refcnt; Lock vbd_lock; /* Protects VBD mapping. */ /* Unique identifier for this interface. */ domid_t domid; unsigned int handle; /* Physical parameters of the comms window. */ unsigned long shmem_frame; unsigned int evtchn; int irq; /* Comms information. */ blkif_ring_t *blk_ring_base; /* ioremap()'ed ptr to shmem_frame. */ BLKIF_RING_IDX blk_req_cons; /* Request consumer. */ BLKIF_RING_IDX blk_resp_prod; /* Private version of resp. producer. */ /* VBDs attached to this interface. */ /* Private fields. */ enum { DISCONNECTED, DISCONNECTING, CONNECTED } status; /* * DISCONNECT response is deferred until pending requests are ack'ed. * We therefore need to store the id from the original request. */ u8 disconnect_rspid; struct blkif_st *hash_next; Queue * blkdev_list; Lock blk_ring_lock; } blkif_t; void blkif_create(blkif_be_create_t *create); void blkif_destroy(blkif_be_destroy_t *destroy); void blkif_connect(blkif_be_connect_t *connect); int blkif_disconnect(blkif_be_disconnect_t *disconnect, u8 rsp_id); void __blkif_disconnect_complete(blkif_t *blkif); blkif_t *blkif_find_by_handle(domid_t domid, unsigned int handle); #define blkif_get(_b) (incref(_b)) #define blkif_put(_b) \ do { \ if ( decref(_b) ) \ __blkif_disconnect_complete(_b); \ } while (0) /* An entry in a list of xen_extents. */ typedef struct _blkif_extent_le { blkif_extent_t extent; /* an individual extent */ struct _blkif_extent_le *next; /* and a pointer to the next */ } blkif_extent_le_t; typedef struct _vbd { blkif_vdev_t vdevice; /* what the domain refers to this vbd as */ unsigned char readonly; /* Non-zero -> read-only */ unsigned char type; /* VDISK_TYPE_xxx */ blkif_extent_le_t *extents; /* list of xen_extents making up this vbd */ } vbd_t; void vbd_create(blkif_be_vbd_create_t *create); void vbd_grow(blkif_be_vbd_grow_t *grow); void vbd_shrink(blkif_be_vbd_shrink_t *shrink); void vbd_destroy(blkif_be_vbd_destroy_t *delete); int vbd_probe(blkif_t *blkif, vdisk_t *vbd_info, int max_vbds); void destroy_all_vbds(blkif_t *blkif); /* Describes a [partial] disk extent (part of a block io request) */ typedef struct { unsigned short dev; unsigned short nr_sects; unsigned long buffer; blkif_sector_t sector_number; } phys_seg_t; int vbd_translate(phys_seg_t *pseg, blkif_t *blkif, int operation); void blkif_interface_init(void); void blkif_ctrlif_init(void); void blkif_deschedule(blkif_t *blkif); void blkif_be_int(int irq, void *dev_id, struct Ureg *regs); #endif /* __BLKIF__BACKEND__COMMON_H__ */