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 #include #include #include #include #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; }