diff options
author | Rusty Russell <rusty@rustcorp.com.au> | 2008-02-04 23:49:56 -0500 |
---|---|---|
committer | Rusty Russell <rusty@rustcorp.com.au> | 2008-02-04 07:49:57 -0500 |
commit | a586d4f6016f7139d8c26df0e6927131168d3b5b (patch) | |
tree | 1c47e1a6b6b8fb18baa42f32980f29c4ae9cbbdc /include/linux/virtio_config.h | |
parent | f35d9d8aae08940b7fdd1bb8110619da2ece6b28 (diff) |
virtio: simplify config mechanism.
Previously we used a type/len pair within the config space, but this
seems overkill. We now simply define a structure which represents the
layout in the config space: the config space can now only be extended
at the end.
The main driver-visible changes:
1) We indicate what fields are present with an explicit feature bit.
2) Virtqueues are explicitly numbered, and not in the config space.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Diffstat (limited to 'include/linux/virtio_config.h')
-rw-r--r-- | include/linux/virtio_config.h | 98 |
1 files changed, 46 insertions, 52 deletions
diff --git a/include/linux/virtio_config.h b/include/linux/virtio_config.h index bcc01888df78..70bb26062d76 100644 --- a/include/linux/virtio_config.h +++ b/include/linux/virtio_config.h | |||
@@ -5,7 +5,7 @@ | |||
5 | * store and access that space differently. */ | 5 | * store and access that space differently. */ |
6 | #include <linux/types.h> | 6 | #include <linux/types.h> |
7 | 7 | ||
8 | /* Status byte for guest to report progress, and synchronize config. */ | 8 | /* Status byte for guest to report progress, and synchronize features. */ |
9 | /* We have seen device and processed generic fields (VIRTIO_CONFIG_F_VIRTIO) */ | 9 | /* We have seen device and processed generic fields (VIRTIO_CONFIG_F_VIRTIO) */ |
10 | #define VIRTIO_CONFIG_S_ACKNOWLEDGE 1 | 10 | #define VIRTIO_CONFIG_S_ACKNOWLEDGE 1 |
11 | /* We have found a driver for the device. */ | 11 | /* We have found a driver for the device. */ |
@@ -15,34 +15,27 @@ | |||
15 | /* We've given up on this device. */ | 15 | /* We've given up on this device. */ |
16 | #define VIRTIO_CONFIG_S_FAILED 0x80 | 16 | #define VIRTIO_CONFIG_S_FAILED 0x80 |
17 | 17 | ||
18 | /* Feature byte (actually 7 bits availabe): */ | ||
19 | /* Requirements/features of the virtio implementation. */ | ||
20 | #define VIRTIO_CONFIG_F_VIRTIO 1 | ||
21 | /* Requirements/features of the virtqueue (may have more than one). */ | ||
22 | #define VIRTIO_CONFIG_F_VIRTQUEUE 2 | ||
23 | |||
24 | #ifdef __KERNEL__ | 18 | #ifdef __KERNEL__ |
25 | struct virtio_device; | 19 | struct virtio_device; |
26 | 20 | ||
27 | /** | 21 | /** |
28 | * virtio_config_ops - operations for configuring a virtio device | 22 | * virtio_config_ops - operations for configuring a virtio device |
29 | * @find: search for the next configuration field of the given type. | 23 | * @feature: search for a feature in this config |
30 | * vdev: the virtio_device | 24 | * vdev: the virtio_device |
31 | * type: the feature type | 25 | * bit: the feature bit |
32 | * len: the (returned) length of the field if found. | 26 | * Returns true if the feature is supported. Acknowledges the feature |
33 | * Returns a token if found, or NULL. Never returnes the same field twice | 27 | * so the host can see it. |
34 | * (ie. it's used up). | 28 | * @get: read the value of a configuration field |
35 | * @get: read the value of a configuration field after find(). | ||
36 | * vdev: the virtio_device | 29 | * vdev: the virtio_device |
37 | * token: the token returned from find(). | 30 | * offset: the offset of the configuration field |
38 | * buf: the buffer to write the field value into. | 31 | * buf: the buffer to write the field value into. |
39 | * len: the length of the buffer (given by find()). | 32 | * len: the length of the buffer |
40 | * Note that contents are conventionally little-endian. | 33 | * Note that contents are conventionally little-endian. |
41 | * @set: write the value of a configuration field after find(). | 34 | * @set: write the value of a configuration field |
42 | * vdev: the virtio_device | 35 | * vdev: the virtio_device |
43 | * token: the token returned from find(). | 36 | * offset: the offset of the configuration field |
44 | * buf: the buffer to read the field value from. | 37 | * buf: the buffer to read the field value from. |
45 | * len: the length of the buffer (given by find()). | 38 | * len: the length of the buffer |
46 | * Note that contents are conventionally little-endian. | 39 | * Note that contents are conventionally little-endian. |
47 | * @get_status: read the status byte | 40 | * @get_status: read the status byte |
48 | * vdev: the virtio_device | 41 | * vdev: the virtio_device |
@@ -50,62 +43,63 @@ struct virtio_device; | |||
50 | * @set_status: write the status byte | 43 | * @set_status: write the status byte |
51 | * vdev: the virtio_device | 44 | * vdev: the virtio_device |
52 | * status: the new status byte | 45 | * status: the new status byte |
53 | * @find_vq: find the first VIRTIO_CONFIG_F_VIRTQUEUE and create a virtqueue. | 46 | * @find_vq: find a virtqueue and instantiate it. |
54 | * vdev: the virtio_device | 47 | * vdev: the virtio_device |
48 | * index: the 0-based virtqueue number in case there's more than one. | ||
55 | * callback: the virqtueue callback | 49 | * callback: the virqtueue callback |
56 | * Returns the new virtqueue or ERR_PTR(). | 50 | * Returns the new virtqueue or ERR_PTR() (eg. -ENOENT). |
57 | * @del_vq: free a virtqueue found by find_vq(). | 51 | * @del_vq: free a virtqueue found by find_vq(). |
58 | */ | 52 | */ |
59 | struct virtio_config_ops | 53 | struct virtio_config_ops |
60 | { | 54 | { |
61 | void *(*find)(struct virtio_device *vdev, u8 type, unsigned *len); | 55 | bool (*feature)(struct virtio_device *vdev, unsigned bit); |
62 | void (*get)(struct virtio_device *vdev, void *token, | 56 | void (*get)(struct virtio_device *vdev, unsigned offset, |
63 | void *buf, unsigned len); | 57 | void *buf, unsigned len); |
64 | void (*set)(struct virtio_device *vdev, void *token, | 58 | void (*set)(struct virtio_device *vdev, unsigned offset, |
65 | const void *buf, unsigned len); | 59 | const void *buf, unsigned len); |
66 | u8 (*get_status)(struct virtio_device *vdev); | 60 | u8 (*get_status)(struct virtio_device *vdev); |
67 | void (*set_status)(struct virtio_device *vdev, u8 status); | 61 | void (*set_status)(struct virtio_device *vdev, u8 status); |
68 | struct virtqueue *(*find_vq)(struct virtio_device *vdev, | 62 | struct virtqueue *(*find_vq)(struct virtio_device *vdev, |
63 | unsigned index, | ||
69 | bool (*callback)(struct virtqueue *)); | 64 | bool (*callback)(struct virtqueue *)); |
70 | void (*del_vq)(struct virtqueue *vq); | 65 | void (*del_vq)(struct virtqueue *vq); |
71 | }; | 66 | }; |
72 | 67 | ||
73 | /** | 68 | /** |
74 | * virtio_config_val - get a single virtio config and mark it used. | 69 | * virtio_config_val - look for a feature and get a single virtio config. |
75 | * @config: the virtio config space | 70 | * @vdev: the virtio device |
76 | * @type: the type to search for. | 71 | * @fbit: the feature bit |
72 | * @offset: the type to search for. | ||
77 | * @val: a pointer to the value to fill in. | 73 | * @val: a pointer to the value to fill in. |
78 | * | 74 | * |
79 | * Once used, the config type is marked with VIRTIO_CONFIG_F_USED so it can't | 75 | * The return value is -ENOENT if the feature doesn't exist. Otherwise |
80 | * be found again. This version does endian conversion. */ | 76 | * the value is endian-corrected and returned in v. */ |
81 | #define virtio_config_val(vdev, type, v) ({ \ | 77 | #define virtio_config_val(vdev, fbit, offset, v) ({ \ |
82 | int _err = __virtio_config_val((vdev),(type),(v),sizeof(*(v))); \ | 78 | int _err; \ |
83 | \ | 79 | if ((vdev)->config->feature((vdev), (fbit))) { \ |
84 | BUILD_BUG_ON(sizeof(*(v)) != 1 && sizeof(*(v)) != 2 \ | 80 | __virtio_config_val((vdev), (offset), (v)); \ |
85 | && sizeof(*(v)) != 4 && sizeof(*(v)) != 8); \ | 81 | _err = 0; \ |
86 | if (!_err) { \ | 82 | } else \ |
87 | switch (sizeof(*(v))) { \ | 83 | _err = -ENOENT; \ |
88 | case 2: le16_to_cpus((__u16 *) v); break; \ | ||
89 | case 4: le32_to_cpus((__u32 *) v); break; \ | ||
90 | case 8: le64_to_cpus((__u64 *) v); break; \ | ||
91 | } \ | ||
92 | } \ | ||
93 | _err; \ | 84 | _err; \ |
94 | }) | 85 | }) |
95 | 86 | ||
96 | int __virtio_config_val(struct virtio_device *dev, | ||
97 | u8 type, void *val, size_t size); | ||
98 | |||
99 | /** | 87 | /** |
100 | * virtio_use_bit - helper to use a feature bit in a bitfield value. | 88 | * __virtio_config_val - get a single virtio config without feature check. |
101 | * @dev: the virtio device | 89 | * @vdev: the virtio device |
102 | * @token: the token as returned from vdev->config->find(). | 90 | * @offset: the type to search for. |
103 | * @len: the length of the field. | 91 | * @val: a pointer to the value to fill in. |
104 | * @bitnum: the bit to test. | ||
105 | * | 92 | * |
106 | * If handed a NULL token, it returns false, otherwise returns bit status. | 93 | * The value is endian-corrected and returned in v. */ |
107 | * If it's one, it sets the mirroring acknowledgement bit. */ | 94 | #define __virtio_config_val(vdev, offset, v) do { \ |
108 | int virtio_use_bit(struct virtio_device *vdev, | 95 | BUILD_BUG_ON(sizeof(*(v)) != 1 && sizeof(*(v)) != 2 \ |
109 | void *token, unsigned int len, unsigned int bitnum); | 96 | && sizeof(*(v)) != 4 && sizeof(*(v)) != 8); \ |
97 | (vdev)->config->get((vdev), (offset), (v), sizeof(*(v))); \ | ||
98 | switch (sizeof(*(v))) { \ | ||
99 | case 2: le16_to_cpus((__u16 *) v); break; \ | ||
100 | case 4: le32_to_cpus((__u32 *) v); break; \ | ||
101 | case 8: le64_to_cpus((__u64 *) v); break; \ | ||
102 | } \ | ||
103 | } while(0) | ||
110 | #endif /* __KERNEL__ */ | 104 | #endif /* __KERNEL__ */ |
111 | #endif /* _LINUX_VIRTIO_CONFIG_H */ | 105 | #endif /* _LINUX_VIRTIO_CONFIG_H */ |