virtio.h 19 KB

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