#include"../x86/kernel/hwio.h" #include"dma.h" const byte _DMA_ADDR_REG[8] = { 0, 2, 4, 6, 0xC0, 0xC4, 0xC8, 0xCC }; const byte _DMA_EXT_ADDR_REG[8] = { 0x83, 0x81, 0x82, 6, 0xC0, 0xC4, 0xC8, 0xCC }; const byte _DMA_COUNT_REG[8] = { 1, 3, 5, 7, 0xC2, 0xC6, 0xCA, 0xCE }; #define DMA_SLAVE_SET_MODE 0x0B #define DMA_MASTER_SET_MODE 0xD6 #define DMA_MODE_MASK_SEL 3 #define DMA_MODE_MASK_TRA 0xc #define DMA_MODE_SELF_TEST 0 #define DMA_MODE_READ_TRANSFER 4 #define DMA_MODE_WRITE_TRANSFER 8 #define DMA_MODE_MASK_AUTO 0x10 #define DMA_MODE_MASK_IDEC 0x20 #define DMA_MODE_MASK 0xc0 #define DMA_MODE_TRANSFER_ON_DEMAND 0 #define DMA_MODE_TRANSFER_SINGLE 0x40 #define DMA_MODE_TRANSFER_BLOCK 0x80 #define DMA_MODE_TRANSFER_CASCADE 0xC0 #define DMA_CMD_MASK_MEMTOMEM 1 #define DMA_CMD_MASK_CHAN0ADDRHOLD 2 #define DMA_CMD_MASK_ENABLE 4 #define DMA_CMD_MASK_TIMING 8 #define DMA_CMD_MASK_PRIORITY 0x10 #define DMA_CMD_MASK_WRITESEL 0x20 #define DMA_CMD_MASK_DREQ 0x40 #define DMA_CMD_MASK_DACK 0x80 #define DMA_SLAVE_INTER_REG 0x0D #define DMA_MASTER_INTER_REG 0xDA #define DMA_SLAVE_CHMASK 0x0A #define DMA_MASTER_CHMASK 0xD4 #define DMA_SLAVE_CLEARBYTE_FLIPFLOP_REG 0x0C #define DMA_MASTER_CLEARBYTE_FLIPFLOP_REG 0xD8 inline void dmaReset(enum DMAC n) { switch (n) { case Slave_DMA: outb(DMA_SLAVE_INTER_REG, 0xFF); case Master_DMA: outb(DMA_MASTER_INTER_REG, 0xFF); default:; } } inline void dmaAddr(byte channel, void* addr) { byte page = ((dword)addr & 0xFF0000) >> 16; outb(_DMA_EXT_ADDR_REG[channel], page); outw(_DMA_ADDR_REG[channel], (dword)addr&0xFFFF); } inline void dmaCount(byte channel, word n) { outw(_DMA_COUNT_REG[channel], n); } inline void dmaMask(byte channel) { if (channel > 3) outb(DMA_MASTER_CHMASK, (1 << (channel))); else outb(DMA_SLAVE_CHMASK, (1 << (channel-4))); } inline void dmaUnmask(byte channel) { if (channel > 3) outb(DMA_MASTER_CHMASK, channel); else outb(DMA_SLAVE_CHMASK, channel); } void dmaMode(byte channel, byte mode) { byte port=DMA_SLAVE_SET_MODE; if (channel > 3) { //Master DMA channel -= 4; port += (DMA_MASTER_SET_MODE - DMA_SLAVE_SET_MODE); } dmaMask(channel); outb(port, mode | channel); dmaUnmask(channel); } inline void dmaRead(byte channel) { dmaMode(channel, DMA_MODE_READ_TRANSFER | DMA_MODE_TRANSFER_SINGLE); } inline void dmaWrite(byte channel) { dmaMode(channel, DMA_MODE_WRITE_TRANSFER | DMA_MODE_TRANSFER_SINGLE); } inline void dmaClearFlipFlop(enum DMAC n) { switch (n) { case Master_DMA: outb(DMA_MASTER_CLEARBYTE_FLIPFLOP_REG, 0xFF); case Slave_DMA: outb(DMA_SLAVE_CLEARBYTE_FLIPFLOP_REG, 0xFF); default:; } }