dma.c 5.3 KB

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