138 lines
3.5 KiB
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);
|
|
}
|