dma.c 6.4 KB

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