Human68k CUI emulator with sound.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

dmac.c 14KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364
  1. /* DMAC ◆ DMA controller */
  2. #include "v68.h"
  3. #include "musashi/m68k.h"
  4. #include "dmac.h"
  5. static void dmac_transfer_start(int chan);
  6. static void dmac_transfer_abort(int chan);
  7. static void dmac_transfer_halt(int chan);
  8. static void dmac_transfer_continue(int chan);
  9. void dmac_init() {
  10. for (int x = 0; x < 4; x++)
  11. {
  12. v68.dmac.channels[x].niv = 0x0f;
  13. v68.dmac.channels[x].eiv = 0x0f;
  14. v68.dmac.channels[x].cpr = 0;
  15. v68.dmac.channels[x].dcr = 0;
  16. v68.dmac.channels[x].ocr = 0;
  17. v68.dmac.channels[x].scr = 0;
  18. v68.dmac.channels[x].ccr = 0;
  19. v68.dmac.channels[x].csr &= 0xfe;
  20. v68.dmac.channels[x].cer = 0;
  21. v68.dmac.channels[x].gcr = 0;
  22. // m_timer[x]->adjust(attotime::never);
  23. v68.dmac.halted[x] = 0;
  24. }
  25. }
  26. static inline int dma_in_progress(int chan) {
  27. return (v68.dmac.channels[chan].csr & 0x08) != 0;
  28. }
  29. void dmac_tick(int chan) {
  30. int data;
  31. int datasize = 1;
  32. verbose1("dmac_tick chan=%d in_progress=%d\n", chan, dma_in_progress(chan));
  33. if (!dma_in_progress(chan)) // DMA in progress in channel x
  34. return;
  35. if (v68.dmac.channels[chan].ocr & 0x80) // direction: 1 = device -> memory
  36. {
  37. switch(v68.dmac.channels[chan].ocr & 0x30) // operation size
  38. {
  39. case 0x00: // 8 bit
  40. data = m68k_read_memory_8(v68.dmac.channels[chan].dar); // read from device address
  41. m68k_write_memory_8(v68.dmac.channels[chan].mar, data); // write to memory address
  42. datasize = 1;
  43. break;
  44. case 0x10: // 16 bit
  45. data = m68k_read_memory_16(v68.dmac.channels[chan].dar); // read from device address
  46. m68k_write_memory_16(v68.dmac.channels[chan].mar, data); // write to memory address
  47. datasize = 2;
  48. break;
  49. case 0x20: // 32 bit
  50. data = m68k_read_memory_16(v68.dmac.channels[chan].dar) << 16; // read from device address
  51. data |= m68k_read_memory_16(v68.dmac.channels[chan].dar+2);
  52. m68k_write_memory_16(v68.dmac.channels[chan].mar, (data & 0xffff0000) >> 16); // write to memory address
  53. m68k_write_memory_16(v68.dmac.channels[chan].mar+2, data & 0x0000ffff);
  54. datasize = 4;
  55. break;
  56. case 0x30: // 8 bit packed (?)
  57. data = m68k_read_memory_8(v68.dmac.channels[chan].dar); // read from device address
  58. m68k_write_memory_8(v68.dmac.channels[chan].mar, data); // write to memory address
  59. datasize = 1;
  60. break;
  61. }
  62. verbose2("dmac_tick device->memory dar=0x%08x mar=0x%08x data=0x%02x\n", v68.dmac.channels[chan].dar, v68.dmac.channels[chan].mar, data);
  63. }
  64. else // memory -> device
  65. {
  66. switch(v68.dmac.channels[chan].ocr & 0x30) // operation size
  67. {
  68. case 0x00: // 8 bit
  69. data = m68k_read_memory_8(v68.dmac.channels[chan].mar); // read from memory address
  70. m68k_write_memory_8(v68.dmac.channels[chan].dar, data); // write to device address
  71. datasize = 1;
  72. break;
  73. case 0x10: // 16 bit
  74. data = m68k_read_memory_16(v68.dmac.channels[chan].mar); // read from memory address
  75. m68k_write_memory_16(v68.dmac.channels[chan].dar, data); // write to device address
  76. datasize = 2;
  77. break;
  78. case 0x20: // 32 bit
  79. data = m68k_read_memory_16(v68.dmac.channels[chan].mar) << 16; // read from memory address
  80. data |= m68k_read_memory_16(v68.dmac.channels[chan].mar+2); // read from memory address
  81. m68k_write_memory_16(v68.dmac.channels[chan].dar, (data & 0xffff0000) >> 16); // write to device address
  82. m68k_write_memory_16(v68.dmac.channels[chan].dar+2, data & 0x0000ffff); // write to device address
  83. datasize = 4;
  84. break;
  85. case 0x30: // 8 bit packed (?)
  86. data = m68k_read_memory_8(v68.dmac.channels[chan].mar); // read from memory address
  87. m68k_write_memory_8(v68.dmac.channels[chan].dar, data); // write to device address
  88. verbose2("dmac_tick 0x%08x -> 0x%08x = 0x%02x\n", v68.dmac.channels[chan].mar, v68.dmac.channels[chan].dar, data);
  89. datasize = 1;
  90. break;
  91. }
  92. verbose2("dmac_tick memory->device mar=0x%08x dar=0x%08x data=0x%02x\n", v68.dmac.channels[chan].mar, v68.dmac.channels[chan].dar, data);
  93. }
  94. // decrease memory transfer counter
  95. if (v68.dmac.channels[chan].mtc > 0)
  96. v68.dmac.channels[chan].mtc--;
  97. // handle change of memory and device addresses
  98. if ((v68.dmac.channels[chan].scr & 0x03) == 0x01)
  99. v68.dmac.channels[chan].dar+=datasize;
  100. else if ((v68.dmac.channels[chan].scr & 0x03) == 0x02)
  101. v68.dmac.channels[chan].dar-=datasize;
  102. if ((v68.dmac.channels[chan].scr & 0x0c) == 0x04)
  103. v68.dmac.channels[chan].mar+=datasize;
  104. else if ((v68.dmac.channels[chan].scr & 0x0c) == 0x08)
  105. v68.dmac.channels[chan].mar-=datasize;
  106. if (v68.dmac.channels[chan].mtc <= 0) {
  107. // End of transfer
  108. verbose2("dmac_tick End of transfer\n");
  109. if ((v68.dmac.channels[chan].ocr & 0x0c) != 0 && v68.dmac.channels[chan].btc > 0)
  110. {
  111. v68.dmac.channels[chan].btc--;
  112. v68.dmac.channels[chan].bar+=6;
  113. v68.dmac.channels[chan].mar = m68k_read_memory_16(v68.dmac.channels[chan].bar) << 16;
  114. v68.dmac.channels[chan].mar |= m68k_read_memory_16(v68.dmac.channels[chan].bar+2);
  115. v68.dmac.channels[chan].mtc = m68k_read_memory_16(v68.dmac.channels[chan].bar+4);
  116. return;
  117. }
  118. // m_timer[x]->adjust(attotime::never);
  119. v68.dmac.channels[chan].csr |= 0xe0; // channel operation complete, block transfer complete
  120. v68.dmac.channels[chan].csr &= ~0x08; // channel no longer active
  121. v68.dmac.channels[chan].ccr &= ~0xc0;
  122. // Burst transfer
  123. if ((v68.dmac.channels[chan].dcr & 0xc0) == 0x00)
  124. {
  125. // m_cpu->set_input_line(INPUT_LINE_HALT, CLEAR_LINE);
  126. }
  127. v68.int_vec = 0x6a;
  128. m68k_set_irq(3);
  129. }
  130. }
  131. static void dmac_transfer_start(int chan) {
  132. verbose1("dmac_transfer_start chan=%d\n", chan);
  133. v68.dmac.channels[chan].csr &= ~0xe0;
  134. v68.dmac.channels[chan].csr |= 0x08; // Channel active
  135. v68.dmac.channels[chan].csr &= ~0x30; // Reset Error and Normal termination bits
  136. if ((v68.dmac.channels[chan].ocr & 0x0c) != 0x00) // Array chain or Link array chain
  137. {
  138. v68.dmac.channels[chan].mar = m68k_read_memory_16(v68.dmac.channels[chan].bar) << 16;
  139. v68.dmac.channels[chan].mar |= m68k_read_memory_16(v68.dmac.channels[chan].bar+2);
  140. v68.dmac.channels[chan].mtc = m68k_read_memory_16(v68.dmac.channels[chan].bar+4);
  141. if (v68.dmac.channels[chan].btc > 0)
  142. v68.dmac.channels[chan].btc--;
  143. }
  144. // Burst transfers will halt the CPU until the transfer is complete
  145. if ((v68.dmac.channels[chan].dcr & 0xc0) == 0x00) // Burst transfer
  146. {
  147. // m_cpu->set_input_line(INPUT_LINE_HALT, ASSERT_LINE);
  148. // m_timer[channel]->adjust(attotime::zero, channel, m_burst_clock[channel]);
  149. } else if (!(v68.dmac.channels[chan].ocr & 2)) {
  150. // m_timer[channel]->adjust(attotime::from_usec(500), channel, m_our_clock[channel]);
  151. } else if ((v68.dmac.channels[chan].ocr & 3) == 3) {
  152. // m_timer[channel]->adjust(attotime::from_usec(500), channel, attotime::never);
  153. } else if ((v68.dmac.channels[chan].ocr & 3) == 2) {
  154. // m_timer[channel]->adjust(attotime::never, channel, attotime::never);
  155. }
  156. v68.dmac.transfer_size[chan] = v68.dmac.channels[chan].mtc;
  157. verbose2("DMA: Transfer begins: size=0x%08x\n",v68.dmac.transfer_size[chan]);
  158. }
  159. static void dmac_transfer_abort(int chan) {
  160. if (!dma_in_progress(chan))
  161. return;
  162. verbose3("DMA#%i: Transfer aborted\n",chan);
  163. // m_timer[channel]->adjust(attotime::never);
  164. v68.dmac.channels[chan].csr |= 0x90; // channel error
  165. v68.dmac.channels[chan].csr &= ~0x08; // channel no longer active
  166. v68.dmac.channels[chan].cer = 0x11;
  167. v68.dmac.channels[chan].ccr &= ~0xc0;
  168. // m_dma_error((offs_t)3, v68.dmac.channels[chan].ccr & 0x08);
  169. v68.int_vec = 0x6b;
  170. m68k_set_irq(3);
  171. }
  172. static void dmac_transfer_halt(int chan) {
  173. v68.dmac.halted[chan] = 1;
  174. // m_timer[channel]->adjust(attotime::never);
  175. }
  176. static void dmac_transfer_continue(int chan) {
  177. if (v68.dmac.halted[chan] != 0)
  178. {
  179. v68.dmac.halted[chan] = 0;
  180. // m_timer[channel]->adjust(attotime::zero, channel, m_our_clock[channel]);
  181. }
  182. }
  183. #define ACCESSING_BITS_0_7 ((mem_mask & 0x000000ffU) != 0)
  184. #define ACCESSING_BITS_8_15 ((mem_mask & 0x0000ff00U) != 0)
  185. void dmac_write_16(uint32_t addr, uint16_t data, uint16_t mem_mask) {
  186. uint8_t chan = (addr >> 6) & 0x03;
  187. uint8_t reg = (addr & 0x1f) >> 1;
  188. verbose2("dmac_write_16 0x%08x = 0x%04x mask=0x%04x chan=%d reg=0x%02x\n", addr, data, mem_mask, chan, reg);
  189. switch(reg) {
  190. case 0x00:
  191. if(ACCESSING_BITS_8_15) {
  192. v68.dmac.channels[chan].csr &= ~((data & 0xf600) >> 8);
  193. verbose2("DMA#%i: Channel status write : %02x data=0x%04x data&0xf600=0x%04x (data&0xf600)>>8=0x%04x ~((data&0xf600)>>8)=%04x\n",chan,v68.dmac.channels[chan].csr, data, data&0xf600, (data&0xf600)>>8, ~((data & 0xf600) >> 8));
  194. // Clearing ERR also resets CER (which is otherwise read-only)
  195. if ((data & 0x1000) != 0)
  196. v68.dmac.channels[chan].cer = 0;
  197. }
  198. break;
  199. case 0x02: // DCR / OCR
  200. if (ACCESSING_BITS_8_15)
  201. {
  202. v68.dmac.channels[chan].dcr = (data & 0xff00) >> 8;
  203. verbose2("DMA#%i: Device Control write : %02x\n",chan,v68.dmac.channels[chan].dcr);
  204. }
  205. if (ACCESSING_BITS_0_7)
  206. {
  207. v68.dmac.channels[chan].ocr = data & 0x00ff;
  208. verbose2("DMA#%i: Operation Control write : %02x\n",chan,v68.dmac.channels[chan].ocr);
  209. }
  210. break;
  211. case 0x03: // SCR / CCR
  212. if (ACCESSING_BITS_8_15)
  213. {
  214. v68.dmac.channels[chan].scr = (data & 0xff00) >> 8;
  215. verbose3("DMA#%i: Sequence Control write : %02x\n",chan,v68.dmac.channels[chan].scr);
  216. }
  217. if (ACCESSING_BITS_0_7)
  218. {
  219. v68.dmac.channels[chan].ccr = data & 0x00ff;
  220. if ((data & 0x0080))
  221. dmac_transfer_start(chan);
  222. if (data & 0x0010) // software abort
  223. dmac_transfer_abort(chan);
  224. if (data & 0x0020) // halt operation
  225. dmac_transfer_halt(chan);
  226. if (data & 0x0040) // continure operation
  227. dmac_transfer_continue(chan);
  228. verbose3("DMA#%i: Channel Control write : %02x\n",chan,v68.dmac.channels[chan].ccr);
  229. }
  230. break;
  231. case 0x05: // MTC
  232. v68.dmac.channels[chan].mtc = data;
  233. verbose2("DMA#%i: Memory Transfer Counter write : 0x%04x\n",chan,v68.dmac.channels[chan].mtc);
  234. break;
  235. case 0x06: // MAR (high)
  236. v68.dmac.channels[chan].mar = (v68.dmac.channels[chan].mar & 0x0000ffff) | (data << 16);
  237. verbose2("DMA#%i: Memory Address write : %08x\n",chan,v68.dmac.channels[chan].mar);
  238. break;
  239. case 0x07: // MAR (low)
  240. v68.dmac.channels[chan].mar = (v68.dmac.channels[chan].mar & 0xffff0000) | (data & 0x0000ffff);
  241. verbose2("DMA#%i: Memory Address write : %08x\n",chan,v68.dmac.channels[chan].mar);
  242. break;
  243. case 0x0a: // DAR (high)
  244. v68.dmac.channels[chan].dar = (v68.dmac.channels[chan].dar & 0x0000ffff) | (data << 16);
  245. verbose2("DMA#%i: Device Address write : %08x\n",chan,v68.dmac.channels[chan].dar);
  246. break;
  247. case 0x0b: // DAR (low)
  248. v68.dmac.channels[chan].dar = (v68.dmac.channels[chan].dar & 0xffff0000) | (data & 0x0000ffff);
  249. verbose2("DMA#%i: Device Address write : %08x\n",chan,v68.dmac.channels[chan].dar);
  250. break;
  251. case 0x0d: // BTC
  252. v68.dmac.channels[chan].btc = data;
  253. verbose3("DMA#%i: Base Transfer Counter write : %04x\n",chan,v68.dmac.channels[chan].btc);
  254. break;
  255. case 0x0e: // BAR (high)
  256. v68.dmac.channels[chan].bar = (v68.dmac.channels[chan].bar & 0x0000ffff) | (data << 16);
  257. verbose3("DMA#%i: Base Address write : %08x\n",chan,v68.dmac.channels[chan].bar);
  258. break;
  259. case 0x0f: // BAR (low)
  260. v68.dmac.channels[chan].bar = (v68.dmac.channels[chan].bar & 0xffff0000) | (data & 0x0000ffff);
  261. verbose3("DMA#%i: Base Address write : %08x\n",chan,v68.dmac.channels[chan].bar);
  262. break;
  263. case 0x12: // NIV
  264. v68.dmac.channels[chan].niv = data & 0xff;
  265. verbose3("DMA#%i: Normal IRQ Vector write : %02x\n",chan,v68.dmac.channels[chan].niv);
  266. break;
  267. case 0x13: // EIV
  268. v68.dmac.channels[chan].eiv = data & 0xff;
  269. verbose3("DMA#%i: Error IRQ Vector write : %02x\n",chan,v68.dmac.channels[chan].eiv);
  270. break;
  271. case 0x14: // MFC
  272. v68.dmac.channels[chan].mfc = data & 0xff;
  273. verbose3("DMA#%i: Memory Function Code write : %02x\n",chan,v68.dmac.channels[chan].mfc);
  274. break;
  275. case 0x16: // CPR
  276. v68.dmac.channels[chan].cpr = data & 0xff;
  277. verbose3("DMA#%i: Channel Priority write : %02x\n",chan,v68.dmac.channels[chan].cpr);
  278. break;
  279. case 0x18: // DFC
  280. v68.dmac.channels[chan].dfc = data & 0xff;
  281. verbose3("DMA#%i: Device Function Code write : %02x\n",chan,v68.dmac.channels[chan].dfc);
  282. break;
  283. case 0x1c: // BFC
  284. v68.dmac.channels[chan].bfc = data & 0xff;
  285. verbose3("DMA#%i: Base Function Code write : %02x\n",chan,v68.dmac.channels[chan].bfc);
  286. break;
  287. case 0x1f:
  288. v68.dmac.channels[chan].gcr = data & 0xff;
  289. verbose3("DMA#%i: General Control write : %02x\n",chan,v68.dmac.channels[chan].gcr);
  290. break;
  291. }
  292. }
  293. uint16_t dmac_read_16(uint32_t offset, uint16_t mem_mask) {
  294. int chan = (offset >> 6) & 0x03;
  295. int reg = (offset & 0x1f) >> 1;
  296. verbose3("dmac_read_16 offset=0x%08x mem_mask=0x%04x chan=0x%02x reg=0x%02x\n", offset, mem_mask, chan, reg);
  297. switch(reg)
  298. {
  299. case 0x00: // CSR / CER
  300. return (v68.dmac.channels[chan].csr << 8) | v68.dmac.channels[chan].cer;
  301. case 0x02: // DCR / OCR
  302. return (v68.dmac.channels[chan].dcr << 8) | v68.dmac.channels[chan].ocr;
  303. case 0x03: // SCR / CCR
  304. return (v68.dmac.channels[chan].scr << 8) | v68.dmac.channels[chan].ccr;
  305. case 0x05: // MTC
  306. return v68.dmac.channels[chan].mtc;
  307. case 0x06: // MAR (high)
  308. return (v68.dmac.channels[chan].mar & 0xffff0000) >> 16;
  309. case 0x07: // MAR (low)
  310. return (v68.dmac.channels[chan].mar & 0x0000ffff);
  311. case 0x0a: // DAR (high)
  312. return (v68.dmac.channels[chan].dar & 0xffff0000) >> 16;
  313. case 0x0b: // DAR (low)
  314. return (v68.dmac.channels[chan].dar & 0x0000ffff);
  315. case 0x0d: // BTC
  316. return v68.dmac.channels[chan].btc;
  317. case 0x0e: // BAR (high)
  318. return (v68.dmac.channels[chan].bar & 0xffff0000) >> 16;
  319. case 0x0f: // BAR (low)
  320. return (v68.dmac.channels[chan].bar & 0x0000ffff);
  321. case 0x12: // NIV
  322. return v68.dmac.channels[chan].niv;
  323. case 0x13: // EIV
  324. return v68.dmac.channels[chan].eiv;
  325. case 0x14: // MFC
  326. return v68.dmac.channels[chan].mfc;
  327. case 0x16: // CPR
  328. return v68.dmac.channels[chan].cpr;
  329. case 0x18: // DFC
  330. return v68.dmac.channels[chan].dfc;
  331. case 0x1c: // BFC
  332. return v68.dmac.channels[chan].bfc;
  333. case 0x1f: // GCR
  334. return v68.dmac.channels[chan].gcr;
  335. }
  336. return 0xff;
  337. }