Add qemu 2.4.0
[kvmfornfv.git] / qemu / roms / seabios / src / hw / dma.c
diff --git a/qemu/roms/seabios/src/hw/dma.c b/qemu/roms/seabios/src/hw/dma.c
new file mode 100644 (file)
index 0000000..20c9fbb
--- /dev/null
@@ -0,0 +1,67 @@
+// Code to support legacy Intel 8237 DMA chip.
+//
+// Copyright (C) 2008,2009  Kevin O'Connor <kevin@koconnor.net>
+// Copyright (C) 2002  MandrakeSoft S.A.
+//
+// This file may be distributed under the terms of the GNU LGPLv3 license.
+
+#include "util.h" // dma_setup
+#include "x86.h" // outb
+
+#define PORT_DMA_ADDR_2        0x0004
+#define PORT_DMA_CNT_2         0x0005
+#define PORT_DMA1_MASK_REG     0x000a
+#define PORT_DMA1_MODE_REG     0x000b
+#define PORT_DMA1_CLEAR_FF_REG 0x000c
+#define PORT_DMA1_MASTER_CLEAR 0x000d
+#define PORT_DMA_PAGE_2        0x0081
+#define PORT_DMA2_MASK_REG     0x00d4
+#define PORT_DMA2_MODE_REG     0x00d6
+#define PORT_DMA2_MASTER_CLEAR 0x00da
+
+// Setup the DMA controller for a floppy transfer.
+int
+dma_floppy(u32 addr, int count, int isWrite)
+{
+    // check for 64K boundary overrun
+    u16 end = count - 1;
+    u32 last_addr = addr + end;
+    if ((addr >> 16) != (last_addr >> 16))
+        return -1;
+
+    u8 mode_register = 0x46; // single mode, increment, autoinit disable,
+    if (isWrite)
+        mode_register = 0x4a;
+
+    outb(0x06, PORT_DMA1_MASK_REG);
+    outb(0x00, PORT_DMA1_CLEAR_FF_REG); // clear flip-flop
+    outb(addr, PORT_DMA_ADDR_2);
+    outb(addr>>8, PORT_DMA_ADDR_2);
+    outb(0x00, PORT_DMA1_CLEAR_FF_REG); // clear flip-flop
+    outb(end, PORT_DMA_CNT_2);
+    outb(end>>8, PORT_DMA_CNT_2);
+
+    // port 0b: DMA-1 Mode Register
+    // transfer type=write, channel 2
+    outb(mode_register, PORT_DMA1_MODE_REG);
+
+    // port 81: DMA-1 Page Register, channel 2
+    outb(addr>>16, PORT_DMA_PAGE_2);
+
+    outb(0x02, PORT_DMA1_MASK_REG); // unmask channel 2
+
+    return 0;
+}
+
+// Reset DMA controller
+void
+dma_setup(void)
+{
+    // first reset the DMA controllers
+    outb(0, PORT_DMA1_MASTER_CLEAR);
+    outb(0, PORT_DMA2_MASTER_CLEAR);
+
+    // then initialize the DMA controllers
+    outb(0xc0, PORT_DMA2_MODE_REG);
+    outb(0x00, PORT_DMA2_MASK_REG);
+}