//--------------------------------------------------------------------------- // L362.C // Using the 80C188XL internal DMA channel 0 for implementing an // 'unsynchronized' Memory to Memory tansfer, i.e., copy one // string to another. // An interrupt is generated on terminal count. // // C/C++ code for the SBC188 board. // C.P. Diduch, March 1999. //--------------------------------------------------------------------------- #define TRUE 1 #define D0SRCL 0xFFC0 // 80C188 DMA0 SRC address: lo 16-bits. #define D0SRCH 0xFFC2 // 80C188 DMA0 SRC address: hi 4-bits. #define D0DSTL 0xFFC4 // 80C188 DMA0 DST address: lo 16-bits. #define D0DSTH 0xFFC6 // 80C188 DMA0 DST address: hi 4-bits. #define D0TC 0xFFC8 // 80C188 DMA0 terminal count register. #define D0CON 0xFFCA // 80C188 DMA0 control register. #define D0TYPE 10 // 80C188 Interrupt TYPE number for DMA0. #define DMA0CON 0xFF34 // 80C188 Interrupt control reg for DMA0. #define EOI 0xFF22 // 80C188 End of interrupt register. #define KEY_PC 0x013C // 8255A PPI Port addresses. #define KEY_CON 0x013E #include #include void int_vect_init(void); // Function prototypes. void timer_init(unsigned MICROSECS); void interrupt isr_0(void); void delay(unsigned MILLISECS); void dma_mem_mem(char *x, char *y, unsigned z, unsigned NO_BYTES); //--------------------------------------------------------------------------- void main(void) { char DATA[] = {1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,3,3,3,3,3,3,3,3,3,3, \ 4,4,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,6,6,6,6,6,6,6,6,6,6}; char BUFF[60]; unsigned SA; disable(); // Clear 80C188 interrupts. outportb(KEY_CON, 0x92); // Initialize KEY_PC as an output port. int_vect_init(); // Initialize interrupt vector table. asm{ mov SA, ds // Get segment address of BUFF[] and DATA[]. } // Initialize and arm DMA0 to transfer 60 bytes from array DATA[] // to array BUFF[]. dma_mem_mem(&BUFF[0], &DATA[0], SA, 60); enable(); // Enable 80C188 interrupts. asm hlt // Wait for a DMA interrupt on // terminal count. delay(1000); } //--------------------------------------------------------------------------- void dma_mem_mem(char *DST, char *SRC, unsigned SA, unsigned NO_BYTES) { long PA; unsigned LO, HI; PA = (16* (long) SA) + (unsigned) SRC; LO = (unsigned) PA; HI = (unsigned) (PA >> 16); outport(D0SRCL, LO); outport(D0SRCH, HI); PA = (16* (long) SA) + (unsigned) DST; LO = (unsigned) PA; HI = (unsigned) (PA >> 16); outport(D0DSTL, LO); outport(D0DSTH, HI); outport(D0TC, NO_BYTES); outport(D0CON, 0xB706); // Unsynchronize transfer terminates // with interrupt. outport(DMA0CON, 0); } //--------------------------------------------------------------------------- void int_vect_init(void) { asm { // Initialize the Interrupt Vector push ax // Table entry for the 80C188XL push bx // DMA0. push ds mov ax, 0 mov ds, ax mov bx, D0TYPE*4 mov word ptr[bx], offset isr_0 mov word ptr[bx+2], seg isr_0 pop ds pop bx pop bx } } //--------------------------------------------------------------------------- // DMA0 Terminal Count Interrupt Service Routine void interrupt isr_0(void) { outportb(KEY_PC, 0xAA); outport(EOI, 0x000A); // Specific End of Interrupt for TIMER2. // Reqired TYPE = 10D for all TIMERS. } //--------------------------------------------------------------------------- void delay(unsigned MILLISECS) { unsigned M; while (MILLISECS != 0) { M = 1000; while (M != 0) {M--;} MILLISECS--; } }