virtio.h 19 KB

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