summaryrefslogtreecommitdiff
path: root/src/VBox/Devices/PC/DevDMA.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/VBox/Devices/PC/DevDMA.cpp')
-rw-r--r--src/VBox/Devices/PC/DevDMA.cpp382
1 files changed, 221 insertions, 161 deletions
diff --git a/src/VBox/Devices/PC/DevDMA.cpp b/src/VBox/Devices/PC/DevDMA.cpp
index ebcefdd5..2ba0c96c 100644
--- a/src/VBox/Devices/PC/DevDMA.cpp
+++ b/src/VBox/Devices/PC/DevDMA.cpp
@@ -4,7 +4,7 @@
*/
/*
- * Copyright (C) 2006-2007 Oracle Corporation
+ * Copyright (C) 2006-2013 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
@@ -57,7 +57,7 @@
#include "VBoxDD.h"
-/* DMA Overview and notes
+/** @page pg_dev_dma DMA Overview and notes
*
* Modern PCs typically emulate AT-compatible DMA. The IBM PC/AT used dual
* cascaded 8237A DMA controllers, augmented with a 74LS612 memory mapper.
@@ -122,7 +122,7 @@ typedef struct {
uint8_t u8Mask; /* Mask register. */
uint8_t u8Temp; /* Temporary (mem/mem) register. */
uint8_t u8ModeCtr; /* Mode register counter for reads. */
- bool bHiByte; /* Byte pointer (T/F -> high/low). */
+ bool fHiByte; /* Byte pointer (T/F -> high/low). */
uint32_t is16bit; /* True for 16-bit DMA. */
} DMAControl;
@@ -171,6 +171,22 @@ enum {
CTL_W_MASK /* Write all DRQ mask bits. */
};
+/* DMA transfer modes. */
+enum {
+ DMODE_DEMAND, /* Demand transfer mode. */
+ DMODE_SINGLE, /* Single transfer mode. */
+ DMODE_BLOCK, /* Block transfer mode. */
+ DMODE_CASCADE /* Cascade mode. */
+};
+
+/* DMA transfer types. */
+enum {
+ DTYPE_VERIFY, /* Verify transfer type. */
+ DTYPE_WRITE, /* Write transfer type. */
+ DTYPE_READ, /* Read transfer type. */
+ DTYPE_ILLEGAL /* Undefined. */
+};
+
/* Convert DMA channel number (0-7) to controller number (0-1). */
#define DMACH2C(c) (c < 4 ? 0 : 1)
@@ -188,6 +204,8 @@ static int dmaMapChannel[4] = {7, 3, 1, 2};
#define IS_MODE_DEC(c) ((c) & 0x20)
/* Test the auto-init bit of mode register. */
#define IS_MODE_AI(c) ((c) & 0x10)
+/* Extract the transfer type bits of mode register. */
+#define GET_MODE_XTYP(c)(((c) & 0x0c) >> 2)
/* Perform a master clear (reset) on a DMA controller. */
static void dmaClear(DMAControl *dc)
@@ -196,7 +214,7 @@ static void dmaClear(DMAControl *dc)
dc->u8Status = 0;
dc->u8Temp = 0;
dc->u8ModeCtr = 0;
- dc->bHiByte = false;
+ dc->fHiByte = false;
dc->u8Mask = ~0;
}
@@ -205,15 +223,14 @@ static inline bool dmaReadBytePtr(DMAControl *dc)
{
bool bHighByte;
- bHighByte = !!dc->bHiByte;
- dc->bHiByte ^= 1;
+ bHighByte = !!dc->fHiByte;
+ dc->fHiByte ^= 1;
return bHighByte;
}
/* DMA address registers writes and reads. */
-static DECLCALLBACK(int) dmaWriteAddr(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT port,
- uint32_t u32, unsigned cb)
+static DECLCALLBACK(int) dmaWriteAddr(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT port, uint32_t u32, unsigned cb)
{
if (cb == 1)
{
@@ -257,8 +274,7 @@ static DECLCALLBACK(int) dmaWriteAddr(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT
return VINF_SUCCESS;
}
-static DECLCALLBACK(int) dmaReadAddr(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT port,
- uint32_t *pu32, unsigned cb)
+static DECLCALLBACK(int) dmaReadAddr(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT port, uint32_t *pu32, unsigned cb)
{
if (cb == 1)
{
@@ -342,7 +358,7 @@ static DECLCALLBACK(int) dmaWriteCtl(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT
break;
}
case CTL_W_CLRBPTR:
- dc->bHiByte = false;
+ dc->fHiByte = false;
break;
case CTL_W_MASTRCLR:
dmaClear(dc);
@@ -369,8 +385,7 @@ static DECLCALLBACK(int) dmaWriteCtl(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT
return VINF_SUCCESS;
}
-static DECLCALLBACK(int) dmaReadCtl(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT port,
- uint32_t *pu32, unsigned cb)
+static DECLCALLBACK(int) dmaReadCtl(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT port, uint32_t *pu32, unsigned cb)
{
if (cb == 1)
{
@@ -381,35 +396,36 @@ static DECLCALLBACK(int) dmaReadCtl(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT p
reg = ((port >> dc->is16bit) & 0x0f) - 8;
Assert((reg >= CTL_R_STAT && reg <= CTL_R_MASK));
- switch (reg) {
- case CTL_R_STAT:
- val = dc->u8Status;
- dc->u8Status &= 0xf0; /* A read clears all TCs. */
- break;
- case CTL_R_DMAREQ:
- val = (dc->u8Status >> 4) | 0xf0;
- break;
- case CTL_R_CMD:
- val = dc->u8Command;
- break;
- case CTL_R_MODE:
- val = dc->ChState[dc->u8ModeCtr].u8Mode | 3;
- dc->u8ModeCtr = (dc->u8ModeCtr + 1) & 3;
- case CTL_R_SETBPTR:
- dc->bHiByte = true;
- break;
- case CTL_R_TEMP:
- val = dc->u8Temp;
- break;
- case CTL_R_CLRMODE:
- dc->u8ModeCtr = 0;
- break;
- case CTL_R_MASK:
- val = dc->u8Mask;
- break;
- default:
- Assert(0);
- break;
+ switch (reg)
+ {
+ case CTL_R_STAT:
+ val = dc->u8Status;
+ dc->u8Status &= 0xf0; /* A read clears all TCs. */
+ break;
+ case CTL_R_DMAREQ:
+ val = (dc->u8Status >> 4) | 0xf0;
+ break;
+ case CTL_R_CMD:
+ val = dc->u8Command;
+ break;
+ case CTL_R_MODE:
+ val = dc->ChState[dc->u8ModeCtr].u8Mode | 3;
+ dc->u8ModeCtr = (dc->u8ModeCtr + 1) & 3;
+ case CTL_R_SETBPTR:
+ dc->fHiByte = true;
+ break;
+ case CTL_R_TEMP:
+ val = dc->u8Temp;
+ break;
+ case CTL_R_CLRMODE:
+ dc->u8ModeCtr = 0;
+ break;
+ case CTL_R_MASK:
+ val = dc->u8Mask;
+ break;
+ default:
+ Assert(0);
+ break;
}
Log(("Ctrl read: port %#06x, reg %#04x, data %#x\n", port, reg, val));
@@ -417,17 +433,15 @@ static DECLCALLBACK(int) dmaReadCtl(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT p
return VINF_SUCCESS;
}
- else
- return VERR_IOM_IOPORT_UNUSED;
+ return VERR_IOM_IOPORT_UNUSED;
}
-/* DMA page registers. There are 16 R/W page registers for compatibility with
+/** DMA page registers. There are 16 R/W page registers for compatibility with
* the IBM PC/AT; only some of those registers are used for DMA. The page register
* accessible via port 80h may be read to insert small delays or used as a scratch
* register by a BIOS.
*/
-static DECLCALLBACK(int) dmaReadPage(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT port,
- uint32_t *pu32, unsigned cb)
+static DECLCALLBACK(int) dmaReadPage(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT port, uint32_t *pu32, unsigned cb)
{
DMAControl *dc = (DMAControl *)pvUser;
int reg;
@@ -439,8 +453,9 @@ static DECLCALLBACK(int) dmaReadPage(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT
Log2(("Read %#x (byte) from page register %#x (channel %d)\n",
*pu32, port, DMAPG2CX(reg)));
return VINF_SUCCESS;
- }
- else if (cb == 2)
+ }
+
+ if (cb == 2)
{
reg = port & 7;
*pu32 = dc->au8Page[reg] | (dc->au8Page[(reg + 1) & 7] << 8);
@@ -448,12 +463,11 @@ static DECLCALLBACK(int) dmaReadPage(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT
*pu32, port, DMAPG2CX(reg)));
return VINF_SUCCESS;
}
- else
- return VERR_IOM_IOPORT_UNUSED;
+
+ return VERR_IOM_IOPORT_UNUSED;
}
-static DECLCALLBACK(int) dmaWritePage(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT port,
- uint32_t u32, unsigned cb)
+static DECLCALLBACK(int) dmaWritePage(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT port, uint32_t u32, unsigned cb)
{
DMAControl *dc = (DMAControl *)pvUser;
int reg;
@@ -467,7 +481,7 @@ static DECLCALLBACK(int) dmaWritePage(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT
Log2(("Wrote %#x to page register %#x (channel %d)\n",
u32, port, DMAPG2CX(reg)));
}
- else if (cb == 2)
+ else if (cb == 2)
{
Assert(!(u32 & ~0xffff)); /* Check for garbage in high bits. */
reg = port & 7;
@@ -486,11 +500,11 @@ static DECLCALLBACK(int) dmaWritePage(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT
return VINF_SUCCESS;
}
-/* EISA style high page registers, for extending the DMA addresses to cover
+/**
+ * EISA style high page registers, for extending the DMA addresses to cover
* the entire 32-bit address space.
*/
-static DECLCALLBACK(int) dmaReadHiPage(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT port,
- uint32_t *pu32, unsigned cb)
+static DECLCALLBACK(int) dmaReadHiPage(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT port, uint32_t *pu32, unsigned cb)
{
if (cb == 1)
{
@@ -503,12 +517,10 @@ static DECLCALLBACK(int) dmaReadHiPage(PPDMDEVINS pDevIns, void *pvUser, RTIOPOR
*pu32, port, DMAPG2CX(reg)));
return VINF_SUCCESS;
}
- else
- return VERR_IOM_IOPORT_UNUSED;
+ return VERR_IOM_IOPORT_UNUSED;
}
-static DECLCALLBACK(int) dmaWriteHiPage(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT port,
- uint32_t u32, unsigned cb)
+static DECLCALLBACK(int) dmaWriteHiPage(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT port, uint32_t u32, unsigned cb)
{
if (cb == 1)
{
@@ -530,10 +542,10 @@ static DECLCALLBACK(int) dmaWriteHiPage(PPDMDEVINS pDevIns, void *pvUser, RTIOPO
return VINF_SUCCESS;
}
-/* Perform any pending transfers on a single DMA channel. */
-static void dmaRunChannel(DMAState *s, int ctlidx, int chidx)
+/** Perform any pending transfers on a single DMA channel. */
+static void dmaRunChannel(DMAState *pThis, int ctlidx, int chidx)
{
- DMAControl *dc = &s->DMAC[ctlidx];
+ DMAControl *dc = &pThis->DMAC[ctlidx];
DMAChannel *ch = &dc->ChState[chidx];
uint32_t start_cnt, end_cnt;
int opmode;
@@ -546,22 +558,42 @@ static void dmaRunChannel(DMAState *s, int ctlidx, int chidx)
/* Addresses and counts are shifted for 16-bit channels. */
start_cnt = ch->u16CurCount << dc->is16bit;
- end_cnt = ch->pfnXferHandler(s->pDevIns, ch->pvUser, (ctlidx * 4) + chidx,
+ /* NB: The device is responsible for examining the DMA mode and not
+ * transferring more than it should if auto-init is not in use.
+ */
+ end_cnt = ch->pfnXferHandler(pThis->pDevIns, ch->pvUser, (ctlidx * 4) + chidx,
start_cnt, (ch->u16BaseCount + 1) << dc->is16bit);
ch->u16CurCount = end_cnt >> dc->is16bit;
+ /* Set the TC (Terminal Count) bit if transfer was completed. */
+ if (ch->u16CurCount == ch->u16BaseCount + 1)
+ switch (opmode)
+ {
+ case DMODE_DEMAND:
+ case DMODE_SINGLE:
+ case DMODE_BLOCK:
+ dc->u8Status |= RT_BIT(chidx);
+ Log3(("TC set for DMA channel %d\n", (ctlidx * 4) + chidx));
+ break;
+ default:
+ break;
+ }
Log3(("DMA position %d, size %d\n", end_cnt, (ch->u16BaseCount + 1) << dc->is16bit));
}
-static bool dmaRun(PPDMDEVINS pDevIns)
+/**
+ * @interface_method_impl{PDMDMAREG,pfnRun}
+ */
+static DECLCALLBACK(bool) dmaRun(PPDMDEVINS pDevIns)
{
- DMAState *s = PDMINS_2_DATA(pDevIns, DMAState *);
+ DMAState *pThis = PDMINS_2_DATA(pDevIns, DMAState *);
DMAControl *dc;
int ctlidx, chidx, mask;
+ PDMCritSectEnter(pDevIns->pCritSectRoR3, VERR_IGNORED);
/* Run all controllers and channels. */
for (ctlidx = 0; ctlidx < 2; ++ctlidx)
{
- dc = &s->DMAC[ctlidx];
+ dc = &pThis->DMAC[ctlidx];
/* If controller is disabled, don't even bother. */
if (dc->u8Command & CMD_DISABLE)
@@ -571,26 +603,32 @@ static bool dmaRun(PPDMDEVINS pDevIns)
{
mask = 1 << chidx;
if (!(dc->u8Mask & mask) && (dc->u8Status & (mask << 4)))
- dmaRunChannel(s, ctlidx, chidx);
+ dmaRunChannel(pThis, ctlidx, chidx);
}
}
+
+ PDMCritSectLeave(pDevIns->pCritSectRoR3);
return 0;
}
-static void dmaRegister(PPDMDEVINS pDevIns, unsigned channel,
- PFNDMATRANSFERHANDLER handler, void *pvUser)
+/**
+ * @interface_method_impl{PDMDMAREG,pfnRegister}
+ */
+static DECLCALLBACK(void) dmaRegister(PPDMDEVINS pDevIns, unsigned uChannel,
+ PFNDMATRANSFERHANDLER pfnTransferHandler, void *pvUser)
{
- DMAState *s = PDMINS_2_DATA(pDevIns, DMAState *);
- DMAChannel *ch = &s->DMAC[DMACH2C(channel)].ChState[channel & 3];
+ DMAState *pThis = PDMINS_2_DATA(pDevIns, DMAState *);
+ DMAChannel *ch = &pThis->DMAC[DMACH2C(uChannel)].ChState[uChannel & 3];
- LogFlow(("dmaRegister: s=%p channel=%u XferHandler=%p pvUser=%p\n",
- s, channel, handler, pvUser));
+ LogFlow(("dmaRegister: pThis=%p uChannel=%u pfnTransferHandler=%p pvUser=%p\n", pThis, uChannel, pfnTransferHandler, pvUser));
- ch->pfnXferHandler = handler;
+ PDMCritSectEnter(pDevIns->pCritSectRoR3, VERR_IGNORED);
+ ch->pfnXferHandler = pfnTransferHandler;
ch->pvUser = pvUser;
+ PDMCritSectLeave(pDevIns->pCritSectRoR3);
}
-/* Reverse the order of bytes in a memory buffer. */
+/** Reverse the order of bytes in a memory buffer. */
static void dmaReverseBuf8(void *buf, unsigned len)
{
uint8_t *pBeg, *pEnd;
@@ -606,7 +644,7 @@ static void dmaReverseBuf8(void *buf, unsigned len)
}
}
-/* Reverse the order of words in a memory buffer. */
+/** Reverse the order of words in a memory buffer. */
static void dmaReverseBuf16(void *buf, unsigned len)
{
uint16_t *pBeg, *pEnd;
@@ -624,52 +662,66 @@ static void dmaReverseBuf16(void *buf, unsigned len)
}
}
-static uint32_t dmaReadMemory(PPDMDEVINS pDevIns, unsigned channel,
- void *buf, uint32_t pos, uint32_t len)
+/**
+ * @interface_method_impl{PDMDMAREG,pfnReadMemory}
+ */
+static DECLCALLBACK(uint32_t) dmaReadMemory(PPDMDEVINS pDevIns, unsigned uChannel,
+ void *pvBuffer, uint32_t off, uint32_t cbBlock)
{
- DMAState *s = PDMINS_2_DATA(pDevIns, DMAState *);
- DMAControl *dc = &s->DMAC[DMACH2C(channel)];
- DMAChannel *ch = &dc->ChState[channel & 3];
+ DMAState *pThis = PDMINS_2_DATA(pDevIns, DMAState *);
+ DMAControl *dc = &pThis->DMAC[DMACH2C(uChannel)];
+ DMAChannel *ch = &dc->ChState[uChannel & 3];
uint32_t page, pagehi;
uint32_t addr;
- LogFlow(("dmaReadMemory: s=%p channel=%u buf=%p pos=%u len=%u\n",
- s, channel, buf, pos, len));
+ LogFlow(("dmaReadMemory: pThis=%p uChannel=%u pvBuffer=%p off=%u cbBlock=%u\n", pThis, uChannel, pvBuffer, off, cbBlock));
+
+ PDMCritSectEnter(pDevIns->pCritSectRoR3, VERR_IGNORED);
/* Build the address for this transfer. */
- page = dc->au8Page[DMACH2PG(channel)] & ~dc->is16bit;
- pagehi = dc->au8PageHi[DMACH2PG(channel)];
+ page = dc->au8Page[DMACH2PG(uChannel)] & ~dc->is16bit;
+ pagehi = dc->au8PageHi[DMACH2PG(uChannel)];
addr = (pagehi << 24) | (page << 16) | (ch->u16CurAddr << dc->is16bit);
if (IS_MODE_DEC(ch->u8Mode))
{
- PDMDevHlpPhysRead(s->pDevIns, addr - pos - len, buf, len);
+ PDMDevHlpPhysRead(pThis->pDevIns, addr - off - cbBlock, pvBuffer, cbBlock);
if (dc->is16bit)
- dmaReverseBuf16(buf, len);
+ dmaReverseBuf16(pvBuffer, cbBlock);
else
- dmaReverseBuf8(buf, len);
+ dmaReverseBuf8(pvBuffer, cbBlock);
}
else
- PDMDevHlpPhysRead(s->pDevIns, addr + pos, buf, len);
+ PDMDevHlpPhysRead(pThis->pDevIns, addr + off, pvBuffer, cbBlock);
- return len;
+ PDMCritSectLeave(pDevIns->pCritSectRoR3);
+ return cbBlock;
}
-static uint32_t dmaWriteMemory(PPDMDEVINS pDevIns, unsigned channel,
- const void *buf, uint32_t pos, uint32_t len)
+/**
+ * @interface_method_impl{PDMDMAREG,pfnWriteMemory}
+ */
+static DECLCALLBACK(uint32_t) dmaWriteMemory(PPDMDEVINS pDevIns, unsigned uChannel,
+ const void *pvBuffer, uint32_t off, uint32_t cbBlock)
{
- DMAState *s = PDMINS_2_DATA(pDevIns, DMAState *);
- DMAControl *dc = &s->DMAC[DMACH2C(channel)];
- DMAChannel *ch = &dc->ChState[channel & 3];
+ DMAState *pThis = PDMINS_2_DATA(pDevIns, DMAState *);
+ DMAControl *dc = &pThis->DMAC[DMACH2C(uChannel)];
+ DMAChannel *ch = &dc->ChState[uChannel & 3];
uint32_t page, pagehi;
uint32_t addr;
- LogFlow(("dmaWriteMemory: s=%p channel=%u buf=%p pos=%u len=%u\n",
- s, channel, buf, pos, len));
+ LogFlow(("dmaWriteMemory: pThis=%p uChannel=%u pvBuffer=%p off=%u cbBlock=%u\n", pThis, uChannel, pvBuffer, off, cbBlock));
+ if (GET_MODE_XTYP(ch->u8Mode) == DTYPE_VERIFY)
+ {
+ Log(("DMA verify transfer, ignoring write.\n"));
+ return cbBlock;
+ }
+
+ PDMCritSectEnter(pDevIns->pCritSectRoR3, VERR_IGNORED);
/* Build the address for this transfer. */
- page = dc->au8Page[DMACH2PG(channel)] & ~dc->is16bit;
- pagehi = dc->au8PageHi[DMACH2PG(channel)];
+ page = dc->au8Page[DMACH2PG(uChannel)] & ~dc->is16bit;
+ pagehi = dc->au8PageHi[DMACH2PG(uChannel)];
addr = (pagehi << 24) | (page << 16) | (ch->u16CurAddr << dc->is16bit);
if (IS_MODE_DEC(ch->u8Mode))
@@ -678,90 +730,98 @@ static uint32_t dmaWriteMemory(PPDMDEVINS pDevIns, unsigned channel,
Assert(0);
#if 0
if (dc->is16bit)
- dmaReverseBuf16(buf, len);
+ dmaReverseBuf16(pvBuffer, cbBlock);
else
- dmaReverseBuf8(buf, len);
+ dmaReverseBuf8(pvBuffer, cbBlock);
#endif
- PDMDevHlpPhysWrite(s->pDevIns, addr - pos - len, buf, len);
+ PDMDevHlpPhysWrite(pThis->pDevIns, addr - off - cbBlock, pvBuffer, cbBlock);
}
else
- PDMDevHlpPhysWrite(s->pDevIns, addr + pos, buf, len);
+ PDMDevHlpPhysWrite(pThis->pDevIns, addr + off, pvBuffer, cbBlock);
- return len;
+ PDMCritSectLeave(pDevIns->pCritSectRoR3);
+ return cbBlock;
}
-static void dmaSetDREQ(PPDMDEVINS pDevIns, unsigned channel, unsigned level)
+/**
+ * @interface_method_impl{PDMDMAREG,pfnSetDREQ}
+ */
+static DECLCALLBACK(void) dmaSetDREQ(PPDMDEVINS pDevIns, unsigned uChannel, unsigned uLevel)
{
- DMAState *s = PDMINS_2_DATA(pDevIns, DMAState *);
- DMAControl *dc = &s->DMAC[DMACH2C(channel)];
+ DMAState *pThis = PDMINS_2_DATA(pDevIns, DMAState *);
+ DMAControl *dc = &pThis->DMAC[DMACH2C(uChannel)];
int chidx;
- LogFlow(("dmaSetDREQ: s=%p channel=%u level=%u\n", s, channel, level));
+ LogFlow(("dmaSetDREQ: pThis=%p uChannel=%u uLevel=%u\n", pThis, uChannel, uLevel));
- chidx = channel & 3;
- if (level)
+ PDMCritSectEnter(pDevIns->pCritSectRoR3, VERR_IGNORED);
+ chidx = uChannel & 3;
+ if (uLevel)
dc->u8Status |= 1 << (chidx + 4);
else
dc->u8Status &= ~(1 << (chidx + 4));
+ PDMCritSectLeave(pDevIns->pCritSectRoR3);
}
-static uint8_t dmaGetChannelMode(PPDMDEVINS pDevIns, unsigned channel)
+/**
+ * @interface_method_impl{PDMDMAREG,pfnGetChannelMode}
+ */
+static DECLCALLBACK(uint8_t) dmaGetChannelMode(PPDMDEVINS pDevIns, unsigned uChannel)
{
- DMAState *s = PDMINS_2_DATA(pDevIns, DMAState *);
+ DMAState *pThis = PDMINS_2_DATA(pDevIns, DMAState *);
- LogFlow(("dmaGetChannelMode: s=%p channel=%u\n", s, channel));
+ LogFlow(("dmaGetChannelMode: pThis=%p uChannel=%u\n", pThis, uChannel));
- return s->DMAC[DMACH2C(channel)].ChState[channel & 3].u8Mode;
+ PDMCritSectEnter(pDevIns->pCritSectRoR3, VERR_IGNORED);
+ uint8_t u8Mode = pThis->DMAC[DMACH2C(uChannel)].ChState[uChannel & 3].u8Mode;
+ PDMCritSectLeave(pDevIns->pCritSectRoR3);
+ return u8Mode;
}
+
+/**
+ * @interface_method_impl{PDMDEVREG,pfnReset}
+ */
static void dmaReset(PPDMDEVINS pDevIns)
{
- DMAState *s = PDMINS_2_DATA(pDevIns, DMAState *);
+ DMAState *pThis = PDMINS_2_DATA(pDevIns, DMAState *);
- LogFlow(("dmaReset: s=%p\n", s));
+ LogFlow(("dmaReset: pThis=%p\n", pThis));
/* NB: The page and address registers are unaffected by a reset
* and in an undefined state after power-up.
*/
- dmaClear(&s->DMAC[0]);
- dmaClear(&s->DMAC[1]);
+ dmaClear(&pThis->DMAC[0]);
+ dmaClear(&pThis->DMAC[1]);
}
-/* Register DMA I/O port handlers. */
-static void dmaIORegister(PPDMDEVINS pDevIns, bool bHighPage)
+/** Register DMA I/O port handlers. */
+static void dmaIORegister(PPDMDEVINS pDevIns, bool fHighPage)
{
- DMAState *s = PDMINS_2_DATA(pDevIns, DMAState *);
- DMAControl *dc8;
- DMAControl *dc16;
-
- dc8 = &s->DMAC[0];
- dc16 = &s->DMAC[1];
+ DMAState *pThis = PDMINS_2_DATA(pDevIns, DMAState *);
+ DMAControl *dc8 = &pThis->DMAC[0];
+ DMAControl *dc16 = &pThis->DMAC[1];
dc8->is16bit = false;
dc16->is16bit = true;
/* Base and current address for each channel. */
- PDMDevHlpIOPortRegister(s->pDevIns, 0x00, 8, dc8,
- dmaWriteAddr, dmaReadAddr, NULL, NULL, "DMA8 Address");
- PDMDevHlpIOPortRegister(s->pDevIns, 0xC0, 16, dc16,
- dmaWriteAddr, dmaReadAddr, NULL, NULL, "DMA16 Address");
+ PDMDevHlpIOPortRegister(pThis->pDevIns, 0x00, 8, dc8, dmaWriteAddr, dmaReadAddr, NULL, NULL, "DMA8 Address");
+ PDMDevHlpIOPortRegister(pThis->pDevIns, 0xC0, 16, dc16, dmaWriteAddr, dmaReadAddr, NULL, NULL, "DMA16 Address");
+
/* Control registers for both DMA controllers. */
- PDMDevHlpIOPortRegister(s->pDevIns, 0x08, 8, dc8,
- dmaWriteCtl, dmaReadCtl, NULL, NULL, "DMA8 Control");
- PDMDevHlpIOPortRegister(s->pDevIns, 0xD0, 16, dc16,
- dmaWriteCtl, dmaReadCtl, NULL, NULL, "DMA16 Control");
+ PDMDevHlpIOPortRegister(pThis->pDevIns, 0x08, 8, dc8, dmaWriteCtl, dmaReadCtl, NULL, NULL, "DMA8 Control");
+ PDMDevHlpIOPortRegister(pThis->pDevIns, 0xD0, 16, dc16, dmaWriteCtl, dmaReadCtl, NULL, NULL, "DMA16 Control");
+
/* Page registers for each channel (plus a few unused ones). */
- PDMDevHlpIOPortRegister(s->pDevIns, 0x80, 8, dc8,
- dmaWritePage, dmaReadPage, NULL, NULL, "DMA8 Page");
- PDMDevHlpIOPortRegister(s->pDevIns, 0x88, 8, dc16,
- dmaWritePage, dmaReadPage, NULL, NULL, "DMA16 Page");
+ PDMDevHlpIOPortRegister(pThis->pDevIns, 0x80, 8, dc8, dmaWritePage, dmaReadPage, NULL, NULL, "DMA8 Page");
+ PDMDevHlpIOPortRegister(pThis->pDevIns, 0x88, 8, dc16, dmaWritePage, dmaReadPage, NULL, NULL, "DMA16 Page");
+
/* Optional EISA style high page registers (address bits 24-31). */
- if (bHighPage)
+ if (fHighPage)
{
- PDMDevHlpIOPortRegister(s->pDevIns, 0x480, 8, dc8,
- dmaWriteHiPage, dmaReadHiPage, NULL, NULL, "DMA8 Page High");
- PDMDevHlpIOPortRegister(s->pDevIns, 0x488, 8, dc16,
- dmaWriteHiPage, dmaReadHiPage, NULL, NULL, "DMA16 Page High");
+ PDMDevHlpIOPortRegister(pThis->pDevIns, 0x480, 8, dc8, dmaWriteHiPage, dmaReadHiPage, NULL, NULL, "DMA8 Page High");
+ PDMDevHlpIOPortRegister(pThis->pDevIns, 0x488, 8, dc16, dmaWriteHiPage, dmaReadHiPage, NULL, NULL, "DMA16 Page High");
}
}
@@ -772,7 +832,7 @@ static void dmaSaveController(PSSMHANDLE pSSMHandle, DMAControl *dc)
/* Save controller state... */
SSMR3PutU8(pSSMHandle, dc->u8Command);
SSMR3PutU8(pSSMHandle, dc->u8Mask);
- SSMR3PutU8(pSSMHandle, dc->bHiByte);
+ SSMR3PutU8(pSSMHandle, dc->fHiByte);
SSMR3PutU32(pSSMHandle, dc->is16bit);
SSMR3PutU8(pSSMHandle, dc->u8Status);
SSMR3PutU8(pSSMHandle, dc->u8Temp);
@@ -802,7 +862,7 @@ static int dmaLoadController(PSSMHANDLE pSSMHandle, DMAControl *dc, int version)
SSMR3GetU8(pSSMHandle, &dc->u8Command);
SSMR3GetU8(pSSMHandle, &dc->u8Mask);
SSMR3GetU8(pSSMHandle, &u8val);
- dc->bHiByte = !!u8val;
+ dc->fHiByte = !!u8val;
SSMR3GetU32(pSSMHandle, &dc->is16bit);
if (version > DMA_SAVESTATE_OLD)
{
@@ -849,25 +909,26 @@ static int dmaLoadController(PSSMHANDLE pSSMHandle, DMAControl *dc, int version)
return 0;
}
+/** @callback_method_impl{FNSSMDEVSAVEEXEC} */
static DECLCALLBACK(int) dmaSaveExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSMHandle)
{
- DMAState *s = PDMINS_2_DATA(pDevIns, DMAState *);
+ DMAState *pThis = PDMINS_2_DATA(pDevIns, DMAState *);
- dmaSaveController(pSSMHandle, &s->DMAC[0]);
- dmaSaveController(pSSMHandle, &s->DMAC[1]);
+ dmaSaveController(pSSMHandle, &pThis->DMAC[0]);
+ dmaSaveController(pSSMHandle, &pThis->DMAC[1]);
return VINF_SUCCESS;
}
-static DECLCALLBACK(int) dmaLoadExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSMHandle,
- uint32_t uVersion, uint32_t uPass)
+/** @callback_method_impl{FNSSMDEVLOADEXEC} */
+static DECLCALLBACK(int) dmaLoadExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSMHandle, uint32_t uVersion, uint32_t uPass)
{
- DMAState *s = PDMINS_2_DATA(pDevIns, DMAState *);
+ DMAState *pThis = PDMINS_2_DATA(pDevIns, DMAState *);
AssertMsgReturn(uVersion <= DMA_SAVESTATE_CURRENT, ("%d\n", uVersion), VERR_SSM_UNSUPPORTED_DATA_UNIT_VERSION);
Assert(uPass == SSM_PASS_FINAL); NOREF(uPass);
- dmaLoadController(pSSMHandle, &s->DMAC[0], uVersion);
- return dmaLoadController(pSSMHandle, &s->DMAC[1], uVersion);
+ dmaLoadController(pSSMHandle, &pThis->DMAC[0], uVersion);
+ return dmaLoadController(pSSMHandle, &pThis->DMAC[1], uVersion);
}
/**
@@ -875,12 +936,12 @@ static DECLCALLBACK(int) dmaLoadExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSMHandle,
*/
static DECLCALLBACK(int) dmaConstruct(PPDMDEVINS pDevIns, int iInstance, PCFGMNODE pCfg)
{
- DMAState *s = PDMINS_2_DATA(pDevIns, DMAState *);
+ DMAState *pThis = PDMINS_2_DATA(pDevIns, DMAState *);
bool bHighPage = false;
PDMDMACREG reg;
int rc;
- s->pDevIns = pDevIns;
+ pThis->pDevIns = pDevIns;
/*
* Validate configuration.
@@ -905,12 +966,11 @@ static DECLCALLBACK(int) dmaConstruct(PPDMDEVINS pDevIns, int iInstance, PCFGMNO
reg.pfnSetDREQ = dmaSetDREQ;
reg.pfnGetChannelMode = dmaGetChannelMode;
- rc = PDMDevHlpDMACRegister(pDevIns, &reg, &s->pHlp);
+ rc = PDMDevHlpDMACRegister(pDevIns, &reg, &pThis->pHlp);
if (RT_FAILURE (rc))
return rc;
- rc = PDMDevHlpSSMRegister(pDevIns, DMA_SAVESTATE_CURRENT, sizeof(*s),
- dmaSaveExec, dmaLoadExec);
+ rc = PDMDevHlpSSMRegister(pDevIns, DMA_SAVESTATE_CURRENT, sizeof(*pThis), dmaSaveExec, dmaLoadExec);
if (RT_FAILURE(rc))
return rc;
@@ -946,7 +1006,7 @@ const PDMDEVREG g_DeviceDMA =
NULL,
/* pfnRelocate */
NULL,
- /* pfnIOCtl */
+ /* pfnMemSetup */
NULL,
/* pfnPowerOn */
NULL,