delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp/1995/01/31/15:03:36

From: Scharrlach <jscharrl AT dv DOT st DOT dlr DOT de>
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 <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 -


  webmaster     delorie software   privacy  
  Copyright © 2019   by DJ Delorie     Updated Jul 2019