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