mac_dbdma.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855
  1. /*
  2. * PowerMac descriptor-based DMA emulation
  3. *
  4. * Copyright (c) 2005-2007 Fabrice Bellard
  5. * Copyright (c) 2007 Jocelyn Mayer
  6. * Copyright (c) 2009 Laurent Vivier
  7. *
  8. * some parts from linux-2.6.28, arch/powerpc/include/asm/dbdma.h
  9. *
  10. * Definitions for using the Apple Descriptor-Based DMA controller
  11. * in Power Macintosh computers.
  12. *
  13. * Copyright (C) 1996 Paul Mackerras.
  14. *
  15. * some parts from mol 0.9.71
  16. *
  17. * Descriptor based DMA emulation
  18. *
  19. * Copyright (C) 1998-2004 Samuel Rydh (samuel@ibrium.se)
  20. *
  21. * Permission is hereby granted, free of charge, to any person obtaining a copy
  22. * of this software and associated documentation files (the "Software"), to deal
  23. * in the Software without restriction, including without limitation the rights
  24. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  25. * copies of the Software, and to permit persons to whom the Software is
  26. * furnished to do so, subject to the following conditions:
  27. *
  28. * The above copyright notice and this permission notice shall be included in
  29. * all copies or substantial portions of the Software.
  30. *
  31. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  32. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  33. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  34. * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  35. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  36. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  37. * THE SOFTWARE.
  38. */
  39. #include "hw.h"
  40. #include "isa.h"
  41. #include "mac_dbdma.h"
  42. #include "qemu/main-loop.h"
  43. /* debug DBDMA */
  44. //#define DEBUG_DBDMA
  45. #ifdef DEBUG_DBDMA
  46. #define DBDMA_DPRINTF(fmt, ...) \
  47. do { printf("DBDMA: " fmt , ## __VA_ARGS__); } while (0)
  48. #else
  49. #define DBDMA_DPRINTF(fmt, ...)
  50. #endif
  51. /*
  52. */
  53. /*
  54. * DBDMA control/status registers. All little-endian.
  55. */
  56. #define DBDMA_CONTROL 0x00
  57. #define DBDMA_STATUS 0x01
  58. #define DBDMA_CMDPTR_HI 0x02
  59. #define DBDMA_CMDPTR_LO 0x03
  60. #define DBDMA_INTR_SEL 0x04
  61. #define DBDMA_BRANCH_SEL 0x05
  62. #define DBDMA_WAIT_SEL 0x06
  63. #define DBDMA_XFER_MODE 0x07
  64. #define DBDMA_DATA2PTR_HI 0x08
  65. #define DBDMA_DATA2PTR_LO 0x09
  66. #define DBDMA_RES1 0x0A
  67. #define DBDMA_ADDRESS_HI 0x0B
  68. #define DBDMA_BRANCH_ADDR_HI 0x0C
  69. #define DBDMA_RES2 0x0D
  70. #define DBDMA_RES3 0x0E
  71. #define DBDMA_RES4 0x0F
  72. #define DBDMA_REGS 16
  73. #define DBDMA_SIZE (DBDMA_REGS * sizeof(uint32_t))
  74. #define DBDMA_CHANNEL_SHIFT 7
  75. #define DBDMA_CHANNEL_SIZE (1 << DBDMA_CHANNEL_SHIFT)
  76. #define DBDMA_CHANNELS (0x1000 >> DBDMA_CHANNEL_SHIFT)
  77. /* Bits in control and status registers */
  78. #define RUN 0x8000
  79. #define PAUSE 0x4000
  80. #define FLUSH 0x2000
  81. #define WAKE 0x1000
  82. #define DEAD 0x0800
  83. #define ACTIVE 0x0400
  84. #define BT 0x0100
  85. #define DEVSTAT 0x00ff
  86. /*
  87. * DBDMA command structure. These fields are all little-endian!
  88. */
  89. typedef struct dbdma_cmd {
  90. uint16_t req_count; /* requested byte transfer count */
  91. uint16_t command; /* command word (has bit-fields) */
  92. uint32_t phy_addr; /* physical data address */
  93. uint32_t cmd_dep; /* command-dependent field */
  94. uint16_t res_count; /* residual count after completion */
  95. uint16_t xfer_status; /* transfer status */
  96. } dbdma_cmd;
  97. /* DBDMA command values in command field */
  98. #define COMMAND_MASK 0xf000
  99. #define OUTPUT_MORE 0x0000 /* transfer memory data to stream */
  100. #define OUTPUT_LAST 0x1000 /* ditto followed by end marker */
  101. #define INPUT_MORE 0x2000 /* transfer stream data to memory */
  102. #define INPUT_LAST 0x3000 /* ditto, expect end marker */
  103. #define STORE_WORD 0x4000 /* write word (4 bytes) to device reg */
  104. #define LOAD_WORD 0x5000 /* read word (4 bytes) from device reg */
  105. #define DBDMA_NOP 0x6000 /* do nothing */
  106. #define DBDMA_STOP 0x7000 /* suspend processing */
  107. /* Key values in command field */
  108. #define KEY_MASK 0x0700
  109. #define KEY_STREAM0 0x0000 /* usual data stream */
  110. #define KEY_STREAM1 0x0100 /* control/status stream */
  111. #define KEY_STREAM2 0x0200 /* device-dependent stream */
  112. #define KEY_STREAM3 0x0300 /* device-dependent stream */
  113. #define KEY_STREAM4 0x0400 /* reserved */
  114. #define KEY_REGS 0x0500 /* device register space */
  115. #define KEY_SYSTEM 0x0600 /* system memory-mapped space */
  116. #define KEY_DEVICE 0x0700 /* device memory-mapped space */
  117. /* Interrupt control values in command field */
  118. #define INTR_MASK 0x0030
  119. #define INTR_NEVER 0x0000 /* don't interrupt */
  120. #define INTR_IFSET 0x0010 /* intr if condition bit is 1 */
  121. #define INTR_IFCLR 0x0020 /* intr if condition bit is 0 */
  122. #define INTR_ALWAYS 0x0030 /* always interrupt */
  123. /* Branch control values in command field */
  124. #define BR_MASK 0x000c
  125. #define BR_NEVER 0x0000 /* don't branch */
  126. #define BR_IFSET 0x0004 /* branch if condition bit is 1 */
  127. #define BR_IFCLR 0x0008 /* branch if condition bit is 0 */
  128. #define BR_ALWAYS 0x000c /* always branch */
  129. /* Wait control values in command field */
  130. #define WAIT_MASK 0x0003
  131. #define WAIT_NEVER 0x0000 /* don't wait */
  132. #define WAIT_IFSET 0x0001 /* wait if condition bit is 1 */
  133. #define WAIT_IFCLR 0x0002 /* wait if condition bit is 0 */
  134. #define WAIT_ALWAYS 0x0003 /* always wait */
  135. typedef struct DBDMA_channel {
  136. int channel;
  137. uint32_t regs[DBDMA_REGS];
  138. qemu_irq irq;
  139. DBDMA_io io;
  140. DBDMA_rw rw;
  141. DBDMA_flush flush;
  142. dbdma_cmd current;
  143. int processing;
  144. } DBDMA_channel;
  145. typedef struct {
  146. MemoryRegion mem;
  147. DBDMA_channel channels[DBDMA_CHANNELS];
  148. } DBDMAState;
  149. #ifdef DEBUG_DBDMA
  150. static void dump_dbdma_cmd(dbdma_cmd *cmd)
  151. {
  152. printf("dbdma_cmd %p\n", cmd);
  153. printf(" req_count 0x%04x\n", le16_to_cpu(cmd->req_count));
  154. printf(" command 0x%04x\n", le16_to_cpu(cmd->command));
  155. printf(" phy_addr 0x%08x\n", le32_to_cpu(cmd->phy_addr));
  156. printf(" cmd_dep 0x%08x\n", le32_to_cpu(cmd->cmd_dep));
  157. printf(" res_count 0x%04x\n", le16_to_cpu(cmd->res_count));
  158. printf(" xfer_status 0x%04x\n", le16_to_cpu(cmd->xfer_status));
  159. }
  160. #else
  161. static void dump_dbdma_cmd(dbdma_cmd *cmd)
  162. {
  163. }
  164. #endif
  165. static void dbdma_cmdptr_load(DBDMA_channel *ch)
  166. {
  167. DBDMA_DPRINTF("dbdma_cmdptr_load 0x%08x\n",
  168. ch->regs[DBDMA_CMDPTR_LO]);
  169. cpu_physical_memory_read(ch->regs[DBDMA_CMDPTR_LO],
  170. (uint8_t*)&ch->current, sizeof(dbdma_cmd));
  171. }
  172. static void dbdma_cmdptr_save(DBDMA_channel *ch)
  173. {
  174. DBDMA_DPRINTF("dbdma_cmdptr_save 0x%08x\n",
  175. ch->regs[DBDMA_CMDPTR_LO]);
  176. DBDMA_DPRINTF("xfer_status 0x%08x res_count 0x%04x\n",
  177. le16_to_cpu(ch->current.xfer_status),
  178. le16_to_cpu(ch->current.res_count));
  179. cpu_physical_memory_write(ch->regs[DBDMA_CMDPTR_LO],
  180. (uint8_t*)&ch->current, sizeof(dbdma_cmd));
  181. }
  182. static void kill_channel(DBDMA_channel *ch)
  183. {
  184. DBDMA_DPRINTF("kill_channel\n");
  185. ch->regs[DBDMA_STATUS] |= DEAD;
  186. ch->regs[DBDMA_STATUS] &= ~ACTIVE;
  187. qemu_irq_raise(ch->irq);
  188. }
  189. static void conditional_interrupt(DBDMA_channel *ch)
  190. {
  191. dbdma_cmd *current = &ch->current;
  192. uint16_t intr;
  193. uint16_t sel_mask, sel_value;
  194. uint32_t status;
  195. int cond;
  196. DBDMA_DPRINTF("conditional_interrupt\n");
  197. intr = le16_to_cpu(current->command) & INTR_MASK;
  198. switch(intr) {
  199. case INTR_NEVER: /* don't interrupt */
  200. return;
  201. case INTR_ALWAYS: /* always interrupt */
  202. qemu_irq_raise(ch->irq);
  203. return;
  204. }
  205. status = ch->regs[DBDMA_STATUS] & DEVSTAT;
  206. sel_mask = (ch->regs[DBDMA_INTR_SEL] >> 16) & 0x0f;
  207. sel_value = ch->regs[DBDMA_INTR_SEL] & 0x0f;
  208. cond = (status & sel_mask) == (sel_value & sel_mask);
  209. switch(intr) {
  210. case INTR_IFSET: /* intr if condition bit is 1 */
  211. if (cond)
  212. qemu_irq_raise(ch->irq);
  213. return;
  214. case INTR_IFCLR: /* intr if condition bit is 0 */
  215. if (!cond)
  216. qemu_irq_raise(ch->irq);
  217. return;
  218. }
  219. }
  220. static int conditional_wait(DBDMA_channel *ch)
  221. {
  222. dbdma_cmd *current = &ch->current;
  223. uint16_t wait;
  224. uint16_t sel_mask, sel_value;
  225. uint32_t status;
  226. int cond;
  227. DBDMA_DPRINTF("conditional_wait\n");
  228. wait = le16_to_cpu(current->command) & WAIT_MASK;
  229. switch(wait) {
  230. case WAIT_NEVER: /* don't wait */
  231. return 0;
  232. case WAIT_ALWAYS: /* always wait */
  233. return 1;
  234. }
  235. status = ch->regs[DBDMA_STATUS] & DEVSTAT;
  236. sel_mask = (ch->regs[DBDMA_WAIT_SEL] >> 16) & 0x0f;
  237. sel_value = ch->regs[DBDMA_WAIT_SEL] & 0x0f;
  238. cond = (status & sel_mask) == (sel_value & sel_mask);
  239. switch(wait) {
  240. case WAIT_IFSET: /* wait if condition bit is 1 */
  241. if (cond)
  242. return 1;
  243. return 0;
  244. case WAIT_IFCLR: /* wait if condition bit is 0 */
  245. if (!cond)
  246. return 1;
  247. return 0;
  248. }
  249. return 0;
  250. }
  251. static void next(DBDMA_channel *ch)
  252. {
  253. uint32_t cp;
  254. ch->regs[DBDMA_STATUS] &= ~BT;
  255. cp = ch->regs[DBDMA_CMDPTR_LO];
  256. ch->regs[DBDMA_CMDPTR_LO] = cp + sizeof(dbdma_cmd);
  257. dbdma_cmdptr_load(ch);
  258. }
  259. static void branch(DBDMA_channel *ch)
  260. {
  261. dbdma_cmd *current = &ch->current;
  262. ch->regs[DBDMA_CMDPTR_LO] = current->cmd_dep;
  263. ch->regs[DBDMA_STATUS] |= BT;
  264. dbdma_cmdptr_load(ch);
  265. }
  266. static void conditional_branch(DBDMA_channel *ch)
  267. {
  268. dbdma_cmd *current = &ch->current;
  269. uint16_t br;
  270. uint16_t sel_mask, sel_value;
  271. uint32_t status;
  272. int cond;
  273. DBDMA_DPRINTF("conditional_branch\n");
  274. /* check if we must branch */
  275. br = le16_to_cpu(current->command) & BR_MASK;
  276. switch(br) {
  277. case BR_NEVER: /* don't branch */
  278. next(ch);
  279. return;
  280. case BR_ALWAYS: /* always branch */
  281. branch(ch);
  282. return;
  283. }
  284. status = ch->regs[DBDMA_STATUS] & DEVSTAT;
  285. sel_mask = (ch->regs[DBDMA_BRANCH_SEL] >> 16) & 0x0f;
  286. sel_value = ch->regs[DBDMA_BRANCH_SEL] & 0x0f;
  287. cond = (status & sel_mask) == (sel_value & sel_mask);
  288. switch(br) {
  289. case BR_IFSET: /* branch if condition bit is 1 */
  290. if (cond)
  291. branch(ch);
  292. else
  293. next(ch);
  294. return;
  295. case BR_IFCLR: /* branch if condition bit is 0 */
  296. if (!cond)
  297. branch(ch);
  298. else
  299. next(ch);
  300. return;
  301. }
  302. }
  303. static QEMUBH *dbdma_bh;
  304. static void channel_run(DBDMA_channel *ch);
  305. static void dbdma_end(DBDMA_io *io)
  306. {
  307. DBDMA_channel *ch = io->channel;
  308. dbdma_cmd *current = &ch->current;
  309. if (conditional_wait(ch))
  310. goto wait;
  311. current->xfer_status = cpu_to_le16(ch->regs[DBDMA_STATUS]);
  312. current->res_count = cpu_to_le16(io->len);
  313. dbdma_cmdptr_save(ch);
  314. if (io->is_last)
  315. ch->regs[DBDMA_STATUS] &= ~FLUSH;
  316. conditional_interrupt(ch);
  317. conditional_branch(ch);
  318. wait:
  319. ch->processing = 0;
  320. if ((ch->regs[DBDMA_STATUS] & RUN) &&
  321. (ch->regs[DBDMA_STATUS] & ACTIVE))
  322. channel_run(ch);
  323. }
  324. static void start_output(DBDMA_channel *ch, int key, uint32_t addr,
  325. uint16_t req_count, int is_last)
  326. {
  327. DBDMA_DPRINTF("start_output\n");
  328. /* KEY_REGS, KEY_DEVICE and KEY_STREAM
  329. * are not implemented in the mac-io chip
  330. */
  331. DBDMA_DPRINTF("addr 0x%x key 0x%x\n", addr, key);
  332. if (!addr || key > KEY_STREAM3) {
  333. kill_channel(ch);
  334. return;
  335. }
  336. ch->io.addr = addr;
  337. ch->io.len = req_count;
  338. ch->io.is_last = is_last;
  339. ch->io.dma_end = dbdma_end;
  340. ch->io.is_dma_out = 1;
  341. ch->processing = 1;
  342. if (ch->rw) {
  343. ch->rw(&ch->io);
  344. }
  345. }
  346. static void start_input(DBDMA_channel *ch, int key, uint32_t addr,
  347. uint16_t req_count, int is_last)
  348. {
  349. DBDMA_DPRINTF("start_input\n");
  350. /* KEY_REGS, KEY_DEVICE and KEY_STREAM
  351. * are not implemented in the mac-io chip
  352. */
  353. if (!addr || key > KEY_STREAM3) {
  354. kill_channel(ch);
  355. return;
  356. }
  357. ch->io.addr = addr;
  358. ch->io.len = req_count;
  359. ch->io.is_last = is_last;
  360. ch->io.dma_end = dbdma_end;
  361. ch->io.is_dma_out = 0;
  362. ch->processing = 1;
  363. if (ch->rw) {
  364. ch->rw(&ch->io);
  365. }
  366. }
  367. static void load_word(DBDMA_channel *ch, int key, uint32_t addr,
  368. uint16_t len)
  369. {
  370. dbdma_cmd *current = &ch->current;
  371. uint32_t val;
  372. DBDMA_DPRINTF("load_word\n");
  373. /* only implements KEY_SYSTEM */
  374. if (key != KEY_SYSTEM) {
  375. printf("DBDMA: LOAD_WORD, unimplemented key %x\n", key);
  376. kill_channel(ch);
  377. return;
  378. }
  379. cpu_physical_memory_read(addr, (uint8_t*)&val, len);
  380. if (len == 2)
  381. val = (val << 16) | (current->cmd_dep & 0x0000ffff);
  382. else if (len == 1)
  383. val = (val << 24) | (current->cmd_dep & 0x00ffffff);
  384. current->cmd_dep = val;
  385. if (conditional_wait(ch))
  386. goto wait;
  387. current->xfer_status = cpu_to_le16(ch->regs[DBDMA_STATUS]);
  388. dbdma_cmdptr_save(ch);
  389. ch->regs[DBDMA_STATUS] &= ~FLUSH;
  390. conditional_interrupt(ch);
  391. next(ch);
  392. wait:
  393. qemu_bh_schedule(dbdma_bh);
  394. }
  395. static void store_word(DBDMA_channel *ch, int key, uint32_t addr,
  396. uint16_t len)
  397. {
  398. dbdma_cmd *current = &ch->current;
  399. uint32_t val;
  400. DBDMA_DPRINTF("store_word\n");
  401. /* only implements KEY_SYSTEM */
  402. if (key != KEY_SYSTEM) {
  403. printf("DBDMA: STORE_WORD, unimplemented key %x\n", key);
  404. kill_channel(ch);
  405. return;
  406. }
  407. val = current->cmd_dep;
  408. if (len == 2)
  409. val >>= 16;
  410. else if (len == 1)
  411. val >>= 24;
  412. cpu_physical_memory_write(addr, (uint8_t*)&val, len);
  413. if (conditional_wait(ch))
  414. goto wait;
  415. current->xfer_status = cpu_to_le16(ch->regs[DBDMA_STATUS]);
  416. dbdma_cmdptr_save(ch);
  417. ch->regs[DBDMA_STATUS] &= ~FLUSH;
  418. conditional_interrupt(ch);
  419. next(ch);
  420. wait:
  421. qemu_bh_schedule(dbdma_bh);
  422. }
  423. static void nop(DBDMA_channel *ch)
  424. {
  425. dbdma_cmd *current = &ch->current;
  426. if (conditional_wait(ch))
  427. goto wait;
  428. current->xfer_status = cpu_to_le16(ch->regs[DBDMA_STATUS]);
  429. dbdma_cmdptr_save(ch);
  430. conditional_interrupt(ch);
  431. conditional_branch(ch);
  432. wait:
  433. qemu_bh_schedule(dbdma_bh);
  434. }
  435. static void stop(DBDMA_channel *ch)
  436. {
  437. ch->regs[DBDMA_STATUS] &= ~(ACTIVE|DEAD|FLUSH);
  438. /* the stop command does not increment command pointer */
  439. }
  440. static void channel_run(DBDMA_channel *ch)
  441. {
  442. dbdma_cmd *current = &ch->current;
  443. uint16_t cmd, key;
  444. uint16_t req_count;
  445. uint32_t phy_addr;
  446. DBDMA_DPRINTF("channel_run\n");
  447. dump_dbdma_cmd(current);
  448. /* clear WAKE flag at command fetch */
  449. ch->regs[DBDMA_STATUS] &= ~WAKE;
  450. cmd = le16_to_cpu(current->command) & COMMAND_MASK;
  451. switch (cmd) {
  452. case DBDMA_NOP:
  453. nop(ch);
  454. return;
  455. case DBDMA_STOP:
  456. stop(ch);
  457. return;
  458. }
  459. key = le16_to_cpu(current->command) & 0x0700;
  460. req_count = le16_to_cpu(current->req_count);
  461. phy_addr = le32_to_cpu(current->phy_addr);
  462. if (key == KEY_STREAM4) {
  463. printf("command %x, invalid key 4\n", cmd);
  464. kill_channel(ch);
  465. return;
  466. }
  467. switch (cmd) {
  468. case OUTPUT_MORE:
  469. start_output(ch, key, phy_addr, req_count, 0);
  470. return;
  471. case OUTPUT_LAST:
  472. start_output(ch, key, phy_addr, req_count, 1);
  473. return;
  474. case INPUT_MORE:
  475. start_input(ch, key, phy_addr, req_count, 0);
  476. return;
  477. case INPUT_LAST:
  478. start_input(ch, key, phy_addr, req_count, 1);
  479. return;
  480. }
  481. if (key < KEY_REGS) {
  482. printf("command %x, invalid key %x\n", cmd, key);
  483. key = KEY_SYSTEM;
  484. }
  485. /* for LOAD_WORD and STORE_WORD, req_count is on 3 bits
  486. * and BRANCH is invalid
  487. */
  488. req_count = req_count & 0x0007;
  489. if (req_count & 0x4) {
  490. req_count = 4;
  491. phy_addr &= ~3;
  492. } else if (req_count & 0x2) {
  493. req_count = 2;
  494. phy_addr &= ~1;
  495. } else
  496. req_count = 1;
  497. switch (cmd) {
  498. case LOAD_WORD:
  499. load_word(ch, key, phy_addr, req_count);
  500. return;
  501. case STORE_WORD:
  502. store_word(ch, key, phy_addr, req_count);
  503. return;
  504. }
  505. }
  506. static void DBDMA_run(DBDMAState *s)
  507. {
  508. int channel;
  509. for (channel = 0; channel < DBDMA_CHANNELS; channel++) {
  510. DBDMA_channel *ch = &s->channels[channel];
  511. uint32_t status = ch->regs[DBDMA_STATUS];
  512. if (!ch->processing && (status & RUN) && (status & ACTIVE)) {
  513. channel_run(ch);
  514. }
  515. }
  516. }
  517. static void DBDMA_run_bh(void *opaque)
  518. {
  519. DBDMAState *s = opaque;
  520. DBDMA_DPRINTF("DBDMA_run_bh\n");
  521. DBDMA_run(s);
  522. }
  523. void DBDMA_register_channel(void *dbdma, int nchan, qemu_irq irq,
  524. DBDMA_rw rw, DBDMA_flush flush,
  525. void *opaque)
  526. {
  527. DBDMAState *s = dbdma;
  528. DBDMA_channel *ch = &s->channels[nchan];
  529. DBDMA_DPRINTF("DBDMA_register_channel 0x%x\n", nchan);
  530. ch->irq = irq;
  531. ch->channel = nchan;
  532. ch->rw = rw;
  533. ch->flush = flush;
  534. ch->io.opaque = opaque;
  535. ch->io.channel = ch;
  536. }
  537. static void
  538. dbdma_control_write(DBDMA_channel *ch)
  539. {
  540. uint16_t mask, value;
  541. uint32_t status;
  542. mask = (ch->regs[DBDMA_CONTROL] >> 16) & 0xffff;
  543. value = ch->regs[DBDMA_CONTROL] & 0xffff;
  544. value &= (RUN | PAUSE | FLUSH | WAKE | DEVSTAT);
  545. status = ch->regs[DBDMA_STATUS];
  546. status = (value & mask) | (status & ~mask);
  547. if (status & WAKE)
  548. status |= ACTIVE;
  549. if (status & RUN) {
  550. status |= ACTIVE;
  551. status &= ~DEAD;
  552. }
  553. if (status & PAUSE)
  554. status &= ~ACTIVE;
  555. if ((ch->regs[DBDMA_STATUS] & RUN) && !(status & RUN)) {
  556. /* RUN is cleared */
  557. status &= ~(ACTIVE|DEAD);
  558. }
  559. DBDMA_DPRINTF(" status 0x%08x\n", status);
  560. ch->regs[DBDMA_STATUS] = status;
  561. if (status & ACTIVE)
  562. qemu_bh_schedule(dbdma_bh);
  563. if ((status & FLUSH) && ch->flush)
  564. ch->flush(&ch->io);
  565. }
  566. static void dbdma_write(void *opaque, hwaddr addr,
  567. uint64_t value, unsigned size)
  568. {
  569. int channel = addr >> DBDMA_CHANNEL_SHIFT;
  570. DBDMAState *s = opaque;
  571. DBDMA_channel *ch = &s->channels[channel];
  572. int reg = (addr - (channel << DBDMA_CHANNEL_SHIFT)) >> 2;
  573. DBDMA_DPRINTF("writel 0x" TARGET_FMT_plx " <= 0x%08x\n", addr, value);
  574. DBDMA_DPRINTF("channel 0x%x reg 0x%x\n",
  575. (uint32_t)addr >> DBDMA_CHANNEL_SHIFT, reg);
  576. /* cmdptr cannot be modified if channel is RUN or ACTIVE */
  577. if (reg == DBDMA_CMDPTR_LO &&
  578. (ch->regs[DBDMA_STATUS] & (RUN | ACTIVE)))
  579. return;
  580. ch->regs[reg] = value;
  581. switch(reg) {
  582. case DBDMA_CONTROL:
  583. dbdma_control_write(ch);
  584. break;
  585. case DBDMA_CMDPTR_LO:
  586. /* 16-byte aligned */
  587. ch->regs[DBDMA_CMDPTR_LO] &= ~0xf;
  588. dbdma_cmdptr_load(ch);
  589. break;
  590. case DBDMA_STATUS:
  591. case DBDMA_INTR_SEL:
  592. case DBDMA_BRANCH_SEL:
  593. case DBDMA_WAIT_SEL:
  594. /* nothing to do */
  595. break;
  596. case DBDMA_XFER_MODE:
  597. case DBDMA_CMDPTR_HI:
  598. case DBDMA_DATA2PTR_HI:
  599. case DBDMA_DATA2PTR_LO:
  600. case DBDMA_ADDRESS_HI:
  601. case DBDMA_BRANCH_ADDR_HI:
  602. case DBDMA_RES1:
  603. case DBDMA_RES2:
  604. case DBDMA_RES3:
  605. case DBDMA_RES4:
  606. /* unused */
  607. break;
  608. }
  609. }
  610. static uint64_t dbdma_read(void *opaque, hwaddr addr,
  611. unsigned size)
  612. {
  613. uint32_t value;
  614. int channel = addr >> DBDMA_CHANNEL_SHIFT;
  615. DBDMAState *s = opaque;
  616. DBDMA_channel *ch = &s->channels[channel];
  617. int reg = (addr - (channel << DBDMA_CHANNEL_SHIFT)) >> 2;
  618. value = ch->regs[reg];
  619. DBDMA_DPRINTF("readl 0x" TARGET_FMT_plx " => 0x%08x\n", addr, value);
  620. DBDMA_DPRINTF("channel 0x%x reg 0x%x\n",
  621. (uint32_t)addr >> DBDMA_CHANNEL_SHIFT, reg);
  622. switch(reg) {
  623. case DBDMA_CONTROL:
  624. value = 0;
  625. break;
  626. case DBDMA_STATUS:
  627. case DBDMA_CMDPTR_LO:
  628. case DBDMA_INTR_SEL:
  629. case DBDMA_BRANCH_SEL:
  630. case DBDMA_WAIT_SEL:
  631. /* nothing to do */
  632. break;
  633. case DBDMA_XFER_MODE:
  634. case DBDMA_CMDPTR_HI:
  635. case DBDMA_DATA2PTR_HI:
  636. case DBDMA_DATA2PTR_LO:
  637. case DBDMA_ADDRESS_HI:
  638. case DBDMA_BRANCH_ADDR_HI:
  639. /* unused */
  640. value = 0;
  641. break;
  642. case DBDMA_RES1:
  643. case DBDMA_RES2:
  644. case DBDMA_RES3:
  645. case DBDMA_RES4:
  646. /* reserved */
  647. break;
  648. }
  649. return value;
  650. }
  651. static const MemoryRegionOps dbdma_ops = {
  652. .read = dbdma_read,
  653. .write = dbdma_write,
  654. .endianness = DEVICE_LITTLE_ENDIAN,
  655. .valid = {
  656. .min_access_size = 4,
  657. .max_access_size = 4,
  658. },
  659. };
  660. static const VMStateDescription vmstate_dbdma_channel = {
  661. .name = "dbdma_channel",
  662. .version_id = 0,
  663. .minimum_version_id = 0,
  664. .minimum_version_id_old = 0,
  665. .fields = (VMStateField[]) {
  666. VMSTATE_UINT32_ARRAY(regs, struct DBDMA_channel, DBDMA_REGS),
  667. VMSTATE_END_OF_LIST()
  668. }
  669. };
  670. static const VMStateDescription vmstate_dbdma = {
  671. .name = "dbdma",
  672. .version_id = 2,
  673. .minimum_version_id = 2,
  674. .minimum_version_id_old = 2,
  675. .fields = (VMStateField[]) {
  676. VMSTATE_STRUCT_ARRAY(channels, DBDMAState, DBDMA_CHANNELS, 1,
  677. vmstate_dbdma_channel, DBDMA_channel),
  678. VMSTATE_END_OF_LIST()
  679. }
  680. };
  681. static void dbdma_reset(void *opaque)
  682. {
  683. DBDMAState *s = opaque;
  684. int i;
  685. for (i = 0; i < DBDMA_CHANNELS; i++)
  686. memset(s->channels[i].regs, 0, DBDMA_SIZE);
  687. }
  688. void* DBDMA_init (MemoryRegion **dbdma_mem)
  689. {
  690. DBDMAState *s;
  691. s = g_malloc0(sizeof(DBDMAState));
  692. memory_region_init_io(&s->mem, &dbdma_ops, s, "dbdma", 0x1000);
  693. *dbdma_mem = &s->mem;
  694. vmstate_register(NULL, -1, &vmstate_dbdma, s);
  695. qemu_register_reset(dbdma_reset, s);
  696. dbdma_bh = qemu_bh_new(DBDMA_run_bh, s);
  697. return s;
  698. }