dma.h 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. /*
  2. * Copyright (c) 2006-2021, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. */
  8. #ifndef _DMA_H
  9. #define _DMA_H
  10. #define MAX_DMA_CHANNELS 8
  11. /* 8237 DMA controllers */
  12. #define IO_DMA1_BASE 0x00 /* 8 bit slave DMA, channels 0..3 */
  13. #define IO_DMA2_BASE 0xC0 /* 16 bit master DMA, ch 4(=slave input)..7 */
  14. /* DMA controller registers */
  15. #define DMA1_CMD_REG 0x08 /* command register (w) */
  16. #define DMA1_STAT_REG 0x08 /* status register (r) */
  17. #define DMA1_REQ_REG 0x09 /* request register (w) */
  18. #define DMA1_MASK_REG 0x0A /* single-channel mask (w) */
  19. #define DMA1_MODE_REG 0x0B /* mode register (w) */
  20. #define DMA1_CLEAR_FF_REG 0x0C /* clear pointer flip-flop (w) */
  21. #define DMA1_TEMP_REG 0x0D /* Temporary Register (r) */
  22. #define DMA1_RESET_REG 0x0D /* Master Clear (w) */
  23. #define DMA1_CLR_MASK_REG 0x0E /* Clear Mask */
  24. #define DMA1_MASK_ALL_REG 0x0F /* all-channels mask (w) */
  25. #define DMA2_CMD_REG 0xD0 /* command register (w) */
  26. #define DMA2_STAT_REG 0xD0 /* status register (r) */
  27. #define DMA2_REQ_REG 0xD2 /* request register (w) */
  28. #define DMA2_MASK_REG 0xD4 /* single-channel mask (w) */
  29. #define DMA2_MODE_REG 0xD6 /* mode register (w) */
  30. #define DMA2_CLEAR_FF_REG 0xD8 /* clear pointer flip-flop (w) */
  31. #define DMA2_TEMP_REG 0xDA /* Temporary Register (r) */
  32. #define DMA2_RESET_REG 0xDA /* Master Clear (w) */
  33. #define DMA2_CLR_MASK_REG 0xDC /* Clear Mask */
  34. #define DMA2_MASK_ALL_REG 0xDE /* all-channels mask (w) */
  35. #define DMA_ADDR_0 0x00 /* DMA address registers */
  36. #define DMA_ADDR_1 0x02
  37. #define DMA_ADDR_2 0x04
  38. #define DMA_ADDR_3 0x06
  39. #define DMA_ADDR_4 0xC0
  40. #define DMA_ADDR_5 0xC4
  41. #define DMA_ADDR_6 0xC8
  42. #define DMA_ADDR_7 0xCC
  43. #define DMA_CNT_0 0x01 /* DMA count registers */
  44. #define DMA_CNT_1 0x03
  45. #define DMA_CNT_2 0x05
  46. #define DMA_CNT_3 0x07
  47. #define DMA_CNT_4 0xC2
  48. #define DMA_CNT_5 0xC6
  49. #define DMA_CNT_6 0xCA
  50. #define DMA_CNT_7 0xCE
  51. #define DMA_PAGE_0 0x87 /* DMA page registers */
  52. #define DMA_PAGE_1 0x83
  53. #define DMA_PAGE_2 0x81
  54. #define DMA_PAGE_3 0x82
  55. #define DMA_PAGE_5 0x8B
  56. #define DMA_PAGE_6 0x89
  57. #define DMA_PAGE_7 0x8A
  58. #define DMA_MODE_READ 0x44 /* I/O to memory, no autoinit, increment, single mode */
  59. #define DMA_MODE_WRITE 0x48 /* memory to I/O, no autoinit, increment, single mode */
  60. #define DMA_MODE_CASCADE 0xC0 /* pass thru DREQ->HRQ, DACK<-HLDA only */
  61. /*
  62. * 启用指定的DMA通道
  63. */
  64. static __inline__ void EnableDma(unsigned int dmanr)
  65. {
  66. if (dmanr<=3)
  67. OUTB(dmanr, DMA1_MASK_REG);
  68. else
  69. OUTB(dmanr & 3, DMA2_MASK_REG);
  70. }
  71. /*
  72. * 禁用指定的DMA通道
  73. */
  74. static __inline__ void DisableDma(unsigned int dmanr)
  75. {
  76. if (dmanr<=3)
  77. OUTB(dmanr | 4, DMA1_MASK_REG);
  78. else
  79. OUTB((dmanr & 3) | 4, DMA2_MASK_REG);
  80. }
  81. /*
  82. * 清空DMA 晶体计数器
  83. */
  84. static __inline__ void ClearDmaFF(unsigned int dmanr)
  85. {
  86. if (dmanr<=3)
  87. OUTB(0, DMA1_CLEAR_FF_REG);
  88. else
  89. OUTB(0, DMA2_CLEAR_FF_REG);
  90. }
  91. /*
  92. * 清空DMA 晶体计数器
  93. */
  94. static __inline__ void SetDmaMode(unsigned int dmanr, char mode)
  95. {
  96. if (dmanr<=3)
  97. OUTB(mode | dmanr, DMA1_MODE_REG);
  98. else
  99. OUTB(mode | (dmanr&3), DMA2_MODE_REG);
  100. }
  101. /*
  102. * 设定DMA 页面寄存器
  103. */
  104. static __inline__ void SetDmaPage(unsigned int dmanr, char pagenr)
  105. {
  106. switch(dmanr) {
  107. case 0:
  108. OUTB(pagenr, DMA_PAGE_0);
  109. break;
  110. case 1:
  111. OUTB(pagenr, DMA_PAGE_1);
  112. break;
  113. case 2:
  114. OUTB(pagenr, DMA_PAGE_2);
  115. break;
  116. case 3:
  117. OUTB(pagenr, DMA_PAGE_3);
  118. break;
  119. case 5:
  120. OUTB(pagenr & 0xfe, DMA_PAGE_5);
  121. break;
  122. case 6:
  123. OUTB(pagenr & 0xfe, DMA_PAGE_6);
  124. break;
  125. case 7:
  126. OUTB(pagenr & 0xfe, DMA_PAGE_7);
  127. break;
  128. }
  129. }
  130. /*
  131. * 设定DMA 传输高速缓冲区地址
  132. */
  133. static __inline__ void SetDmaAddr(unsigned int dmanr, unsigned int a)
  134. {
  135. SetDmaPage(dmanr, a>>16);
  136. if (dmanr <= 3) {
  137. OUTB( a & 0xff, ((dmanr&3)<<1) + IO_DMA1_BASE );
  138. OUTB( (a>>8) & 0xff, ((dmanr&3)<<1) + IO_DMA1_BASE );
  139. } else {
  140. OUTB( (a>>1) & 0xff, ((dmanr&3)<<2) + IO_DMA2_BASE );
  141. OUTB( (a>>9) & 0xff, ((dmanr&3)<<2) + IO_DMA2_BASE );
  142. }
  143. }
  144. /*
  145. * 设定DMA 传输块数
  146. */
  147. static __inline__ void SetDmaCount(unsigned int dmanr, unsigned int count)
  148. {
  149. count--;
  150. if (dmanr <= 3) {
  151. OUTB( count & 0xff, ((dmanr&3)<<1) + 1 + IO_DMA1_BASE );
  152. OUTB( (count>>8) & 0xff, ((dmanr&3)<<1) + 1 + IO_DMA1_BASE );
  153. } else {
  154. OUTB( (count>>1) & 0xff, ((dmanr&3)<<2) + 2 + IO_DMA2_BASE );
  155. OUTB( (count>>9) & 0xff, ((dmanr&3)<<2) + 2 + IO_DMA2_BASE );
  156. }
  157. }
  158. /*
  159. * 获得DMA 传输剩余块数
  160. */
  161. static __inline__ int GetDmaResidue(unsigned int dmanr)
  162. {
  163. unsigned int io_port = (dmanr<=3)? ((dmanr&3)<<1) + 1 + IO_DMA1_BASE
  164. : ((dmanr&3)<<2) + 2 + IO_DMA2_BASE;
  165. /* using short to get 16-bit wrap around */
  166. unsigned short count;
  167. count = 1 + inb(io_port);
  168. count += inb(io_port) << 8;
  169. return (dmanr<=3)? count : (count<<1);
  170. }
  171. #endif