Partner sites: Aminet - Amiga downloadsIntuitionBase - Amiga guidesAmigaNN - Amiga newsAmiFund - Sponsor projects

[Y]UtilityBase
Your guide to Amiga development
Not logged in
  HomeProjectsForumArticlesResourcesLinksChatAbout 
Search
Login
Username:
Password:
Register now!
Forgot your password?
Aminet - Development
bullet.lha (dev/lib)
MCC_TheBar-26.6.lha (dev/mui)
MCC_TextEditor-15.35.lha (dev/mui)
MCC_BetterString-11.19.lha (dev/mui)
fw_c2p_p2c.lha (dev/lib)
plib_examples.lha (dev/src)
plib.lha (dev/lib)
MCC_NList-0.107.lha (dev/mui)
MCC_NList-0.106.lha (dev/mui)
ruby-1.8.7.i386-aros.tar.bz2 (dev/lang)
More...
Newest users
prowler
apache64 (Chris)
cpeel2300 (Chris)
Branquito
chris (Chris Young)

Pending:
ZebraZeem, Mad_Dog, hhjoker, voxel, JosDuchIt, MarcB, MarBo, Sollaris, sara, species
More...
Who's Online
Online members:


12 guests are online.

You are an Anonymous user. You can register for free by clicking here.
News sites
Amiga-News.de
Amiga.org
AmigaNN
Amigans.net
Amigaweb.net
AmigaWorld.net
AROS-Exec
MorphOS-News.de
MorphZone
polarBoing
Tutorials
Change Graphics cards in AmigaOS 4.
Installing the latest OS4 SDK in Cubic IDE
Writing Installer scripts for AmiUpdate
Cross Compiling for OS4 or OS3 using MS Visual Studio 2005
Installing an AmigaOS 4 cross compiler
More...
Sources
How to open and use the exec debug interface
How to install a hardware interrupt
Install SObjs with Installer
How to make clean picture datatypes
Most of the old ClassACT examples converted to OS4
More...
Documentations
How to write portable code for Amiga (english)
Comment écrire du code portable pour Amiga (français)
Development How to with OS3.9 SDK
The PartyPack Hack
The Amiga PDA Programming Guidelines
More...
DreamHost

Support
UtilityBase

[Valid RSS]

UtilityBase needs your help!

How to install a hardware interrupt
by Alfkil Thorbjørn Wennermark
Link: How to install a hardware interrupt (c)

I was looking for a way to install a genuine hw interrupt, and this code is the proper way to do so. Thanks to Steven Solie, Thomas Frieden, Jörg Strohmayer and Colin Wenzel.

When trying to install an exec interrupt handler, I quickly realised,
that the IExec->AddIntServer didn't really do the job. All the
trapnumbers defined in exec/interrupts.h will make this
function fail, except for TRAPNUM_ILLEGAL_INSTRUCTION, that has
no relevance on ppc machines.

After some (a lot of) guidance from the real people, I have come up
with this example, that uses SetIntVector to install a global
interrupt handler for that particular interrupt. Beware, when you use
SetIntVector, you _have to_ manually call the old interrupt handler
(returned from SetIntVector) if you don't want your entire system
to go boom!

Also, if you are trying to catch exceptions from a specific task (eg.
for debugging purposes) you should use the AddDebugHook
function from the exec debug interface (more on this in a future
article).

Here is the example:


/* realinterrupt.c - HW interrupt example code.
Edited and updated for amigaos 4 by Alfkil T. Wennermark 2010
Edited and bug-tested by Steven Solie.

Thanks to: Steven Solie, Jörg Strohmayer, Thomas Frieden and Colin Wenzel :-) */


/* REMARK: On a SAM/SAM-flex system, the returned counter will be a very large number.
We have yet to figure out, why this is. On AmigaOne's it will be 1 as expected. */



#include <exec/types.h>
#include <proto/exec.h>
#include <proto/dos.h>

#include <exec/memory.h>
#include <exec/interrupts.h>

#include <dos/dos.h>


#include <stdio.h>

uint32 *beef;


struct IData {
uint32 counter;
struct Interrupt *oldinterrupt;
};

struct IData *idata;

#if 0//This will not work, because it doesn't call the old interrupt
asm (
".globl icoden"
"n"
"icode:n"
"lwz %r3, 0(%r5)n"
"addi %r3, %r3, 5n"
"stw %r3, 0(%r5)n"
"li %r3, 1n"
"blrn"
);
#endif


ULONG icode( struct ExceptionContext *context, struct ExecBase *sb, APTR trapData)
{
struct IData *d = (struct IData *)trapData;
struct Interrupt *oldi = d->oldinterrupt;

d->counter++;

//NB-NB-NB: You _need_ to call the old interrupt, otherwise you will go boom!
typedef uint32 (*OLDVEC)();

return ((OLDVEC)oldi->is_Code)(context, sb, oldi->is_Data);
}


int main()
{
enum enTrapNumbers trapnumber = TRAPNUM_DATA_SEGMENT_VIOLATION;

if (!(idata = IExec->AllocMem(sizeof(struct IData), MEMF_SHARED | MEMF_CLEAR)))
return RETURN_FAIL;

struct Interrupt *interrupt = IExec->AllocSysObjectTags(ASOT_INTERRUPT,
ASOINTR_Code, icode,
ASOINTR_Data, idata,
TAG_END);

if (interrupt == NULL)
{
IExec->FreeMem (idata, sizeof (struct IData));
return(-20);
}

interrupt->is_Node.ln_Pri = -1;
interrupt->is_Node.ln_Name = "my personal interrupt";

//printf("icode = %#08xn", icode (NULL, NULL, idata));
//printf("counter = %dn", idata->counter);

printf("calling AddIntServer...n");
fflush(stdout);

//IExec->Forbid();
idata->oldinterrupt = IExec->SetIntVector(trapnumber, interrupt);
//IExec->Permit();

if(!idata->oldinterrupt)
{
printf("server not installed!n");
}
else
{
printf("server installedn");
fflush(stdout);

idata->counter = 0;

//#if 0
/* cause a data storage violation: */
beef = (uint32 *)0;
*beef = 0L;
//#endif

IDOS->Delay(10);

printf("counter = %dn", idata->counter);

/* Remember to restore the old interrupt vector, or you will die ;-) */
IExec->SetIntVector(trapnumber, idata->oldinterrupt);
}

IExec->FreeSysObject(ASOT_INTERRUPT, interrupt);
IExec->FreeMem (idata, sizeof (struct IData));

return 0;
}



Rate this item
12345678910


Last poster Message


Posted: 2010-06-15 06:09 · Edited by: Hypex
Hi Alfkil.

I also had the same problem myself and enquired of Thomas at the time. It is unfortunate that AddIntServer() won't work as the SetIntVector() solution is a bit permanent and not as multitasking friendly.

It does work for vertical blanking interrupts, however. Even with 68K.

I'd like to add that an early version of AllocSysObjectTags(), at least from OS4.0 had a bug where it did not clear the memory it returned for the struct Interrupt. As we usually set the fields ourselves this would usually not be a problem but I found that the Node fields were trashed with random data and that made it a problem!

I worked around this by specifying ASOT_MemoryOvr, MEMF_PUBLIC | MEMF_CLEAR. If this is no longer necessary then that is good. :-)

Given the above code, it's a useful skeleton for catching illegal memory access, or even possibly custom chip space access for emulation. ;-)

I am hoping in the future that we will be provided access to such features, being able to add our own interrupt safely for this. Or even use the MMU API to do it at an equally safe level. Of course, this is the reason that no such mechanism was said to exist, and why we have to "hack" it into the system because the OS4 developers don't want us touching this stuff and risking system instability with core low level functions.

:: Your comment
Bold Style  Italic Style  Underlined Style  Image Link  Insert URL  Email Link  Quote  C/C++ Source  Disable *What`s that?


Before posting non-english message, check your browser`s encoding!
» Name » Password

UtilityBase is a site focused on development for Amiga systems,
spanning over all different Amiga clones, that be AmigaOS 3.x, 4.x, MorphOS, AROS or AmigaDE/Anywhere.
News syndication: RSS
Contact address: mail@utilitybase com