2001-10-23 03:01:17 +04:00
|
|
|
/* $NetBSD: ofwgen_intr.c,v 1.1 2001/10/22 23:01:19 thorpej Exp $ */
|
1997-04-17 01:20:35 +04:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Copyright (C) 1997 Wolfgang Solfrank.
|
|
|
|
* Copyright (C) 1997 TooLs GmbH.
|
|
|
|
* All rights reserved.
|
|
|
|
*
|
|
|
|
* 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.
|
|
|
|
* 3. All advertising materials mentioning features or use of this software
|
|
|
|
* must display the following acknowledgement:
|
|
|
|
* This product includes software developed by TooLs GmbH.
|
|
|
|
* 4. The name of TooLs GmbH may not be used to endorse or promote products
|
|
|
|
* derived from this software without specific prior written permission.
|
|
|
|
*
|
|
|
|
* THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``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 TOOLS GMBH 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.
|
|
|
|
*/
|
2001-10-23 03:01:17 +04:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Software-simulated spl/interrupt routines. Used in generic
|
|
|
|
* OpenFirmware driver configurations.
|
|
|
|
*/
|
|
|
|
|
1997-04-17 01:20:35 +04:00
|
|
|
#include <sys/param.h>
|
2001-08-26 06:47:33 +04:00
|
|
|
#include <sys/systm.h>
|
1997-04-17 01:20:35 +04:00
|
|
|
|
2001-08-26 06:47:33 +04:00
|
|
|
#include <machine/autoconf.h>
|
1997-04-17 01:20:35 +04:00
|
|
|
|
2001-10-23 03:01:17 +04:00
|
|
|
static int ofwgen_splhigh(void);
|
|
|
|
static int ofwgen_spl0(void);
|
|
|
|
static int ofwgen_splbio(void);
|
|
|
|
static int ofwgen_splnet(void);
|
|
|
|
static int ofwgen_spltty(void);
|
|
|
|
static int ofwgen_splvm(void);
|
|
|
|
static int ofwgen_splclock(void);
|
|
|
|
static int ofwgen_spllowersoftclock(void);
|
|
|
|
static int ofwgen_splsoftclock(void);
|
|
|
|
static int ofwgen_splsoftnet(void);
|
|
|
|
static int ofwgen_splx(int);
|
|
|
|
static void ofwgen_setsoftclock(void);
|
|
|
|
static void ofwgen_setsoftnet(void);
|
|
|
|
static void ofwgen_clock_return(struct clockframe *, int);
|
|
|
|
static void ofwgen_irq_establish(int, int, void (*)(void *), void *);
|
|
|
|
|
|
|
|
struct machvec ofwgen_machvec = {
|
|
|
|
ofwgen_splhigh,
|
|
|
|
ofwgen_spl0,
|
|
|
|
ofwgen_splbio,
|
|
|
|
ofwgen_splnet,
|
|
|
|
ofwgen_spltty,
|
|
|
|
ofwgen_splvm,
|
|
|
|
ofwgen_splclock,
|
|
|
|
ofwgen_spllowersoftclock,
|
|
|
|
ofwgen_splsoftclock,
|
|
|
|
ofwgen_splsoftnet,
|
|
|
|
ofwgen_splx,
|
|
|
|
ofwgen_setsoftclock,
|
|
|
|
ofwgen_setsoftnet,
|
|
|
|
ofwgen_clock_return,
|
|
|
|
ofwgen_irq_establish,
|
1997-04-17 01:20:35 +04:00
|
|
|
};
|
|
|
|
|
|
|
|
/*
|
2001-10-23 03:01:17 +04:00
|
|
|
* Current interrupt priority level.
|
1997-04-17 01:20:35 +04:00
|
|
|
*/
|
2001-10-23 03:01:17 +04:00
|
|
|
static int cpl;
|
|
|
|
|
1997-04-17 01:20:35 +04:00
|
|
|
#define SPLBIO 0x01
|
|
|
|
#define SPLNET 0x02
|
|
|
|
#define SPLTTY 0x04
|
|
|
|
#define SPLIMP 0x08
|
|
|
|
#define SPLSOFTCLOCK 0x10
|
|
|
|
#define SPLSOFTNET 0x20
|
|
|
|
#define SPLCLOCK 0x80
|
|
|
|
|
|
|
|
static int clockpending, softclockpending, softnetpending;
|
|
|
|
|
|
|
|
static int
|
2001-08-26 06:47:33 +04:00
|
|
|
splraise(int bits)
|
1997-04-17 01:20:35 +04:00
|
|
|
{
|
|
|
|
int old;
|
|
|
|
|
|
|
|
old = cpl;
|
|
|
|
cpl |= bits;
|
|
|
|
|
|
|
|
return old;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2001-10-23 03:01:17 +04:00
|
|
|
ofwgen_splx(int new)
|
1997-04-17 01:20:35 +04:00
|
|
|
{
|
2001-08-26 06:47:33 +04:00
|
|
|
int old = cpl;
|
1997-04-17 01:20:35 +04:00
|
|
|
int emsr, dmsr;
|
|
|
|
|
2001-10-23 03:01:17 +04:00
|
|
|
__asm __volatile ("mfmsr %0" : "=r"(emsr));
|
1997-04-17 01:20:35 +04:00
|
|
|
dmsr = emsr & ~PSL_EE;
|
|
|
|
|
|
|
|
cpl = new;
|
|
|
|
|
|
|
|
while (1) {
|
|
|
|
cpl = new;
|
|
|
|
|
2001-10-23 03:01:17 +04:00
|
|
|
__asm __volatile ("mtmsr %0" :: "r"(dmsr));
|
1997-04-17 01:20:35 +04:00
|
|
|
if (clockpending && !(cpl & SPLCLOCK)) {
|
|
|
|
struct clockframe frame;
|
|
|
|
|
|
|
|
cpl |= SPLCLOCK;
|
|
|
|
clockpending--;
|
2001-10-23 03:01:17 +04:00
|
|
|
__asm __volatile ("mtmsr %0" :: "r"(emsr));
|
1997-04-17 01:20:35 +04:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Fake a clock interrupt frame
|
|
|
|
*/
|
|
|
|
frame.pri = new;
|
|
|
|
frame.depth = intr_depth + 1;
|
|
|
|
frame.srr1 = 0;
|
2001-10-23 03:01:17 +04:00
|
|
|
frame.srr0 = (int)ofwgen_splx;
|
1997-04-17 01:20:35 +04:00
|
|
|
/*
|
|
|
|
* Do standard timer interrupt stuff
|
|
|
|
*/
|
|
|
|
hardclock(&frame);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (softclockpending && !(cpl & SPLSOFTCLOCK)) {
|
|
|
|
cpl |= SPLSOFTCLOCK;
|
|
|
|
softclockpending = 0;
|
2001-10-23 03:01:17 +04:00
|
|
|
__asm __volatile ("mtmsr %0" :: "r"(emsr));
|
2001-01-15 23:19:50 +03:00
|
|
|
softclock(NULL);
|
1997-04-17 01:20:35 +04:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (softnetpending && !(cpl & SPLSOFTNET)) {
|
|
|
|
cpl |= SPLSOFTNET;
|
|
|
|
softnetpending = 0;
|
2001-10-23 03:01:17 +04:00
|
|
|
__asm __volatile ("mtmsr %0" :: "r"(emsr));
|
1997-04-17 01:20:35 +04:00
|
|
|
softnet();
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2001-10-23 03:01:17 +04:00
|
|
|
__asm __volatile ("mtmsr %0" :: "r"(emsr));
|
1997-04-17 01:20:35 +04:00
|
|
|
return old;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2001-10-23 03:01:17 +04:00
|
|
|
ofwgen_splhigh(void)
|
1997-04-17 01:20:35 +04:00
|
|
|
{
|
2001-10-23 03:01:17 +04:00
|
|
|
|
1997-04-17 01:20:35 +04:00
|
|
|
return splraise(-1);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2001-10-23 03:01:17 +04:00
|
|
|
ofwgen_spl0(void)
|
1997-04-17 01:20:35 +04:00
|
|
|
{
|
2001-10-23 03:01:17 +04:00
|
|
|
|
|
|
|
return ofwgen_splx(0);
|
1997-04-17 01:20:35 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2001-10-23 03:01:17 +04:00
|
|
|
ofwgen_splbio(void)
|
1997-04-17 01:20:35 +04:00
|
|
|
{
|
2001-10-23 03:01:17 +04:00
|
|
|
|
1997-04-17 01:20:35 +04:00
|
|
|
return splraise(SPLBIO | SPLSOFTCLOCK | SPLSOFTNET);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2001-10-23 03:01:17 +04:00
|
|
|
ofwgen_splnet(void)
|
1997-04-17 01:20:35 +04:00
|
|
|
{
|
2001-10-23 03:01:17 +04:00
|
|
|
|
1997-04-17 01:20:35 +04:00
|
|
|
return splraise(SPLNET | SPLSOFTCLOCK | SPLSOFTNET);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2001-10-23 03:01:17 +04:00
|
|
|
ofwgen_spltty(void)
|
1997-04-17 01:20:35 +04:00
|
|
|
{
|
2001-10-23 03:01:17 +04:00
|
|
|
|
1997-04-17 01:20:35 +04:00
|
|
|
return splraise(SPLTTY | SPLSOFTCLOCK | SPLSOFTNET);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2001-10-23 03:01:17 +04:00
|
|
|
ofwgen_splvm(void)
|
1997-04-17 01:20:35 +04:00
|
|
|
{
|
2001-10-23 03:01:17 +04:00
|
|
|
|
2001-10-06 07:51:48 +04:00
|
|
|
return splraise(SPLIMP | SPLBIO | SPLNET | SPLTTY | SPLSOFTCLOCK |
|
|
|
|
SPLSOFTNET);
|
1997-04-17 01:20:35 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2001-10-23 03:01:17 +04:00
|
|
|
ofwgen_splclock(void)
|
1997-04-17 01:20:35 +04:00
|
|
|
{
|
2001-10-23 03:01:17 +04:00
|
|
|
|
1997-04-17 01:20:35 +04:00
|
|
|
return splraise(SPLCLOCK | SPLSOFTCLOCK | SPLSOFTNET);
|
|
|
|
}
|
|
|
|
|
1999-08-05 22:08:08 +04:00
|
|
|
static int
|
2001-10-23 03:01:17 +04:00
|
|
|
ofwgen_spllowersoftclock(void)
|
1999-08-05 22:08:08 +04:00
|
|
|
{
|
2001-10-23 03:01:17 +04:00
|
|
|
|
|
|
|
return ofwgen_splx(SPLSOFTCLOCK);
|
1999-08-05 22:08:08 +04:00
|
|
|
}
|
|
|
|
|
1997-04-17 01:20:35 +04:00
|
|
|
static int
|
2001-10-23 03:01:17 +04:00
|
|
|
ofwgen_splsoftclock(void)
|
1997-04-17 01:20:35 +04:00
|
|
|
{
|
2001-10-23 03:01:17 +04:00
|
|
|
|
1997-04-17 01:20:35 +04:00
|
|
|
return splraise(SPLSOFTCLOCK);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2001-10-23 03:01:17 +04:00
|
|
|
ofwgen_splsoftnet(void)
|
1997-04-17 01:20:35 +04:00
|
|
|
{
|
2001-10-23 03:01:17 +04:00
|
|
|
|
2001-10-06 07:51:48 +04:00
|
|
|
/* splsoftnet() needs to block softclock */
|
|
|
|
return splraise(SPLSOFTNET|SPLSOFTCLOCK);
|
1997-04-17 01:20:35 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2001-10-23 03:01:17 +04:00
|
|
|
ofwgen_setsoftclock(void)
|
1997-04-17 01:20:35 +04:00
|
|
|
{
|
2001-10-23 03:01:17 +04:00
|
|
|
|
1997-04-17 01:20:35 +04:00
|
|
|
softclockpending = 1;
|
|
|
|
if (!(cpl & SPLSOFTCLOCK))
|
2001-10-23 03:01:17 +04:00
|
|
|
ofwgen_splx(cpl);
|
1997-04-17 01:20:35 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2001-10-23 03:01:17 +04:00
|
|
|
ofwgen_setsoftnet(void)
|
1997-04-17 01:20:35 +04:00
|
|
|
{
|
2001-10-23 03:01:17 +04:00
|
|
|
|
1997-04-17 01:20:35 +04:00
|
|
|
softnetpending = 1;
|
|
|
|
if (!(cpl & SPLSOFTNET))
|
2001-10-23 03:01:17 +04:00
|
|
|
ofwgen_splx(cpl);
|
1997-04-17 01:20:35 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2001-10-23 03:01:17 +04:00
|
|
|
ofwgen_irq_establish(int irq, int level, void (*handler)(void *), void *arg)
|
1997-04-17 01:20:35 +04:00
|
|
|
{
|
2001-10-23 03:01:17 +04:00
|
|
|
|
|
|
|
panic("ofwgen_irq_establish");
|
1997-04-17 01:20:35 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2001-10-23 03:01:17 +04:00
|
|
|
* This one is similar to ofwgen_splx, but returns with interrupts disabled.
|
1997-04-17 01:20:35 +04:00
|
|
|
* It is intended for use during interrupt exit (as the name implies :-)).
|
|
|
|
*/
|
|
|
|
static void
|
2001-08-26 06:47:33 +04:00
|
|
|
intr_return(struct clockframe *frame, int level)
|
1997-04-17 01:20:35 +04:00
|
|
|
{
|
|
|
|
int emsr, dmsr;
|
|
|
|
|
2001-10-23 03:01:17 +04:00
|
|
|
__asm __volatile ("mfmsr %0" : "=r"(emsr));
|
1997-04-17 01:20:35 +04:00
|
|
|
dmsr = emsr & ~PSL_EE;
|
|
|
|
|
|
|
|
cpl = level;
|
|
|
|
|
|
|
|
while (1) {
|
|
|
|
cpl = level;
|
|
|
|
|
2001-10-23 03:01:17 +04:00
|
|
|
__asm __volatile ("mtmsr %0" :: "r"(dmsr));
|
1997-04-17 01:20:35 +04:00
|
|
|
if (clockpending && !(cpl & SPLCLOCK)) {
|
|
|
|
cpl |= SPLCLOCK;
|
|
|
|
clockpending--;
|
2001-10-23 03:01:17 +04:00
|
|
|
__asm __volatile ("mtmsr %0" :: "r"(emsr));
|
1997-04-17 01:20:35 +04:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Do standard timer interrupt stuff
|
|
|
|
*/
|
|
|
|
hardclock(frame);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (softclockpending && !(cpl & SPLSOFTCLOCK)) {
|
|
|
|
|
|
|
|
cpl |= SPLSOFTCLOCK;
|
|
|
|
softclockpending = 0;
|
2001-10-23 03:01:17 +04:00
|
|
|
__asm __volatile ("mtmsr %0" :: "r"(emsr));
|
1997-04-17 01:20:35 +04:00
|
|
|
|
2001-08-26 06:47:33 +04:00
|
|
|
softclock(NULL);
|
1997-04-17 01:20:35 +04:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (softnetpending && !(cpl & SPLSOFTNET)) {
|
|
|
|
cpl |= SPLSOFTNET;
|
|
|
|
softnetpending = 0;
|
2001-10-23 03:01:17 +04:00
|
|
|
__asm __volatile ("mtmsr %0" :: "r"(emsr));
|
1997-04-17 01:20:35 +04:00
|
|
|
softnet();
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2001-10-23 03:01:17 +04:00
|
|
|
ofwgen_clock_return(struct clockframe *frame, int nticks)
|
1997-04-17 01:20:35 +04:00
|
|
|
{
|
2001-10-23 03:01:17 +04:00
|
|
|
int pri, msr;
|
1997-04-17 01:20:35 +04:00
|
|
|
|
|
|
|
pri = cpl;
|
|
|
|
|
|
|
|
if (pri & SPLCLOCK)
|
|
|
|
clockpending += nticks;
|
|
|
|
else {
|
|
|
|
cpl = pri | SPLCLOCK | SPLSOFTCLOCK | SPLSOFTNET;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Reenable interrupts
|
|
|
|
*/
|
2001-10-23 03:01:17 +04:00
|
|
|
__asm __volatile ("mfmsr %0; ori %0,%0,%1; mtmsr %0"
|
1997-04-17 01:20:35 +04:00
|
|
|
: "=r"(msr) : "K"((u_short)PSL_EE));
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Do standard timer interrupt stuff.
|
|
|
|
* Do softclock stuff only on the last iteration.
|
|
|
|
*/
|
|
|
|
frame->pri = pri | SPLSOFTCLOCK;
|
|
|
|
while (--nticks > 0)
|
|
|
|
hardclock(frame);
|
|
|
|
frame->pri = pri;
|
|
|
|
hardclock(frame);
|
|
|
|
}
|
|
|
|
intr_return(frame, pri);
|
|
|
|
}
|