MS-DOS 6.22 Floppy Disk DMA Channel Allocation

In MS-DOS 6.22, Direct Memory Access (DMA) channel allocation for floppy disk controllers is not handled dynamically by the operating system, but rather through rigid adherence to legacy IBM PC hardware conventions, ROM BIOS routines, and memory virtualization services. Because the standard PC architecture hardwires the NEC µPD765-compatible floppy disk controller to DMA Channel 2, MS-DOS 6.22 delegates lower-level DMA configuration to the system BIOS while using internal buffering and the Virtual DMA Specification (VDS) to prevent memory addressing faults during I/O operations.

The Fixed Hardware Standard

Under the IBM PC/AT architecture inherited by MS-DOS 6.22, DMA channels are static and managed by dual Intel 8237 DMA controllers. The system does not feature an operating-system-level arbiter to dynamically assign channels to peripheral devices.

  • Assigned Channel: DMA Channel 2 (an 8-bit channel on the primary DMA controller).
  • Associated Interrupt: IRQ 6, which signals operation completion from the Floppy Disk Controller (FDC) to the CPU.
  • Page Register: Port 0x81, which supplies the upper address bits (A16–A23) required for 24-bit physical memory addressing on ISA buses.

Because these hardware lines are physically connected on the motherboard or expansion bus, MS-DOS 6.22 treats the Channel 2 assignment as an unchangeable constant.

BIOS Abstraction via INT 13h

MS-DOS 6.22 does not typically write directly to the 8237 DMA registers (0x04 for address, 0x05 for count, and 0x0A for the mask register) when handling high-level file operations. Instead, the DOS kernel (MSDOS.SYS) converts file requests into logical sector reads or writes, which are passed to the default block device driver in IO.SYS.

IO.SYS calls the system ROM BIOS via software interrupt INT 13h (specifically Function 02h for Read Sectors and Function 03h for Write Sectors). The BIOS executes the following sequence:

  1. Masks (disables) DMA Channel 2 via port 0x0A.
  2. Clears the internal byte flip-flop via port 0x0C.
  3. Sets the DMA transfer mode (single mode, read/write, auto-initialization disabled) via port 0x0B.
  4. Writes the base memory address and 64KB page register (0x81).
  5. Writes the transfer count (number of bytes minus one).
  6. Unmasks DMA Channel 2.
  7. Issues the command to the floppy disk controller via I/O port 0x3F5.

64KB Boundary Restrictions and DOS Buffers

The Intel 8237 DMA controller cannot increment its address counter past a 64KB physical segment boundary; if a transfer attempts to cross this boundary, the address wraps around to the beginning of the same 64KB block, causing memory corruption.

To prevent this:

  • If a target user buffer crosses a 64KB physical boundary, MS-DOS 6.22 redirects the transfer to an internal disk buffer allocated via the BUFFERS command in CONFIG.SYS.
  • Once the BIOS completes the DMA transfer into this internal buffer (which is guaranteed not to cross a boundary), MS-DOS copies the data into the application's target memory space using standard CPU-driven instructions.

DMA Management Under EMM386 and VDS

When MS-DOS 6.22 operates with expanded memory managers such as EMM386.EXE, the processor runs in Virtual 8086 mode with paging enabled. In this state, logical memory addresses do not match physical bus addresses, creating a conflict for legacy ISA DMA controllers that bypass the CPU's MMU.

MS-DOS 6.22 addresses this using the Virtual DMA Specification (VDS, INT 4Bh):

  1. Address Translation: When a floppy disk DMA request is issued, the memory manager intercepts the call to translate the virtual address into a physical address before the 8237 registers are programmed.
  2. Scatter/Gather and Bounce Buffering: If the target transfer region spans non-contiguous physical pages or crosses a 64KB hardware boundary, EMM386 allocates a temporary contiguous "bounce buffer" located below the 16MB boundary.
  3. Execution: DMA Channel 2 reads or writes to this bounce buffer directly. Once the transfer completes, the memory manager moves the data to the final virtual memory destination.