Move the DMA controller code in resume.c and hw/floppy.c to a new file hw/dma.c. This centralizes the DMA controller code into one place.
Also, don't unmask the floppy DRQ during floppy setup - there is no reason to unmask the DRQ prior to a command being programmed into the DMA controller.
Signed-off-by: Kevin O'Connor kevin@koconnor.net --- Makefile | 2 +- src/hw/dma.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/hw/floppy.c | 40 ++++++---------------------------------- src/resume.c | 13 ------------- src/util.h | 5 ++++- 5 files changed, 67 insertions(+), 49 deletions(-) create mode 100644 src/hw/dma.c
diff --git a/Makefile b/Makefile index 0cdb6d3..4c78d69 100644 --- a/Makefile +++ b/Makefile @@ -11,7 +11,7 @@ OUT=out/ SRCBOTH=misc.c stacks.c output.c string.c x86.c block.c cdrom.c mouse.c kbd.c \ serial.c clock.c resume.c pnpbios.c vgahooks.c pcibios.c apm.c \ fw/smp.c \ - hw/pci.c hw/timer.c hw/rtc.c hw/pic.c hw/ps2port.c \ + hw/pci.c hw/timer.c hw/dma.c hw/rtc.c hw/pic.c hw/ps2port.c \ hw/usb.c hw/usb-uhci.c hw/usb-ohci.c hw/usb-ehci.c \ hw/usb-hid.c hw/usb-msc.c hw/usb-uas.c \ hw/blockcmd.c hw/floppy.c hw/ata.c hw/ahci.c hw/ramdisk.c \ diff --git a/src/hw/dma.c b/src/hw/dma.c new file mode 100644 index 0000000..2051ab0 --- /dev/null +++ b/src/hw/dma.c @@ -0,0 +1,56 @@ +// 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 "ioport.h" // PORT_DMA1_MASK_REG +#include "util.h" // dma_setup + +// 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); +} diff --git a/src/hw/floppy.c b/src/hw/floppy.c index cf1ab87..0479ac7 100644 --- a/src/hw/floppy.c +++ b/src/hw/floppy.c @@ -153,8 +153,6 @@ floppy_setup(void) addFloppy(1, type); }
- outb(0x02, PORT_DMA1_MASK_REG); - enable_hwirq(6, FUNC16(entry_0e)); }
@@ -433,7 +431,7 @@ check_recal_drive(struct drive_s *drive_g)
/**************************************************************** - * Floppy DMA + * Floppy DMA transfer ****************************************************************/
// Perform a floppy transfer command (setup DMA and issue PIO). @@ -444,39 +442,13 @@ floppy_cmd(struct disk_op_s *op, int blocksize, struct floppy_pio_s *pio) if (ret) return ret;
- // es:bx = pointer to where to place information from diskette - u32 addr = (u32)op->buf_fl; - int count = op->count * blocksize; - - // check for 64K boundary overrun - u16 end = count - 1; - u32 last_addr = addr + end; - if ((addr >> 16) != (last_addr >> 16)) + // Setup DMA controller + int isWrite = pio->data[0] != 0xe6; + ret = dma_floppy((u32)op->buf_fl, op->count * blocksize, isWrite); + if (ret) return DISK_RET_EBOUNDARY;
- u8 mode_register = 0x4a; // single mode, increment, autoinit disable, - if (pio->data[0] == 0xe6) - // read - mode_register = 0x46; - - //DEBUGF("floppy dma c2\n"); - 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 - + // Invoke floppy controller ret = floppy_select_drive(pio->data[1] & 1); if (ret) return ret; diff --git a/src/resume.c b/src/resume.c index 12daf0f..370bfe3 100644 --- a/src/resume.c +++ b/src/resume.c @@ -21,19 +21,6 @@ // Indicator if POST phase has been run. int HaveRunPost VARFSEG;
-// 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); -} - // Handler for post calls that look like a resume. void VISIBLE16 handle_resume(void) diff --git a/src/util.h b/src/util.h index 9c45925..d51e30f 100644 --- a/src/util.h +++ b/src/util.h @@ -124,6 +124,10 @@ void wrmsr_smp(u32 index, u64 val); void smp_setup(void); int apic_id_is_present(u8 apic_id);
+// hw/dma.c +int dma_floppy(u32 addr, int count, int isWrite); +void dma_setup(void); + // hw/floppy.c extern struct floppy_ext_dbt_s diskette_param_table2; void floppy_setup(void); @@ -204,7 +208,6 @@ void reloc_preinit(void *f, void *arg);
// resume.c extern int HaveRunPost; -void dma_setup(void);
// romlayout.S void reset_vector(void) __noreturn;