dma.h 5.6 KB

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