📄 lsys5.cpp
字号:
#include <lsys.h>
#include <conio.h>
#include <stdlib.h>
#include <dos.h>
///////////////////////////////////////////////////////////////////////////
char *lsys_dos_alloc(int size,short *selector);
void lsys_dos_free(short selector);
void lsys_mem_lock(void *mem,ushort size);
void lsys_mem_unlock(void *mem,ushort size);
char lsys_dma_alloc(int size,long *phy,short *selector);
char lsys_dma_free(int size,long phy,short selector);
void lsys_dma_start(char channel,unsigned long addr,short size,char auto_init,char input);
void lsys_dma_stop(char channel);
long lsys_dma_todo(char channel);
///////////////////////////////////////////////////////////////////////
char *lsys_dos_alloc(int size,short *selector)
{ union REGS r;
r.x.eax = 0x0100; r.x.ebx = (size + 15) >> 4;
int386(0x31, &r, &r); if (r.x.cflag) return NULL;
*selector = r.w.dx;
return (char*)((r.x.eax & 0xFFFF) << 4);
}
void lsys_dos_free(short selector)
{ union REGS r;
r.x.eax = 0x0101; r.w.dx = selector;
int386(0x31, &r, &r);
}
void lsys_mem_lock(void *mem,ushort size)
{ union REGS r;
r.x.eax = 0x0600;
r.w.bx = (FP_OFF(mem) & 0xFFFF0000) >> 16;
r.w.cx = FP_OFF(mem) & 0x0000FFFF;
r.w.si = 0;
r.w.di = size;
int386(0x31, &r, &r);
}
void lsys_mem_unlock(void *mem,ushort size)
{ union REGS r;
r.x.eax = 0x0601;
r.w.bx = (FP_OFF(mem) & 0xFFFF0000) >> 16;
r.w.cx = FP_OFF(mem) & 0x0000FFFF;
r.w.si = 0;
r.w.di = size;
int386(0x31, &r, &r);
}
char lsys_dma_alloc(int size,long *phy,short *selector)
{ *phy=(long)lsys_dos_alloc(size*2,selector);
if (*phy==NULL) return -1;
if ((*phy>>16) != ((*phy+size)>>16) ) *phy+=size;
lsys_mem_lock((char*)*phy,size);
return 0;
}
char lsys_dma_free(int size,long phy,short selector)
{ if (phy==0||size==0) return -1;
lsys_mem_unlock((char*)phy,size);
lsys_dos_free(selector);
return 0;
}
///////////////////////////////////////////////////////////////////////
/* DMA Controler #1 (8-bit controller) */
#define DMA1_STAT 0x08 /* read status register */
#define DMA1_WCMD 0x08 /* write command register */
#define DMA1_WREQ 0x09 /* write request register */
#define DMA1_SNGL 0x0A /* write single bit register */
#define DMA1_MODE 0x0B /* write mode register */
#define DMA1_CLRFF 0x0C /* clear byte ptr flip/flop */
#define DMA1_MCLR 0x0D /* master clear register */
#define DMA1_CLRM 0x0E /* clear mask register */
#define DMA1_WRTALL 0x0F /* write all mask register */
/* DMA Controler #2 (16-bit controller) */
#define DMA2_STAT 0xD0 /* read status register */
#define DMA2_WCMD 0xD0 /* write command register */
#define DMA2_WREQ 0xD2 /* write request register */
#define DMA2_SNGL 0xD4 /* write single bit register */
#define DMA2_MODE 0xD6 /* write mode register */
#define DMA2_CLRFF 0xD8 /* clear byte ptr flip/flop */
#define DMA2_MCLR 0xDA /* master clear register */
#define DMA2_CLRM 0xDC /* clear mask register */
#define DMA2_WRTALL 0xDE /* write all mask register */
/* stuff for each DMA channel */
#define DMA0_ADDR 0x00 /* chan 0 base adddress */
#define DMA0_CNT 0x01 /* chan 0 base count */
#define DMA1_ADDR 0x02 /* chan 1 base adddress */
#define DMA1_CNT 0x03 /* chan 1 base count */
#define DMA2_ADDR 0x04 /* chan 2 base adddress */
#define DMA2_CNT 0x05 /* chan 2 base count */
#define DMA3_ADDR 0x06 /* chan 3 base adddress */
#define DMA3_CNT 0x07 /* chan 3 base count */
#define DMA4_ADDR 0xC0 /* chan 4 base adddress */
#define DMA4_CNT 0xC2 /* chan 4 base count */
#define DMA5_ADDR 0xC4 /* chan 5 base adddress */
#define DMA5_CNT 0xC6 /* chan 5 base count */
#define DMA6_ADDR 0xC8 /* chan 6 base adddress */
#define DMA6_CNT 0xCA /* chan 6 base count */
#define DMA7_ADDR 0xCC /* chan 7 base adddress */
#define DMA7_CNT 0xCE /* chan 7 base count */
#define DMA0_PAGE 0x87 /* chan 0 page register (refresh) */
#define DMA1_PAGE 0x83 /* chan 1 page register */
#define DMA2_PAGE 0x81 /* chan 2 page register */
#define DMA3_PAGE 0x82 /* chan 3 page register */
#define DMA4_PAGE 0x8F /* chan 4 page register (unuseable) */
#define DMA5_PAGE 0x8B /* chan 5 page register */
#define DMA6_PAGE 0x89 /* chan 6 page register */
#define DMA7_PAGE 0x8A /* chan 7 page register */
typedef struct {
unsigned char dma_disable; /* bits to disable dma channel */
unsigned char dma_enable; /* bits to enable dma channel */
unsigned short page; /* page port location */
unsigned short addr; /* addr port location */
unsigned short count; /* count port location */
unsigned short single; /* single mode port location */
unsigned short mode; /* mode port location */
unsigned short clear_ff; /* clear flip-flop port location */
unsigned char write; /* bits for write transfer */
unsigned char read; /* bits for read transfer */
} DMA_ENTRY;
static DMA_ENTRY mydma[] =
{ /* channel 0 */
{ 0x04, 0x00, DMA0_PAGE, DMA0_ADDR, DMA0_CNT,
DMA1_SNGL, DMA1_MODE, DMA1_CLRFF, 0x48, 0x44 },
/* channel 1 */
{ 0x05, 0x01, DMA1_PAGE, DMA1_ADDR, DMA1_CNT,
DMA1_SNGL,DMA1_MODE,DMA1_CLRFF,0x49,0x45 },
/* channel 2 */
{ 0x06, 0x02, DMA2_PAGE, DMA2_ADDR, DMA2_CNT,
DMA1_SNGL, DMA1_MODE, DMA1_CLRFF, 0x4A, 0x46 },
/* channel 3 */
{ 0x07, 0x03, DMA3_PAGE, DMA3_ADDR, DMA3_CNT,
DMA1_SNGL, DMA1_MODE, DMA1_CLRFF, 0x4B, 0x47 },
/* channel 4 */
{ 0x04, 0x00, DMA4_PAGE, DMA4_ADDR, DMA4_CNT,
DMA2_SNGL, DMA2_MODE, DMA2_CLRFF, 0x48, 0x44 },
/* channel 5 */
{ 0x05, 0x01, DMA5_PAGE, DMA5_ADDR, DMA5_CNT,
DMA2_SNGL, DMA2_MODE, DMA2_CLRFF, 0x49, 0x45 },
/* channel 6 */
{ 0x06, 0x02, DMA6_PAGE, DMA6_ADDR, DMA6_CNT,
DMA2_SNGL, DMA2_MODE, DMA2_CLRFF, 0x4A, 0x46 },
/* channel 7 */
{ 0x07, 0x03, DMA7_PAGE, DMA7_ADDR, DMA7_CNT,
DMA2_SNGL, DMA2_MODE, DMA2_CLRFF, 0x4B, 0x47 }
};
// dma_start:
// Starts the DMA controller for the specified channel, transferring
// size bytes from addr (the block must not cross a page boundary).
// If auto_init is set, it will use the endless repeat DMA mode.
void lsys_dma_start(char channel,unsigned long addr,short size,char auto_init,char input)
{ DMA_ENTRY *tdma;
unsigned long page, offset;
int mode;
tdma = &mydma[channel]; page = addr >> 16;
if (channel >= 4) { /* 16 bit data is halved */
addr >>= 1; size >>= 1;
}
offset = addr & 0xFFFF; size--;
mode = (input) ? tdma->read : tdma->write;
if (auto_init) mode |= 0x10;
outp(tdma->single, tdma->dma_disable); /* disable channel */
outp(tdma->mode, mode); /* set mode */
outp(tdma->clear_ff, 0); /* clear flip-flop */
outp(tdma->addr, offset & 0xFF); /* address LSB */
outp(tdma->addr, offset >> 8); /* address MSB */
outp(tdma->page, page); /* page number */
outp(tdma->clear_ff, 0); /* clear flip-flop */
outp(tdma->count, size & 0xFF); /* count LSB */
outp(tdma->count, size >> 8); /* count MSB */
outp(tdma->single, tdma->dma_enable); /* enable channel */
}
void lsys_dma_stop(char channel)
{ DMA_ENTRY *tdma = &mydma[channel];
outp(tdma->single, tdma->dma_disable);
}
// dma_todo:
// Returns the current position in a dma transfer. Interrupts should be
// disabled before calling this function.
long lsys_dma_todo(char channel)
{ int val1, val2;
DMA_ENTRY *tdma = &mydma[channel];
outp(tdma->clear_ff, 0xff);
do {
val1 = inp(tdma->count);
val1 |= inp(tdma->count) << 8;
val2 = inp(tdma->count);
val2 |= inp(tdma->count) << 8;
val1 -= val2;
} while (val1 > 0x40);
if (channel > 3) val2 <<= 1;
return val2;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -