[BACK]Return to intr.h CVS log [TXT][DIR] Up to [local] / sys / arch / sgi / include

File: [local] / sys / arch / sgi / include / intr.h (download)

Revision 1.1, Tue Mar 4 16:07:51 2008 UTC (16 years, 3 months ago) by nbrk
Branch point for: MAIN

Initial revision

/*	$OpenBSD: intr.h,v 1.18 2007/06/20 16:50:41 miod Exp $ */

/*
 * Copyright (c) 2001-2004 Opsycon AB  (www.opsycon.se / www.opsycon.com)
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 */

#ifndef _MACHINE_INTR_H_
#define _MACHINE_INTR_H_

/*
 *  The interrupt mask cpl is a mask which can be used with the
 *  CPU interrupt mask register or an external HW mask register.
 *  If interrupts are masked by the CPU interrupt mask all external
 *  masks should be enabled and any routing set up so that the
 *  interrupt source is routed to the CPU interrupt corresponding
 *  to the interrupts "priority level". In this case the generic
 *  interrupt handler can be used.
 *
 *  The IMASK_EXTERNAL define is used to select whether the CPU
 *  interrupt mask should be controlled by the cpl mask value
 *  or not. If the mask is external, the CPU mask is never changed
 *  from the value it gets when interrupt dispatchers are registred.
 *  When an external masking register is used dedicated interrupt
 *  handlers must be written as well as ipending handlers.
 */
#define	IMASK_EXTERNAL		/* XXX move this to config */

/* This define controls whether splraise is inlined or not */
/* #define INLINE_SPLRAISE */


/* Interrupt priority `levels'; not mutually exclusive. */
#define	IPL_NONE	0	/* nothing */
#define	IPL_BIO		1	/* block I/O */
#define IPL_AUDIO	IPL_BIO
#define	IPL_NET		2	/* network */
#define	IPL_TTY		3	/* terminal */
#define	IPL_VM		4	/* memory allocation */
#define	IPL_CLOCK	5	/* clock */
#define	IPL_HIGH	6	/* everything */
#define	NIPLS		7	/* Number of levels */

/* Interrupt sharing types. */
#define	IST_NONE	0	/* none */
#define	IST_PULSE	1	/* pulsed */
#define	IST_EDGE	2	/* edge-triggered */
#define	IST_LEVEL	3	/* level-triggered */

/* Soft interrupt masks. */
#define	SINT_CLOCK	31
#define	SINT_CLOCKMASK	(1 << SINT_CLOCK)
#define	SINT_NET	30
#define	SINT_NETMASK	((1 << SINT_NET) | SINT_CLOCKMASK)
#define	SINT_TTY	29
#define	SINT_TTYMASK	((1 << SINT_TTY) | SINT_CLOCKMASK)
#define	SINT_ALLMASK	(SINT_CLOCKMASK | SINT_NETMASK | SINT_TTYMASK)
#define	SPL_CLOCK	28
#define	SPL_CLOCKMASK	(1 << SPL_CLOCK)

#ifndef _LOCORE

#define splbio()		splraise(imask[IPL_BIO])
#define splnet()		splraise(imask[IPL_NET])
#define spltty()		splraise(imask[IPL_TTY])
#define splaudio()		splraise(imask[IPL_AUDIO])
#define splclock()		splraise(imask[IPL_CLOCK])
#define splvm()			splraise(imask[IPL_VM])
#define splsoftclock()		splraise(SINT_CLOCKMASK)
#define splsoftnet()		splraise(SINT_NETMASK|SINT_CLOCKMASK)
#define splsofttty()		splraise(SINT_TTYMASK)
#define splstatclock()		splhigh()
#define splsched()		splhigh()
#define splhigh()		splraise(-1)
#define spl0()			spllower(0)

#include <machine/atomic.h>

#define setsoftclock()  	atomic_setbits_int(&ipending, SINT_CLOCKMASK)
#define setsoftnet()    	atomic_setbits_int(&ipending, SINT_NETMASK)
#define setsofttty()    	atomic_setbits_int(&ipending, SINT_TTYMASK)

void	splinit(void);

#define	splassert(X)

/*
 *  Schedule prioritys for base interrupts (cpu)
 */
#define	INTPRI_CLOCK	1
#define	INTPRI_MACEIO	2	/* O2 I/O interrupt */
#define	INTPRI_XBOWMUX	2	/* Origin 200/2000 I/O interrupt */
#define	INTPRI_MACEAUX	3

/*
 *   Define a type for interrupt masks. We may need 64 bits here.
 */
typedef u_int32_t intrmask_t;		/* Type of var holding interrupt mask */

#define	INTMASKSIZE	(sizeof(intrmask_t) * 8)

extern volatile intrmask_t cpl;
extern volatile intrmask_t ipending;
extern volatile intrmask_t astpending;

extern intrmask_t imask[NIPLS];

/*
 *  A note on clock interrupts. Clock interrupts are always
 *  allowed to happen but will not be serviced if masked.
 *  The reason for this is that clocks usually sits on INT5
 *  and can not be easily masked if external HW masking is used.
 */

/* Inlines */
static __inline void register_pending_int_handler(void (*)(int));
static __inline void splx(int newcpl);
static __inline int spllower(int newcpl);

typedef void  (int_f) (int);
extern int_f *pending_hand;

static __inline void
register_pending_int_handler(void(*pending)(int))
{
	pending_hand = pending;
}

/*
 */
#ifdef INLINE_SPLRAISE
static __inline int splraise(int newcpl);
static __inline int
splraise(int newcpl)
{
	int oldcpl;

	__asm__ (" .set noreorder\n");
	oldcpl = cpl;
	cpl = oldcpl | newcpl;
	__asm__ (" sync\n .set reorder\n");
	return (oldcpl);
}
#else
int splraise(int newcpl);
#endif

static __inline void
splx(int newcpl)
{
	if (ipending & ~newcpl)
		(*pending_hand)(newcpl);
	else
		cpl = newcpl;
}

static __inline int
spllower(int newcpl)
{
	int oldcpl;

	oldcpl = cpl;
	if (ipending & ~newcpl)
		(*pending_hand)(newcpl);
	else
		cpl = newcpl;
	return (oldcpl);
}

/*
 * Interrupt control struct used by interrupt dispatchers
 * to hold interrupt handler info.
 */

#include <sys/evcount.h>

struct intrhand {
	struct	intrhand *ih_next;
	int	(*ih_fun)(void *);
	void	*ih_arg;
	int	ih_level;
	int	ih_irq;
	char	*ih_what;
	void	*frame;
	struct evcount  ih_count;
};

extern struct intrhand *intrhand[INTMASKSIZE];

/*
 * Low level interrupt dispatcher registration data.
 */
#define NLOWINT	16		/* Number of low level registrations possible */

struct trap_frame;

extern intrmask_t idle_mask;
extern int last_low_int;

void set_intr(int, intrmask_t, intrmask_t(*)(intrmask_t, struct trap_frame *));

#ifdef IMASK_EXTERNAL
void hw_setintrmask(intrmask_t);
extern void *hwmask_addr;
#endif

/*
 *  Generic interrupt handling code that can be used for simple
 *  interrupt hardware models. Functions can also be used by
 *  more complex code especially the mask calculation code.
 */

void *generic_intr_establish(void *, u_long, int, int,
	    int (*)(void *), void *, char *);
void generic_intr_disestablish(void *, void *);
void generic_intr_makemasks(void);
void generic_do_pending_int(int);
intrmask_t generic_iointr(intrmask_t, struct trap_frame *);

#endif /* _LOCORE */

#endif /* _MACHINE_INTR_H_ */