dma.c 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264
  1. #include "u.h"
  2. #include "../port/lib.h"
  3. #include "mem.h"
  4. #include "dat.h"
  5. #include "fns.h"
  6. typedef struct DMAport DMAport;
  7. typedef struct DMA DMA;
  8. typedef struct DMAxfer DMAxfer;
  9. /*
  10. * state of a dma transfer
  11. */
  12. struct DMAxfer
  13. {
  14. ulong bpa; /* bounce buffer physical address */
  15. void* bva; /* bounce buffer virtual address */
  16. int blen; /* bounce buffer length */
  17. void* va; /* virtual address destination/src */
  18. long len; /* bytes to be transferred */
  19. int isread;
  20. };
  21. /*
  22. * the dma controllers. the first half of this structure specifies
  23. * the I/O ports used by the DMA controllers.
  24. */
  25. struct DMAport
  26. {
  27. uchar addr[4]; /* current address (4 channels) */
  28. uchar count[4]; /* current count (4 channels) */
  29. uchar page[4]; /* page registers (4 channels) */
  30. uchar cmd; /* command status register */
  31. uchar req; /* request registers */
  32. uchar sbm; /* single bit mask register */
  33. uchar mode; /* mode register */
  34. uchar cbp; /* clear byte pointer */
  35. uchar mc; /* master clear */
  36. uchar cmask; /* clear mask register */
  37. uchar wam; /* write all mask register bit */
  38. };
  39. struct DMA
  40. {
  41. DMAport;
  42. int shift;
  43. Lock;
  44. DMAxfer x[4];
  45. };
  46. DMA dma[2] = {
  47. { 0x00, 0x02, 0x04, 0x06,
  48. 0x01, 0x03, 0x05, 0x07,
  49. 0x87, 0x83, 0x81, 0x82,
  50. 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
  51. 0 },
  52. { 0xc0, 0xc4, 0xc8, 0xcc,
  53. 0xc2, 0xc6, 0xca, 0xce,
  54. 0x8f, 0x8b, 0x89, 0x8a,
  55. 0xd0, 0xd2, 0xd4, 0xd6, 0xd8, 0xda, 0xdc, 0xde,
  56. 1 },
  57. };
  58. extern int i8237dma;
  59. static void* i8237bva[2];
  60. static int i8237used;
  61. /*
  62. * DMA must be in the first 16MB. This gets called early by the
  63. * initialisation routines of any devices which require DMA to ensure
  64. * the allocated bounce buffers are below the 16MB limit.
  65. */
  66. void
  67. _i8237alloc(void)
  68. {
  69. void* bva;
  70. if(i8237dma <= 0)
  71. return;
  72. if(i8237dma > 2)
  73. i8237dma = 2;
  74. bva = xspanalloc(64*1024*i8237dma, BY2PG, 64*1024);
  75. if(bva == nil || PADDR(bva)+64*1024*i8237dma > 16*MB){
  76. /*
  77. * This will panic with the current
  78. * implementation of xspanalloc().
  79. if(bva != nil)
  80. xfree(bva);
  81. */
  82. return;
  83. }
  84. i8237bva[0] = bva;
  85. if(i8237dma == 2)
  86. i8237bva[1] = ((uchar*)i8237bva[0])+64*1024;
  87. }
  88. /*
  89. * DMA must be in the first 16MB. This gets called early by the
  90. * initialisation routines of any devices which require DMA to ensure
  91. * the allocated bounce buffers are below the 16MB limit.
  92. */
  93. int
  94. dmainit(int chan, int maxtransfer)
  95. {
  96. DMA *dp;
  97. DMAxfer *xp;
  98. static int once;
  99. if(once == 0){
  100. if(ioalloc(0x00, 0x10, 0, "dma") < 0
  101. || ioalloc(0x80, 0x10, 0, "dma") < 0
  102. || ioalloc(0xd0, 0x10, 0, "dma") < 0)
  103. panic("dmainit");
  104. once = 1;
  105. }
  106. if(maxtransfer > 64*1024)
  107. maxtransfer = 64*1024;
  108. dp = &dma[(chan>>2)&1];
  109. chan = chan & 3;
  110. xp = &dp->x[chan];
  111. if(xp->bva != nil){
  112. if(xp->blen < maxtransfer)
  113. return 1;
  114. return 0;
  115. }
  116. if(i8237used >= i8237dma || i8237bva[i8237used] == nil){
  117. print("no i8237 DMA bounce buffer < 16MB\n");
  118. return 1;
  119. }
  120. xp->bva = i8237bva[i8237used++];
  121. xp->bpa = PADDR(xp->bva);
  122. xp->blen = maxtransfer;
  123. xp->len = 0;
  124. xp->isread = 0;
  125. return 0;
  126. }
  127. /*
  128. * setup a dma transfer. if the destination is not in kernel
  129. * memory, allocate a page for the transfer.
  130. *
  131. * we assume BIOS has set up the command register before we
  132. * are booted.
  133. *
  134. * return the updated transfer length (we can't transfer across 64k
  135. * boundaries)
  136. */
  137. long
  138. dmasetup(int chan, void *va, long len, int isread)
  139. {
  140. DMA *dp;
  141. ulong pa;
  142. uchar mode;
  143. DMAxfer *xp;
  144. dp = &dma[(chan>>2)&1];
  145. chan = chan & 3;
  146. xp = &dp->x[chan];
  147. /*
  148. * if this isn't kernel memory or crossing 64k boundary or above 16 meg
  149. * use the bounce buffer.
  150. */
  151. if((ulong)va < KZERO
  152. || ((pa=PADDR(va))&0xFFFF0000) != ((pa+len)&0xFFFF0000)
  153. || pa >= 16*MB){
  154. if(xp->bva == nil)
  155. return -1;
  156. if(len > xp->blen)
  157. len = xp->blen;
  158. if(!isread)
  159. memmove(xp->bva, va, len);
  160. xp->va = va;
  161. xp->len = len;
  162. xp->isread = isread;
  163. pa = xp->bpa;
  164. }
  165. else
  166. xp->len = 0;
  167. /*
  168. * this setup must be atomic
  169. */
  170. ilock(dp);
  171. mode = (isread ? 0x44 : 0x48) | chan;
  172. outb(dp->mode, mode); /* single mode dma (give CPU a chance at mem) */
  173. outb(dp->page[chan], pa>>16);
  174. outb(dp->cbp, 0); /* set count & address to their first byte */
  175. outb(dp->addr[chan], pa>>dp->shift); /* set address */
  176. outb(dp->addr[chan], pa>>(8+dp->shift));
  177. outb(dp->count[chan], (len>>dp->shift)-1); /* set count */
  178. outb(dp->count[chan], ((len>>dp->shift)-1)>>8);
  179. outb(dp->sbm, chan); /* enable the channel */
  180. iunlock(dp);
  181. return len;
  182. }
  183. int
  184. dmadone(int chan)
  185. {
  186. DMA *dp;
  187. dp = &dma[(chan>>2)&1];
  188. chan = chan & 3;
  189. return inb(dp->cmd) & (1<<chan);
  190. }
  191. /*
  192. * this must be called after a dma has been completed.
  193. *
  194. * if a page has been allocated for the dma,
  195. * copy the data into the actual destination
  196. * and free the page.
  197. */
  198. void
  199. dmaend(int chan)
  200. {
  201. DMA *dp;
  202. DMAxfer *xp;
  203. dp = &dma[(chan>>2)&1];
  204. chan = chan & 3;
  205. /*
  206. * disable the channel
  207. */
  208. ilock(dp);
  209. outb(dp->sbm, 4|chan);
  210. iunlock(dp);
  211. xp = &dp->x[chan];
  212. if(xp->len == 0 || !xp->isread)
  213. return;
  214. /*
  215. * copy out of temporary page
  216. */
  217. memmove(xp->va, xp->bva, xp->len);
  218. xp->len = 0;
  219. }
  220. /*
  221. int
  222. dmacount(int chan)
  223. {
  224. int retval;
  225. DMA *dp;
  226. dp = &dma[(chan>>2)&1];
  227. outb(dp->cbp, 0);
  228. retval = inb(dp->count[chan]);
  229. retval |= inb(dp->count[chan]) << 8;
  230. return((retval<<dp->shift)+1);
  231. }
  232. */