/***** dma.c ********************************************************* * (c) 2010 CTA Systems Inc. All rights reserved. Glory To God * * * * Direct Memory Access (DMA) Routines * * =================================== * * * ************************************************************ cta os */ #include "dma.h" #include enum DMA0_IO { DMA0_STATUS_REG = 0x08, DMA0_COMMAND_REG = 0x08, DMA0_REQUEST_REG = 0x09, DMA0_CHANMASK_REG = 0x0a, DMA0_MODE_REG = 0x0b, DMA0_CLEARBYTE_FLIPFLOP_REG = 0x0c, DMA0_TEMP_REG = 0x0d, DMA0_MASTER_CLEAR_REG = 0x0d, DMA0_CLEAR_MASK_REG = 0x0e, DMA0_MASK_REG = 0x0f }; enum DMA1_IO { DMA1_STATUS_REG = 0xd0, DMA1_COMMAND_REG = 0xd0, DMA1_REQUEST_REG = 0xd2, DMA1_CHANMASK_REG = 0xd4, DMA1_MODE_REG = 0xd6, DMA1_CLEARBYTE_FLIPFLOP_REG = 0xd8, DMA1_INTER_REG = 0xda, DMA1_UNMASK_ALL_REG = 0xdc, DMA1_MASK_REG = 0xde }; void i86_dma_set_address(unsigned short channel, unsigned char low, unsigned char high) { if (channel > 7) return; // Ignore if channel > 7 // Calculate port unsigned short port = (channel >= 4) ? 4*(channel - 4) + 0xc0 : 2*channel; // Set address outportb (port, low); outportb (port, high); } void i86_dma_set_count (unsigned short channel, unsigned char low, unsigned char high) { if (channel > 7) return; // Ignore if channel > 7 // Calculate port unsigned short port = (channel >= 4) ? 4*(channel - 4) + 0xc2 : (2*channel) + 1; // Set count outportb (port, low); outportb (port, high); } void i86_dma_set_external_page_registers (unsigned char channel, unsigned char val) { unsigned short port = 0; switch (channel) { case 1: port = 0x83; break; case 2: port = 0x81; break; case 3: port = 0x82; break; // <- nothing should ever write to chan 4 case 5: port = 0x89; break; case 6: port = 0x87; break; case 7: port = 0x88; break; default: if (channel == 4 || channel > 14) return; } outportb(port, val); } void i86_dma_mask_channel (unsigned char channel) { if (channel <= 4) outportb (DMA0_CHANMASK_REG, (1<< (channel -1))); else outportb (DMA1_CHANMASK_REG, (1<< (channel -5))); } void i86_dma_unmask_channel (unsigned char channel) { if (channel <= 4) outportb (DMA0_CHANMASK_REG, channel); else outportb (DMA1_CHANMASK_REG, channel); } void i86_dma_unmask_all() { outportb (DMA1_UNMASK_ALL_REG, 0xff); } void i86_dma_reset_flipflop (unsigned char dma) { switch (dma) { case 0: outportb (DMA0_CLEARBYTE_FLIPFLOP_REG, 0xff); case 1: outportb (DMA1_CLEARBYTE_FLIPFLOP_REG, 0xff); } } void i86_dma_reset () { outportb (DMA0_TEMP_REG, 0xff); } void i86_dma_set_mode(unsigned char channel, unsigned char mode) { unsigned char dma = (channel < 4) ? 0:1; unsigned char chan = (dma == 0) ? channel : channel-4; i86_dma_mask_channel (channel); outportb ((channel < 4) ? DMA0_MODE_REG : DMA1_MODE_REG, chan | mode); i86_dma_unmask_all (); } void i86_dma_set_read (unsigned char channel) { i86_dma_set_mode (channel, DMA_MODE_READ_TRANSFER | DMA_MODE_TRANSFER_SINGLE); } void i86_dma_set_write (unsigned char channel) { i86_dma_set_mode (channel, DMA_MODE_WRITE_TRANSFER | DMA_MODE_TRANSFER_SINGLE); }