www.delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp/1994/10/13/21:17:41

From: dtauritz AT WI DOT LeidenUniv DOT NL (D.R.Tauritz)
Organization: Leiden University,
Dept. of Mathematics & Computer Science,
The Netherlands
Subject: Segmentation Violations Solved! Code included!
To: djgpp AT sun DOT soe DOT clarkson DOT edu
Date: Thu, 13 Oct 1994 17:02:09 +0100 (MET)

Thanks to all who reacted to my message concerning "Segmentation Violations".
As the subject line implies I've solved the problem, thanks to your advice.
Actually it was Grzegorz Jablonski who handed me the solution by giving me a
pointer to sb02.zip (not the djgpp directory at oak, but in the sound
directory!), the improved version of the sblaster code included in djgpp 1.12
I hope DJ replaces the old code with this updated version with the next
release, it is very much improved! As Long Doan pointed out, the
_go32_..._chain_... routine doesn't work correctly, luckily I didn't have to
bypass go32 as he did, the problem is nicely circumvented in the sb02 code
and it works for me too! For all who are interested in writing interrupt
routines I've appended a copy of the working code at the end of this message.
This code also answers Eli Zaretskii's second question concerning the use of
disable() and enable() in interrupt routines; you only need one routine for
the real mode as well as the protected mode case and the use of disable() at
the start of your interrupt routine, as well as the use of enable() at the
end of your interrupt routine, is harmless as well as unnecessary. I tried
all combinations without noticing any difference. And last but not least I
got a message from Ken Graham warning me that the volatile keyword did not
always work correctly in older DJGPP versions, version 1.12 mnt.2 luckily
seems to work correctly, at least for me...

Well, thanks again to all that helped me solve this one. I hope the appended
code is of use to someone, at least it seems to be a clean and easy way of
writing interrupt routines. Enjoy!

The best of wishes,

Daniel

-----------------------------------------------------------------------------
| Daniel R. Tauritz                            | Maintainer of the          |
| E-mail: dtauritz AT wi DOT leidenuniv DOT nl            |   Aria FAQ                 |
| Department of Mathematics & Computer Science |   Aria Internet Department |
| University of Leiden                         |   Aria Support List        |
| The Netherlands                              |   Leiden Audio Archives    |
-----------------------------------------------------------------------------
|     The Aria Internet Department: ftp.wi.leidenuniv.nl:pub/audio/aria     |
-----------------------------------------------------------------------------



#include <stdio.h>
#include <pc.h>
#include <dos.h>
#include <dpmi.h>
#include <go32.h>

#define BASEPORT     0x290
#define MY_INTERRUPT 0x72
#define MY_IRQ       10

_go32_dpmi_seginfo oldirq_rm, rm_si, oldirq_pm, pm_si;
_go32_dpmi_registers rm_regs;
volatile int tics;

void aria_putmem (int address, int word)
{
  outportw (BASEPORT+4, address);
  outportw (BASEPORT+6, word);
  return;
}

int aria_getmem (int address)
{
  int word;
  outportw (BASEPORT+4, address);
  word=inportw (BASEPORT+6);
  return word;
}

void aria_sendcmd (unsigned command)
{
  unsigned i=65535;
  while (i--)
  {
    if (!(inportw(BASEPORT+2) & 0x8000))
    {
      outportw (BASEPORT, command);
      return;
    }
  }
  printf ("time out\n");
  exit(1);
}

void aria_init()
{
  int ready=0;

  outportw (BASEPORT+2,0xc8);          /* Aria init */
  aria_putmem (0x6102,0);              /* Clear task init flag */

  /* Aria DSP Init */
  disable();
  aria_sendcmd (0x00);
  aria_sendcmd (0x00);
  aria_sendcmd (0x00);
  aria_sendcmd (0x00);
  aria_sendcmd (0xffff);
  enable();

  /* Wait for Aria DSP init to complete */
  while (ready != 1)
  {
    outportw (BASEPORT+4, 0x6102);
    ready = inportw (BASEPORT+6);
  }

  outportw (BASEPORT+2,0xca);           /* Complete Aria init */

  return;
}

void aria_irqhandler(_go32_dpmi_registers *reg)
{
  tics++;
  outportb (0xa0,0x20);   /* secondary controller EOI */
  outportb (0x20,0x20);   /* primary controller EOI   */
  enable();
}

void aria_install_interrupt_handler (void (*aria_irqhandler)
                                     (_go32_dpmi_registers *))
{
  int ret;

  /* Install real mode interrupt handler */
  rm_si.pm_offset = (int) aria_irqhandler;
  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(MY_INTERRUPT, &oldirq_rm);
  _go32_dpmi_set_real_mode_interrupt_vector(MY_INTERRUPT, &rm_si);

  /* Install protected mode interrupt handler */
  pm_si.pm_offset = (int) aria_irqhandler;
  ret = _go32_dpmi_allocate_iret_wrapper(&pm_si);
  if (ret != 0)
  {
    printf ("cannot allocate protected mode wrapper, error=%04x\n",ret);
    exit(1);
  }
  pm_si.pm_selector = _go32_my_cs();
  _go32_dpmi_get_protected_mode_interrupt_vector (MY_INTERRUPT, &oldirq_pm);
  _go32_dpmi_set_protected_mode_interrupt_vector(MY_INTERRUPT, &pm_si);

  /* Enable interrupts via Aria's IRQ */
  outportw (0xA1,inportb(0xA1) & ~(1<<(MY_IRQ-8)));
  enable();
}

void aria_generate_interrupt()
{
  /* Generate interrupt via IRQ 10 (software interrupt 0x72) */
  disable();
  aria_sendcmd (0xa);
  aria_sendcmd (0xffff);
  enable();
}

void aria_release_interrupt_handler ()
{
  disable();

  /* Disable interrupts via Aria's IRQ */
  outportw (0xA1,inportb(0xA1) | (1<<(MY_IRQ-8)));

  /* Remove our real mode interrupt handler */
  _go32_dpmi_set_real_mode_interrupt_vector(MY_INTERRUPT, &oldirq_rm);
  if (rm_si.size != -1)
    _go32_dpmi_free_real_mode_callback(&rm_si);
  rm_si.size = -1;

  /* Remove our protected mode interrupt handler */
  if (pm_si.size != -1)
    _go32_dpmi_free_iret_wrapper (&pm_si);
  pm_si.size = -1;
  _go32_dpmi_set_protected_mode_interrupt_vector(MY_INTERRUPT,&oldirq_pm);

  enable();
}

void aria_reset ()
{
  outportw (BASEPORT+2,0x40);
  return;
}

int main()
{
  char key=' ';
  int i;

  aria_init();
  aria_install_interrupt_handler(aria_irqhandler);

  while (key!='q')
  {
    printf ("tics=%d\n",tics);
    key=getkey();

    aria_generate_interrupt();
    for (i=0;i<30000;i++);   /* Wait for DSP to complete interrupt request */
  }

  aria_release_interrupt_handler();
  aria_reset();
  return 0;
}

- Raw text -


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