bus.h 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679
  1. /* $OpenBSD: bus.h,v 1.14 2015/03/30 20:30:22 miod Exp $ */
  2. /*
  3. * Copyright (c) 2003, Miodrag Vallat.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions
  7. * are met:
  8. * 1. Redistributions of source code must retain the above copyright
  9. * notice, this list of conditions and the following disclaimer.
  10. * 2. Redistributions in binary form must reproduce the above copyright
  11. * notice, this list of conditions and the following disclaimer in the
  12. * documentation and/or other materials provided with the distribution.
  13. *
  14. * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  15. * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  16. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  17. * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
  18. * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  19. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  20. * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  21. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  22. * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
  23. * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  24. * POSSIBILITY OF SUCH DAMAGE.
  25. */
  26. /*
  27. * ``No-nonsense'' sparc bus_space implementation.
  28. *
  29. * This is a stripped down bus_space implementation for sparc, providing
  30. * simple enough functions, suitable for inlining.
  31. * To achieve this goal, it relies upon the following assumptions:
  32. * - everything is memory-mapped. Hence, tags are basically not used,
  33. * and most operation are just simple pointer arithmetic with the handle.
  34. * - interrupt functions are not implemented; callers will provide their
  35. * own wrappers on a need-to-do basis.
  36. */
  37. #ifndef _MACHINE_BUS_H_
  38. #define _MACHINE_BUS_H_
  39. typedef u_long bus_space_handle_t;
  40. /*
  41. * bus_space_tag_t are pointer to *modified* rom_reg structures.
  42. * rr_iospace is used to also carry bus endianness information.
  43. */
  44. typedef struct rom_reg *bus_space_tag_t;
  45. typedef struct sparc_bus_dma_tag *bus_dma_tag_t;
  46. typedef struct sparc_bus_dmamap *bus_dmamap_t;
  47. #include <machine/autoconf.h>
  48. #include <uvm/uvm_extern.h>
  49. #define TAG_LITTLE_ENDIAN 0x80000000
  50. #define SET_TAG_BIG_ENDIAN(t) ((t))->rr_iospace &= ~TAG_LITTLE_ENDIAN
  51. #define SET_TAG_LITTLE_ENDIAN(t) ((t))->rr_iospace |= TAG_LITTLE_ENDIAN
  52. #define IS_TAG_LITTLE_ENDIAN(t) ((t)->rr_iospace & TAG_LITTLE_ENDIAN)
  53. typedef u_long bus_addr_t;
  54. typedef u_long bus_size_t;
  55. /*
  56. * General bus_space function set
  57. */
  58. static int bus_space_map(bus_space_tag_t, bus_addr_t, bus_size_t, int,
  59. bus_space_handle_t *);
  60. static int bus_space_unmap(bus_space_tag_t, bus_space_handle_t,
  61. bus_size_t);
  62. #define BUS_SPACE_MAP_CACHEABLE 0x01
  63. #define BUS_SPACE_MAP_LINEAR 0x02
  64. #define BUS_SPACE_MAP_PREFETCHABLE 0x04
  65. #define BUS_SPACE_BARRIER_READ 0x01
  66. #define BUS_SPACE_BARRIER_WRITE 0x02
  67. static void bus_space_barrier(bus_space_tag_t, bus_space_handle_t,
  68. bus_addr_t, bus_size_t, int);
  69. static void* bus_space_vaddr(bus_space_tag_t, bus_space_handle_t);
  70. static int bus_space_subregion(bus_space_tag_t, bus_space_handle_t,
  71. bus_addr_t, bus_size_t, bus_space_handle_t *);
  72. static __inline__ int
  73. bus_space_map(bus_space_tag_t tag, bus_addr_t addr, bus_size_t size, int flags,
  74. bus_space_handle_t *handle)
  75. {
  76. if ((*handle = (bus_space_handle_t)mapiodev(tag, addr, size)) != 0)
  77. return (0);
  78. return (ENOMEM);
  79. }
  80. static __inline__ int
  81. bus_space_unmap(bus_space_tag_t tag, bus_space_handle_t handle, bus_size_t size)
  82. {
  83. /*
  84. * The mapiodev() call eventually ended up as a set of pmap_kenter_pa()
  85. * calls. Although the iospace va will not be reclaimed, at least
  86. * relinquish the wiring.
  87. */
  88. pmap_kremove((vaddr_t)handle, size);
  89. pmap_update(pmap_kernel());
  90. return (0);
  91. }
  92. static __inline__ void
  93. bus_space_barrier(bus_space_tag_t tag, bus_space_handle_t handle,
  94. bus_addr_t offset, bus_size_t size, int flags)
  95. {
  96. /* no membar is necessary for sparc so far */
  97. }
  98. static __inline__ void *
  99. bus_space_vaddr(bus_space_tag_t tag, bus_space_handle_t handle)
  100. {
  101. return ((void *)handle);
  102. }
  103. static __inline__ int
  104. bus_space_subregion(bus_space_tag_t tag, bus_space_handle_t handle,
  105. bus_addr_t offset, bus_size_t size, bus_space_handle_t *newh)
  106. {
  107. *newh = handle + offset;
  108. return (0);
  109. }
  110. /*
  111. * Read/Write/Region functions
  112. * Most of these are straightforward and assume that everything is properly
  113. * aligned.
  114. */
  115. #define bus_space_read_1(tag, handle, offset) \
  116. ((void)(tag), *(volatile u_int8_t *)((handle) + (offset)))
  117. #define __bus_space_read_2(tag, handle, offset) \
  118. *(volatile u_int16_t *)((handle) + (offset))
  119. #define __bus_space_read_4(tag, handle, offset) \
  120. *(volatile u_int32_t *)((handle) + (offset))
  121. #define bus_space_read_2(tag, handle, offset) \
  122. ((IS_TAG_LITTLE_ENDIAN(tag)) ? \
  123. letoh16(__bus_space_read_2(tag, handle, offset)) : \
  124. __bus_space_read_2(tag, handle, offset))
  125. #define bus_space_read_4(tag, handle, offset) \
  126. ((IS_TAG_LITTLE_ENDIAN(tag)) ? \
  127. letoh32(__bus_space_read_4(tag, handle, offset)) : \
  128. __bus_space_read_4(tag, handle, offset))
  129. static void bus_space_read_multi_1(bus_space_tag_t, bus_space_handle_t,
  130. bus_addr_t, u_int8_t *, size_t);
  131. static __inline__ void
  132. bus_space_read_multi_1(bus_space_tag_t tag, bus_space_handle_t handle,
  133. bus_addr_t offset, u_int8_t *dest, size_t count)
  134. {
  135. while ((int)--count >= 0)
  136. *dest++ = bus_space_read_1(tag, handle, offset);
  137. }
  138. static void bus_space_read_multi_2(bus_space_tag_t, bus_space_handle_t,
  139. bus_addr_t, u_int16_t *, size_t);
  140. static __inline__ void
  141. bus_space_read_multi_2(bus_space_tag_t tag, bus_space_handle_t handle,
  142. bus_addr_t offset, u_int16_t *dest, size_t count)
  143. {
  144. while ((int)--count >= 0)
  145. *dest++ = bus_space_read_2(tag, handle, offset);
  146. }
  147. static void bus_space_read_multi_4(bus_space_tag_t, bus_space_handle_t,
  148. bus_addr_t, u_int32_t *, size_t);
  149. static __inline__ void
  150. bus_space_read_multi_4(bus_space_tag_t tag, bus_space_handle_t handle,
  151. bus_addr_t offset, u_int32_t *dest, size_t count)
  152. {
  153. while ((int)--count >= 0)
  154. *dest++ = bus_space_read_4(tag, handle, offset);
  155. }
  156. static void bus_space_read_raw_multi_2(bus_space_tag_t, bus_space_handle_t,
  157. bus_addr_t, u_int8_t *, size_t);
  158. static __inline__ void
  159. bus_space_read_raw_multi_2(bus_space_tag_t tag, bus_space_handle_t handle,
  160. bus_addr_t offset, u_int8_t *dest, size_t size)
  161. {
  162. size >>= 1;
  163. while ((int)--size >= 0) {
  164. *(u_int16_t *)dest =
  165. __bus_space_read_2(tag, handle, offset);
  166. dest += 2;
  167. }
  168. }
  169. static void bus_space_read_raw_multi_4(bus_space_tag_t, bus_space_handle_t,
  170. bus_addr_t, u_int8_t *, size_t);
  171. static __inline__ void
  172. bus_space_read_raw_multi_4(bus_space_tag_t tag, bus_space_handle_t handle,
  173. bus_addr_t offset, u_int8_t *dest, size_t size)
  174. {
  175. size >>= 2;
  176. while ((int)--size >= 0) {
  177. *(u_int32_t *)dest =
  178. __bus_space_read_4(tag, handle, offset);
  179. dest += 4;
  180. }
  181. }
  182. #define bus_space_write_1(tag, handle, offset, value) \
  183. ((void)(tag), *(volatile u_int8_t *)((handle) + (offset)) = (value))
  184. #define __bus_space_write_2(tag, handle, offset, value) \
  185. *(volatile u_int16_t *)((handle) + (offset)) = (value)
  186. #define __bus_space_write_4(tag, handle, offset, value) \
  187. *(volatile u_int32_t *)((handle) + (offset)) = (value)
  188. #define bus_space_write_2(tag, handle, offset, value) \
  189. __bus_space_write_2(tag, handle, offset, \
  190. (IS_TAG_LITTLE_ENDIAN(tag)) ? htole16(value) : (value))
  191. #define bus_space_write_4(tag, handle, offset, value) \
  192. __bus_space_write_4(tag, handle, offset, \
  193. (IS_TAG_LITTLE_ENDIAN(tag)) ? htole32(value) : (value))
  194. static void bus_space_write_multi_1(bus_space_tag_t, bus_space_handle_t,
  195. bus_addr_t, u_int8_t *, size_t);
  196. static __inline__ void
  197. bus_space_write_multi_1(bus_space_tag_t tag, bus_space_handle_t handle,
  198. bus_addr_t offset, u_int8_t *dest, size_t count)
  199. {
  200. while ((int)--count >= 0)
  201. bus_space_write_1(tag, handle, offset, *dest++);
  202. }
  203. static void bus_space_write_multi_2(bus_space_tag_t, bus_space_handle_t,
  204. bus_addr_t, u_int16_t *, size_t);
  205. static __inline__ void
  206. bus_space_write_multi_2(bus_space_tag_t tag, bus_space_handle_t handle,
  207. bus_addr_t offset, u_int16_t *dest, size_t count)
  208. {
  209. while ((int)--count >= 0)
  210. bus_space_write_2(tag, handle, offset, *dest++);
  211. }
  212. static void bus_space_write_multi_4(bus_space_tag_t, bus_space_handle_t,
  213. bus_addr_t, u_int32_t *, size_t);
  214. static __inline__ void
  215. bus_space_write_multi_4(bus_space_tag_t tag, bus_space_handle_t handle,
  216. bus_addr_t offset, u_int32_t *dest, size_t count)
  217. {
  218. while ((int)--count >= 0)
  219. bus_space_write_4(tag, handle, offset, *dest);
  220. }
  221. static void bus_space_write_raw_multi_2(bus_space_tag_t, bus_space_handle_t,
  222. bus_addr_t, u_int8_t *, size_t);
  223. static __inline__ void
  224. bus_space_write_raw_multi_2(bus_space_tag_t tag, bus_space_handle_t handle,
  225. bus_addr_t offset, u_int8_t *dest, size_t size)
  226. {
  227. size >>= 1;
  228. while ((int)--size >= 0) {
  229. __bus_space_write_2(tag, handle, offset,
  230. *(u_int16_t *)dest);
  231. dest += 2;
  232. }
  233. }
  234. static void bus_space_write_raw_multi_4(bus_space_tag_t, bus_space_handle_t,
  235. bus_addr_t, u_int8_t *, size_t);
  236. static __inline__ void
  237. bus_space_write_raw_multi_4(bus_space_tag_t tag, bus_space_handle_t handle,
  238. bus_addr_t offset, u_int8_t *dest, size_t size)
  239. {
  240. size >>= 2;
  241. while ((int)--size >= 0) {
  242. __bus_space_write_4(tag, handle, offset,
  243. *(u_int32_t *)dest);
  244. dest += 4;
  245. }
  246. }
  247. static void bus_space_set_multi_1(bus_space_tag_t, bus_space_handle_t,
  248. bus_addr_t, u_int8_t, size_t);
  249. static __inline__ void
  250. bus_space_set_multi_1(bus_space_tag_t tag, bus_space_handle_t handle,
  251. bus_addr_t offset, u_int8_t value, size_t count)
  252. {
  253. while ((int)--count >= 0)
  254. bus_space_write_1(tag, handle, offset, value);
  255. }
  256. static void bus_space_set_multi_2(bus_space_tag_t, bus_space_handle_t,
  257. bus_addr_t, u_int16_t, size_t);
  258. static __inline__ void
  259. bus_space_set_multi_2(bus_space_tag_t tag, bus_space_handle_t handle,
  260. bus_addr_t offset, u_int16_t value, size_t count)
  261. {
  262. while ((int)--count >= 0)
  263. bus_space_write_2(tag, handle, offset, value);
  264. }
  265. static void bus_space_set_multi_4(bus_space_tag_t, bus_space_handle_t,
  266. bus_addr_t, u_int32_t, size_t);
  267. static __inline__ void
  268. bus_space_set_multi_4(bus_space_tag_t tag, bus_space_handle_t handle,
  269. bus_addr_t offset, u_int32_t value, size_t count)
  270. {
  271. while ((int)--count >= 0)
  272. bus_space_write_4(tag, handle, offset, value);
  273. }
  274. static void bus_space_write_region_1(bus_space_tag_t, bus_space_handle_t,
  275. bus_addr_t, u_int8_t *, size_t);
  276. static __inline__ void
  277. bus_space_write_region_1(bus_space_tag_t tag, bus_space_handle_t handle,
  278. bus_addr_t offset, u_int8_t *dest, size_t count)
  279. {
  280. while ((int)--count >= 0)
  281. bus_space_write_1(tag, handle, offset++, *dest++);
  282. }
  283. static void bus_space_write_region_2(bus_space_tag_t, bus_space_handle_t,
  284. bus_addr_t, u_int16_t *, size_t);
  285. static __inline__ void
  286. bus_space_write_region_2(bus_space_tag_t tag, bus_space_handle_t handle,
  287. bus_addr_t offset, u_int16_t *dest, size_t count)
  288. {
  289. while ((int)--count >= 0) {
  290. bus_space_write_2(tag, handle, offset, *dest++);
  291. offset += 2;
  292. }
  293. }
  294. static void bus_space_write_region_4(bus_space_tag_t, bus_space_handle_t,
  295. bus_addr_t, u_int32_t *, size_t);
  296. static __inline__ void
  297. bus_space_write_region_4(bus_space_tag_t tag, bus_space_handle_t handle,
  298. bus_addr_t offset, u_int32_t *dest, size_t count)
  299. {
  300. while ((int)--count >= 0) {
  301. bus_space_write_4(tag, handle, offset, *dest++);
  302. offset +=4;
  303. }
  304. }
  305. static void bus_space_write_raw_region_2(bus_space_tag_t, bus_space_handle_t,
  306. bus_addr_t, u_int8_t *, size_t);
  307. static __inline__ void
  308. bus_space_write_raw_region_2(bus_space_tag_t tag, bus_space_handle_t handle,
  309. bus_addr_t offset, u_int8_t *dest, size_t size)
  310. {
  311. size >>= 1;
  312. while ((int)--size >= 0) {
  313. __bus_space_write_2(tag, handle, offset, *(u_int16_t *)dest);
  314. offset += 2;
  315. dest += 2;
  316. }
  317. }
  318. static void bus_space_write_raw_region_4(bus_space_tag_t, bus_space_handle_t,
  319. bus_addr_t, u_int8_t *, size_t);
  320. static __inline__ void
  321. bus_space_write_raw_region_4(bus_space_tag_t tag, bus_space_handle_t handle,
  322. bus_addr_t offset, u_int8_t *dest, size_t size)
  323. {
  324. size >>= 2;
  325. while ((int)--size >= 0) {
  326. __bus_space_write_4(tag, handle, offset, *(u_int32_t *)dest);
  327. offset += 4;
  328. dest += 4;
  329. }
  330. }
  331. static void bus_space_read_region_1(bus_space_tag_t, bus_space_handle_t,
  332. bus_addr_t, u_int8_t *, size_t);
  333. static __inline__ void
  334. bus_space_read_region_1(bus_space_tag_t tag, bus_space_handle_t handle,
  335. bus_addr_t offset, u_int8_t *dest, size_t count)
  336. {
  337. while ((int)--count >= 0)
  338. *dest++ = bus_space_read_1(tag, handle, offset++);
  339. }
  340. static void bus_space_read_region_2(bus_space_tag_t, bus_space_handle_t,
  341. bus_addr_t, u_int16_t *, size_t);
  342. static __inline__ void
  343. bus_space_read_region_2(bus_space_tag_t tag, bus_space_handle_t handle,
  344. bus_addr_t offset, u_int16_t *dest, size_t count)
  345. {
  346. while ((int)--count >= 0) {
  347. *dest++ = bus_space_read_2(tag, handle, offset);
  348. offset += 2;
  349. }
  350. }
  351. static void bus_space_read_region_4(bus_space_tag_t, bus_space_handle_t,
  352. bus_addr_t, u_int32_t *, size_t);
  353. static __inline__ void
  354. bus_space_read_region_4(bus_space_tag_t tag, bus_space_handle_t handle,
  355. bus_addr_t offset, u_int32_t *dest, size_t count)
  356. {
  357. while ((int)--count >= 0) {
  358. *dest++ = bus_space_read_4(tag, handle, offset);
  359. offset += 4;
  360. }
  361. }
  362. static void bus_space_set_region_1(bus_space_tag_t, bus_space_handle_t,
  363. bus_addr_t, u_int8_t, size_t);
  364. static __inline__ void
  365. bus_space_set_region_1(bus_space_tag_t tag, bus_space_handle_t handle,
  366. bus_addr_t offset, u_int8_t value, size_t count)
  367. {
  368. while ((int)--count >= 0)
  369. bus_space_write_1(tag, handle, offset++, value);
  370. }
  371. static void bus_space_set_region_2(bus_space_tag_t, bus_space_handle_t,
  372. bus_addr_t, u_int16_t, size_t);
  373. static __inline__ void
  374. bus_space_set_region_2(bus_space_tag_t tag, bus_space_handle_t handle,
  375. bus_addr_t offset, u_int16_t value, size_t count)
  376. {
  377. while ((int)--count >= 0) {
  378. bus_space_write_2(tag, handle, offset, value);
  379. offset += 2;
  380. }
  381. }
  382. static void bus_space_set_region_4(bus_space_tag_t, bus_space_handle_t,
  383. bus_addr_t, u_int32_t, size_t);
  384. static __inline__ void
  385. bus_space_set_region_4(bus_space_tag_t tag, bus_space_handle_t handle,
  386. bus_addr_t offset, u_int32_t value, size_t count)
  387. {
  388. while ((int)--count >= 0) {
  389. bus_space_write_4(tag, handle, offset, value);
  390. offset += 4;
  391. }
  392. }
  393. static void bus_space_read_raw_region_2(bus_space_tag_t, bus_space_handle_t,
  394. bus_addr_t, u_int8_t *, size_t);
  395. static __inline__ void
  396. bus_space_read_raw_region_2(bus_space_tag_t tag, bus_space_handle_t handle,
  397. bus_addr_t offset, u_int8_t *dest, size_t size)
  398. {
  399. size >>= 1;
  400. while ((int)--size >= 0) {
  401. *(u_int16_t *)dest = __bus_space_read_2(tag, handle, offset);
  402. offset += 2;
  403. dest += 2;
  404. }
  405. }
  406. static void bus_space_read_raw_region_4(bus_space_tag_t, bus_space_handle_t,
  407. bus_addr_t, u_int8_t *, size_t);
  408. static __inline__ void
  409. bus_space_read_raw_region_4(bus_space_tag_t tag, bus_space_handle_t handle,
  410. bus_addr_t offset, u_int8_t *dest, size_t size)
  411. {
  412. size >>= 2;
  413. while ((int)--size >= 0) {
  414. *(u_int32_t *)dest = __bus_space_read_4(tag, handle, offset);
  415. offset += 4;
  416. dest += 4;
  417. }
  418. }
  419. /*
  420. * Flags used in various bus DMA methods.
  421. */
  422. #define BUS_DMA_WAITOK 0x000 /* safe to sleep (pseudo-flag) */
  423. #define BUS_DMA_NOWAIT 0x001 /* not safe to sleep */
  424. #define BUS_DMA_ALLOCNOW 0x002 /* perform resource allocation now */
  425. #define BUS_DMA_COHERENT 0x004 /* hint: map memory DMA coherent */
  426. #define BUS_DMA_STREAMING 0x008 /* hint: sequential, unidirectional */
  427. #define BUS_DMA_BUS1 0x010 /* placeholders for bus functions... */
  428. #define BUS_DMA_BUS2 0x020
  429. #define BUS_DMA_BUS3 0x040
  430. #define BUS_DMA_BUS4 0x080
  431. #define BUS_DMA_READ 0x100 /* mapping is device -> memory only */
  432. #define BUS_DMA_WRITE 0x200 /* mapping is memory -> device only */
  433. #define BUS_DMA_NOCACHE 0x400 /* hint: map non-cached memory */
  434. #define BUS_DMA_ZERO 0x800 /* zero memory in dmamem_alloc */
  435. /* For devices that have a 24-bit address space */
  436. #define BUS_DMA_24BIT BUS_DMA_BUS1
  437. /* Forwards needed by prototypes below. */
  438. struct mbuf;
  439. struct uio;
  440. /*
  441. * Operations performed by bus_dmamap_sync().
  442. */
  443. #define BUS_DMASYNC_PREREAD 0x01 /* pre-read synchronization */
  444. #define BUS_DMASYNC_POSTREAD 0x02 /* post-read synchronization */
  445. #define BUS_DMASYNC_PREWRITE 0x04 /* pre-write synchronization */
  446. #define BUS_DMASYNC_POSTWRITE 0x08 /* post-write synchronization */
  447. /*
  448. * bus_dma_segment_t
  449. *
  450. * Describes a single contiguous DMA transaction. Values
  451. * are suitable for programming into DMA registers.
  452. */
  453. struct sparc_bus_dma_segment {
  454. bus_addr_t ds_addr; /* DVMA address */
  455. bus_size_t ds_len; /* length of transfer */
  456. bus_size_t _ds_sgsize; /* size of allocated DVMA segment */
  457. void *_ds_mlist; /* page list when dmamem_alloc'ed */
  458. vaddr_t _ds_va; /* VA when dmamem_map'ed */
  459. };
  460. typedef struct sparc_bus_dma_segment bus_dma_segment_t;
  461. /*
  462. * bus_dma_tag_t
  463. *
  464. * A machine-dependent opaque type describing the implementation of
  465. * DMA for a given bus.
  466. */
  467. struct sparc_bus_dma_tag {
  468. void *_cookie; /* cookie used in the guts */
  469. /*
  470. * DMA mapping methods.
  471. */
  472. int (*_dmamap_create)(bus_dma_tag_t, bus_size_t, int,
  473. bus_size_t, bus_size_t, int, bus_dmamap_t *);
  474. void (*_dmamap_destroy)(bus_dma_tag_t, bus_dmamap_t);
  475. int (*_dmamap_load)(bus_dma_tag_t, bus_dmamap_t, void *,
  476. bus_size_t, struct proc *, int);
  477. int (*_dmamap_load_mbuf)(bus_dma_tag_t, bus_dmamap_t,
  478. struct mbuf *, int);
  479. int (*_dmamap_load_uio)(bus_dma_tag_t, bus_dmamap_t,
  480. struct uio *, int);
  481. int (*_dmamap_load_raw)(bus_dma_tag_t, bus_dmamap_t,
  482. bus_dma_segment_t *, int, bus_size_t, int);
  483. void (*_dmamap_unload)(bus_dma_tag_t, bus_dmamap_t);
  484. void (*_dmamap_sync)(bus_dma_tag_t, bus_dmamap_t,
  485. bus_addr_t, bus_size_t, int);
  486. /*
  487. * DMA memory utility functions.
  488. */
  489. int (*_dmamem_alloc)(bus_dma_tag_t, bus_size_t, bus_size_t,
  490. bus_size_t, bus_dma_segment_t *, int, int *, int);
  491. void (*_dmamem_free)(bus_dma_tag_t,
  492. bus_dma_segment_t *, int);
  493. int (*_dmamem_map)(bus_dma_tag_t, bus_dma_segment_t *,
  494. int, size_t, caddr_t *, int);
  495. void (*_dmamem_unmap)(bus_dma_tag_t, void *, size_t);
  496. paddr_t (*_dmamem_mmap)(bus_dma_tag_t, bus_dma_segment_t *,
  497. int, off_t, int, int);
  498. };
  499. #define bus_dmamap_create(t, s, n, m, b, f, p) \
  500. (*(t)->_dmamap_create)((t), (s), (n), (m), (b), (f), (p))
  501. #define bus_dmamap_destroy(t, p) \
  502. (*(t)->_dmamap_destroy)((t), (p))
  503. #define bus_dmamap_load(t, m, b, s, p, f) \
  504. (*(t)->_dmamap_load)((t), (m), (b), (s), (p), (f))
  505. #define bus_dmamap_load_mbuf(t, m, b, f) \
  506. (*(t)->_dmamap_load_mbuf)((t), (m), (b), (f))
  507. #define bus_dmamap_load_uio(t, m, u, f) \
  508. (*(t)->_dmamap_load_uio)((t), (m), (u), (f))
  509. #define bus_dmamap_load_raw(t, m, sg, n, s, f) \
  510. (*(t)->_dmamap_load_raw)((t), (m), (sg), (n), (s), (f))
  511. #define bus_dmamap_unload(t, p) \
  512. (*(t)->_dmamap_unload)((t), (p))
  513. #define bus_dmamap_sync(t, p, o, l, ops) \
  514. (void)((t)->_dmamap_sync ? \
  515. (*(t)->_dmamap_sync)((t), (p), (o), (l), (ops)) : (void)0)
  516. #define bus_dmamem_alloc(t, s, a, b, sg, n, r, f) \
  517. (*(t)->_dmamem_alloc)((t), (s), (a), (b), (sg), (n), (r), (f))
  518. #define bus_dmamem_free(t, sg, n) \
  519. (*(t)->_dmamem_free)((t), (sg), (n))
  520. #define bus_dmamem_map(t, sg, n, s, k, f) \
  521. (*(t)->_dmamem_map)((t), (sg), (n), (s), (k), (f))
  522. #define bus_dmamem_unmap(t, k, s) \
  523. (*(t)->_dmamem_unmap)((t), (k), (s))
  524. #define bus_dmamem_mmap(t, sg, n, o, p, f) \
  525. (*(t)->_dmamem_mmap)((t), (sg), (n), (o), (p), (f))
  526. #define bus_dmatag_subregion(t, mna, mxa, nt, f) EOPNOTSUPP
  527. #define bus_dmatag_destroy(t)
  528. /*
  529. * bus_dmamap_t
  530. *
  531. * Describes a DMA mapping.
  532. */
  533. struct sparc_bus_dmamap {
  534. /*
  535. * PRIVATE MEMBERS: not for use by machine-independent code.
  536. */
  537. bus_size_t _dm_size; /* largest DMA transfer mappable */
  538. int _dm_segcnt; /* number of segs this map can map */
  539. bus_size_t _dm_maxmaxsegsz; /* fixed largest possible segment */
  540. bus_size_t _dm_boundary; /* don't cross this */
  541. int _dm_flags; /* misc. flags */
  542. void *_dm_cookie; /* cookie for bus-specific functions */
  543. u_long _dm_align; /* DVMA alignment; must be a
  544. multiple of the page size */
  545. u_long _dm_ex_start; /* constraints on DVMA map */
  546. u_long _dm_ex_end; /* allocations; used by the VME bus
  547. driver and by the IOMMU driver
  548. when mapping 24-bit devices */
  549. /*
  550. * PUBLIC MEMBERS: these are used by machine-independent code.
  551. */
  552. bus_size_t dm_maxsegsz; /* largest possible segment */
  553. bus_size_t dm_mapsize; /* size of the mapping */
  554. int dm_nsegs; /* # valid segments in mapping */
  555. bus_dma_segment_t dm_segs[1]; /* segments; variable length */
  556. };
  557. int _bus_dmamap_create(bus_dma_tag_t, bus_size_t, int, bus_size_t,
  558. bus_size_t, int, bus_dmamap_t *);
  559. void _bus_dmamap_destroy(bus_dma_tag_t, bus_dmamap_t);
  560. int _bus_dmamap_load_mbuf(bus_dma_tag_t, bus_dmamap_t,
  561. struct mbuf *, int);
  562. int _bus_dmamap_load_uio(bus_dma_tag_t, bus_dmamap_t,
  563. struct uio *, int);
  564. int _bus_dmamap_load_raw(bus_dma_tag_t, bus_dmamap_t,
  565. bus_dma_segment_t *, int, bus_size_t, int);
  566. void _bus_dmamap_unload(bus_dma_tag_t, bus_dmamap_t);
  567. void _bus_dmamap_sync(bus_dma_tag_t, bus_dmamap_t, bus_addr_t,
  568. bus_size_t, int);
  569. int _bus_dmamem_alloc(bus_dma_tag_t tag, bus_size_t size,
  570. bus_size_t alignment, bus_size_t boundary,
  571. bus_dma_segment_t *segs, int nsegs, int *rsegs, int flags);
  572. void _bus_dmamem_free(bus_dma_tag_t tag, bus_dma_segment_t *segs,
  573. int nsegs);
  574. void _bus_dmamem_unmap(bus_dma_tag_t tag, void *kva,
  575. size_t size);
  576. paddr_t _bus_dmamem_mmap(bus_dma_tag_t tag, bus_dma_segment_t *segs,
  577. int nsegs, off_t off, int prot, int flags);
  578. int _bus_dmamem_alloc_range(bus_dma_tag_t tag, bus_size_t size,
  579. bus_size_t alignment, bus_size_t boundary,
  580. bus_dma_segment_t *segs, int nsegs, int *rsegs, int flags,
  581. vaddr_t low, vaddr_t high);
  582. vaddr_t _bus_dma_valloc_skewed(size_t, u_long, u_long, u_long);
  583. #endif /* _MACHINE_BUS_H_ */