1
/* $Id: DevDMA.cpp 4071 2007-08-07 17:07:59Z vboxsync $ */
3
* DMA Controller Device.
7
* Copyright (C) 2006-2007 innotek GmbH
9
* This file is part of VirtualBox Open Source Edition (OSE), as
10
* available from http://www.virtualbox.org. This file is free software;
11
* you can redistribute it and/or modify it under the terms of the GNU
12
* General Public License as published by the Free Software Foundation,
13
* in version 2 as it comes in the "COPYING" file of the VirtualBox OSE
14
* distribution. VirtualBox OSE is distributed in the hope that it will
15
* be useful, but WITHOUT ANY WARRANTY of any kind.
16
* --------------------------------------------------------------------
18
* This code is based on:
22
* Copyright (c) 2003 Vassili Karpov (malc)
24
* Permission is hereby granted, free of charge, to any person obtaining a copy
25
* of this software and associated documentation files (the "Software"), to deal
26
* in the Software without restriction, including without limitation the rights
27
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
28
* copies of the Software, and to permit persons to whom the Software is
29
* furnished to do so, subject to the following conditions:
31
* The above copyright notice and this permission notice shall be included in
32
* all copies or substantial portions of the Software.
34
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
35
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
36
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
37
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
38
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
39
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
45
/*******************************************************************************
47
*******************************************************************************/
48
#include <VBox/pdmdev.h>
51
#define LOG_GROUP LOG_GROUP_DEFAULT ///@todo LOG_GROUP_DEV_DMA
53
#include <iprt/assert.h>
54
#include <iprt/uuid.h>
55
#include <iprt/string.h>
61
#include "../vl_vbox.h"
62
typedef PFNDMATRANSFERHANDLER DMA_transfer_handler;
68
/* #define DEBUG_DMA */
72
#define dolog(...) fprintf (stderr, "dma: " __VA_ARGS__)
74
#define lwarn(...) fprintf (stderr, "dma: " __VA_ARGS__)
75
#define linfo(...) fprintf (stderr, "dma: " __VA_ARGS__)
76
#define ldebug(...) fprintf (stderr, "dma: " __VA_ARGS__)
94
static void DMA_DPRINTF (const char *fmt, ...)
96
if (LogIsEnabled ()) {
99
RTLogLogger (NULL, NULL, "dma: %N", fmt, &args); /* %N - nested va_list * type formatting call. */
104
DECLINLINE(void) DMA_DPRINTF(const char *pszFmt, ...) {}
107
#define dolog DMA_DPRINTF
108
#define lwarn DMA_DPRINTF
109
#define linfo DMA_DPRINTF
110
#define ldebug DMA_DPRINTF
114
#define LENOFA(a) ((int) (sizeof(a)/sizeof(a[0])))
124
DMA_transfer_handler transfer_handler;
137
struct dma_regs regs[4];
143
struct dma_cont dma_controllers[2];
147
CMD_MEMORY_TO_MEMORY = 0x01,
148
CMD_FIXED_ADDRESS = 0x02,
149
CMD_BLOCK_CONTROLLER = 0x04,
150
CMD_COMPRESSED_TIME = 0x08,
151
CMD_CYCLIC_PRIORITY = 0x10,
152
CMD_EXTENDED_WRITE = 0x20,
155
CMD_NOT_SUPPORTED = CMD_MEMORY_TO_MEMORY | CMD_FIXED_ADDRESS
156
| CMD_COMPRESSED_TIME | CMD_CYCLIC_PRIORITY | CMD_EXTENDED_WRITE
157
| CMD_LOW_DREQ | CMD_LOW_DACK
161
static int channels[8] = {-1, 2, 3, 1, -1, -1, -1, 0};
163
static void write_page (void *opaque, uint32_t nport, uint32_t data)
165
struct dma_cont *d = (struct dma_cont*)opaque;
168
ichan = channels[nport & 7];
170
dolog ("invalid channel %#x %#x\n", nport, data);
173
d->regs[ichan].page = data;
176
static void write_pageh (void *opaque, uint32_t nport, uint32_t data)
178
struct dma_cont *d = (struct dma_cont*)opaque;
181
ichan = channels[nport & 7];
183
dolog ("invalid channel %#x %#x\n", nport, data);
186
d->regs[ichan].pageh = data;
189
static uint32_t read_page (void *opaque, uint32_t nport)
191
struct dma_cont *d = (struct dma_cont*)opaque;
194
ichan = channels[nport & 7];
196
dolog ("invalid channel read %#x\n", nport);
199
return d->regs[ichan].page;
202
static uint32_t read_pageh (void *opaque, uint32_t nport)
204
struct dma_cont *d = (struct dma_cont*)opaque;
207
ichan = channels[nport & 7];
209
dolog ("invalid channel read %#x\n", nport);
212
return d->regs[ichan].pageh;
215
static inline void init_chan (struct dma_cont *d, int ichan)
220
r->now[ADDR] = r->base[ADDR] << d->dshift;
224
static inline int getff (struct dma_cont *d)
233
static uint32_t read_chan (void *opaque, uint32_t nport)
235
struct dma_cont *d = (struct dma_cont*)opaque;
236
int ichan, nreg, iport, ff, val, dir;
239
iport = (nport >> d->dshift) & 0x0f;
244
dir = ((r->mode >> 5) & 1) ? -1 : 1;
247
val = (r->base[COUNT] << d->dshift) - r->now[COUNT];
249
val = r->now[ADDR] + r->now[COUNT] * dir;
251
ldebug ("read_chan %#x -> %d\n", iport, val);
252
return (val >> (d->dshift + (ff << 3))) & 0xff;
255
static void write_chan (void *opaque, uint32_t nport, uint32_t data)
257
struct dma_cont *d = (struct dma_cont*)opaque;
258
int iport, ichan, nreg;
261
iport = (nport >> d->dshift) & 0x0f;
266
r->base[nreg] = (r->base[nreg] & 0xff) | ((data << 8) & 0xff00);
267
init_chan (d, ichan);
269
r->base[nreg] = (r->base[nreg] & 0xff00) | (data & 0xff);
273
static void write_cont (void *opaque, uint32_t nport, uint32_t data)
275
struct dma_cont *d = (struct dma_cont*)opaque;
276
int iport, ichan = 0;
278
iport = (nport >> d->dshift) & 0x0f;
280
case 0x08: /* command */
281
if ((data != 0) && (data & CMD_NOT_SUPPORTED)) {
282
dolog ("command %#x not supported\n", data);
291
d->status |= 1 << (ichan + 4);
294
d->status &= ~(1 << (ichan + 4));
296
d->status &= ~(1 << ichan);
299
case 0x0a: /* single mask */
301
d->mask |= 1 << (data & 3);
303
d->mask &= ~(1 << (data & 3));
306
case 0x0b: /* mode */
311
int op, ai, dir, opmode;
312
op = (data >> 2) & 3;
313
ai = (data >> 4) & 1;
314
dir = (data >> 5) & 1;
315
opmode = (data >> 6) & 3;
317
linfo ("ichan %d, op %d, ai %d, dir %d, opmode %d\n",
318
ichan, op, ai, dir, opmode);
321
d->regs[ichan].mode = data;
325
case 0x0c: /* clear flip flop */
329
case 0x0d: /* reset */
336
case 0x0e: /* clear mask for all channels */
340
case 0x0f: /* write mask for all channels */
345
dolog ("unknown iport %#x\n", iport);
351
linfo ("write_cont: nport %#06x, ichan % 2d, val %#06x\n",
357
static uint32_t read_cont (void *opaque, uint32_t nport)
359
struct dma_cont *d = (struct dma_cont*)opaque;
362
iport = (nport >> d->dshift) & 0x0f;
364
case 0x08: /* status */
368
case 0x0f: /* mask */
376
ldebug ("read_cont: nport %#06x, iport %#04x val %#x\n", nport, iport, val);
380
static uint8_t DMA_get_channel_mode (DMAState *s, int nchan)
382
return s->dma_controllers[nchan > 3].regs[nchan & 3].mode;
385
static void DMA_hold_DREQ (DMAState *s, int nchan)
391
linfo ("held cont=%d chan=%d\n", ncont, ichan);
392
s->dma_controllers[ncont].status |= 1 << (ichan + 4);
395
static void DMA_release_DREQ (DMAState *s, int nchan)
401
linfo ("released cont=%d chan=%d\n", ncont, ichan);
402
s->dma_controllers[ncont].status &= ~(1 << (ichan + 4));
405
static void channel_run (DMAState *s, int ncont, int ichan)
408
struct dma_regs *r = &s->dma_controllers[ncont].regs[ichan];
412
dir = (r->mode >> 5) & 1;
413
opmode = (r->mode >> 6) & 3;
416
dolog ("DMA in address decrement mode\n");
419
dolog ("DMA not in single mode select %#x\n", opmode);
423
r = s->dma_controllers[ncont].regs + ichan;
424
n = r->transfer_handler (s->pDevIns, r->opaque, ichan + (ncont << 2),
425
r->now[COUNT], (r->base[COUNT] + 1) << ncont);
427
ldebug ("dma_pos %d size %d\n", n, (r->base[COUNT] + 1) << ncont);
430
static void DMA_run (DMAState *s)
435
d = s->dma_controllers;
437
for (icont = 0; icont < 2; icont++, d++) {
438
for (ichan = 0; ichan < 4; ichan++) {
443
if ((0 == (d->mask & mask)) && (0 != (d->status & (mask << 4))))
444
channel_run (s, icont, ichan);
449
static void DMA_register_channel (DMAState *s, unsigned nchan,
450
DMA_transfer_handler transfer_handler,
455
LogFlow (("DMA_register_channel: s=%p nchan=%d transfer_handler=%p opaque=%p\n",
456
s, nchan, transfer_handler, opaque));
461
r = s->dma_controllers[ncont].regs + ichan;
462
r->transfer_handler = transfer_handler;
466
static uint32_t DMA_read_memory (DMAState *s,
472
struct dma_regs *r = &s->dma_controllers[nchan > 3].regs[nchan & 3];
473
uint32_t addr = ((r->pageh & 0x7f) << 24) | (r->page << 16) | r->now[ADDR];
475
if (r->mode & 0x20) {
477
uint8_t *p = (uint8_t*)buf;
480
PDMDevHlpPhysRead (s->pDevIns, addr - pos - len, buf, len);
482
cpu_physical_memory_read (addr - pos - len, buf, len);
484
/* What about 16bit transfers? */
485
for (i = 0; i < len >> 1; i++) {
486
uint8_t b = p[len - i - 1];
492
PDMDevHlpPhysRead (s->pDevIns, addr + pos, buf, len);
494
cpu_physical_memory_read (addr + pos, buf, len);
499
static uint32_t DMA_write_memory (DMAState *s,
505
struct dma_regs *r = &s->dma_controllers[nchan > 3].regs[nchan & 3];
506
uint32_t addr = ((r->pageh & 0x7f) << 24) | (r->page << 16) | r->now[ADDR];
508
if (r->mode & 0x20) {
510
uint8_t *p = (uint8_t *) buf;
513
PDMDevHlpPhysWrite (s->pDevIns, addr - pos - len, buf, len);
515
cpu_physical_memory_write (addr - pos - len, buf, len);
517
/* What about 16bit transfers? */
518
for (i = 0; i < len; i++) {
519
uint8_t b = p[len - i - 1];
525
PDMDevHlpPhysWrite (s->pDevIns, addr + pos, buf, len);
527
cpu_physical_memory_write (addr + pos, buf, len);
535
/* request the emulator to transfer a new DMA memory block ASAP */
536
void DMA_schedule(int nchan)
538
cpu_interrupt(cpu_single_env, CPU_INTERRUPT_EXIT);
542
static void dma_reset(void *opaque)
544
struct dma_cont *d = (struct dma_cont*)opaque;
545
write_cont (d, (0x0d << d->dshift), 0);
549
#define IO_READ_PROTO(n) \
550
static DECLCALLBACK(int) io_read_##n (PPDMDEVINS pDevIns, \
557
#define IO_WRITE_PROTO(n) \
558
static DECLCALLBACK(int) io_write_##n (PPDMDEVINS pDevIns, \
564
IO_WRITE_PROTO (chan)
567
write_chan (pvUser, Port, u32);
571
Log (("Unknown write to %#x of size %d, value %#x\n",
578
IO_WRITE_PROTO (page)
581
write_page (pvUser, Port, u32);
585
Log (("Unknown write to %#x of size %d, value %#x\n",
592
IO_WRITE_PROTO (pageh)
595
write_pageh (pvUser, Port, u32);
599
Log (("Unknown write to %#x of size %d, value %#x\n",
606
IO_WRITE_PROTO (cont)
609
write_cont (pvUser, Port, u32);
613
Log (("Unknown write to %#x of size %d, value %#x\n",
623
*pu32 = read_chan (pvUser, Port);
627
return VERR_IOM_IOPORT_UNUSED;
634
*pu32 = read_page (pvUser, Port);
638
return VERR_IOM_IOPORT_UNUSED;
642
IO_READ_PROTO (pageh)
645
*pu32 = read_pageh (pvUser, Port);
649
return VERR_IOM_IOPORT_UNUSED;
656
*pu32 = read_cont (pvUser, Port);
660
return VERR_IOM_IOPORT_UNUSED;
665
/* dshift = 0: 8 bit DMA, 1 = 16 bit DMA */
666
static void dma_init2(DMAState *s, struct dma_cont *d, int base, int dshift,
667
int page_base, int pageh_base)
669
const static int page_port_list[] = { 0x1, 0x2, 0x3, 0x7 };
673
for (i = 0; i < 8; i++) {
675
PDMDevHlpIOPortRegister (s->pDevIns, base + (i << dshift), 1, d,
676
io_write_chan, io_read_chan, NULL, NULL, "DMA");
678
register_ioport_write (base + (i << dshift), 1, 1, write_chan, d);
679
register_ioport_read (base + (i << dshift), 1, 1, read_chan, d);
682
for (i = 0; i < LENOFA (page_port_list); i++) {
684
PDMDevHlpIOPortRegister (s->pDevIns, page_base + page_port_list[i], 1, d,
685
io_write_page, io_read_page, NULL, NULL, "DMA Page");
687
register_ioport_write (page_base + page_port_list[i], 1, 1,
689
register_ioport_read (page_base + page_port_list[i], 1, 1,
692
if (pageh_base >= 0) {
694
PDMDevHlpIOPortRegister (s->pDevIns, pageh_base + page_port_list[i], 1, d,
695
io_write_pageh, io_read_pageh, NULL, NULL, "DMA Page High");
697
register_ioport_write (pageh_base + page_port_list[i], 1, 1,
699
register_ioport_read (pageh_base + page_port_list[i], 1, 1,
704
for (i = 0; i < 8; i++) {
706
PDMDevHlpIOPortRegister (s->pDevIns, base + ((i + 8) << dshift), 1, d,
707
io_write_cont, io_read_cont, NULL, NULL, "DMA cont");
709
register_ioport_write (base + ((i + 8) << dshift), 1, 1,
711
register_ioport_read (base + ((i + 8) << dshift), 1, 1,
716
qemu_register_reset(dma_reset, d);
721
static void dma_save (QEMUFile *f, void *opaque)
723
struct dma_cont *d = (struct dma_cont*)opaque;
726
/* qemu_put_8s (f, &d->status); */
727
qemu_put_8s (f, &d->command);
728
qemu_put_8s (f, &d->mask);
729
qemu_put_8s (f, &d->flip_flop);
730
qemu_put_be32s (f, &d->dshift);
732
for (i = 0; i < 4; ++i) {
733
struct dma_regs *r = &d->regs[i];
734
qemu_put_be32s (f, &r->now[0]);
735
qemu_put_be32s (f, &r->now[1]);
736
qemu_put_be16s (f, &r->base[0]);
737
qemu_put_be16s (f, &r->base[1]);
738
qemu_put_8s (f, &r->mode);
739
qemu_put_8s (f, &r->page);
740
qemu_put_8s (f, &r->pageh);
741
qemu_put_8s (f, &r->dack);
742
qemu_put_8s (f, &r->eop);
746
static int dma_load (QEMUFile *f, void *opaque, int version_id)
748
struct dma_cont *d = (struct dma_cont*)opaque;
753
return VERR_SSM_UNSUPPORTED_DATA_UNIT_VERSION;
758
/* qemu_get_8s (f, &d->status); */
759
qemu_get_8s (f, &d->command);
760
qemu_get_8s (f, &d->mask);
761
qemu_get_8s (f, &d->flip_flop);
762
qemu_get_be32s (f, &d->dshift);
764
for (i = 0; i < 4; ++i) {
765
struct dma_regs *r = &d->regs[i];
766
qemu_get_be32s (f, &r->now[0]);
767
qemu_get_be32s (f, &r->now[1]);
768
qemu_get_be16s (f, &r->base[0]);
769
qemu_get_be16s (f, &r->base[1]);
770
qemu_get_8s (f, &r->mode);
771
qemu_get_8s (f, &r->page);
772
qemu_get_8s (f, &r->pageh);
773
qemu_get_8s (f, &r->dack);
774
qemu_get_8s (f, &r->eop);
780
void DMA_init (int high_page_enable)
782
dma_init2(&dma_controllers[0], 0x00, 0, 0x80,
783
high_page_enable ? 0x480 : -1);
784
dma_init2(&dma_controllers[1], 0xc0, 1, 0x88,
785
high_page_enable ? 0x488 : -1);
786
register_savevm ("dma", 0, 1, dma_save, dma_load, &dma_controllers[0]);
787
register_savevm ("dma", 1, 1, dma_save, dma_load, &dma_controllers[1]);
792
static bool run_wrapper (PPDMDEVINS pDevIns)
794
DMA_run (PDMINS2DATA (pDevIns, DMAState *));
798
static void register_channel_wrapper (PPDMDEVINS pDevIns,
800
PFNDMATRANSFERHANDLER f,
803
DMAState *s = PDMINS2DATA (pDevIns, DMAState *);
804
DMA_register_channel (s, nchan, f, opaque);
807
static uint32_t rd_mem_wrapper (PPDMDEVINS pDevIns,
813
DMAState *s = PDMINS2DATA (pDevIns, DMAState *);
814
return DMA_read_memory (s, nchan, buf, pos, len);
817
static uint32_t wr_mem_wrapper (PPDMDEVINS pDevIns,
823
DMAState *s = PDMINS2DATA (pDevIns, DMAState *);
824
return DMA_write_memory (s, nchan, buf, pos, len);
827
static void set_DREQ_wrapper (PPDMDEVINS pDevIns,
831
DMAState *s = PDMINS2DATA (pDevIns, DMAState *);
833
DMA_hold_DREQ (s, nchan);
836
DMA_release_DREQ (s, nchan);
840
static uint8_t get_mode_wrapper (PPDMDEVINS pDevIns, unsigned nchan)
842
DMAState *s = PDMINS2DATA (pDevIns, DMAState *);
843
return DMA_get_channel_mode (s, nchan);
846
static void DMAReset (PPDMDEVINS pDevIns)
848
DMAState *s = PDMINS2DATA (pDevIns, DMAState *);
849
dma_reset (&s->dma_controllers[0]);
850
dma_reset (&s->dma_controllers[1]);
853
static DECLCALLBACK(int) SaveExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSMHandle)
855
DMAState *s = PDMINS2DATA (pDevIns, DMAState *);
856
dma_save (pSSMHandle, &s->dma_controllers[0]);
857
dma_save (pSSMHandle, &s->dma_controllers[1]);
861
static DECLCALLBACK(int) LoadExec (PPDMDEVINS pDevIns,
862
PSSMHANDLE pSSMHandle,
865
DMAState *s = PDMINS2DATA (pDevIns, DMAState *);
867
if (u32Version != 1) {
869
return VERR_SSM_UNSUPPORTED_DATA_UNIT_VERSION;
872
dma_load (pSSMHandle, &s->dma_controllers[0], u32Version);
873
return dma_load (pSSMHandle, &s->dma_controllers[1], u32Version);
877
* Construct a device instance for a VM.
879
* @returns VBox status.
880
* @param pDevIns The device instance data.
881
* If the registration structure is needed, pDevIns->pDevReg points to it.
882
* @param iInstance Instance number. Use this to figure out which registers and such to use.
883
* The device number is also found in pDevIns->iInstance, but since it's
884
* likely to be freqently used PDM passes it as parameter.
885
* @param pCfgHandle Configuration node handle for the device. Use this to obtain the configuration
886
* of the device instance. It's also found in pDevIns->pCfgHandle, but like
887
* iInstance it's expected to be used a bit in this function.
889
static DECLCALLBACK(int) DMAConstruct(PPDMDEVINS pDevIns,
891
PCFGMNODE pCfgHandle)
893
DMAState *s = PDMINS2DATA (pDevIns, DMAState *);
894
bool high_page_enable = 0;
898
s->pDevIns = pDevIns;
901
* Validate configuration.
903
if (!CFGMR3AreValuesValid(pCfgHandle, "\0")) /* "HighPageEnable\0")) */
904
return VERR_PDM_DEVINS_UNKNOWN_CFG_VALUES;
907
rc = CFGMR3QueryBool (pCfgHandle, "HighPageEnable", &high_page_enable);
908
if (VBOX_FAILURE (rc)) {
913
dma_init2(s, &s->dma_controllers[0], 0x00, 0, 0x80,
914
high_page_enable ? 0x480 : -1);
915
dma_init2(s, &s->dma_controllers[1], 0xc0, 1, 0x88,
916
high_page_enable ? 0x488 : -1);
918
reg.u32Version = PDM_DMACREG_VERSION;
919
reg.pfnRun = run_wrapper;
920
reg.pfnRegister = register_channel_wrapper;
921
reg.pfnReadMemory = rd_mem_wrapper;
922
reg.pfnWriteMemory = wr_mem_wrapper;
923
reg.pfnSetDREQ = set_DREQ_wrapper;
924
reg.pfnGetChannelMode = get_mode_wrapper;
926
Assert(pDevIns->pDevHlp->pfnDMARegister);
927
rc = pDevIns->pDevHlp->pfnDMACRegister (pDevIns, ®, &s->pHlp);
928
if (VBOX_FAILURE (rc)) {
932
rc = PDMDevHlpSSMRegister (pDevIns, pDevIns->pDevReg->szDeviceName, iInstance, 1, sizeof (*s),
933
NULL, SaveExec, NULL, NULL, LoadExec, NULL);
934
if (VBOX_FAILURE(rc))
941
* The device registration structure.
943
const PDMDEVREG g_DeviceDMA =
954
"DMA Controller Device",
956
PDM_DEVREG_FLAGS_HOST_BITS_DEFAULT | PDM_DEVREG_FLAGS_GUEST_BITS_DEFAULT,
958
PDM_DEVREG_CLASS_DMA,
983
/* pfnQueryInterface. */
985
/* pfnInitComplete */