From: Scharrlach Subject: DMA+interrupt problem To: djgpp AT sun DOT soe DOT clarkson DOT edu (DJGPP mailing list) Date: Tue, 31 Jan 1995 13:25:10 +0100 (NFT) Hi! I have a small problem using interrupts and DMA - I am not quite sure what my problem is, either the DMA is not working with my program (but it works with a MS-C prog) or the interrupt is not handled correctly. Anyway, here comes the piece of code which is responsible for all the DMA-stuff (it is the modified code of the MS-C example, I used the soundblaster example as guide for how to convert it): cameraint() - Interrupt service routine DMAinit() - initialises the whole thing GoDMA(buffer, num) - start new DMA sequence, i.e. transfer 2*num Bytes into "buffer" StopDMA() - restore all interrupt vectors, etc. The program tries to communicate with a 16bit expansion card, which uses DMA channel 5 and IRQ 12. I am using the whole thing with djgpp 1.12m2 and GCC 2.6 Thanks in advance and sorry if you don't like looong listings :) Jochen -------------------snip-------------------------------------- #include "..\inc\cam.h" #include #include #include /* GO32 DPMI structs */ static _go32_dpmi_seginfo dosmem; static _go32_dpmi_seginfo oldirq_rm; static _go32_dpmi_registers rm_regs; static _go32_dpmi_seginfo rm_si; static _go32_dpmi_seginfo oldirq_pm; static _go32_dpmi_seginfo pm_si; #define int_vect (0x74) static volatile int DMAflg; void waitForSync(void) { while (DMAflg); } int checkForSync(void) { return (DMAflg); } void cameraint(_go32_dpmi_registers *reg) /*void _interrupt _far cameraint() Interrupt service routine*/ { DMAflg=0; /*Set DMA finished flag*/ outportw(cam.cambase+8,0); /*Prevent further interupts and*/ disable(); outportb(0xa1, inportb(0xa1) | 0x10); enable(); outportw(cam.cambase+2,0); outportb(0xa0, 0x64); outportb(0x20, 0x62); outportw(cam.cambase+6,0); } void GoDMA(unsigned long buff, int num) { DMAflg=-1; /*Set flag non-zero*/ disable(); outportb(0x0d4,5); /*Disable interrupt mask*/ enable(); outportb(0x8b, buff >> 17); outportb(0xd8, 1); outportb(0xc4, (buff>>1)&255); outportb(0xc4, (buff>>9)&255); outportb(0xd8, 1); outportb(0xc6, num&255); outportb(0xc6, (num>>8)&255); disable(); outportb(0xd6, 5); outportb(0xd4, 1); enable(); outportb(0x21, inportb(0x21) & 251); outportb(0xa1, inportb(0x21) & 239); outportw(cam.cambase+8,0); /*Clear camera interrupt*/ outportw(cam.cambase+6,1); /*Enable DMA and interupts*/ outportw(cam.cambase+4,1); } void rm_interrupt_install() { int ret; rm_si.pm_offset = (int) cameraint; ret = _go32_dpmi_allocate_real_mode_callback_iret(&rm_si, &rm_regs); if (ret != 0) { printf("cannot allocate real mode callback, error=%04x\n", ret); exit(1); } disable(); _go32_dpmi_get_real_mode_interrupt_vector(int_vect, &oldirq_rm); _go32_dpmi_set_real_mode_interrupt_vector(int_vect, &rm_si); enable(); } void rm_interrupt_cleanup() { disable(); _go32_dpmi_set_real_mode_interrupt_vector(int_vect, &oldirq_rm); _go32_dpmi_free_real_mode_callback(&rm_si); enable(); } void pm_interrupt_install() { disable(); _go32_dpmi_get_protected_mode_interrupt_vector(int_vect, &oldirq_pm); pm_si.pm_offset = (int) cameraint; _go32_dpmi_allocate_iret_wrapper(&pm_si); pm_si.pm_selector = _go32_my_cs(); _go32_dpmi_set_protected_mode_interrupt_vector(int_vect, &pm_si); enable(); } void pm_interrupt_cleanup() { disable(); _go32_dpmi_set_protected_mode_interrupt_vector (int_vect, &oldirq_pm); enable(); } void installInt() { pm_interrupt_install(); rm_interrupt_install(); } void cleanupInt() { pm_interrupt_cleanup(); rm_interrupt_cleanup(); } void DMAinit( void ) { dosmem.size = (BufSize*3)/16; if (_go32_dpmi_allocate_dos_memory(&dosmem)) { printf("unable to allocate dos memory - max size is %d\n", dosmem.size); exit(1); } (unsigned long) dosBuff[0] = dosmem.rm_segment*16 + BufSize - ((dosmem.rm_segment*16) & (BufSize-1)); (unsigned long) dosBuff[1] = dosBuff[0] + BufSize; printf("DOSbuffer: Adresse: %x Groesse: %x\n", dosmem.rm_segment*16, dosmem.size*16); printf("Block1: %x Block2: %x\n\n", dosBuff[0], dosBuff[1]); /*Set interface to prevent unwanted interrupts*/ outportw(cam.cambase+6,0); outportw(cam.cambase+8,0); outportw(cam.cambase+4,0); /* oldcint = _dos_getvect( 0x74 ); Get old interupt address*/ /* _dos_setvect( 0x74, cameraint ); Set new interupt routine (see below)*/ installInt(); } void StopDMA( void ) { outportw(cam.cambase+6,0); /*Prevent further interupts or DMA requests*/ outportw(cam.cambase+8,0); outportw(cam.cambase+4,0); cleanupInt(); /* _dos_setvect( 0x74, oldcint ); Reset interrupt vector*/ _go32_dpmi_free_dos_memory(&dosmem); }