virtio.h 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711
  1. /* SPDX-License-Identifier: GPL-2.0+ */
  2. /*
  3. * Copyright (C) 2018, Tuomas Tynkkynen <tuomas.tynkkynen@iki.fi>
  4. * Copyright (C) 2018, Bin Meng <bmeng.cn@gmail.com>
  5. *
  6. * VirtIO is a virtualization standard for network and disk device drivers
  7. * where just the guest's device driver "knows" it is running in a virtual
  8. * environment, and cooperates with the hypervisor. This enables guests to
  9. * get high performance network and disk operations, and gives most of the
  10. * performance benefits of paravirtualization. In the U-Boot case, the guest
  11. * is U-Boot itself, while the virtual environment are normally QEMU targets
  12. * like ARM, RISC-V and x86.
  13. *
  14. * See http://docs.oasis-open.org/virtio/virtio/v1.0/virtio-v1.0.pdf for
  15. * the VirtIO specification v1.0.
  16. *
  17. * This file is largely based on Linux kernel virtio_*.h files
  18. */
  19. #ifndef __VIRTIO_H__
  20. #define __VIRTIO_H__
  21. #include <linux/bitops.h>
  22. #include <linux/bug.h>
  23. #define VIRTIO_ID_NET 1 /* virtio net */
  24. #define VIRTIO_ID_BLOCK 2 /* virtio block */
  25. #define VIRTIO_ID_RNG 4 /* virtio rng */
  26. #define VIRTIO_ID_MAX_NUM 5
  27. #define VIRTIO_NET_DRV_NAME "virtio-net"
  28. #define VIRTIO_BLK_DRV_NAME "virtio-blk"
  29. #define VIRTIO_RNG_DRV_NAME "virtio-rng"
  30. /* Status byte for guest to report progress, and synchronize features */
  31. /* We have seen device and processed generic fields (VIRTIO_CONFIG_F_VIRTIO) */
  32. #define VIRTIO_CONFIG_S_ACKNOWLEDGE 1
  33. /* We have found a driver for the device */
  34. #define VIRTIO_CONFIG_S_DRIVER 2
  35. /* Driver has used its parts of the config, and is happy */
  36. #define VIRTIO_CONFIG_S_DRIVER_OK 4
  37. /* Driver has finished configuring features */
  38. #define VIRTIO_CONFIG_S_FEATURES_OK 8
  39. /* Device entered invalid state, driver must reset it */
  40. #define VIRTIO_CONFIG_S_NEEDS_RESET 0x40
  41. /* We've given up on this device */
  42. #define VIRTIO_CONFIG_S_FAILED 0x80
  43. /*
  44. * Virtio feature bits VIRTIO_TRANSPORT_F_START through VIRTIO_TRANSPORT_F_END
  45. * are reserved for the transport being used (eg: virtio_ring, virtio_pci etc.),
  46. * the rest are per-device feature bits.
  47. */
  48. #define VIRTIO_TRANSPORT_F_START 28
  49. #define VIRTIO_TRANSPORT_F_END 38
  50. #ifndef VIRTIO_CONFIG_NO_LEGACY
  51. /*
  52. * Do we get callbacks when the ring is completely used,
  53. * even if we've suppressed them?
  54. */
  55. #define VIRTIO_F_NOTIFY_ON_EMPTY 24
  56. /* Can the device handle any descriptor layout? */
  57. #define VIRTIO_F_ANY_LAYOUT 27
  58. #endif /* VIRTIO_CONFIG_NO_LEGACY */
  59. /* v1.0 compliant */
  60. #define VIRTIO_F_VERSION_1 32
  61. /*
  62. * If clear - device has the IOMMU bypass quirk feature.
  63. * If set - use platform tools to detect the IOMMU.
  64. *
  65. * Note the reverse polarity (compared to most other features),
  66. * this is for compatibility with legacy systems.
  67. */
  68. #define VIRTIO_F_IOMMU_PLATFORM 33
  69. /* Does the device support Single Root I/O Virtualization? */
  70. #define VIRTIO_F_SR_IOV 37
  71. /**
  72. * virtio scatter-gather struct
  73. *
  74. * @addr: sg buffer address
  75. * @lengh: sg buffer length
  76. */
  77. struct virtio_sg {
  78. void *addr;
  79. size_t length;
  80. };
  81. struct virtqueue;
  82. /* virtio bus operations */
  83. struct dm_virtio_ops {
  84. /**
  85. * get_config() - read the value of a configuration field
  86. *
  87. * @vdev: the real virtio device
  88. * @offset: the offset of the configuration field
  89. * @buf: the buffer to write the field value into
  90. * @len: the length of the buffer
  91. * @return 0 if OK, -ve on error
  92. */
  93. int (*get_config)(struct udevice *vdev, unsigned int offset,
  94. void *buf, unsigned int len);
  95. /**
  96. * set_config() - write the value of a configuration field
  97. *
  98. * @vdev: the real virtio device
  99. * @offset: the offset of the configuration field
  100. * @buf: the buffer to read the field value from
  101. * @len: the length of the buffer
  102. * @return 0 if OK, -ve on error
  103. */
  104. int (*set_config)(struct udevice *vdev, unsigned int offset,
  105. const void *buf, unsigned int len);
  106. /**
  107. * generation() - config generation counter
  108. *
  109. * @vdev: the real virtio device
  110. * @counter: the returned config generation counter
  111. * @return 0 if OK, -ve on error
  112. */
  113. int (*generation)(struct udevice *vdev, u32 *counter);
  114. /**
  115. * get_status() - read the status byte
  116. *
  117. * @vdev: the real virtio device
  118. * @status: the returned status byte
  119. * @return 0 if OK, -ve on error
  120. */
  121. int (*get_status)(struct udevice *vdev, u8 *status);
  122. /**
  123. * set_status() - write the status byte
  124. *
  125. * @vdev: the real virtio device
  126. * @status: the new status byte
  127. * @return 0 if OK, -ve on error
  128. */
  129. int (*set_status)(struct udevice *vdev, u8 status);
  130. /**
  131. * reset() - reset the device
  132. *
  133. * @vdev: the real virtio device
  134. * @return 0 if OK, -ve on error
  135. */
  136. int (*reset)(struct udevice *vdev);
  137. /**
  138. * get_features() - get the array of feature bits for this device
  139. *
  140. * @vdev: the real virtio device
  141. * @features: the first 32 feature bits (all we currently need)
  142. * @return 0 if OK, -ve on error
  143. */
  144. int (*get_features)(struct udevice *vdev, u64 *features);
  145. /**
  146. * set_features() - confirm what device features we'll be using
  147. *
  148. * @vdev: the real virtio device
  149. * @return 0 if OK, -ve on error
  150. */
  151. int (*set_features)(struct udevice *vdev);
  152. /**
  153. * find_vqs() - find virtqueues and instantiate them
  154. *
  155. * @vdev: the real virtio device
  156. * @nvqs: the number of virtqueues to find
  157. * @vqs: on success, includes new virtqueues
  158. * @return 0 if OK, -ve on error
  159. */
  160. int (*find_vqs)(struct udevice *vdev, unsigned int nvqs,
  161. struct virtqueue *vqs[]);
  162. /**
  163. * del_vqs() - free virtqueues found by find_vqs()
  164. *
  165. * @vdev: the real virtio device
  166. * @return 0 if OK, -ve on error
  167. */
  168. int (*del_vqs)(struct udevice *vdev);
  169. /**
  170. * notify() - notify the device to process the queue
  171. *
  172. * @vdev: the real virtio device
  173. * @vq: virtqueue to process
  174. * @return 0 if OK, -ve on error
  175. */
  176. int (*notify)(struct udevice *vdev, struct virtqueue *vq);
  177. };
  178. /* Get access to a virtio bus' operations */
  179. #define virtio_get_ops(dev) ((struct dm_virtio_ops *)(dev)->driver->ops)
  180. /**
  181. * virtio uclass per device private data
  182. *
  183. * @vqs: virtualqueue for the virtio device
  184. * @vdev: the real virtio device underneath
  185. * @legacy: is it a legacy device?
  186. * @device: virtio device ID
  187. * @vendor: virtio vendor ID
  188. * @features: negotiated supported features
  189. * @feature_table: an array of feature supported by the driver
  190. * @feature_table_size: number of entries in the feature table array
  191. * @feature_table_legacy: same as feature_table but working in legacy mode
  192. * @feature_table_size_legacy: number of entries in feature table legacy array
  193. */
  194. struct virtio_dev_priv {
  195. struct list_head vqs;
  196. struct udevice *vdev;
  197. bool legacy;
  198. u32 device;
  199. u32 vendor;
  200. u64 features;
  201. const u32 *feature_table;
  202. u32 feature_table_size;
  203. const u32 *feature_table_legacy;
  204. u32 feature_table_size_legacy;
  205. };
  206. /**
  207. * virtio_get_config() - read the value of a configuration field
  208. *
  209. * @vdev: the real virtio device
  210. * @offset: the offset of the configuration field
  211. * @buf: the buffer to write the field value into
  212. * @len: the length of the buffer
  213. * @return 0 if OK, -ve on error
  214. */
  215. int virtio_get_config(struct udevice *vdev, unsigned int offset,
  216. void *buf, unsigned int len);
  217. /**
  218. * virtio_set_config() - write the value of a configuration field
  219. *
  220. * @vdev: the real virtio device
  221. * @offset: the offset of the configuration field
  222. * @buf: the buffer to read the field value from
  223. * @len: the length of the buffer
  224. * @return 0 if OK, -ve on error
  225. */
  226. int virtio_set_config(struct udevice *vdev, unsigned int offset,
  227. void *buf, unsigned int len);
  228. /**
  229. * virtio_generation() - config generation counter
  230. *
  231. * @vdev: the real virtio device
  232. * @counter: the returned config generation counter
  233. * @return 0 if OK, -ve on error
  234. */
  235. int virtio_generation(struct udevice *vdev, u32 *counter);
  236. /**
  237. * virtio_get_status() - read the status byte
  238. *
  239. * @vdev: the real virtio device
  240. * @status: the returned status byte
  241. * @return 0 if OK, -ve on error
  242. */
  243. int virtio_get_status(struct udevice *vdev, u8 *status);
  244. /**
  245. * virtio_set_status() - write the status byte
  246. *
  247. * @vdev: the real virtio device
  248. * @status: the new status byte
  249. * @return 0 if OK, -ve on error
  250. */
  251. int virtio_set_status(struct udevice *vdev, u8 status);
  252. /**
  253. * virtio_reset() - reset the device
  254. *
  255. * @vdev: the real virtio device
  256. * @return 0 if OK, -ve on error
  257. */
  258. int virtio_reset(struct udevice *vdev);
  259. /**
  260. * virtio_get_features() - get the array of feature bits for this device
  261. *
  262. * @vdev: the real virtio device
  263. * @features: the first 32 feature bits (all we currently need)
  264. * @return 0 if OK, -ve on error
  265. */
  266. int virtio_get_features(struct udevice *vdev, u64 *features);
  267. /**
  268. * virtio_set_features() - confirm what device features we'll be using
  269. *
  270. * @vdev: the real virtio device
  271. * @return 0 if OK, -ve on error
  272. */
  273. int virtio_set_features(struct udevice *vdev);
  274. /**
  275. * virtio_find_vqs() - find virtqueues and instantiate them
  276. *
  277. * @vdev: the real virtio device
  278. * @nvqs: the number of virtqueues to find
  279. * @vqs: on success, includes new virtqueues
  280. * @return 0 if OK, -ve on error
  281. */
  282. int virtio_find_vqs(struct udevice *vdev, unsigned int nvqs,
  283. struct virtqueue *vqs[]);
  284. /**
  285. * virtio_del_vqs() - free virtqueues found by find_vqs()
  286. *
  287. * @vdev: the real virtio device
  288. * @return 0 if OK, -ve on error
  289. */
  290. int virtio_del_vqs(struct udevice *vdev);
  291. /**
  292. * virtio_notify() - notify the device to process the queue
  293. *
  294. * @vdev: the real virtio device
  295. * @vq: virtqueue to process
  296. * @return 0 if OK, -ve on error
  297. */
  298. int virtio_notify(struct udevice *vdev, struct virtqueue *vq);
  299. /**
  300. * virtio_add_status() - helper to set a new status code to the device
  301. *
  302. * @vdev: the real virtio device
  303. * @status: new status code to be added
  304. */
  305. void virtio_add_status(struct udevice *vdev, u8 status);
  306. /**
  307. * virtio_finalize_features() - helper to finalize features
  308. *
  309. * @vdev: the real virtio device
  310. * @return 0 if OK, -ve on error
  311. */
  312. int virtio_finalize_features(struct udevice *vdev);
  313. /**
  314. * virtio_driver_features_init() - initialize driver supported features
  315. *
  316. * This fills in the virtio device parent per child private data with the given
  317. * information, which contains driver supported features and legacy features.
  318. *
  319. * This API should be called in the virtio device driver's bind method, so that
  320. * later virtio transport uclass driver can utilize the driver supplied features
  321. * to negotiate with the device on the final supported features.
  322. *
  323. * @priv: virtio uclass per device private data
  324. * @feature: an array of feature supported by the driver
  325. * @feature_size: number of entries in the feature table array
  326. * @feature_legacy: same as feature_table but working in legacy mode
  327. * @feature_legacy_size:number of entries in feature table legacy array
  328. */
  329. void virtio_driver_features_init(struct virtio_dev_priv *priv,
  330. const u32 *feature,
  331. u32 feature_size,
  332. const u32 *feature_legacy,
  333. u32 feature_legacy_size);
  334. /**
  335. * virtio_init() - helper to enumerate all known virtio devices
  336. *
  337. * @return 0 if OK, -ve on error
  338. */
  339. int virtio_init(void);
  340. static inline u16 __virtio16_to_cpu(bool little_endian, __virtio16 val)
  341. {
  342. if (little_endian)
  343. return le16_to_cpu((__force __le16)val);
  344. else
  345. return be16_to_cpu((__force __be16)val);
  346. }
  347. static inline __virtio16 __cpu_to_virtio16(bool little_endian, u16 val)
  348. {
  349. if (little_endian)
  350. return (__force __virtio16)cpu_to_le16(val);
  351. else
  352. return (__force __virtio16)cpu_to_be16(val);
  353. }
  354. static inline u32 __virtio32_to_cpu(bool little_endian, __virtio32 val)
  355. {
  356. if (little_endian)
  357. return le32_to_cpu((__force __le32)val);
  358. else
  359. return be32_to_cpu((__force __be32)val);
  360. }
  361. static inline __virtio32 __cpu_to_virtio32(bool little_endian, u32 val)
  362. {
  363. if (little_endian)
  364. return (__force __virtio32)cpu_to_le32(val);
  365. else
  366. return (__force __virtio32)cpu_to_be32(val);
  367. }
  368. static inline u64 __virtio64_to_cpu(bool little_endian, __virtio64 val)
  369. {
  370. if (little_endian)
  371. return le64_to_cpu((__force __le64)val);
  372. else
  373. return be64_to_cpu((__force __be64)val);
  374. }
  375. static inline __virtio64 __cpu_to_virtio64(bool little_endian, u64 val)
  376. {
  377. if (little_endian)
  378. return (__force __virtio64)cpu_to_le64(val);
  379. else
  380. return (__force __virtio64)cpu_to_be64(val);
  381. }
  382. /**
  383. * __virtio_test_bit - helper to test feature bits
  384. *
  385. * For use by transports. Devices should normally use virtio_has_feature,
  386. * which includes more checks.
  387. *
  388. * @udev: the transport device
  389. * @fbit: the feature bit
  390. */
  391. static inline bool __virtio_test_bit(struct udevice *udev, unsigned int fbit)
  392. {
  393. struct virtio_dev_priv *uc_priv = dev_get_uclass_priv(udev);
  394. /* Did you forget to fix assumptions on max features? */
  395. if (__builtin_constant_p(fbit))
  396. BUILD_BUG_ON(fbit >= 64);
  397. else
  398. WARN_ON(fbit >= 64);
  399. return uc_priv->features & BIT_ULL(fbit);
  400. }
  401. /**
  402. * __virtio_set_bit - helper to set feature bits
  403. *
  404. * For use by transports.
  405. *
  406. * @udev: the transport device
  407. * @fbit: the feature bit
  408. */
  409. static inline void __virtio_set_bit(struct udevice *udev, unsigned int fbit)
  410. {
  411. struct virtio_dev_priv *uc_priv = dev_get_uclass_priv(udev);
  412. /* Did you forget to fix assumptions on max features? */
  413. if (__builtin_constant_p(fbit))
  414. BUILD_BUG_ON(fbit >= 64);
  415. else
  416. WARN_ON(fbit >= 64);
  417. uc_priv->features |= BIT_ULL(fbit);
  418. }
  419. /**
  420. * __virtio_clear_bit - helper to clear feature bits
  421. *
  422. * For use by transports.
  423. *
  424. * @vdev: the transport device
  425. * @fbit: the feature bit
  426. */
  427. static inline void __virtio_clear_bit(struct udevice *udev, unsigned int fbit)
  428. {
  429. struct virtio_dev_priv *uc_priv = dev_get_uclass_priv(udev);
  430. /* Did you forget to fix assumptions on max features? */
  431. if (__builtin_constant_p(fbit))
  432. BUILD_BUG_ON(fbit >= 64);
  433. else
  434. WARN_ON(fbit >= 64);
  435. uc_priv->features &= ~BIT_ULL(fbit);
  436. }
  437. /**
  438. * virtio_has_feature - helper to determine if this device has this feature
  439. *
  440. * Note this API is only usable after the virtio device driver's bind phase,
  441. * as the feature has been negotiated between the device and the driver.
  442. *
  443. * @vdev: the virtio device
  444. * @fbit: the feature bit
  445. */
  446. static inline bool virtio_has_feature(struct udevice *vdev, unsigned int fbit)
  447. {
  448. if (!(vdev->flags & DM_FLAG_BOUND))
  449. WARN_ON(true);
  450. return __virtio_test_bit(vdev->parent, fbit);
  451. }
  452. static inline bool virtio_legacy_is_little_endian(void)
  453. {
  454. #ifdef __LITTLE_ENDIAN
  455. return true;
  456. #else
  457. return false;
  458. #endif
  459. }
  460. static inline bool virtio_is_little_endian(struct udevice *vdev)
  461. {
  462. struct virtio_dev_priv *uc_priv = dev_get_uclass_priv(vdev->parent);
  463. return !uc_priv->legacy || virtio_legacy_is_little_endian();
  464. }
  465. /* Memory accessors */
  466. static inline u16 virtio16_to_cpu(struct udevice *vdev, __virtio16 val)
  467. {
  468. return __virtio16_to_cpu(virtio_is_little_endian(vdev), val);
  469. }
  470. static inline __virtio16 cpu_to_virtio16(struct udevice *vdev, u16 val)
  471. {
  472. return __cpu_to_virtio16(virtio_is_little_endian(vdev), val);
  473. }
  474. static inline u32 virtio32_to_cpu(struct udevice *vdev, __virtio32 val)
  475. {
  476. return __virtio32_to_cpu(virtio_is_little_endian(vdev), val);
  477. }
  478. static inline __virtio32 cpu_to_virtio32(struct udevice *vdev, u32 val)
  479. {
  480. return __cpu_to_virtio32(virtio_is_little_endian(vdev), val);
  481. }
  482. static inline u64 virtio64_to_cpu(struct udevice *vdev, __virtio64 val)
  483. {
  484. return __virtio64_to_cpu(virtio_is_little_endian(vdev), val);
  485. }
  486. static inline __virtio64 cpu_to_virtio64(struct udevice *vdev, u64 val)
  487. {
  488. return __cpu_to_virtio64(virtio_is_little_endian(vdev), val);
  489. }
  490. /* Read @count fields, @bytes each */
  491. static inline void __virtio_cread_many(struct udevice *vdev,
  492. unsigned int offset,
  493. void *buf, size_t count, size_t bytes)
  494. {
  495. u32 old, gen;
  496. int i;
  497. /* no need to check return value as generation can be optional */
  498. virtio_generation(vdev, &gen);
  499. do {
  500. old = gen;
  501. for (i = 0; i < count; i++)
  502. virtio_get_config(vdev, offset + bytes * i,
  503. buf + i * bytes, bytes);
  504. virtio_generation(vdev, &gen);
  505. } while (gen != old);
  506. }
  507. static inline void virtio_cread_bytes(struct udevice *vdev,
  508. unsigned int offset,
  509. void *buf, size_t len)
  510. {
  511. __virtio_cread_many(vdev, offset, buf, len, 1);
  512. }
  513. static inline u8 virtio_cread8(struct udevice *vdev, unsigned int offset)
  514. {
  515. u8 ret;
  516. virtio_get_config(vdev, offset, &ret, sizeof(ret));
  517. return ret;
  518. }
  519. static inline void virtio_cwrite8(struct udevice *vdev,
  520. unsigned int offset, u8 val)
  521. {
  522. virtio_set_config(vdev, offset, &val, sizeof(val));
  523. }
  524. static inline u16 virtio_cread16(struct udevice *vdev,
  525. unsigned int offset)
  526. {
  527. u16 ret;
  528. virtio_get_config(vdev, offset, &ret, sizeof(ret));
  529. return virtio16_to_cpu(vdev, (__force __virtio16)ret);
  530. }
  531. static inline void virtio_cwrite16(struct udevice *vdev,
  532. unsigned int offset, u16 val)
  533. {
  534. val = (__force u16)cpu_to_virtio16(vdev, val);
  535. virtio_set_config(vdev, offset, &val, sizeof(val));
  536. }
  537. static inline u32 virtio_cread32(struct udevice *vdev,
  538. unsigned int offset)
  539. {
  540. u32 ret;
  541. virtio_get_config(vdev, offset, &ret, sizeof(ret));
  542. return virtio32_to_cpu(vdev, (__force __virtio32)ret);
  543. }
  544. static inline void virtio_cwrite32(struct udevice *vdev,
  545. unsigned int offset, u32 val)
  546. {
  547. val = (__force u32)cpu_to_virtio32(vdev, val);
  548. virtio_set_config(vdev, offset, &val, sizeof(val));
  549. }
  550. static inline u64 virtio_cread64(struct udevice *vdev,
  551. unsigned int offset)
  552. {
  553. u64 ret;
  554. __virtio_cread_many(vdev, offset, &ret, 1, sizeof(ret));
  555. return virtio64_to_cpu(vdev, (__force __virtio64)ret);
  556. }
  557. static inline void virtio_cwrite64(struct udevice *vdev,
  558. unsigned int offset, u64 val)
  559. {
  560. val = (__force u64)cpu_to_virtio64(vdev, val);
  561. virtio_set_config(vdev, offset, &val, sizeof(val));
  562. }
  563. /* Config space read accessor */
  564. #define virtio_cread(vdev, structname, member, ptr) \
  565. do { \
  566. /* Must match the member's type, and be integer */ \
  567. if (!typecheck(typeof((((structname *)0)->member)), *(ptr))) \
  568. (*ptr) = 1; \
  569. \
  570. switch (sizeof(*ptr)) { \
  571. case 1: \
  572. *(ptr) = virtio_cread8(vdev, \
  573. offsetof(structname, member)); \
  574. break; \
  575. case 2: \
  576. *(ptr) = virtio_cread16(vdev, \
  577. offsetof(structname, member)); \
  578. break; \
  579. case 4: \
  580. *(ptr) = virtio_cread32(vdev, \
  581. offsetof(structname, member)); \
  582. break; \
  583. case 8: \
  584. *(ptr) = virtio_cread64(vdev, \
  585. offsetof(structname, member)); \
  586. break; \
  587. default: \
  588. WARN_ON(true); \
  589. } \
  590. } while (0)
  591. /* Config space write accessor */
  592. #define virtio_cwrite(vdev, structname, member, ptr) \
  593. do { \
  594. /* Must match the member's type, and be integer */ \
  595. if (!typecheck(typeof((((structname *)0)->member)), *(ptr))) \
  596. WARN_ON((*ptr) == 1); \
  597. \
  598. switch (sizeof(*ptr)) { \
  599. case 1: \
  600. virtio_cwrite8(vdev, \
  601. offsetof(structname, member), \
  602. *(ptr)); \
  603. break; \
  604. case 2: \
  605. virtio_cwrite16(vdev, \
  606. offsetof(structname, member), \
  607. *(ptr)); \
  608. break; \
  609. case 4: \
  610. virtio_cwrite32(vdev, \
  611. offsetof(structname, member), \
  612. *(ptr)); \
  613. break; \
  614. case 8: \
  615. virtio_cwrite64(vdev, \
  616. offsetof(structname, member), \
  617. *(ptr)); \
  618. break; \
  619. default: \
  620. WARN_ON(true); \
  621. } \
  622. } while (0)
  623. /* Conditional config space accessors */
  624. #define virtio_cread_feature(vdev, fbit, structname, member, ptr) \
  625. ({ \
  626. int _r = 0; \
  627. if (!virtio_has_feature(vdev, fbit)) \
  628. _r = -ENOENT; \
  629. else \
  630. virtio_cread(vdev, structname, member, ptr); \
  631. _r; \
  632. })
  633. #endif /* __VIRTIO_H__ */