Mail Archives: djgpp/1995/01/31/18:25:18
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 <dos.h>
#include <go32.h>
#include <dpmi.h>
/* 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);
}
- Raw text -