Index: hw/fdc.c =================================================================== --- hw/fdc.c (revision 5771) +++ hw/fdc.c (working copy) @@ -471,7 +471,12 @@ uint8_t version; /* HW */ qemu_irq irq; - int dma_chann; + fdcdma_memory_read_write dma_memory_read; + fdcdma_memory_read_write dma_memory_write; + fdcdma_hold_release dma_hold; + fdcdma_hold_release dma_release; + void *dma_opaque; + int i8257_dma_chann; target_phys_addr_t io_base; /* Controller state */ QEMUTimer *result_timer; @@ -771,7 +776,7 @@ fdctrl->sra |= FD_SRA_nDRV2; fdctrl->cur_drv = 0; fdctrl->dor = FD_DOR_nRESET; - fdctrl->dor |= (fdctrl->dma_chann != -1) ? FD_DOR_DMAEN : 0; + fdctrl->dor |= (fdctrl->dma_memory_read && fdctrl->dma_memory_write) ? FD_DOR_DMAEN : 0; fdctrl->msr = FD_MSR_RQM; /* FIFO state */ fdctrl->data_pos = 0; @@ -1068,8 +1073,8 @@ fdctrl->fifo[5] = cur_drv->sect; fdctrl->fifo[6] = FD_SECTOR_SC; fdctrl->data_dir = FD_DIR_READ; - if (!(fdctrl->msr & FD_MSR_NONDMA)) { - DMA_release_DREQ(fdctrl->dma_chann); + if (!(fdctrl->msr & FD_MSR_NONDMA) && fdctrl->dma_release) { + fdctrl->dma_release(fdctrl->dma_opaque); } fdctrl->msr |= FD_MSR_RQM | FD_MSR_DIO; fdctrl->msr &= ~FD_MSR_NONDMA; @@ -1144,29 +1149,15 @@ } fdctrl->eot = fdctrl->fifo[6]; if (fdctrl->dor & FD_DOR_DMAEN) { - int dma_mode; - /* DMA transfer are enabled. Check if DMA channel is well programmed */ - dma_mode = DMA_get_channel_mode(fdctrl->dma_chann); - dma_mode = (dma_mode >> 2) & 3; - FLOPPY_DPRINTF("dma_mode=%d direction=%d (%d - %d)\n", - dma_mode, direction, - (128 << fdctrl->fifo[5]) * - (cur_drv->last_sect - ks + 1), fdctrl->data_len); - if (((direction == FD_DIR_SCANE || direction == FD_DIR_SCANL || - direction == FD_DIR_SCANH) && dma_mode == 0) || - (direction == FD_DIR_WRITE && dma_mode == 2) || - (direction == FD_DIR_READ && dma_mode == 1)) { - /* No access is allowed until DMA transfer has completed */ + /* DMA transfer are enabled */ + if (fdctrl->dma_hold) { + fdctrl->dma_hold(fdctrl->dma_opaque); + } else { + /* Do the transfer synchronously... */ fdctrl->msr &= ~FD_MSR_RQM; - /* Now, we just have to wait for the DMA controller to - * recall us... - */ - DMA_hold_DREQ(fdctrl->dma_chann); - DMA_schedule(fdctrl->dma_chann); - return; - } else { - FLOPPY_ERROR("dma_mode=%d direction=%d\n", dma_mode, direction); + fdctrl_transfer_handler(fdctrl, -1, 0, fdctrl->data_len); } + return; } FLOPPY_DPRINTF("start non-DMA transfer\n"); fdctrl->msr |= FD_MSR_NONDMA; @@ -1174,8 +1165,6 @@ fdctrl->msr |= FD_MSR_DIO; /* IO based transfer: calculate len */ fdctrl_raise_irq(fdctrl, 0x00); - - return; } /* Prepare a transfer of deleted data */ @@ -1241,13 +1230,11 @@ switch (fdctrl->data_dir) { case FD_DIR_READ: /* READ commands */ - DMA_write_memory (nchan, fdctrl->fifo + rel_pos, - fdctrl->data_pos, len); + fdctrl->dma_memory_write(fdctrl->dma_opaque, fdctrl->fifo + rel_pos, len); break; case FD_DIR_WRITE: /* WRITE commands */ - DMA_read_memory (nchan, fdctrl->fifo + rel_pos, - fdctrl->data_pos, len); + fdctrl->dma_memory_read(fdctrl->dma_opaque, fdctrl->fifo + rel_pos, len); if (bdrv_write(cur_drv->bs, fd_sector(cur_drv), fdctrl->fifo, 1) < 0) { FLOPPY_ERROR("writing sector %d\n", fd_sector(cur_drv)); @@ -1260,7 +1247,7 @@ { uint8_t tmpbuf[FD_SECTOR_LEN]; int ret; - DMA_read_memory (nchan, tmpbuf, fdctrl->data_pos, len); + fdctrl->dma_memory_read(fdctrl->dma_opaque, tmpbuf, len); ret = memcmp(tmpbuf, fdctrl->fifo + rel_pos, len); if (ret == 0) { status2 = FD_SR2_SEH; @@ -1833,7 +1820,12 @@ } /* Init functions */ -static fdctrl_t *fdctrl_init_common (qemu_irq irq, int dma_chann, +static fdctrl_t *fdctrl_init_common (qemu_irq irq, + fdcdma_memory_read_write dma_memory_read, + fdcdma_memory_read_write dma_memory_write, + fdcdma_hold_release dma_hold, + fdcdma_hold_release dma_release, + void *dma_opaque, target_phys_addr_t io_base, BlockDriverState **fds) { @@ -1862,12 +1854,13 @@ fdctrl->version = 0x90; /* Intel 82078 controller */ fdctrl->irq = irq; - fdctrl->dma_chann = dma_chann; + fdctrl->dma_memory_read = dma_memory_read; + fdctrl->dma_memory_write = dma_memory_write; + fdctrl->dma_hold = dma_hold; + fdctrl->dma_release = dma_release; + fdctrl->dma_opaque = dma_opaque; fdctrl->io_base = io_base; fdctrl->config = FD_CONFIG_EIS | FD_CONFIG_EFIFO; /* Implicit seek, polling & FIFO enabled */ - if (fdctrl->dma_chann != -1) { - DMA_register_channel(dma_chann, &fdctrl_transfer_handler, fdctrl); - } for (i = 0; i < MAX_FD; i++) { fd_init(&fdctrl->drives[i], fds[i]); } @@ -1881,14 +1874,21 @@ return fdctrl; } -fdctrl_t *fdctrl_init (qemu_irq irq, int dma_chann, int mem_mapped, +fdctrl_t *fdctrl_init (qemu_irq irq, + fdcdma_memory_read_write dma_memory_read, + fdcdma_memory_read_write dma_memory_write, + fdcdma_hold_release dma_hold, + fdcdma_hold_release dma_release, + void *dma_opaque, int mem_mapped, target_phys_addr_t io_base, BlockDriverState **fds) { fdctrl_t *fdctrl; int io_mem; - fdctrl = fdctrl_init_common(irq, dma_chann, io_base, fds); + fdctrl = fdctrl_init_common(irq, dma_memory_read, dma_memory_write, + dma_hold, dma_release, + dma_opaque, io_base, fds); fdctrl->sun4m = 0; if (mem_mapped) { @@ -1915,7 +1915,7 @@ fdctrl_t *fdctrl; int io_mem; - fdctrl = fdctrl_init_common(irq, -1, io_base, fds); + fdctrl = fdctrl_init_common(irq, NULL, NULL, NULL, NULL, NULL, io_base, fds); fdctrl->sun4m = 1; io_mem = cpu_register_io_memory(0, fdctrl_mem_read_strict, fdctrl_mem_write_strict, @@ -1925,3 +1925,81 @@ return fdctrl; } + +static void i8257_dma_read(void *opaque, uint8_t *buf, int len) +{ + fdctrl_t *fdctrl = opaque; + DMA_read_memory(fdctrl->i8257_dma_chann, buf, fdctrl->data_pos, len); +} + +static void i8257_dma_write(void *opaque, uint8_t *buf, int len) +{ + fdctrl_t *fdctrl = opaque; + DMA_write_memory(fdctrl->i8257_dma_chann, buf, fdctrl->data_pos, len); +} + +static void i8257_dma_hold(void *opaque) +{ + fdctrl_t *fdctrl = opaque; + int dma_mode; + int direction = fdctrl->data_dir; + + /* DMA transfer are enabled. Check if DMA channel is well programmed */ + dma_mode = DMA_get_channel_mode(fdctrl->i8257_dma_chann); + dma_mode = (dma_mode >> 2) & 3; + FLOPPY_DPRINTF("dma_mode=%d direction=%d (%d - %d)\n", + dma_mode, direction, + (128 << fdctrl->fifo[5]) * + (cur_drv->last_sect - fdctrl->fifo[4] + 1), fdctrl->data_len); + if (((direction == FD_DIR_SCANE || direction == FD_DIR_SCANL || + direction == FD_DIR_SCANH) && dma_mode == 0) || + (direction == FD_DIR_WRITE && dma_mode == 2) || + (direction == FD_DIR_READ && dma_mode == 1)) { + /* No access is allowed until DMA transfer has completed */ + fdctrl->msr &= ~FD_MSR_RQM; + /* Now, we just have to wait for the DMA controller to + * recall us... + */ + DMA_hold_DREQ(fdctrl->i8257_dma_chann); + DMA_schedule(fdctrl->i8257_dma_chann); + } else { + FLOPPY_ERROR("dma_mode=%d direction=%d\n", dma_mode, direction); + } +} + +static void i8257_dma_release(void *opaque) +{ + fdctrl_t *fdctrl = opaque; + DMA_release_DREQ(fdctrl->i8257_dma_chann); +} + +fdctrl_t *fdctrl_i8257_init (qemu_irq irq, int i8257_dma_chann, + int mem_mapped, + target_phys_addr_t io_base, + BlockDriverState **fds) +{ + fdcdma_memory_read_write dma_memory_read = NULL; + fdcdma_memory_read_write dma_memory_write = NULL; + fdcdma_hold_release dma_hold = NULL; + fdcdma_hold_release dma_release = NULL; + fdctrl_t *fdctrl; + + if (i8257_dma_chann != -1) { + dma_memory_read = i8257_dma_read; + dma_memory_write = i8257_dma_write; + dma_hold = i8257_dma_hold; + dma_release = i8257_dma_release; + } + + fdctrl = fdctrl_init(irq, dma_memory_read, dma_memory_write, + i8257_dma_hold, i8257_dma_release, NULL, + mem_mapped, io_base, fds); + + if (i8257_dma_chann != -1) { + fdctrl->dma_opaque = fdctrl; + fdctrl->i8257_dma_chann = i8257_dma_chann; + DMA_register_channel(fdctrl->i8257_dma_chann, &fdctrl_transfer_handler, fdctrl); + } + + return fdctrl; +} \ No newline at end of file Index: hw/fdc.h =================================================================== --- hw/fdc.h (revision 5771) +++ hw/fdc.h (working copy) @@ -3,9 +3,20 @@ typedef struct fdctrl_t fdctrl_t; -fdctrl_t *fdctrl_init (qemu_irq irq, int dma_chann, int mem_mapped, +typedef void (*fdcdma_memory_read_write)(void *opaque, uint8_t *buf, int len); +typedef void (*fdcdma_hold_release)(void *opaque); +fdctrl_t *fdctrl_init (qemu_irq irq, + fdcdma_memory_read_write dma_memory_read, + fdcdma_memory_read_write dma_memory_write, + fdcdma_hold_release dma_hold, + fdcdma_hold_release dma_release, + void *dma_opaque, int mem_mapped, target_phys_addr_t io_base, BlockDriverState **fds); +fdctrl_t *fdctrl_i8257_init (qemu_irq irq, int i8257_dma_chann, + int mem_mapped, + target_phys_addr_t io_base, + BlockDriverState **fds); fdctrl_t *sun4m_fdctrl_init (qemu_irq irq, target_phys_addr_t io_base, BlockDriverState **fds, qemu_irq *fdc_tc); int fdctrl_get_drive_type(fdctrl_t *fdctrl, int drive_num); Index: hw/mips_jazz.c =================================================================== --- hw/mips_jazz.c (revision 5771) +++ hw/mips_jazz.c (working copy) @@ -221,7 +221,7 @@ else fds[n] = NULL; } - fdctrl_init(rc4030[1], 0, 1, 0x80003000, fds); + fdctrl_init(rc4030[1], NULL, NULL, NULL, NULL, NULL, 1, 0x80003000, fds); /* Real time clock */ rtc_init(0x70, i8259[8]); Index: hw/mips_malta.c =================================================================== --- hw/mips_malta.c (revision 5771) +++ hw/mips_malta.c (working copy) @@ -929,7 +929,7 @@ else fd[i] = NULL; } - floppy_controller = fdctrl_init(i8259[6], 2, 0, 0x3f0, fd); + floppy_controller = fdctrl_i8257_init(i8259[6], 2, 0, 0x3f0, fd); /* Sound card */ #ifdef HAS_AUDIO Index: hw/pc.c =================================================================== --- hw/pc.c (revision 5771) +++ hw/pc.c (working copy) @@ -1052,7 +1052,7 @@ else fd[i] = NULL; } - floppy_controller = fdctrl_init(i8259[6], 2, 0, 0x3f0, fd); + floppy_controller = fdctrl_i8257_init(i8259[6], 2, 0, 0x3f0, fd); cmos_init(below_4g_mem_size, above_4g_mem_size, boot_device, hd); Index: hw/ppc_prep.c =================================================================== --- hw/ppc_prep.c (revision 5771) +++ hw/ppc_prep.c (working copy) @@ -709,7 +709,7 @@ else fd[i] = NULL; } - fdctrl_init(i8259[6], 2, 0, 0x3f0, fd); + fdctrl_i8257_init(i8259[6], 2, 0, 0x3f0, fd); /* Register speaker port */ register_ioport_read(0x61, 1, 1, speaker_ioport_read, NULL); Index: hw/sun4m.c =================================================================== --- hw/sun4m.c (revision 5771) +++ hw/sun4m.c (working copy) @@ -1589,7 +1589,7 @@ if (hwdef->fd_base != (target_phys_addr_t)-1) { /* there is zero or one floppy drive */ - fd[1] = fd[0] = NULL; + memset(fd, 0, sizeof(fd)); drive_index = drive_get_index(IF_FLOPPY, 0, 0); if (drive_index != -1) fd[0] = drives_table[drive_index].bdrv; Index: hw/sun4u.c =================================================================== --- hw/sun4u.c (revision 5771) +++ hw/sun4u.c (working copy) @@ -508,7 +508,7 @@ else fd[i] = NULL; } - floppy_controller = fdctrl_init(NULL/*6*/, 2, 0, 0x3f0, fd); + floppy_controller = fdctrl_i8257_init(NULL/*6*/, 2, 0, 0x3f0, fd); nvram = m48t59_init(NULL/*8*/, 0, 0x0074, NVRAM_SIZE, 59); sun4u_NVRAM_set_params(nvram, NVRAM_SIZE, "Sun4u", RAM_size, boot_devices, KERNEL_LOAD_ADDR, kernel_size,