luxos/SysCore/hal/dma/dma.c

138 lines
3.5 KiB
C

/***** dma.c *********************************************************
* (c) 2010 CTA Systems Inc. All rights reserved. Glory To God *
* *
* Direct Memory Access (DMA) Routines *
* =================================== *
* *
************************************************************ cta os */
#include "dma.h"
#include <system.h>
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);
}