2
0

mac_dbdma.c 21 KB

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