* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
-#include <stdio.h>
-#include <stdlib.h>
-#include <inttypes.h>
-
-#include "cpu.h"
#include "vl.h"
#define log(...) fprintf (stderr, "dma: " __VA_ARGS__)
#define ldebug(...)
#endif
-#define MEM_REAL(addr) ((addr)+(uint32_t)(phys_ram_base))
#define LENOFA(a) ((int) (sizeof(a)/sizeof(a[0])))
struct dma_regs {
uint8_t page;
uint8_t dack;
uint8_t eop;
- DMA_read_handler read_handler;
- DMA_misc_handler misc_handler;
+ DMA_transfer_handler transfer_handler;
+ void *opaque;
};
#define ADDR 0
};
-static void write_page (CPUState *env, uint32_t nport, uint32_t data)
+static void write_page (void *opaque, uint32_t nport, uint32_t data)
{
int ichan;
int ncont;
return ff;
}
-static uint32_t read_chan (CPUState *env, uint32_t nport)
+static uint32_t read_chan (void *opaque, uint32_t nport)
{
int ff;
int ncont, ichan, nreg;
return (val >> (ncont + (ff << 3))) & 0xff;
}
-static void write_chan (uint32_t nport, int size, uint32_t data)
+static void write_chan (void *opaque, uint32_t nport, uint32_t data)
{
int ncont, ichan, nreg;
struct dma_regs *r;
nreg = (nport >> ncont) & 1;
r = dma_controllers[ncont].regs + ichan;
- if (2 == size) {
- r->base[nreg] = data;
+ if (getff (ncont)) {
+ r->base[nreg] = (r->base[nreg] & 0xff) | ((data << 8) & 0xff00);
init_chan (ncont, ichan);
+ } else {
+ r->base[nreg] = (r->base[nreg] & 0xff00) | (data & 0xff);
}
- else {
- if (getff (ncont)) {
- r->base[nreg] = (r->base[nreg] & 0xff) | ((data << 8) & 0xff00);
- init_chan (ncont, ichan);
- }
- else {
- r->base[nreg] = (r->base[nreg] & 0xff00) | (data & 0xff);
- }
- }
-}
-static void write_chanb (CPUState *env, uint32_t nport, uint32_t data)
-{
- write_chan (nport, 1, data);
-}
-
-static void write_chanw (CPUState *env, uint32_t nport, uint32_t data)
-{
- write_chan (nport, 2, data);
}
-static void write_cont (CPUState *env, uint32_t nport, uint32_t data)
+static void write_cont (void *opaque, uint32_t nport, uint32_t data)
{
int iport, ichan, ncont;
struct dma_cont *d;
{
struct dma_regs *r;
int n;
- int irq;
- uint32_t addr;
+ target_ulong addr;
/* int ai, dir; */
r = dma_controllers[ncont].regs + ichan;
/* ai = r->mode & 16; */
/* dir = r->mode & 32 ? -1 : 1; */
- addr = MEM_REAL ((r->page << 16) | r->now[ADDR]);
-
- irq = -1;
- n = r->read_handler (addr, (r->base[COUNT] << ncont) + (1 << ncont), &irq);
+ addr = (r->page << 16) | r->now[ADDR];
+ n = r->transfer_handler (r->opaque, addr,
+ (r->base[COUNT] << ncont) + (1 << ncont));
r->now[COUNT] = n;
- ldebug ("dma_pos %d irq %d size %d\n",
- n, irq, (r->base[1] << ncont) + (1 << ncont));
-
- if (-1 != irq) {
- pic_set_irq (irq, 1);
- }
+ ldebug ("dma_pos %d size %d\n",
+ n, (r->base[1] << ncont) + (1 << ncont));
}
void DMA_run (void)
{
- static int in_dma;
struct dma_cont *d;
int icont, ichan;
- if (in_dma) {
- log ("attempt to re-enter dma\n");
- return;
- }
-
- in_dma = 1;
d = dma_controllers;
for (icont = 0; icont < 2; icont++, d++) {
channel_run (icont, ichan);
}
}
- in_dma = 0;
}
void DMA_register_channel (int nchan,
- DMA_read_handler read_handler,
- DMA_misc_handler misc_handler)
+ DMA_transfer_handler transfer_handler,
+ void *opaque)
{
struct dma_regs *r;
int ichan, ncont;
ichan = nchan & 3;
r = dma_controllers[ncont].regs + ichan;
- r->read_handler = read_handler;
- r->misc_handler = misc_handler;
+ r->transfer_handler = transfer_handler;
+ r->opaque = opaque;
+}
+
+/* request the emulator to transfer a new DMA memory block ASAP */
+void DMA_schedule(int nchan)
+{
+ cpu_interrupt(cpu_single_env, CPU_INTERRUPT_EXIT);
}
void DMA_init (void)
int page_port_list[] = { 0x1, 0x2, 0x3, 0x7 };
for (i = 0; i < 8; i++) {
- register_ioport_write (i, 1, write_chanb, 1);
- register_ioport_write (i, 1, write_chanw, 2);
+ register_ioport_write (i, 1, 1, write_chan, NULL);
- register_ioport_write (0xc0 + (i << 1), 1, write_chanb, 1);
- register_ioport_write (0xc0 + (i << 1), 1, write_chanw, 2);
+ register_ioport_write (0xc0 + (i << 1), 1, 1, write_chan, NULL);
- register_ioport_read (i, 1, read_chan, 1);
- register_ioport_read (0xc0 + (i << 1), 1, read_chan, 2);
+ register_ioport_read (i, 1, 1, read_chan, NULL);
+ register_ioport_read (0xc0 + (i << 1), 1, 1, read_chan, NULL);
}
for (i = 0; i < LENOFA (page_port_list); i++) {
- register_ioport_write (page_port_list[i] + 0x80, 1, write_page, 1);
- register_ioport_write (page_port_list[i] + 0x88, 1, write_page, 1);
+ register_ioport_write (page_port_list[i] + 0x80, 1, 1, write_page, NULL);
+ register_ioport_write (page_port_list[i] + 0x88, 1, 1, write_page, NULL);
}
for (i = 0; i < 8; i++) {
- register_ioport_write (i + 8, 1, write_cont, 1);
- register_ioport_write (0xd0 + (i << 1), 1, write_cont, 1);
+ register_ioport_write (i + 8, 1, 1, write_cont, NULL);
+ register_ioport_write (0xd0 + (i << 1), 1, 1, write_cont, NULL);
}
- write_cont (NULL, 0xd, 0);
- write_cont (NULL, 0xdd, 0);
+ write_cont (NULL, 0x0d, 0);
+ write_cont (NULL, 0xda, 0);
}