Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/geert/linux-m68k
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/geert/linux-m68k: (29 commits) m68k/mac: Remove mac_irq_{en,dis}able() wrappers m68k/irq: Remove obsolete support for user vector interrupt fixups m68k/irq: Remove obsolete m68k irq framework m68k/q40: Convert Q40/Q60 to genirq m68k/sun3: Convert Sun3/3x to genirq m68k/sun3: Use the kstat_irqs_cpu() wrapper m68k/apollo: Convert Apollo to genirq m68k/vme: Convert VME to genirq m68k/hp300: Convert HP9000/300 and HP9000/400 to genirq m68k/mac: Optimize interrupts using chain handlers m68k/mac: Convert Mac to genirq m68k/amiga: Optimize interrupts using chain handlers m68k/amiga: Convert Amiga to genirq m68k/amiga: Refactor amiints.c m68k/atari: Remove code and comments about different irq types m68k/atari: Convert Atari to genirq m68k/irq: Add genirq support m68k/irq: Remove obsolete IRQ_FLG_* users m68k/irq: Rename {,__}m68k_handle_int() m68k/irq: Add m68k_setup_irq_controller() ...
This commit is contained in:
Коммит
8f042aa75a
|
@ -4,8 +4,8 @@ config M68K
|
|||
select HAVE_IDE
|
||||
select HAVE_AOUT if MMU
|
||||
select GENERIC_ATOMIC64 if MMU
|
||||
select HAVE_GENERIC_HARDIRQS if !MMU
|
||||
select GENERIC_IRQ_SHOW if !MMU
|
||||
select HAVE_GENERIC_HARDIRQS
|
||||
select GENERIC_IRQ_SHOW
|
||||
select ARCH_HAVE_NMI_SAFE_CMPXCHG if RMW_INSNS
|
||||
|
||||
config RWSEM_GENERIC_SPINLOCK
|
||||
|
|
|
@ -2,6 +2,15 @@ if MMU
|
|||
|
||||
comment "Bus Support"
|
||||
|
||||
config DIO
|
||||
bool "DIO bus support"
|
||||
depends on HP300
|
||||
default y
|
||||
help
|
||||
Say Y here to enable support for the "DIO" expansion bus used in
|
||||
HP300 machines. If you are using such a system you almost certainly
|
||||
want this.
|
||||
|
||||
config NUBUS
|
||||
bool
|
||||
depends on MAC
|
||||
|
|
|
@ -24,6 +24,37 @@ config PROC_HARDWARE
|
|||
including the model, CPU, MMU, clock speed, BogoMIPS rating,
|
||||
and memory size.
|
||||
|
||||
config NATFEAT
|
||||
bool "ARAnyM emulator support"
|
||||
depends on ATARI
|
||||
help
|
||||
This option enables support for ARAnyM native features, such as
|
||||
access to a disk image as /dev/hda.
|
||||
|
||||
config NFBLOCK
|
||||
tristate "NatFeat block device support"
|
||||
depends on BLOCK && NATFEAT
|
||||
help
|
||||
Say Y to include support for the ARAnyM NatFeat block device
|
||||
which allows direct access to the hard drives without using
|
||||
the hardware emulation.
|
||||
|
||||
config NFCON
|
||||
tristate "NatFeat console driver"
|
||||
depends on NATFEAT
|
||||
help
|
||||
Say Y to include support for the ARAnyM NatFeat console driver
|
||||
which allows the console output to be redirected to the stderr
|
||||
output of ARAnyM.
|
||||
|
||||
config NFETH
|
||||
tristate "NatFeat Ethernet support"
|
||||
depends on ETHERNET && NATFEAT
|
||||
help
|
||||
Say Y to include support for the ARAnyM NatFeat network device
|
||||
which will emulate a regular ethernet device while presenting an
|
||||
ethertap device to the host system.
|
||||
|
||||
endmenu
|
||||
|
||||
menu "Character devices"
|
||||
|
|
|
@ -1,43 +1,15 @@
|
|||
/*
|
||||
* linux/arch/m68k/amiga/amiints.c -- Amiga Linux interrupt handling code
|
||||
* Amiga Linux interrupt handling code
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU General Public
|
||||
* License. See the file COPYING in the main directory of this archive
|
||||
* for more details.
|
||||
*
|
||||
* 11/07/96: rewritten interrupt handling, irq lists are exists now only for
|
||||
* this sources where it makes sense (VERTB/PORTS/EXTER) and you must
|
||||
* be careful that dev_id for this sources is unique since this the
|
||||
* only possibility to distinguish between different handlers for
|
||||
* free_irq. irq lists also have different irq flags:
|
||||
* - IRQ_FLG_FAST: handler is inserted at top of list (after other
|
||||
* fast handlers)
|
||||
* - IRQ_FLG_SLOW: handler is inserted at bottom of list and before
|
||||
* they're executed irq level is set to the previous
|
||||
* one, but handlers don't need to be reentrant, if
|
||||
* reentrance occurred, slow handlers will be just
|
||||
* called again.
|
||||
* The whole interrupt handling for CIAs is moved to cia.c
|
||||
* /Roman Zippel
|
||||
*
|
||||
* 07/08/99: rewamp of the interrupt handling - we now have two types of
|
||||
* interrupts, normal and fast handlers, fast handlers being
|
||||
* marked with IRQF_DISABLED and runs with all other interrupts
|
||||
* disabled. Normal interrupts disable their own source but
|
||||
* run with all other interrupt sources enabled.
|
||||
* PORTS and EXTER interrupts are always shared even if the
|
||||
* drivers do not explicitly mark this when calling
|
||||
* request_irq which they really should do.
|
||||
* This is similar to the way interrupts are handled on all
|
||||
* other architectures and makes a ton of sense besides
|
||||
* having the advantage of making it easier to share
|
||||
* drivers.
|
||||
* /Jes
|
||||
*/
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/irq.h>
|
||||
|
||||
#include <asm/irq.h>
|
||||
#include <asm/traps.h>
|
||||
|
@ -45,20 +17,128 @@
|
|||
#include <asm/amigaints.h>
|
||||
#include <asm/amipcmcia.h>
|
||||
|
||||
static void amiga_enable_irq(unsigned int irq);
|
||||
static void amiga_disable_irq(unsigned int irq);
|
||||
static irqreturn_t ami_int1(int irq, void *dev_id);
|
||||
static irqreturn_t ami_int3(int irq, void *dev_id);
|
||||
static irqreturn_t ami_int4(int irq, void *dev_id);
|
||||
static irqreturn_t ami_int5(int irq, void *dev_id);
|
||||
|
||||
static struct irq_controller amiga_irq_controller = {
|
||||
/*
|
||||
* Enable/disable a particular machine specific interrupt source.
|
||||
* Note that this may affect other interrupts in case of a shared interrupt.
|
||||
* This function should only be called for a _very_ short time to change some
|
||||
* internal data, that may not be changed by the interrupt at the same time.
|
||||
*/
|
||||
|
||||
static void amiga_irq_enable(struct irq_data *data)
|
||||
{
|
||||
amiga_custom.intena = IF_SETCLR | (1 << (data->irq - IRQ_USER));
|
||||
}
|
||||
|
||||
static void amiga_irq_disable(struct irq_data *data)
|
||||
{
|
||||
amiga_custom.intena = 1 << (data->irq - IRQ_USER);
|
||||
}
|
||||
|
||||
static struct irq_chip amiga_irq_chip = {
|
||||
.name = "amiga",
|
||||
.lock = __SPIN_LOCK_UNLOCKED(amiga_irq_controller.lock),
|
||||
.enable = amiga_enable_irq,
|
||||
.disable = amiga_disable_irq,
|
||||
.irq_enable = amiga_irq_enable,
|
||||
.irq_disable = amiga_irq_disable,
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* The builtin Amiga hardware interrupt handlers.
|
||||
*/
|
||||
|
||||
static void ami_int1(unsigned int irq, struct irq_desc *desc)
|
||||
{
|
||||
unsigned short ints = amiga_custom.intreqr & amiga_custom.intenar;
|
||||
|
||||
/* if serial transmit buffer empty, interrupt */
|
||||
if (ints & IF_TBE) {
|
||||
amiga_custom.intreq = IF_TBE;
|
||||
generic_handle_irq(IRQ_AMIGA_TBE);
|
||||
}
|
||||
|
||||
/* if floppy disk transfer complete, interrupt */
|
||||
if (ints & IF_DSKBLK) {
|
||||
amiga_custom.intreq = IF_DSKBLK;
|
||||
generic_handle_irq(IRQ_AMIGA_DSKBLK);
|
||||
}
|
||||
|
||||
/* if software interrupt set, interrupt */
|
||||
if (ints & IF_SOFT) {
|
||||
amiga_custom.intreq = IF_SOFT;
|
||||
generic_handle_irq(IRQ_AMIGA_SOFT);
|
||||
}
|
||||
}
|
||||
|
||||
static void ami_int3(unsigned int irq, struct irq_desc *desc)
|
||||
{
|
||||
unsigned short ints = amiga_custom.intreqr & amiga_custom.intenar;
|
||||
|
||||
/* if a blitter interrupt */
|
||||
if (ints & IF_BLIT) {
|
||||
amiga_custom.intreq = IF_BLIT;
|
||||
generic_handle_irq(IRQ_AMIGA_BLIT);
|
||||
}
|
||||
|
||||
/* if a copper interrupt */
|
||||
if (ints & IF_COPER) {
|
||||
amiga_custom.intreq = IF_COPER;
|
||||
generic_handle_irq(IRQ_AMIGA_COPPER);
|
||||
}
|
||||
|
||||
/* if a vertical blank interrupt */
|
||||
if (ints & IF_VERTB) {
|
||||
amiga_custom.intreq = IF_VERTB;
|
||||
generic_handle_irq(IRQ_AMIGA_VERTB);
|
||||
}
|
||||
}
|
||||
|
||||
static void ami_int4(unsigned int irq, struct irq_desc *desc)
|
||||
{
|
||||
unsigned short ints = amiga_custom.intreqr & amiga_custom.intenar;
|
||||
|
||||
/* if audio 0 interrupt */
|
||||
if (ints & IF_AUD0) {
|
||||
amiga_custom.intreq = IF_AUD0;
|
||||
generic_handle_irq(IRQ_AMIGA_AUD0);
|
||||
}
|
||||
|
||||
/* if audio 1 interrupt */
|
||||
if (ints & IF_AUD1) {
|
||||
amiga_custom.intreq = IF_AUD1;
|
||||
generic_handle_irq(IRQ_AMIGA_AUD1);
|
||||
}
|
||||
|
||||
/* if audio 2 interrupt */
|
||||
if (ints & IF_AUD2) {
|
||||
amiga_custom.intreq = IF_AUD2;
|
||||
generic_handle_irq(IRQ_AMIGA_AUD2);
|
||||
}
|
||||
|
||||
/* if audio 3 interrupt */
|
||||
if (ints & IF_AUD3) {
|
||||
amiga_custom.intreq = IF_AUD3;
|
||||
generic_handle_irq(IRQ_AMIGA_AUD3);
|
||||
}
|
||||
}
|
||||
|
||||
static void ami_int5(unsigned int irq, struct irq_desc *desc)
|
||||
{
|
||||
unsigned short ints = amiga_custom.intreqr & amiga_custom.intenar;
|
||||
|
||||
/* if serial receive buffer full interrupt */
|
||||
if (ints & IF_RBF) {
|
||||
/* acknowledge of IF_RBF must be done by the serial interrupt */
|
||||
generic_handle_irq(IRQ_AMIGA_RBF);
|
||||
}
|
||||
|
||||
/* if a disk sync interrupt */
|
||||
if (ints & IF_DSKSYN) {
|
||||
amiga_custom.intreq = IF_DSKSYN;
|
||||
generic_handle_irq(IRQ_AMIGA_DSKSYN);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* void amiga_init_IRQ(void)
|
||||
*
|
||||
|
@ -72,16 +152,13 @@ static struct irq_controller amiga_irq_controller = {
|
|||
|
||||
void __init amiga_init_IRQ(void)
|
||||
{
|
||||
if (request_irq(IRQ_AUTO_1, ami_int1, 0, "int1", NULL))
|
||||
pr_err("Couldn't register int%d\n", 1);
|
||||
if (request_irq(IRQ_AUTO_3, ami_int3, 0, "int3", NULL))
|
||||
pr_err("Couldn't register int%d\n", 3);
|
||||
if (request_irq(IRQ_AUTO_4, ami_int4, 0, "int4", NULL))
|
||||
pr_err("Couldn't register int%d\n", 4);
|
||||
if (request_irq(IRQ_AUTO_5, ami_int5, 0, "int5", NULL))
|
||||
pr_err("Couldn't register int%d\n", 5);
|
||||
m68k_setup_irq_controller(&amiga_irq_chip, handle_simple_irq, IRQ_USER,
|
||||
AMI_STD_IRQS);
|
||||
|
||||
m68k_setup_irq_controller(&amiga_irq_controller, IRQ_USER, AMI_STD_IRQS);
|
||||
irq_set_chained_handler(IRQ_AUTO_1, ami_int1);
|
||||
irq_set_chained_handler(IRQ_AUTO_3, ami_int3);
|
||||
irq_set_chained_handler(IRQ_AUTO_4, ami_int4);
|
||||
irq_set_chained_handler(IRQ_AUTO_5, ami_int5);
|
||||
|
||||
/* turn off PCMCIA interrupts */
|
||||
if (AMIGAHW_PRESENT(PCMCIA))
|
||||
|
@ -95,120 +172,3 @@ void __init amiga_init_IRQ(void)
|
|||
cia_init_IRQ(&ciaa_base);
|
||||
cia_init_IRQ(&ciab_base);
|
||||
}
|
||||
|
||||
/*
|
||||
* Enable/disable a particular machine specific interrupt source.
|
||||
* Note that this may affect other interrupts in case of a shared interrupt.
|
||||
* This function should only be called for a _very_ short time to change some
|
||||
* internal data, that may not be changed by the interrupt at the same time.
|
||||
*/
|
||||
|
||||
static void amiga_enable_irq(unsigned int irq)
|
||||
{
|
||||
amiga_custom.intena = IF_SETCLR | (1 << (irq - IRQ_USER));
|
||||
}
|
||||
|
||||
static void amiga_disable_irq(unsigned int irq)
|
||||
{
|
||||
amiga_custom.intena = 1 << (irq - IRQ_USER);
|
||||
}
|
||||
|
||||
/*
|
||||
* The builtin Amiga hardware interrupt handlers.
|
||||
*/
|
||||
|
||||
static irqreturn_t ami_int1(int irq, void *dev_id)
|
||||
{
|
||||
unsigned short ints = amiga_custom.intreqr & amiga_custom.intenar;
|
||||
|
||||
/* if serial transmit buffer empty, interrupt */
|
||||
if (ints & IF_TBE) {
|
||||
amiga_custom.intreq = IF_TBE;
|
||||
m68k_handle_int(IRQ_AMIGA_TBE);
|
||||
}
|
||||
|
||||
/* if floppy disk transfer complete, interrupt */
|
||||
if (ints & IF_DSKBLK) {
|
||||
amiga_custom.intreq = IF_DSKBLK;
|
||||
m68k_handle_int(IRQ_AMIGA_DSKBLK);
|
||||
}
|
||||
|
||||
/* if software interrupt set, interrupt */
|
||||
if (ints & IF_SOFT) {
|
||||
amiga_custom.intreq = IF_SOFT;
|
||||
m68k_handle_int(IRQ_AMIGA_SOFT);
|
||||
}
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static irqreturn_t ami_int3(int irq, void *dev_id)
|
||||
{
|
||||
unsigned short ints = amiga_custom.intreqr & amiga_custom.intenar;
|
||||
|
||||
/* if a blitter interrupt */
|
||||
if (ints & IF_BLIT) {
|
||||
amiga_custom.intreq = IF_BLIT;
|
||||
m68k_handle_int(IRQ_AMIGA_BLIT);
|
||||
}
|
||||
|
||||
/* if a copper interrupt */
|
||||
if (ints & IF_COPER) {
|
||||
amiga_custom.intreq = IF_COPER;
|
||||
m68k_handle_int(IRQ_AMIGA_COPPER);
|
||||
}
|
||||
|
||||
/* if a vertical blank interrupt */
|
||||
if (ints & IF_VERTB) {
|
||||
amiga_custom.intreq = IF_VERTB;
|
||||
m68k_handle_int(IRQ_AMIGA_VERTB);
|
||||
}
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static irqreturn_t ami_int4(int irq, void *dev_id)
|
||||
{
|
||||
unsigned short ints = amiga_custom.intreqr & amiga_custom.intenar;
|
||||
|
||||
/* if audio 0 interrupt */
|
||||
if (ints & IF_AUD0) {
|
||||
amiga_custom.intreq = IF_AUD0;
|
||||
m68k_handle_int(IRQ_AMIGA_AUD0);
|
||||
}
|
||||
|
||||
/* if audio 1 interrupt */
|
||||
if (ints & IF_AUD1) {
|
||||
amiga_custom.intreq = IF_AUD1;
|
||||
m68k_handle_int(IRQ_AMIGA_AUD1);
|
||||
}
|
||||
|
||||
/* if audio 2 interrupt */
|
||||
if (ints & IF_AUD2) {
|
||||
amiga_custom.intreq = IF_AUD2;
|
||||
m68k_handle_int(IRQ_AMIGA_AUD2);
|
||||
}
|
||||
|
||||
/* if audio 3 interrupt */
|
||||
if (ints & IF_AUD3) {
|
||||
amiga_custom.intreq = IF_AUD3;
|
||||
m68k_handle_int(IRQ_AMIGA_AUD3);
|
||||
}
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static irqreturn_t ami_int5(int irq, void *dev_id)
|
||||
{
|
||||
unsigned short ints = amiga_custom.intreqr & amiga_custom.intenar;
|
||||
|
||||
/* if serial receive buffer full interrupt */
|
||||
if (ints & IF_RBF) {
|
||||
/* acknowledge of IF_RBF must be done by the serial interrupt */
|
||||
m68k_handle_int(IRQ_AMIGA_RBF);
|
||||
}
|
||||
|
||||
/* if a disk sync interrupt */
|
||||
if (ints & IF_DSKSYN) {
|
||||
amiga_custom.intreq = IF_DSKSYN;
|
||||
m68k_handle_int(IRQ_AMIGA_DSKSYN);
|
||||
}
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
|
|
@ -93,13 +93,14 @@ static irqreturn_t cia_handler(int irq, void *dev_id)
|
|||
amiga_custom.intreq = base->int_mask;
|
||||
for (; ints; mach_irq++, ints >>= 1) {
|
||||
if (ints & 1)
|
||||
m68k_handle_int(mach_irq);
|
||||
generic_handle_irq(mach_irq);
|
||||
}
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static void cia_enable_irq(unsigned int irq)
|
||||
static void cia_irq_enable(struct irq_data *data)
|
||||
{
|
||||
unsigned int irq = data->irq;
|
||||
unsigned char mask;
|
||||
|
||||
if (irq >= IRQ_AMIGA_CIAB) {
|
||||
|
@ -113,19 +114,20 @@ static void cia_enable_irq(unsigned int irq)
|
|||
}
|
||||
}
|
||||
|
||||
static void cia_disable_irq(unsigned int irq)
|
||||
static void cia_irq_disable(struct irq_data *data)
|
||||
{
|
||||
unsigned int irq = data->irq;
|
||||
|
||||
if (irq >= IRQ_AMIGA_CIAB)
|
||||
cia_able_irq(&ciab_base, 1 << (irq - IRQ_AMIGA_CIAB));
|
||||
else
|
||||
cia_able_irq(&ciaa_base, 1 << (irq - IRQ_AMIGA_CIAA));
|
||||
}
|
||||
|
||||
static struct irq_controller cia_irq_controller = {
|
||||
static struct irq_chip cia_irq_chip = {
|
||||
.name = "cia",
|
||||
.lock = __SPIN_LOCK_UNLOCKED(cia_irq_controller.lock),
|
||||
.enable = cia_enable_irq,
|
||||
.disable = cia_disable_irq,
|
||||
.irq_enable = cia_irq_enable,
|
||||
.irq_disable = cia_irq_disable,
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -134,9 +136,9 @@ static struct irq_controller cia_irq_controller = {
|
|||
* into this chain.
|
||||
*/
|
||||
|
||||
static void auto_enable_irq(unsigned int irq)
|
||||
static void auto_irq_enable(struct irq_data *data)
|
||||
{
|
||||
switch (irq) {
|
||||
switch (data->irq) {
|
||||
case IRQ_AUTO_2:
|
||||
amiga_custom.intena = IF_SETCLR | IF_PORTS;
|
||||
break;
|
||||
|
@ -146,9 +148,9 @@ static void auto_enable_irq(unsigned int irq)
|
|||
}
|
||||
}
|
||||
|
||||
static void auto_disable_irq(unsigned int irq)
|
||||
static void auto_irq_disable(struct irq_data *data)
|
||||
{
|
||||
switch (irq) {
|
||||
switch (data->irq) {
|
||||
case IRQ_AUTO_2:
|
||||
amiga_custom.intena = IF_PORTS;
|
||||
break;
|
||||
|
@ -158,24 +160,25 @@ static void auto_disable_irq(unsigned int irq)
|
|||
}
|
||||
}
|
||||
|
||||
static struct irq_controller auto_irq_controller = {
|
||||
static struct irq_chip auto_irq_chip = {
|
||||
.name = "auto",
|
||||
.lock = __SPIN_LOCK_UNLOCKED(auto_irq_controller.lock),
|
||||
.enable = auto_enable_irq,
|
||||
.disable = auto_disable_irq,
|
||||
.irq_enable = auto_irq_enable,
|
||||
.irq_disable = auto_irq_disable,
|
||||
};
|
||||
|
||||
void __init cia_init_IRQ(struct ciabase *base)
|
||||
{
|
||||
m68k_setup_irq_controller(&cia_irq_controller, base->cia_irq, CIA_IRQS);
|
||||
m68k_setup_irq_controller(&cia_irq_chip, handle_simple_irq,
|
||||
base->cia_irq, CIA_IRQS);
|
||||
|
||||
/* clear any pending interrupt and turn off all interrupts */
|
||||
cia_set_irq(base, CIA_ICR_ALL);
|
||||
cia_able_irq(base, CIA_ICR_ALL);
|
||||
|
||||
/* override auto int and install CIA handler */
|
||||
m68k_setup_irq_controller(&auto_irq_controller, base->handler_irq, 1);
|
||||
m68k_irq_startup(base->handler_irq);
|
||||
m68k_setup_irq_controller(&auto_irq_chip, handle_simple_irq,
|
||||
base->handler_irq, 1);
|
||||
m68k_irq_startup_irq(base->handler_irq);
|
||||
if (request_irq(base->handler_irq, cia_handler, IRQF_SHARED,
|
||||
base->name, base))
|
||||
pr_err("Couldn't register %s interrupt\n", base->name);
|
||||
|
|
|
@ -1,19 +1,13 @@
|
|||
#include <linux/interrupt.h>
|
||||
#include <linux/irq.h>
|
||||
|
||||
#include <asm/irq.h>
|
||||
#include <asm/traps.h>
|
||||
#include <asm/apollohw.h>
|
||||
|
||||
void dn_process_int(unsigned int irq, struct pt_regs *fp)
|
||||
unsigned int apollo_irq_startup(struct irq_data *data)
|
||||
{
|
||||
__m68k_handle_int(irq, fp);
|
||||
unsigned int irq = data->irq;
|
||||
|
||||
*(volatile unsigned char *)(pica)=0x20;
|
||||
*(volatile unsigned char *)(picb)=0x20;
|
||||
}
|
||||
|
||||
int apollo_irq_startup(unsigned int irq)
|
||||
{
|
||||
if (irq < 8)
|
||||
*(volatile unsigned char *)(pica+1) &= ~(1 << irq);
|
||||
else
|
||||
|
@ -21,24 +15,33 @@ int apollo_irq_startup(unsigned int irq)
|
|||
return 0;
|
||||
}
|
||||
|
||||
void apollo_irq_shutdown(unsigned int irq)
|
||||
void apollo_irq_shutdown(struct irq_data *data)
|
||||
{
|
||||
unsigned int irq = data->irq;
|
||||
|
||||
if (irq < 8)
|
||||
*(volatile unsigned char *)(pica+1) |= (1 << irq);
|
||||
else
|
||||
*(volatile unsigned char *)(picb+1) |= (1 << (irq - 8));
|
||||
}
|
||||
|
||||
static struct irq_controller apollo_irq_controller = {
|
||||
void apollo_irq_eoi(struct irq_data *data)
|
||||
{
|
||||
*(volatile unsigned char *)(pica) = 0x20;
|
||||
*(volatile unsigned char *)(picb) = 0x20;
|
||||
}
|
||||
|
||||
static struct irq_chip apollo_irq_chip = {
|
||||
.name = "apollo",
|
||||
.lock = __SPIN_LOCK_UNLOCKED(apollo_irq_controller.lock),
|
||||
.startup = apollo_irq_startup,
|
||||
.shutdown = apollo_irq_shutdown,
|
||||
.irq_startup = apollo_irq_startup,
|
||||
.irq_shutdown = apollo_irq_shutdown,
|
||||
.irq_eoi = apollo_irq_eoi,
|
||||
};
|
||||
|
||||
|
||||
void __init dn_init_IRQ(void)
|
||||
{
|
||||
m68k_setup_user_interrupt(VEC_USER + 96, 16, dn_process_int);
|
||||
m68k_setup_irq_controller(&apollo_irq_controller, IRQ_APOLLO, 16);
|
||||
m68k_setup_user_interrupt(VEC_USER + 96, 16);
|
||||
m68k_setup_irq_controller(&apollo_irq_chip, handle_fasteoi_irq,
|
||||
IRQ_APOLLO, 16);
|
||||
}
|
||||
|
|
|
@ -60,244 +60,8 @@
|
|||
* <asm/atariints.h>): Autovector interrupts are 1..7, then follow ST-MFP,
|
||||
* TT-MFP, SCC, and finally VME interrupts. Vector numbers for the latter can
|
||||
* be allocated by atari_register_vme_int().
|
||||
*
|
||||
* Each interrupt can be of three types:
|
||||
*
|
||||
* - SLOW: The handler runs with all interrupts enabled, except the one it
|
||||
* was called by (to avoid reentering). This should be the usual method.
|
||||
* But it is currently possible only for MFP ints, since only the MFP
|
||||
* offers an easy way to mask interrupts.
|
||||
*
|
||||
* - FAST: The handler runs with all interrupts disabled. This should be used
|
||||
* only for really fast handlers, that just do actions immediately
|
||||
* necessary, and let the rest do a bottom half or task queue.
|
||||
*
|
||||
* - PRIORITIZED: The handler can be interrupted by higher-level ints
|
||||
* (greater IPL, no MFP priorities!). This is the method of choice for ints
|
||||
* which should be slow, but are not from a MFP.
|
||||
*
|
||||
* The feature of more than one handler for one int source is still there, but
|
||||
* only applicable if all handers are of the same type. To not slow down
|
||||
* processing of ints with only one handler by the chaining feature, the list
|
||||
* calling function atari_call_irq_list() is only plugged in at the time the
|
||||
* second handler is registered.
|
||||
*
|
||||
* Implementation notes: For fast-as-possible int handling, there are separate
|
||||
* entry points for each type (slow/fast/prio). The assembler handler calls
|
||||
* the irq directly in the usual case, no C wrapper is involved. In case of
|
||||
* multiple handlers, atari_call_irq_list() is registered as handler and calls
|
||||
* in turn the real irq's. To ease access from assembler level to the irq
|
||||
* function pointer and accompanying data, these two are stored in a separate
|
||||
* array, irq_handler[]. The rest of data (type, name) are put into a second
|
||||
* array, irq_param, that is accessed from C only. For each slow interrupt (32
|
||||
* in all) there are separate handler functions, which makes it possible to
|
||||
* hard-code the MFP register address and value, are necessary to mask the
|
||||
* int. If there'd be only one generic function, lots of calculations would be
|
||||
* needed to determine MFP register and int mask from the vector number :-(
|
||||
*
|
||||
* Furthermore, slow ints may not lower the IPL below its previous value
|
||||
* (before the int happened). This is needed so that an int of class PRIO, on
|
||||
* that this int may be stacked, cannot be reentered. This feature is
|
||||
* implemented as follows: If the stack frame format is 1 (throwaway), the int
|
||||
* is not stacked, and the IPL is anded with 0xfbff, resulting in a new level
|
||||
* 2, which still blocks the HSYNC, but no interrupts of interest. If the
|
||||
* frame format is 0, the int is nested, and the old IPL value can be found in
|
||||
* the sr copy in the frame.
|
||||
*/
|
||||
|
||||
#if 0
|
||||
|
||||
#define NUM_INT_SOURCES (8 + NUM_ATARI_SOURCES)
|
||||
|
||||
typedef void (*asm_irq_handler)(void);
|
||||
|
||||
struct irqhandler {
|
||||
irqreturn_t (*handler)(int, void *, struct pt_regs *);
|
||||
void *dev_id;
|
||||
};
|
||||
|
||||
struct irqparam {
|
||||
unsigned long flags;
|
||||
const char *devname;
|
||||
};
|
||||
|
||||
/*
|
||||
* Array with irq's and their parameter data. This array is accessed from low
|
||||
* level assembler code, so an element size of 8 allows usage of index scaling
|
||||
* addressing mode.
|
||||
*/
|
||||
static struct irqhandler irq_handler[NUM_INT_SOURCES];
|
||||
|
||||
/*
|
||||
* This array hold the rest of parameters of int handlers: type
|
||||
* (slow,fast,prio) and the name of the handler. These values are only
|
||||
* accessed from C
|
||||
*/
|
||||
static struct irqparam irq_param[NUM_INT_SOURCES];
|
||||
|
||||
/* check for valid int number (complex, sigh...) */
|
||||
#define IS_VALID_INTNO(n) \
|
||||
((n) > 0 && \
|
||||
/* autovec and ST-MFP ok anyway */ \
|
||||
(((n) < TTMFP_SOURCE_BASE) || \
|
||||
/* TT-MFP ok if present */ \
|
||||
((n) >= TTMFP_SOURCE_BASE && (n) < SCC_SOURCE_BASE && \
|
||||
ATARIHW_PRESENT(TT_MFP)) || \
|
||||
/* SCC ok if present and number even */ \
|
||||
((n) >= SCC_SOURCE_BASE && (n) < VME_SOURCE_BASE && \
|
||||
!((n) & 1) && ATARIHW_PRESENT(SCC)) || \
|
||||
/* greater numbers ok if they are registered VME vectors */ \
|
||||
((n) >= VME_SOURCE_BASE && (n) < VME_SOURCE_BASE + VME_MAX_SOURCES && \
|
||||
free_vme_vec_bitmap & (1 << ((n) - VME_SOURCE_BASE)))))
|
||||
|
||||
|
||||
/*
|
||||
* Here start the assembler entry points for interrupts
|
||||
*/
|
||||
|
||||
#define IRQ_NAME(nr) atari_slow_irq_##nr##_handler(void)
|
||||
|
||||
#define BUILD_SLOW_IRQ(n) \
|
||||
asmlinkage void IRQ_NAME(n); \
|
||||
/* Dummy function to allow asm with operands. */ \
|
||||
void atari_slow_irq_##n##_dummy (void) { \
|
||||
__asm__ (__ALIGN_STR "\n" \
|
||||
"atari_slow_irq_" #n "_handler:\t" \
|
||||
" addl %6,%5\n" /* preempt_count() += HARDIRQ_OFFSET */ \
|
||||
SAVE_ALL_INT "\n" \
|
||||
GET_CURRENT(%%d0) "\n" \
|
||||
" andb #~(1<<(%c3&7)),%a4:w\n" /* mask this interrupt */ \
|
||||
/* get old IPL from stack frame */ \
|
||||
" bfextu %%sp@(%c2){#5,#3},%%d0\n" \
|
||||
" movew %%sr,%%d1\n" \
|
||||
" bfins %%d0,%%d1{#21,#3}\n" \
|
||||
" movew %%d1,%%sr\n" /* set IPL = previous value */ \
|
||||
" addql #1,%a0\n" \
|
||||
" lea %a1,%%a0\n" \
|
||||
" pea %%sp@\n" /* push addr of frame */ \
|
||||
" movel %%a0@(4),%%sp@-\n" /* push handler data */ \
|
||||
" pea (%c3+8)\n" /* push int number */ \
|
||||
" movel %%a0@,%%a0\n" \
|
||||
" jbsr %%a0@\n" /* call the handler */ \
|
||||
" addql #8,%%sp\n" \
|
||||
" addql #4,%%sp\n" \
|
||||
" orw #0x0600,%%sr\n" \
|
||||
" andw #0xfeff,%%sr\n" /* set IPL = 6 again */ \
|
||||
" orb #(1<<(%c3&7)),%a4:w\n" /* now unmask the int again */ \
|
||||
" jbra ret_from_interrupt\n" \
|
||||
: : "i" (&kstat_cpu(0).irqs[n+8]), "i" (&irq_handler[n+8]), \
|
||||
"n" (PT_OFF_SR), "n" (n), \
|
||||
"i" (n & 8 ? (n & 16 ? &tt_mfp.int_mk_a : &st_mfp.int_mk_a) \
|
||||
: (n & 16 ? &tt_mfp.int_mk_b : &st_mfp.int_mk_b)), \
|
||||
"m" (preempt_count()), "di" (HARDIRQ_OFFSET) \
|
||||
); \
|
||||
for (;;); /* fake noreturn */ \
|
||||
}
|
||||
|
||||
BUILD_SLOW_IRQ(0);
|
||||
BUILD_SLOW_IRQ(1);
|
||||
BUILD_SLOW_IRQ(2);
|
||||
BUILD_SLOW_IRQ(3);
|
||||
BUILD_SLOW_IRQ(4);
|
||||
BUILD_SLOW_IRQ(5);
|
||||
BUILD_SLOW_IRQ(6);
|
||||
BUILD_SLOW_IRQ(7);
|
||||
BUILD_SLOW_IRQ(8);
|
||||
BUILD_SLOW_IRQ(9);
|
||||
BUILD_SLOW_IRQ(10);
|
||||
BUILD_SLOW_IRQ(11);
|
||||
BUILD_SLOW_IRQ(12);
|
||||
BUILD_SLOW_IRQ(13);
|
||||
BUILD_SLOW_IRQ(14);
|
||||
BUILD_SLOW_IRQ(15);
|
||||
BUILD_SLOW_IRQ(16);
|
||||
BUILD_SLOW_IRQ(17);
|
||||
BUILD_SLOW_IRQ(18);
|
||||
BUILD_SLOW_IRQ(19);
|
||||
BUILD_SLOW_IRQ(20);
|
||||
BUILD_SLOW_IRQ(21);
|
||||
BUILD_SLOW_IRQ(22);
|
||||
BUILD_SLOW_IRQ(23);
|
||||
BUILD_SLOW_IRQ(24);
|
||||
BUILD_SLOW_IRQ(25);
|
||||
BUILD_SLOW_IRQ(26);
|
||||
BUILD_SLOW_IRQ(27);
|
||||
BUILD_SLOW_IRQ(28);
|
||||
BUILD_SLOW_IRQ(29);
|
||||
BUILD_SLOW_IRQ(30);
|
||||
BUILD_SLOW_IRQ(31);
|
||||
|
||||
asm_irq_handler slow_handlers[32] = {
|
||||
[0] = atari_slow_irq_0_handler,
|
||||
[1] = atari_slow_irq_1_handler,
|
||||
[2] = atari_slow_irq_2_handler,
|
||||
[3] = atari_slow_irq_3_handler,
|
||||
[4] = atari_slow_irq_4_handler,
|
||||
[5] = atari_slow_irq_5_handler,
|
||||
[6] = atari_slow_irq_6_handler,
|
||||
[7] = atari_slow_irq_7_handler,
|
||||
[8] = atari_slow_irq_8_handler,
|
||||
[9] = atari_slow_irq_9_handler,
|
||||
[10] = atari_slow_irq_10_handler,
|
||||
[11] = atari_slow_irq_11_handler,
|
||||
[12] = atari_slow_irq_12_handler,
|
||||
[13] = atari_slow_irq_13_handler,
|
||||
[14] = atari_slow_irq_14_handler,
|
||||
[15] = atari_slow_irq_15_handler,
|
||||
[16] = atari_slow_irq_16_handler,
|
||||
[17] = atari_slow_irq_17_handler,
|
||||
[18] = atari_slow_irq_18_handler,
|
||||
[19] = atari_slow_irq_19_handler,
|
||||
[20] = atari_slow_irq_20_handler,
|
||||
[21] = atari_slow_irq_21_handler,
|
||||
[22] = atari_slow_irq_22_handler,
|
||||
[23] = atari_slow_irq_23_handler,
|
||||
[24] = atari_slow_irq_24_handler,
|
||||
[25] = atari_slow_irq_25_handler,
|
||||
[26] = atari_slow_irq_26_handler,
|
||||
[27] = atari_slow_irq_27_handler,
|
||||
[28] = atari_slow_irq_28_handler,
|
||||
[29] = atari_slow_irq_29_handler,
|
||||
[30] = atari_slow_irq_30_handler,
|
||||
[31] = atari_slow_irq_31_handler
|
||||
};
|
||||
|
||||
asmlinkage void atari_fast_irq_handler( void );
|
||||
asmlinkage void atari_prio_irq_handler( void );
|
||||
|
||||
/* Dummy function to allow asm with operands. */
|
||||
void atari_fast_prio_irq_dummy (void) {
|
||||
__asm__ (__ALIGN_STR "\n"
|
||||
"atari_fast_irq_handler:\n\t"
|
||||
"orw #0x700,%%sr\n" /* disable all interrupts */
|
||||
"atari_prio_irq_handler:\n\t"
|
||||
"addl %3,%2\n\t" /* preempt_count() += HARDIRQ_OFFSET */
|
||||
SAVE_ALL_INT "\n\t"
|
||||
GET_CURRENT(%%d0) "\n\t"
|
||||
/* get vector number from stack frame and convert to source */
|
||||
"bfextu %%sp@(%c1){#4,#10},%%d0\n\t"
|
||||
"subw #(0x40-8),%%d0\n\t"
|
||||
"jpl 1f\n\t"
|
||||
"addw #(0x40-8-0x18),%%d0\n"
|
||||
"1:\tlea %a0,%%a0\n\t"
|
||||
"addql #1,%%a0@(%%d0:l:4)\n\t"
|
||||
"lea irq_handler,%%a0\n\t"
|
||||
"lea %%a0@(%%d0:l:8),%%a0\n\t"
|
||||
"pea %%sp@\n\t" /* push frame address */
|
||||
"movel %%a0@(4),%%sp@-\n\t" /* push handler data */
|
||||
"movel %%d0,%%sp@-\n\t" /* push int number */
|
||||
"movel %%a0@,%%a0\n\t"
|
||||
"jsr %%a0@\n\t" /* and call the handler */
|
||||
"addql #8,%%sp\n\t"
|
||||
"addql #4,%%sp\n\t"
|
||||
"jbra ret_from_interrupt"
|
||||
: : "i" (&kstat_cpu(0).irqs), "n" (PT_OFF_FORMATVEC),
|
||||
"m" (preempt_count()), "di" (HARDIRQ_OFFSET)
|
||||
);
|
||||
for (;;);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Bitmap for free interrupt vector numbers
|
||||
* (new vectors starting from 0x70 can be allocated by
|
||||
|
@ -320,31 +84,44 @@ extern void atari_microwire_cmd(int cmd);
|
|||
|
||||
extern int atari_SCC_reset_done;
|
||||
|
||||
static int atari_startup_irq(unsigned int irq)
|
||||
static unsigned int atari_irq_startup(struct irq_data *data)
|
||||
{
|
||||
m68k_irq_startup(irq);
|
||||
unsigned int irq = data->irq;
|
||||
|
||||
m68k_irq_startup(data);
|
||||
atari_turnon_irq(irq);
|
||||
atari_enable_irq(irq);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void atari_shutdown_irq(unsigned int irq)
|
||||
static void atari_irq_shutdown(struct irq_data *data)
|
||||
{
|
||||
unsigned int irq = data->irq;
|
||||
|
||||
atari_disable_irq(irq);
|
||||
atari_turnoff_irq(irq);
|
||||
m68k_irq_shutdown(irq);
|
||||
m68k_irq_shutdown(data);
|
||||
|
||||
if (irq == IRQ_AUTO_4)
|
||||
vectors[VEC_INT4] = falcon_hblhandler;
|
||||
}
|
||||
|
||||
static struct irq_controller atari_irq_controller = {
|
||||
static void atari_irq_enable(struct irq_data *data)
|
||||
{
|
||||
atari_enable_irq(data->irq);
|
||||
}
|
||||
|
||||
static void atari_irq_disable(struct irq_data *data)
|
||||
{
|
||||
atari_disable_irq(data->irq);
|
||||
}
|
||||
|
||||
static struct irq_chip atari_irq_chip = {
|
||||
.name = "atari",
|
||||
.lock = __SPIN_LOCK_UNLOCKED(atari_irq_controller.lock),
|
||||
.startup = atari_startup_irq,
|
||||
.shutdown = atari_shutdown_irq,
|
||||
.enable = atari_enable_irq,
|
||||
.disable = atari_disable_irq,
|
||||
.irq_startup = atari_irq_startup,
|
||||
.irq_shutdown = atari_irq_shutdown,
|
||||
.irq_enable = atari_irq_enable,
|
||||
.irq_disable = atari_irq_disable,
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -360,8 +137,9 @@ static struct irq_controller atari_irq_controller = {
|
|||
|
||||
void __init atari_init_IRQ(void)
|
||||
{
|
||||
m68k_setup_user_interrupt(VEC_USER, NUM_ATARI_SOURCES - IRQ_USER, NULL);
|
||||
m68k_setup_irq_controller(&atari_irq_controller, 1, NUM_ATARI_SOURCES - 1);
|
||||
m68k_setup_user_interrupt(VEC_USER, NUM_ATARI_SOURCES - IRQ_USER);
|
||||
m68k_setup_irq_controller(&atari_irq_chip, handle_simple_irq, 1,
|
||||
NUM_ATARI_SOURCES - 1);
|
||||
|
||||
/* Initialize the MFP(s) */
|
||||
|
||||
|
|
|
@ -86,7 +86,7 @@ static void bvme6000_get_model(char *model)
|
|||
*/
|
||||
static void __init bvme6000_init_IRQ(void)
|
||||
{
|
||||
m68k_setup_user_interrupt(VEC_USER, 192, NULL);
|
||||
m68k_setup_user_interrupt(VEC_USER, 192);
|
||||
}
|
||||
|
||||
void __init config_bvme6000(void)
|
||||
|
|
|
@ -70,7 +70,7 @@ void __init hp300_sched_init(irq_handler_t vector)
|
|||
|
||||
asm volatile(" movpw %0,%1@(5)" : : "d" (INTVAL), "a" (CLOCKBASE));
|
||||
|
||||
if (request_irq(IRQ_AUTO_6, hp300_tick, IRQ_FLG_STD, "timer tick", vector))
|
||||
if (request_irq(IRQ_AUTO_6, hp300_tick, 0, "timer tick", vector))
|
||||
pr_err("Couldn't register timer interrupt\n");
|
||||
|
||||
out_8(CLOCKBASE + CLKCR2, 0x1); /* select CR1 */
|
||||
|
|
|
@ -18,6 +18,11 @@
|
|||
|
||||
#ifdef CONFIG_MMU
|
||||
|
||||
static inline void ack_bad_irq(unsigned int irq)
|
||||
{
|
||||
pr_crit("unexpected IRQ trap at vector %02x\n", irq);
|
||||
}
|
||||
|
||||
/* entry.S is sensitive to the offsets of these fields */
|
||||
typedef struct {
|
||||
unsigned int __softirq_pending;
|
||||
|
|
|
@ -27,11 +27,6 @@
|
|||
|
||||
#ifdef CONFIG_MMU
|
||||
|
||||
#include <linux/linkage.h>
|
||||
#include <linux/hardirq.h>
|
||||
#include <linux/irqreturn.h>
|
||||
#include <linux/spinlock_types.h>
|
||||
|
||||
/*
|
||||
* Interrupt source definitions
|
||||
* General interrupt sources are the level 1-7.
|
||||
|
@ -54,10 +49,6 @@
|
|||
|
||||
#define IRQ_USER 8
|
||||
|
||||
extern unsigned int irq_canonicalize(unsigned int irq);
|
||||
|
||||
struct pt_regs;
|
||||
|
||||
/*
|
||||
* various flags for request_irq() - the Amiga now uses the standard
|
||||
* mechanism like all other architectures - IRQF_DISABLED and
|
||||
|
@ -71,57 +62,27 @@ struct pt_regs;
|
|||
#define IRQ_FLG_STD (0x8000) /* internally used */
|
||||
#endif
|
||||
|
||||
/*
|
||||
* This structure is used to chain together the ISRs for a particular
|
||||
* interrupt source (if it supports chaining).
|
||||
*/
|
||||
typedef struct irq_node {
|
||||
irqreturn_t (*handler)(int, void *);
|
||||
void *dev_id;
|
||||
struct irq_node *next;
|
||||
unsigned long flags;
|
||||
const char *devname;
|
||||
} irq_node_t;
|
||||
struct irq_data;
|
||||
struct irq_chip;
|
||||
struct irq_desc;
|
||||
extern unsigned int m68k_irq_startup(struct irq_data *data);
|
||||
extern unsigned int m68k_irq_startup_irq(unsigned int irq);
|
||||
extern void m68k_irq_shutdown(struct irq_data *data);
|
||||
extern void m68k_setup_auto_interrupt(void (*handler)(unsigned int,
|
||||
struct pt_regs *));
|
||||
extern void m68k_setup_user_interrupt(unsigned int vec, unsigned int cnt);
|
||||
extern void m68k_setup_irq_controller(struct irq_chip *,
|
||||
void (*handle)(unsigned int irq,
|
||||
struct irq_desc *desc),
|
||||
unsigned int irq, unsigned int cnt);
|
||||
|
||||
/*
|
||||
* This structure has only 4 elements for speed reasons
|
||||
*/
|
||||
struct irq_handler {
|
||||
int (*handler)(int, void *);
|
||||
unsigned long flags;
|
||||
void *dev_id;
|
||||
const char *devname;
|
||||
};
|
||||
|
||||
struct irq_controller {
|
||||
const char *name;
|
||||
spinlock_t lock;
|
||||
int (*startup)(unsigned int irq);
|
||||
void (*shutdown)(unsigned int irq);
|
||||
void (*enable)(unsigned int irq);
|
||||
void (*disable)(unsigned int irq);
|
||||
};
|
||||
|
||||
extern int m68k_irq_startup(unsigned int);
|
||||
extern void m68k_irq_shutdown(unsigned int);
|
||||
|
||||
/*
|
||||
* This function returns a new irq_node_t
|
||||
*/
|
||||
extern irq_node_t *new_irq_node(void);
|
||||
|
||||
extern void m68k_setup_auto_interrupt(void (*handler)(unsigned int, struct pt_regs *));
|
||||
extern void m68k_setup_user_interrupt(unsigned int vec, unsigned int cnt,
|
||||
void (*handler)(unsigned int, struct pt_regs *));
|
||||
extern void m68k_setup_irq_controller(struct irq_controller *, unsigned int, unsigned int);
|
||||
|
||||
asmlinkage void m68k_handle_int(unsigned int);
|
||||
asmlinkage void __m68k_handle_int(unsigned int, struct pt_regs *);
|
||||
extern unsigned int irq_canonicalize(unsigned int irq);
|
||||
|
||||
#else
|
||||
#define irq_canonicalize(irq) (irq)
|
||||
#endif /* CONFIG_MMU */
|
||||
|
||||
asmlinkage void do_IRQ(int irq, struct pt_regs *regs);
|
||||
extern atomic_t irq_err_count;
|
||||
|
||||
#endif /* _M68K_IRQ_H_ */
|
||||
|
|
|
@ -12,6 +12,8 @@ extern void mac_reset(void);
|
|||
extern void mac_poweroff(void);
|
||||
extern void mac_init_IRQ(void);
|
||||
extern int mac_irq_pending(unsigned int);
|
||||
extern void mac_irq_enable(struct irq_data *data);
|
||||
extern void mac_irq_disable(struct irq_data *data);
|
||||
|
||||
/*
|
||||
* Floppy driver magic hook - probably shouldn't be here
|
||||
|
|
|
@ -24,6 +24,3 @@
|
|||
#define Q40_IRQ10_MASK (1<<5)
|
||||
#define Q40_IRQ14_MASK (1<<6)
|
||||
#define Q40_IRQ15_MASK (1<<7)
|
||||
|
||||
extern unsigned long q40_probe_irq_on (void);
|
||||
extern int q40_probe_irq_off (unsigned long irqs);
|
||||
|
|
|
@ -6,16 +6,15 @@ extra-$(CONFIG_MMU) := head.o
|
|||
extra-$(CONFIG_SUN3) := sun3-head.o
|
||||
extra-y += vmlinux.lds
|
||||
|
||||
obj-y := entry.o m68k_ksyms.o module.o process.o ptrace.o setup.o signal.o \
|
||||
sys_m68k.o syscalltable.o time.o traps.o
|
||||
obj-y := entry.o irq.o m68k_ksyms.o module.o process.o ptrace.o setup.o \
|
||||
signal.o sys_m68k.o syscalltable.o time.o traps.o
|
||||
|
||||
obj-$(CONFIG_MMU) += ints.o devres.o vectors.o
|
||||
devres-$(CONFIG_MMU) = ../../../kernel/irq/devres.o
|
||||
obj-$(CONFIG_MMU) += ints.o vectors.o
|
||||
|
||||
ifndef CONFIG_MMU_SUN3
|
||||
obj-y += dma.o
|
||||
endif
|
||||
ifndef CONFIG_MMU
|
||||
obj-y += init_task.o irq.o
|
||||
obj-y += init_task.o
|
||||
endif
|
||||
|
||||
|
|
|
@ -48,7 +48,7 @@
|
|||
.globl sys_fork, sys_clone, sys_vfork
|
||||
.globl ret_from_interrupt, bad_interrupt
|
||||
.globl auto_irqhandler_fixup
|
||||
.globl user_irqvec_fixup, user_irqhandler_fixup
|
||||
.globl user_irqvec_fixup
|
||||
|
||||
.text
|
||||
ENTRY(buserr)
|
||||
|
@ -207,7 +207,7 @@ ENTRY(auto_inthandler)
|
|||
movel %sp,%sp@-
|
||||
movel %d0,%sp@- | put vector # on stack
|
||||
auto_irqhandler_fixup = . + 2
|
||||
jsr __m68k_handle_int | process the IRQ
|
||||
jsr do_IRQ | process the IRQ
|
||||
addql #8,%sp | pop parameters off stack
|
||||
|
||||
ret_from_interrupt:
|
||||
|
@ -240,8 +240,7 @@ user_irqvec_fixup = . + 2
|
|||
|
||||
movel %sp,%sp@-
|
||||
movel %d0,%sp@- | put vector # on stack
|
||||
user_irqhandler_fixup = . + 2
|
||||
jsr __m68k_handle_int | process the IRQ
|
||||
jsr do_IRQ | process the IRQ
|
||||
addql #8,%sp | pop parameters off stack
|
||||
|
||||
subqb #1,%curptr@(TASK_INFO+TINFO_PREEMPT+1)
|
||||
|
|
|
@ -4,25 +4,6 @@
|
|||
* This file is subject to the terms and conditions of the GNU General Public
|
||||
* License. See the file COPYING in the main directory of this archive
|
||||
* for more details.
|
||||
*
|
||||
* 07/03/96: Timer initialization, and thus mach_sched_init(),
|
||||
* removed from request_irq() and moved to init_time().
|
||||
* We should therefore consider renaming our add_isr() and
|
||||
* remove_isr() to request_irq() and free_irq()
|
||||
* respectively, so they are compliant with the other
|
||||
* architectures. /Jes
|
||||
* 11/07/96: Changed all add_/remove_isr() to request_/free_irq() calls.
|
||||
* Removed irq list support, if any machine needs an irq server
|
||||
* it must implement this itself (as it's already done), instead
|
||||
* only default handler are used with mach_default_handler.
|
||||
* request_irq got some flags different from other architectures:
|
||||
* - IRQ_FLG_REPLACE : Replace an existing handler (the default one
|
||||
* can be replaced without this flag)
|
||||
* - IRQ_FLG_LOCK : handler can't be replaced
|
||||
* There are other machine depending flags, see there
|
||||
* If you want to replace a default handler you should know what
|
||||
* you're doing, since it might handle different other irq sources
|
||||
* which must be served /Roman Zippel
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
|
@ -47,33 +28,22 @@
|
|||
#endif
|
||||
|
||||
extern u32 auto_irqhandler_fixup[];
|
||||
extern u32 user_irqhandler_fixup[];
|
||||
extern u16 user_irqvec_fixup[];
|
||||
|
||||
/* table for system interrupt handlers */
|
||||
static struct irq_node *irq_list[NR_IRQS];
|
||||
static struct irq_controller *irq_controller[NR_IRQS];
|
||||
static int irq_depth[NR_IRQS];
|
||||
|
||||
static int m68k_first_user_vec;
|
||||
|
||||
static struct irq_controller auto_irq_controller = {
|
||||
static struct irq_chip auto_irq_chip = {
|
||||
.name = "auto",
|
||||
.lock = __SPIN_LOCK_UNLOCKED(auto_irq_controller.lock),
|
||||
.startup = m68k_irq_startup,
|
||||
.shutdown = m68k_irq_shutdown,
|
||||
.irq_startup = m68k_irq_startup,
|
||||
.irq_shutdown = m68k_irq_shutdown,
|
||||
};
|
||||
|
||||
static struct irq_controller user_irq_controller = {
|
||||
static struct irq_chip user_irq_chip = {
|
||||
.name = "user",
|
||||
.lock = __SPIN_LOCK_UNLOCKED(user_irq_controller.lock),
|
||||
.startup = m68k_irq_startup,
|
||||
.shutdown = m68k_irq_shutdown,
|
||||
.irq_startup = m68k_irq_startup,
|
||||
.irq_shutdown = m68k_irq_shutdown,
|
||||
};
|
||||
|
||||
#define NUM_IRQ_NODES 100
|
||||
static irq_node_t nodes[NUM_IRQ_NODES];
|
||||
|
||||
/*
|
||||
* void init_IRQ(void)
|
||||
*
|
||||
|
@ -96,7 +66,7 @@ void __init init_IRQ(void)
|
|||
}
|
||||
|
||||
for (i = IRQ_AUTO_1; i <= IRQ_AUTO_7; i++)
|
||||
irq_controller[i] = &auto_irq_controller;
|
||||
irq_set_chip_and_handler(i, &auto_irq_chip, handle_simple_irq);
|
||||
|
||||
mach_init_IRQ();
|
||||
}
|
||||
|
@ -106,7 +76,7 @@ void __init init_IRQ(void)
|
|||
* @handler: called from auto vector interrupts
|
||||
*
|
||||
* setup the handler to be called from auto vector interrupts instead of the
|
||||
* standard __m68k_handle_int(), it will be called with irq numbers in the range
|
||||
* standard do_IRQ(), it will be called with irq numbers in the range
|
||||
* from IRQ_AUTO_1 - IRQ_AUTO_7.
|
||||
*/
|
||||
void __init m68k_setup_auto_interrupt(void (*handler)(unsigned int, struct pt_regs *))
|
||||
|
@ -120,217 +90,49 @@ void __init m68k_setup_auto_interrupt(void (*handler)(unsigned int, struct pt_re
|
|||
* m68k_setup_user_interrupt
|
||||
* @vec: first user vector interrupt to handle
|
||||
* @cnt: number of active user vector interrupts
|
||||
* @handler: called from user vector interrupts
|
||||
*
|
||||
* setup user vector interrupts, this includes activating the specified range
|
||||
* of interrupts, only then these interrupts can be requested (note: this is
|
||||
* different from auto vector interrupts). An optional handler can be installed
|
||||
* to be called instead of the default __m68k_handle_int(), it will be called
|
||||
* with irq numbers starting from IRQ_USER.
|
||||
* different from auto vector interrupts).
|
||||
*/
|
||||
void __init m68k_setup_user_interrupt(unsigned int vec, unsigned int cnt,
|
||||
void (*handler)(unsigned int, struct pt_regs *))
|
||||
void __init m68k_setup_user_interrupt(unsigned int vec, unsigned int cnt)
|
||||
{
|
||||
int i;
|
||||
|
||||
BUG_ON(IRQ_USER + cnt > NR_IRQS);
|
||||
m68k_first_user_vec = vec;
|
||||
for (i = 0; i < cnt; i++)
|
||||
irq_controller[IRQ_USER + i] = &user_irq_controller;
|
||||
irq_set_chip(IRQ_USER + i, &user_irq_chip);
|
||||
*user_irqvec_fixup = vec - IRQ_USER;
|
||||
if (handler)
|
||||
*user_irqhandler_fixup = (u32)handler;
|
||||
flush_icache();
|
||||
}
|
||||
|
||||
/**
|
||||
* m68k_setup_irq_controller
|
||||
* @contr: irq controller which controls specified irq
|
||||
* @chip: irq chip which controls specified irq
|
||||
* @handle: flow handler which handles specified irq
|
||||
* @irq: first irq to be managed by the controller
|
||||
* @cnt: number of irqs to be managed by the controller
|
||||
*
|
||||
* Change the controller for the specified range of irq, which will be used to
|
||||
* manage these irq. auto/user irq already have a default controller, which can
|
||||
* be changed as well, but the controller probably should use m68k_irq_startup/
|
||||
* m68k_irq_shutdown.
|
||||
*/
|
||||
void m68k_setup_irq_controller(struct irq_controller *contr, unsigned int irq,
|
||||
void m68k_setup_irq_controller(struct irq_chip *chip,
|
||||
irq_flow_handler_t handle, unsigned int irq,
|
||||
unsigned int cnt)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < cnt; i++)
|
||||
irq_controller[irq + i] = contr;
|
||||
for (i = 0; i < cnt; i++) {
|
||||
irq_set_chip(irq + i, chip);
|
||||
if (handle)
|
||||
irq_set_handler(irq + i, handle);
|
||||
}
|
||||
}
|
||||
|
||||
irq_node_t *new_irq_node(void)
|
||||
{
|
||||
irq_node_t *node;
|
||||
short i;
|
||||
|
||||
for (node = nodes, i = NUM_IRQ_NODES-1; i >= 0; node++, i--) {
|
||||
if (!node->handler) {
|
||||
memset(node, 0, sizeof(*node));
|
||||
return node;
|
||||
}
|
||||
}
|
||||
|
||||
printk ("new_irq_node: out of nodes\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int setup_irq(unsigned int irq, struct irq_node *node)
|
||||
{
|
||||
struct irq_controller *contr;
|
||||
struct irq_node **prev;
|
||||
unsigned long flags;
|
||||
|
||||
if (irq >= NR_IRQS || !(contr = irq_controller[irq])) {
|
||||
printk("%s: Incorrect IRQ %d from %s\n",
|
||||
__func__, irq, node->devname);
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&contr->lock, flags);
|
||||
|
||||
prev = irq_list + irq;
|
||||
if (*prev) {
|
||||
/* Can't share interrupts unless both agree to */
|
||||
if (!((*prev)->flags & node->flags & IRQF_SHARED)) {
|
||||
spin_unlock_irqrestore(&contr->lock, flags);
|
||||
return -EBUSY;
|
||||
}
|
||||
while (*prev)
|
||||
prev = &(*prev)->next;
|
||||
}
|
||||
|
||||
if (!irq_list[irq]) {
|
||||
if (contr->startup)
|
||||
contr->startup(irq);
|
||||
else
|
||||
contr->enable(irq);
|
||||
}
|
||||
node->next = NULL;
|
||||
*prev = node;
|
||||
|
||||
spin_unlock_irqrestore(&contr->lock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int request_irq(unsigned int irq,
|
||||
irq_handler_t handler,
|
||||
unsigned long flags, const char *devname, void *dev_id)
|
||||
{
|
||||
struct irq_node *node;
|
||||
int res;
|
||||
|
||||
node = new_irq_node();
|
||||
if (!node)
|
||||
return -ENOMEM;
|
||||
|
||||
node->handler = handler;
|
||||
node->flags = flags;
|
||||
node->dev_id = dev_id;
|
||||
node->devname = devname;
|
||||
|
||||
res = setup_irq(irq, node);
|
||||
if (res)
|
||||
node->handler = NULL;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(request_irq);
|
||||
|
||||
void free_irq(unsigned int irq, void *dev_id)
|
||||
{
|
||||
struct irq_controller *contr;
|
||||
struct irq_node **p, *node;
|
||||
unsigned long flags;
|
||||
|
||||
if (irq >= NR_IRQS || !(contr = irq_controller[irq])) {
|
||||
printk("%s: Incorrect IRQ %d\n", __func__, irq);
|
||||
return;
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&contr->lock, flags);
|
||||
|
||||
p = irq_list + irq;
|
||||
while ((node = *p)) {
|
||||
if (node->dev_id == dev_id)
|
||||
break;
|
||||
p = &node->next;
|
||||
}
|
||||
|
||||
if (node) {
|
||||
*p = node->next;
|
||||
node->handler = NULL;
|
||||
} else
|
||||
printk("%s: Removing probably wrong IRQ %d\n",
|
||||
__func__, irq);
|
||||
|
||||
if (!irq_list[irq]) {
|
||||
if (contr->shutdown)
|
||||
contr->shutdown(irq);
|
||||
else
|
||||
contr->disable(irq);
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&contr->lock, flags);
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(free_irq);
|
||||
|
||||
void enable_irq(unsigned int irq)
|
||||
{
|
||||
struct irq_controller *contr;
|
||||
unsigned long flags;
|
||||
|
||||
if (irq >= NR_IRQS || !(contr = irq_controller[irq])) {
|
||||
printk("%s: Incorrect IRQ %d\n",
|
||||
__func__, irq);
|
||||
return;
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&contr->lock, flags);
|
||||
if (irq_depth[irq]) {
|
||||
if (!--irq_depth[irq]) {
|
||||
if (contr->enable)
|
||||
contr->enable(irq);
|
||||
}
|
||||
} else
|
||||
WARN_ON(1);
|
||||
spin_unlock_irqrestore(&contr->lock, flags);
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(enable_irq);
|
||||
|
||||
void disable_irq(unsigned int irq)
|
||||
{
|
||||
struct irq_controller *contr;
|
||||
unsigned long flags;
|
||||
|
||||
if (irq >= NR_IRQS || !(contr = irq_controller[irq])) {
|
||||
printk("%s: Incorrect IRQ %d\n",
|
||||
__func__, irq);
|
||||
return;
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&contr->lock, flags);
|
||||
if (!irq_depth[irq]++) {
|
||||
if (contr->disable)
|
||||
contr->disable(irq);
|
||||
}
|
||||
spin_unlock_irqrestore(&contr->lock, flags);
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(disable_irq);
|
||||
|
||||
void disable_irq_nosync(unsigned int irq) __attribute__((alias("disable_irq")));
|
||||
|
||||
EXPORT_SYMBOL(disable_irq_nosync);
|
||||
|
||||
int m68k_irq_startup(unsigned int irq)
|
||||
unsigned int m68k_irq_startup_irq(unsigned int irq)
|
||||
{
|
||||
if (irq <= IRQ_AUTO_7)
|
||||
vectors[VEC_SPUR + irq] = auto_inthandler;
|
||||
|
@ -339,8 +141,15 @@ int m68k_irq_startup(unsigned int irq)
|
|||
return 0;
|
||||
}
|
||||
|
||||
void m68k_irq_shutdown(unsigned int irq)
|
||||
unsigned int m68k_irq_startup(struct irq_data *data)
|
||||
{
|
||||
return m68k_irq_startup_irq(data->irq);
|
||||
}
|
||||
|
||||
void m68k_irq_shutdown(struct irq_data *data)
|
||||
{
|
||||
unsigned int irq = data->irq;
|
||||
|
||||
if (irq <= IRQ_AUTO_7)
|
||||
vectors[VEC_SPUR + irq] = bad_inthandler;
|
||||
else
|
||||
|
@ -348,33 +157,6 @@ void m68k_irq_shutdown(unsigned int irq)
|
|||
}
|
||||
|
||||
|
||||
/*
|
||||
* Do we need these probe functions on the m68k?
|
||||
*
|
||||
* ... may be useful with ISA devices
|
||||
*/
|
||||
unsigned long probe_irq_on (void)
|
||||
{
|
||||
#ifdef CONFIG_Q40
|
||||
if (MACH_IS_Q40)
|
||||
return q40_probe_irq_on();
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(probe_irq_on);
|
||||
|
||||
int probe_irq_off (unsigned long irqs)
|
||||
{
|
||||
#ifdef CONFIG_Q40
|
||||
if (MACH_IS_Q40)
|
||||
return q40_probe_irq_off(irqs);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(probe_irq_off);
|
||||
|
||||
unsigned int irq_canonicalize(unsigned int irq)
|
||||
{
|
||||
#ifdef CONFIG_Q40
|
||||
|
@ -386,52 +168,9 @@ unsigned int irq_canonicalize(unsigned int irq)
|
|||
|
||||
EXPORT_SYMBOL(irq_canonicalize);
|
||||
|
||||
asmlinkage void m68k_handle_int(unsigned int irq)
|
||||
{
|
||||
struct irq_node *node;
|
||||
kstat_cpu(0).irqs[irq]++;
|
||||
node = irq_list[irq];
|
||||
do {
|
||||
node->handler(irq, node->dev_id);
|
||||
node = node->next;
|
||||
} while (node);
|
||||
}
|
||||
|
||||
asmlinkage void __m68k_handle_int(unsigned int irq, struct pt_regs *regs)
|
||||
{
|
||||
struct pt_regs *old_regs;
|
||||
old_regs = set_irq_regs(regs);
|
||||
m68k_handle_int(irq);
|
||||
set_irq_regs(old_regs);
|
||||
}
|
||||
|
||||
asmlinkage void handle_badint(struct pt_regs *regs)
|
||||
{
|
||||
kstat_cpu(0).irqs[0]++;
|
||||
printk("unexpected interrupt from %u\n", regs->vector);
|
||||
atomic_inc(&irq_err_count);
|
||||
pr_warn("unexpected interrupt from %u\n", regs->vector);
|
||||
}
|
||||
|
||||
int show_interrupts(struct seq_file *p, void *v)
|
||||
{
|
||||
struct irq_controller *contr;
|
||||
struct irq_node *node;
|
||||
int i = *(loff_t *) v;
|
||||
|
||||
/* autovector interrupts */
|
||||
if (irq_list[i]) {
|
||||
contr = irq_controller[i];
|
||||
node = irq_list[i];
|
||||
seq_printf(p, "%-8s %3u: %10u %s", contr->name, i, kstat_cpu(0).irqs[i], node->devname);
|
||||
while ((node = node->next))
|
||||
seq_printf(p, ", %s", node->devname);
|
||||
seq_puts(p, "\n");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PROC_FS
|
||||
void init_irq_proc(void)
|
||||
{
|
||||
/* Insert /proc/irq driver here */
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#include <linux/mm.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/irq.h>
|
||||
|
||||
#include <asm/traps.h>
|
||||
#include <asm/bootinfo.h>
|
||||
|
@ -20,9 +21,6 @@
|
|||
|
||||
/* #define DEBUG_IRQS */
|
||||
|
||||
extern void mac_enable_irq(unsigned int);
|
||||
extern void mac_disable_irq(unsigned int);
|
||||
|
||||
int baboon_present;
|
||||
static volatile struct baboon *baboon;
|
||||
static unsigned char baboon_disabled;
|
||||
|
@ -53,7 +51,7 @@ void __init baboon_init(void)
|
|||
* Baboon interrupt handler. This works a lot like a VIA.
|
||||
*/
|
||||
|
||||
static irqreturn_t baboon_irq(int irq, void *dev_id)
|
||||
static void baboon_irq(unsigned int irq, struct irq_desc *desc)
|
||||
{
|
||||
int irq_bit, irq_num;
|
||||
unsigned char events;
|
||||
|
@ -64,15 +62,16 @@ static irqreturn_t baboon_irq(int irq, void *dev_id)
|
|||
(uint) baboon->mb_status);
|
||||
#endif
|
||||
|
||||
if (!(events = baboon->mb_ifr & 0x07))
|
||||
return IRQ_NONE;
|
||||
events = baboon->mb_ifr & 0x07;
|
||||
if (!events)
|
||||
return;
|
||||
|
||||
irq_num = IRQ_BABOON_0;
|
||||
irq_bit = 1;
|
||||
do {
|
||||
if (events & irq_bit) {
|
||||
baboon->mb_ifr &= ~irq_bit;
|
||||
m68k_handle_int(irq_num);
|
||||
generic_handle_irq(irq_num);
|
||||
}
|
||||
irq_bit <<= 1;
|
||||
irq_num++;
|
||||
|
@ -82,7 +81,6 @@ static irqreturn_t baboon_irq(int irq, void *dev_id)
|
|||
/* for now we need to smash all interrupts */
|
||||
baboon->mb_ifr &= ~events;
|
||||
#endif
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -92,8 +90,7 @@ static irqreturn_t baboon_irq(int irq, void *dev_id)
|
|||
void __init baboon_register_interrupts(void)
|
||||
{
|
||||
baboon_disabled = 0;
|
||||
if (request_irq(IRQ_NUBUS_C, baboon_irq, 0, "baboon", (void *)baboon))
|
||||
pr_err("Couldn't register baboon interrupt\n");
|
||||
irq_set_chained_handler(IRQ_NUBUS_C, baboon_irq);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -111,7 +108,7 @@ void baboon_irq_enable(int irq)
|
|||
|
||||
baboon_disabled &= ~(1 << irq_idx);
|
||||
if (!baboon_disabled)
|
||||
mac_enable_irq(IRQ_NUBUS_C);
|
||||
mac_irq_enable(irq_get_irq_data(IRQ_NUBUS_C));
|
||||
}
|
||||
|
||||
void baboon_irq_disable(int irq)
|
||||
|
@ -124,7 +121,7 @@ void baboon_irq_disable(int irq)
|
|||
|
||||
baboon_disabled |= 1 << irq_idx;
|
||||
if (baboon_disabled)
|
||||
mac_disable_irq(IRQ_NUBUS_C);
|
||||
mac_irq_disable(irq_get_irq_data(IRQ_NUBUS_C));
|
||||
}
|
||||
|
||||
void baboon_irq_clear(int irq)
|
||||
|
|
|
@ -305,15 +305,13 @@ void __init iop_register_interrupts(void)
|
|||
{
|
||||
if (iop_ism_present) {
|
||||
if (oss_present) {
|
||||
if (request_irq(OSS_IRQLEV_IOPISM, iop_ism_irq,
|
||||
IRQ_FLG_LOCK, "ISM IOP",
|
||||
(void *) IOP_NUM_ISM))
|
||||
if (request_irq(OSS_IRQLEV_IOPISM, iop_ism_irq, 0,
|
||||
"ISM IOP", (void *)IOP_NUM_ISM))
|
||||
pr_err("Couldn't register ISM IOP interrupt\n");
|
||||
oss_irq_enable(IRQ_MAC_ADB);
|
||||
} else {
|
||||
if (request_irq(IRQ_VIA2_0, iop_ism_irq,
|
||||
IRQ_FLG_LOCK|IRQ_FLG_FAST, "ISM IOP",
|
||||
(void *) IOP_NUM_ISM))
|
||||
if (request_irq(IRQ_VIA2_0, iop_ism_irq, 0, "ISM IOP",
|
||||
(void *)IOP_NUM_ISM))
|
||||
pr_err("Couldn't register ISM IOP interrupt\n");
|
||||
}
|
||||
if (!iop_alive(iop_base[IOP_NUM_ISM])) {
|
||||
|
|
|
@ -190,14 +190,10 @@ irqreturn_t mac_debug_handler(int, void *);
|
|||
|
||||
/* #define DEBUG_MACINTS */
|
||||
|
||||
void mac_enable_irq(unsigned int irq);
|
||||
void mac_disable_irq(unsigned int irq);
|
||||
|
||||
static struct irq_controller mac_irq_controller = {
|
||||
static struct irq_chip mac_irq_chip = {
|
||||
.name = "mac",
|
||||
.lock = __SPIN_LOCK_UNLOCKED(mac_irq_controller.lock),
|
||||
.enable = mac_enable_irq,
|
||||
.disable = mac_disable_irq,
|
||||
.irq_enable = mac_irq_enable,
|
||||
.irq_disable = mac_irq_disable,
|
||||
};
|
||||
|
||||
void __init mac_init_IRQ(void)
|
||||
|
@ -205,7 +201,7 @@ void __init mac_init_IRQ(void)
|
|||
#ifdef DEBUG_MACINTS
|
||||
printk("mac_init_IRQ(): Setting things up...\n");
|
||||
#endif
|
||||
m68k_setup_irq_controller(&mac_irq_controller, IRQ_USER,
|
||||
m68k_setup_irq_controller(&mac_irq_chip, handle_simple_irq, IRQ_USER,
|
||||
NUM_MAC_SOURCES - IRQ_USER);
|
||||
/* Make sure the SONIC interrupt is cleared or things get ugly */
|
||||
#ifdef SHUTUP_SONIC
|
||||
|
@ -241,16 +237,17 @@ void __init mac_init_IRQ(void)
|
|||
}
|
||||
|
||||
/*
|
||||
* mac_enable_irq - enable an interrupt source
|
||||
* mac_disable_irq - disable an interrupt source
|
||||
* mac_irq_enable - enable an interrupt source
|
||||
* mac_irq_disable - disable an interrupt source
|
||||
* mac_clear_irq - clears a pending interrupt
|
||||
* mac_pending_irq - Returns the pending status of an IRQ (nonzero = pending)
|
||||
* mac_irq_pending - returns the pending status of an IRQ (nonzero = pending)
|
||||
*
|
||||
* These routines are just dispatchers to the VIA/OSS/PSC routines.
|
||||
*/
|
||||
|
||||
void mac_enable_irq(unsigned int irq)
|
||||
void mac_irq_enable(struct irq_data *data)
|
||||
{
|
||||
int irq = data->irq;
|
||||
int irq_src = IRQ_SRC(irq);
|
||||
|
||||
switch(irq_src) {
|
||||
|
@ -283,8 +280,9 @@ void mac_enable_irq(unsigned int irq)
|
|||
}
|
||||
}
|
||||
|
||||
void mac_disable_irq(unsigned int irq)
|
||||
void mac_irq_disable(struct irq_data *data)
|
||||
{
|
||||
int irq = data->irq;
|
||||
int irq_src = IRQ_SRC(irq);
|
||||
|
||||
switch(irq_src) {
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include <linux/mm.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/irq.h>
|
||||
|
||||
#include <asm/bootinfo.h>
|
||||
#include <asm/macintosh.h>
|
||||
|
@ -29,10 +30,7 @@
|
|||
int oss_present;
|
||||
volatile struct mac_oss *oss;
|
||||
|
||||
static irqreturn_t oss_irq(int, void *);
|
||||
static irqreturn_t oss_nubus_irq(int, void *);
|
||||
|
||||
extern irqreturn_t via1_irq(int, void *);
|
||||
extern void via1_irq(unsigned int irq, struct irq_desc *desc);
|
||||
|
||||
/*
|
||||
* Initialize the OSS
|
||||
|
@ -59,26 +57,6 @@ void __init oss_init(void)
|
|||
oss->irq_level[OSS_VIA1] = OSS_IRQLEV_VIA1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Register the OSS and NuBus interrupt dispatchers.
|
||||
*/
|
||||
|
||||
void __init oss_register_interrupts(void)
|
||||
{
|
||||
if (request_irq(OSS_IRQLEV_SCSI, oss_irq, IRQ_FLG_LOCK,
|
||||
"scsi", (void *) oss))
|
||||
pr_err("Couldn't register %s interrupt\n", "scsi");
|
||||
if (request_irq(OSS_IRQLEV_NUBUS, oss_nubus_irq, IRQ_FLG_LOCK,
|
||||
"nubus", (void *) oss))
|
||||
pr_err("Couldn't register %s interrupt\n", "nubus");
|
||||
if (request_irq(OSS_IRQLEV_SOUND, oss_irq, IRQ_FLG_LOCK,
|
||||
"sound", (void *) oss))
|
||||
pr_err("Couldn't register %s interrupt\n", "sound");
|
||||
if (request_irq(OSS_IRQLEV_VIA1, via1_irq, IRQ_FLG_LOCK,
|
||||
"via1", (void *) via1))
|
||||
pr_err("Couldn't register %s interrupt\n", "via1");
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize OSS for Nubus access
|
||||
*/
|
||||
|
@ -92,17 +70,17 @@ void __init oss_nubus_init(void)
|
|||
* and SCSI; everything else is routed to its own autovector IRQ.
|
||||
*/
|
||||
|
||||
static irqreturn_t oss_irq(int irq, void *dev_id)
|
||||
static void oss_irq(unsigned int irq, struct irq_desc *desc)
|
||||
{
|
||||
int events;
|
||||
|
||||
events = oss->irq_pending & (OSS_IP_SOUND|OSS_IP_SCSI);
|
||||
if (!events)
|
||||
return IRQ_NONE;
|
||||
return;
|
||||
|
||||
#ifdef DEBUG_IRQS
|
||||
if ((console_loglevel == 10) && !(events & OSS_IP_SCSI)) {
|
||||
printk("oss_irq: irq %d events = 0x%04X\n", irq,
|
||||
printk("oss_irq: irq %u events = 0x%04X\n", irq,
|
||||
(int) oss->irq_pending);
|
||||
}
|
||||
#endif
|
||||
|
@ -113,11 +91,10 @@ static irqreturn_t oss_irq(int irq, void *dev_id)
|
|||
/* FIXME: call sound handler */
|
||||
} else if (events & OSS_IP_SCSI) {
|
||||
oss->irq_pending &= ~OSS_IP_SCSI;
|
||||
m68k_handle_int(IRQ_MAC_SCSI);
|
||||
generic_handle_irq(IRQ_MAC_SCSI);
|
||||
} else {
|
||||
/* FIXME: error check here? */
|
||||
}
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -126,13 +103,13 @@ static irqreturn_t oss_irq(int irq, void *dev_id)
|
|||
* Unlike the VIA/RBV this is on its own autovector interrupt level.
|
||||
*/
|
||||
|
||||
static irqreturn_t oss_nubus_irq(int irq, void *dev_id)
|
||||
static void oss_nubus_irq(unsigned int irq, struct irq_desc *desc)
|
||||
{
|
||||
int events, irq_bit, i;
|
||||
|
||||
events = oss->irq_pending & OSS_IP_NUBUS;
|
||||
if (!events)
|
||||
return IRQ_NONE;
|
||||
return;
|
||||
|
||||
#ifdef DEBUG_NUBUS_INT
|
||||
if (console_loglevel > 7) {
|
||||
|
@ -148,10 +125,21 @@ static irqreturn_t oss_nubus_irq(int irq, void *dev_id)
|
|||
irq_bit >>= 1;
|
||||
if (events & irq_bit) {
|
||||
oss->irq_pending &= ~irq_bit;
|
||||
m68k_handle_int(NUBUS_SOURCE_BASE + i);
|
||||
generic_handle_irq(NUBUS_SOURCE_BASE + i);
|
||||
}
|
||||
} while(events & (irq_bit - 1));
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
/*
|
||||
* Register the OSS and NuBus interrupt dispatchers.
|
||||
*/
|
||||
|
||||
void __init oss_register_interrupts(void)
|
||||
{
|
||||
irq_set_chained_handler(OSS_IRQLEV_SCSI, oss_irq);
|
||||
irq_set_chained_handler(OSS_IRQLEV_NUBUS, oss_nubus_irq);
|
||||
irq_set_chained_handler(OSS_IRQLEV_SOUND, oss_irq);
|
||||
irq_set_chained_handler(OSS_IRQLEV_VIA1, via1_irq);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include <linux/mm.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/irq.h>
|
||||
|
||||
#include <asm/traps.h>
|
||||
#include <asm/bootinfo.h>
|
||||
|
@ -30,8 +31,6 @@
|
|||
int psc_present;
|
||||
volatile __u8 *psc;
|
||||
|
||||
irqreturn_t psc_irq(int, void *);
|
||||
|
||||
/*
|
||||
* Debugging dump, used in various places to see what's going on.
|
||||
*/
|
||||
|
@ -111,53 +110,53 @@ void __init psc_init(void)
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Register the PSC interrupt dispatchers for autovector interrupts 3-6.
|
||||
*/
|
||||
|
||||
void __init psc_register_interrupts(void)
|
||||
{
|
||||
if (request_irq(IRQ_AUTO_3, psc_irq, 0, "psc3", (void *) 0x30))
|
||||
pr_err("Couldn't register psc%d interrupt\n", 3);
|
||||
if (request_irq(IRQ_AUTO_4, psc_irq, 0, "psc4", (void *) 0x40))
|
||||
pr_err("Couldn't register psc%d interrupt\n", 4);
|
||||
if (request_irq(IRQ_AUTO_5, psc_irq, 0, "psc5", (void *) 0x50))
|
||||
pr_err("Couldn't register psc%d interrupt\n", 5);
|
||||
if (request_irq(IRQ_AUTO_6, psc_irq, 0, "psc6", (void *) 0x60))
|
||||
pr_err("Couldn't register psc%d interrupt\n", 6);
|
||||
}
|
||||
|
||||
/*
|
||||
* PSC interrupt handler. It's a lot like the VIA interrupt handler.
|
||||
*/
|
||||
|
||||
irqreturn_t psc_irq(int irq, void *dev_id)
|
||||
static void psc_irq(unsigned int irq, struct irq_desc *desc)
|
||||
{
|
||||
int pIFR = pIFRbase + ((int) dev_id);
|
||||
int pIER = pIERbase + ((int) dev_id);
|
||||
unsigned int offset = (unsigned int)irq_desc_get_handler_data(desc);
|
||||
int pIFR = pIFRbase + offset;
|
||||
int pIER = pIERbase + offset;
|
||||
int irq_num;
|
||||
unsigned char irq_bit, events;
|
||||
|
||||
#ifdef DEBUG_IRQS
|
||||
printk("psc_irq: irq %d pIFR = 0x%02X pIER = 0x%02X\n",
|
||||
printk("psc_irq: irq %u pIFR = 0x%02X pIER = 0x%02X\n",
|
||||
irq, (int) psc_read_byte(pIFR), (int) psc_read_byte(pIER));
|
||||
#endif
|
||||
|
||||
events = psc_read_byte(pIFR) & psc_read_byte(pIER) & 0xF;
|
||||
if (!events)
|
||||
return IRQ_NONE;
|
||||
return;
|
||||
|
||||
irq_num = irq << 3;
|
||||
irq_bit = 1;
|
||||
do {
|
||||
if (events & irq_bit) {
|
||||
psc_write_byte(pIFR, irq_bit);
|
||||
m68k_handle_int(irq_num);
|
||||
generic_handle_irq(irq_num);
|
||||
}
|
||||
irq_num++;
|
||||
irq_bit <<= 1;
|
||||
} while (events >= irq_bit);
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
/*
|
||||
* Register the PSC interrupt dispatchers for autovector interrupts 3-6.
|
||||
*/
|
||||
|
||||
void __init psc_register_interrupts(void)
|
||||
{
|
||||
irq_set_chained_handler(IRQ_AUTO_3, psc_irq);
|
||||
irq_set_handler_data(IRQ_AUTO_3, (void *)0x30);
|
||||
irq_set_chained_handler(IRQ_AUTO_4, psc_irq);
|
||||
irq_set_handler_data(IRQ_AUTO_4, (void *)0x40);
|
||||
irq_set_chained_handler(IRQ_AUTO_5, psc_irq);
|
||||
irq_set_handler_data(IRQ_AUTO_5, (void *)0x50);
|
||||
irq_set_chained_handler(IRQ_AUTO_6, psc_irq);
|
||||
irq_set_handler_data(IRQ_AUTO_6, (void *)0x60);
|
||||
}
|
||||
|
||||
void psc_irq_enable(int irq) {
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#include <linux/delay.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/irq.h>
|
||||
|
||||
#include <asm/bootinfo.h>
|
||||
#include <asm/macintosh.h>
|
||||
|
@ -77,9 +78,6 @@ static int gIER,gIFR,gBufA,gBufB;
|
|||
static u8 nubus_disabled;
|
||||
|
||||
void via_debug_dump(void);
|
||||
irqreturn_t via1_irq(int, void *);
|
||||
irqreturn_t via2_irq(int, void *);
|
||||
irqreturn_t via_nubus_irq(int, void *);
|
||||
void via_irq_enable(int irq);
|
||||
void via_irq_disable(int irq);
|
||||
void via_irq_clear(int irq);
|
||||
|
@ -281,39 +279,10 @@ void __init via_init_clock(irq_handler_t func)
|
|||
via1[vT1CL] = MAC_CLOCK_LOW;
|
||||
via1[vT1CH] = MAC_CLOCK_HIGH;
|
||||
|
||||
if (request_irq(IRQ_MAC_TIMER_1, func, IRQ_FLG_LOCK, "timer", func))
|
||||
if (request_irq(IRQ_MAC_TIMER_1, func, 0, "timer", func))
|
||||
pr_err("Couldn't register %s interrupt\n", "timer");
|
||||
}
|
||||
|
||||
/*
|
||||
* Register the interrupt dispatchers for VIA or RBV machines only.
|
||||
*/
|
||||
|
||||
void __init via_register_interrupts(void)
|
||||
{
|
||||
if (via_alt_mapping) {
|
||||
if (request_irq(IRQ_AUTO_1, via1_irq,
|
||||
IRQ_FLG_LOCK|IRQ_FLG_FAST, "software",
|
||||
(void *) via1))
|
||||
pr_err("Couldn't register %s interrupt\n", "software");
|
||||
if (request_irq(IRQ_AUTO_6, via1_irq,
|
||||
IRQ_FLG_LOCK|IRQ_FLG_FAST, "via1",
|
||||
(void *) via1))
|
||||
pr_err("Couldn't register %s interrupt\n", "via1");
|
||||
} else {
|
||||
if (request_irq(IRQ_AUTO_1, via1_irq,
|
||||
IRQ_FLG_LOCK|IRQ_FLG_FAST, "via1",
|
||||
(void *) via1))
|
||||
pr_err("Couldn't register %s interrupt\n", "via1");
|
||||
}
|
||||
if (request_irq(IRQ_AUTO_2, via2_irq, IRQ_FLG_LOCK|IRQ_FLG_FAST,
|
||||
"via2", (void *) via2))
|
||||
pr_err("Couldn't register %s interrupt\n", "via2");
|
||||
if (request_irq(IRQ_MAC_NUBUS, via_nubus_irq,
|
||||
IRQ_FLG_LOCK|IRQ_FLG_FAST, "nubus", (void *) via2))
|
||||
pr_err("Couldn't register %s interrupt\n", "nubus");
|
||||
}
|
||||
|
||||
/*
|
||||
* Debugging dump, used in various places to see what's going on.
|
||||
*/
|
||||
|
@ -446,48 +415,46 @@ void __init via_nubus_init(void)
|
|||
* via6522.c :-), disable/pending masks added.
|
||||
*/
|
||||
|
||||
irqreturn_t via1_irq(int irq, void *dev_id)
|
||||
void via1_irq(unsigned int irq, struct irq_desc *desc)
|
||||
{
|
||||
int irq_num;
|
||||
unsigned char irq_bit, events;
|
||||
|
||||
events = via1[vIFR] & via1[vIER] & 0x7F;
|
||||
if (!events)
|
||||
return IRQ_NONE;
|
||||
return;
|
||||
|
||||
irq_num = VIA1_SOURCE_BASE;
|
||||
irq_bit = 1;
|
||||
do {
|
||||
if (events & irq_bit) {
|
||||
via1[vIFR] = irq_bit;
|
||||
m68k_handle_int(irq_num);
|
||||
generic_handle_irq(irq_num);
|
||||
}
|
||||
++irq_num;
|
||||
irq_bit <<= 1;
|
||||
} while (events >= irq_bit);
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
irqreturn_t via2_irq(int irq, void *dev_id)
|
||||
static void via2_irq(unsigned int irq, struct irq_desc *desc)
|
||||
{
|
||||
int irq_num;
|
||||
unsigned char irq_bit, events;
|
||||
|
||||
events = via2[gIFR] & via2[gIER] & 0x7F;
|
||||
if (!events)
|
||||
return IRQ_NONE;
|
||||
return;
|
||||
|
||||
irq_num = VIA2_SOURCE_BASE;
|
||||
irq_bit = 1;
|
||||
do {
|
||||
if (events & irq_bit) {
|
||||
via2[gIFR] = irq_bit | rbv_clear;
|
||||
m68k_handle_int(irq_num);
|
||||
generic_handle_irq(irq_num);
|
||||
}
|
||||
++irq_num;
|
||||
irq_bit <<= 1;
|
||||
} while (events >= irq_bit);
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -495,7 +462,7 @@ irqreturn_t via2_irq(int irq, void *dev_id)
|
|||
* VIA2 dispatcher as a fast interrupt handler.
|
||||
*/
|
||||
|
||||
irqreturn_t via_nubus_irq(int irq, void *dev_id)
|
||||
void via_nubus_irq(unsigned int irq, struct irq_desc *desc)
|
||||
{
|
||||
int slot_irq;
|
||||
unsigned char slot_bit, events;
|
||||
|
@ -506,7 +473,7 @@ irqreturn_t via_nubus_irq(int irq, void *dev_id)
|
|||
else
|
||||
events &= ~via2[vDirA];
|
||||
if (!events)
|
||||
return IRQ_NONE;
|
||||
return;
|
||||
|
||||
do {
|
||||
slot_irq = IRQ_NUBUS_F;
|
||||
|
@ -514,7 +481,7 @@ irqreturn_t via_nubus_irq(int irq, void *dev_id)
|
|||
do {
|
||||
if (events & slot_bit) {
|
||||
events &= ~slot_bit;
|
||||
m68k_handle_int(slot_irq);
|
||||
generic_handle_irq(slot_irq);
|
||||
}
|
||||
--slot_irq;
|
||||
slot_bit >>= 1;
|
||||
|
@ -528,7 +495,24 @@ irqreturn_t via_nubus_irq(int irq, void *dev_id)
|
|||
else
|
||||
events &= ~via2[vDirA];
|
||||
} while (events);
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
/*
|
||||
* Register the interrupt dispatchers for VIA or RBV machines only.
|
||||
*/
|
||||
|
||||
void __init via_register_interrupts(void)
|
||||
{
|
||||
if (via_alt_mapping) {
|
||||
/* software interrupt */
|
||||
irq_set_chained_handler(IRQ_AUTO_1, via1_irq);
|
||||
/* via1 interrupt */
|
||||
irq_set_chained_handler(IRQ_AUTO_6, via1_irq);
|
||||
} else {
|
||||
irq_set_chained_handler(IRQ_AUTO_1, via1_irq);
|
||||
}
|
||||
irq_set_chained_handler(IRQ_AUTO_2, via2_irq);
|
||||
irq_set_chained_handler(IRQ_MAC_NUBUS, via_nubus_irq);
|
||||
}
|
||||
|
||||
void via_irq_enable(int irq) {
|
||||
|
|
|
@ -81,7 +81,7 @@ static void mvme147_get_model(char *model)
|
|||
|
||||
void __init mvme147_init_IRQ(void)
|
||||
{
|
||||
m68k_setup_user_interrupt(VEC_USER, 192, NULL);
|
||||
m68k_setup_user_interrupt(VEC_USER, 192);
|
||||
}
|
||||
|
||||
void __init config_mvme147(void)
|
||||
|
@ -114,8 +114,7 @@ static irqreturn_t mvme147_timer_int (int irq, void *dev_id)
|
|||
void mvme147_sched_init (irq_handler_t timer_routine)
|
||||
{
|
||||
tick_handler = timer_routine;
|
||||
if (request_irq(PCC_IRQ_TIMER1, mvme147_timer_int, IRQ_FLG_REPLACE,
|
||||
"timer 1", NULL))
|
||||
if (request_irq(PCC_IRQ_TIMER1, mvme147_timer_int, 0, "timer 1", NULL))
|
||||
pr_err("Couldn't register timer interrupt\n");
|
||||
|
||||
/* Init the clock with a value */
|
||||
|
|
|
@ -117,7 +117,7 @@ static void mvme16x_get_hardware_list(struct seq_file *m)
|
|||
|
||||
static void __init mvme16x_init_IRQ (void)
|
||||
{
|
||||
m68k_setup_user_interrupt(VEC_USER, 192, NULL);
|
||||
m68k_setup_user_interrupt(VEC_USER, 192);
|
||||
}
|
||||
|
||||
#define pcc2chip ((volatile u_char *)0xfff42000)
|
||||
|
|
|
@ -15,10 +15,10 @@
|
|||
#include <linux/kernel.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/irq.h>
|
||||
|
||||
#include <asm/ptrace.h>
|
||||
#include <asm/system.h>
|
||||
#include <asm/irq.h>
|
||||
#include <asm/traps.h>
|
||||
|
||||
#include <asm/q40_master.h>
|
||||
|
@ -35,35 +35,36 @@
|
|||
*/
|
||||
|
||||
static void q40_irq_handler(unsigned int, struct pt_regs *fp);
|
||||
static void q40_enable_irq(unsigned int);
|
||||
static void q40_disable_irq(unsigned int);
|
||||
static void q40_irq_enable(struct irq_data *data);
|
||||
static void q40_irq_disable(struct irq_data *data);
|
||||
|
||||
unsigned short q40_ablecount[35];
|
||||
unsigned short q40_state[35];
|
||||
|
||||
static int q40_irq_startup(unsigned int irq)
|
||||
static unsigned int q40_irq_startup(struct irq_data *data)
|
||||
{
|
||||
unsigned int irq = data->irq;
|
||||
|
||||
/* test for ISA ints not implemented by HW */
|
||||
switch (irq) {
|
||||
case 1: case 2: case 8: case 9:
|
||||
case 11: case 12: case 13:
|
||||
printk("%s: ISA IRQ %d not implemented by HW\n", __func__, irq);
|
||||
return -ENXIO;
|
||||
/* FIXME return -ENXIO; */
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void q40_irq_shutdown(unsigned int irq)
|
||||
static void q40_irq_shutdown(struct irq_data *data)
|
||||
{
|
||||
}
|
||||
|
||||
static struct irq_controller q40_irq_controller = {
|
||||
static struct irq_chip q40_irq_chip = {
|
||||
.name = "q40",
|
||||
.lock = __SPIN_LOCK_UNLOCKED(q40_irq_controller.lock),
|
||||
.startup = q40_irq_startup,
|
||||
.shutdown = q40_irq_shutdown,
|
||||
.enable = q40_enable_irq,
|
||||
.disable = q40_disable_irq,
|
||||
.irq_startup = q40_irq_startup,
|
||||
.irq_shutdown = q40_irq_shutdown,
|
||||
.irq_enable = q40_irq_enable,
|
||||
.irq_disable = q40_irq_disable,
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -81,13 +82,14 @@ static int disabled;
|
|||
|
||||
void __init q40_init_IRQ(void)
|
||||
{
|
||||
m68k_setup_irq_controller(&q40_irq_controller, 1, Q40_IRQ_MAX);
|
||||
m68k_setup_irq_controller(&q40_irq_chip, handle_simple_irq, 1,
|
||||
Q40_IRQ_MAX);
|
||||
|
||||
/* setup handler for ISA ints */
|
||||
m68k_setup_auto_interrupt(q40_irq_handler);
|
||||
|
||||
m68k_irq_startup(IRQ_AUTO_2);
|
||||
m68k_irq_startup(IRQ_AUTO_4);
|
||||
m68k_irq_startup_irq(IRQ_AUTO_2);
|
||||
m68k_irq_startup_irq(IRQ_AUTO_4);
|
||||
|
||||
/* now enable some ints.. */
|
||||
master_outb(1, EXT_ENABLE_REG); /* ISA IRQ 5-15 */
|
||||
|
@ -218,11 +220,11 @@ static void q40_irq_handler(unsigned int irq, struct pt_regs *fp)
|
|||
switch (irq) {
|
||||
case 4:
|
||||
case 6:
|
||||
__m68k_handle_int(Q40_IRQ_SAMPLE, fp);
|
||||
do_IRQ(Q40_IRQ_SAMPLE, fp);
|
||||
return;
|
||||
}
|
||||
if (mir & Q40_IRQ_FRAME_MASK) {
|
||||
__m68k_handle_int(Q40_IRQ_FRAME, fp);
|
||||
do_IRQ(Q40_IRQ_FRAME, fp);
|
||||
master_outb(-1, FRAME_CLEAR_REG);
|
||||
}
|
||||
if ((mir & Q40_IRQ_SER_MASK) || (mir & Q40_IRQ_EXT_MASK)) {
|
||||
|
@ -257,7 +259,7 @@ static void q40_irq_handler(unsigned int irq, struct pt_regs *fp)
|
|||
goto iirq;
|
||||
}
|
||||
q40_state[irq] |= IRQ_INPROGRESS;
|
||||
__m68k_handle_int(irq, fp);
|
||||
do_IRQ(irq, fp);
|
||||
q40_state[irq] &= ~IRQ_INPROGRESS;
|
||||
|
||||
/* naively enable everything, if that fails than */
|
||||
|
@ -288,25 +290,29 @@ static void q40_irq_handler(unsigned int irq, struct pt_regs *fp)
|
|||
mir = master_inb(IIRQ_REG);
|
||||
/* should test whether keyboard irq is really enabled, doing it in defhand */
|
||||
if (mir & Q40_IRQ_KEYB_MASK)
|
||||
__m68k_handle_int(Q40_IRQ_KEYBOARD, fp);
|
||||
do_IRQ(Q40_IRQ_KEYBOARD, fp);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void q40_enable_irq(unsigned int irq)
|
||||
void q40_irq_enable(struct irq_data *data)
|
||||
{
|
||||
unsigned int irq = data->irq;
|
||||
|
||||
if (irq >= 5 && irq <= 15) {
|
||||
mext_disabled--;
|
||||
if (mext_disabled > 0)
|
||||
printk("q40_enable_irq : nested disable/enable\n");
|
||||
printk("q40_irq_enable : nested disable/enable\n");
|
||||
if (mext_disabled == 0)
|
||||
master_outb(1, EXT_ENABLE_REG);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void q40_disable_irq(unsigned int irq)
|
||||
void q40_irq_disable(struct irq_data *data)
|
||||
{
|
||||
unsigned int irq = data->irq;
|
||||
|
||||
/* disable ISA iqs : only do something if the driver has been
|
||||
* verified to be Q40 "compatible" - right now IDE, NE2K
|
||||
* Any driver should not attempt to sleep across disable_irq !!
|
||||
|
@ -319,13 +325,3 @@ void q40_disable_irq(unsigned int irq)
|
|||
printk("disable_irq nesting count %d\n",mext_disabled);
|
||||
}
|
||||
}
|
||||
|
||||
unsigned long q40_probe_irq_on(void)
|
||||
{
|
||||
printk("irq probing not working - reconfigure the driver to avoid this\n");
|
||||
return -1;
|
||||
}
|
||||
int q40_probe_irq_off(unsigned long irqs)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
|
|
@ -51,25 +51,29 @@ void sun3_disable_irq(unsigned int irq)
|
|||
|
||||
static irqreturn_t sun3_int7(int irq, void *dev_id)
|
||||
{
|
||||
*sun3_intreg |= (1 << irq);
|
||||
if (!(kstat_cpu(0).irqs[irq] % 2000))
|
||||
sun3_leds(led_pattern[(kstat_cpu(0).irqs[irq] % 16000) / 2000]);
|
||||
unsigned int cnt;
|
||||
|
||||
cnt = kstat_irqs_cpu(irq, 0);
|
||||
if (!(cnt % 2000))
|
||||
sun3_leds(led_pattern[cnt % 16000 / 2000]);
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static irqreturn_t sun3_int5(int irq, void *dev_id)
|
||||
{
|
||||
unsigned int cnt;
|
||||
|
||||
#ifdef CONFIG_SUN3
|
||||
intersil_clear();
|
||||
#endif
|
||||
*sun3_intreg |= (1 << irq);
|
||||
#ifdef CONFIG_SUN3
|
||||
intersil_clear();
|
||||
#endif
|
||||
xtime_update(1);
|
||||
update_process_times(user_mode(get_irq_regs()));
|
||||
if (!(kstat_cpu(0).irqs[irq] % 20))
|
||||
sun3_leds(led_pattern[(kstat_cpu(0).irqs[irq] % 160) / 20]);
|
||||
cnt = kstat_irqs_cpu(irq, 0);
|
||||
if (!(cnt % 20))
|
||||
sun3_leds(led_pattern[cnt % 160 / 20]);
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
|
@ -79,29 +83,33 @@ static irqreturn_t sun3_vec255(int irq, void *dev_id)
|
|||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static void sun3_inthandle(unsigned int irq, struct pt_regs *fp)
|
||||
static void sun3_irq_enable(struct irq_data *data)
|
||||
{
|
||||
*sun3_intreg &= ~(1 << irq);
|
||||
sun3_enable_irq(data->irq);
|
||||
};
|
||||
|
||||
__m68k_handle_int(irq, fp);
|
||||
}
|
||||
static void sun3_irq_disable(struct irq_data *data)
|
||||
{
|
||||
sun3_disable_irq(data->irq);
|
||||
};
|
||||
|
||||
static struct irq_controller sun3_irq_controller = {
|
||||
static struct irq_chip sun3_irq_chip = {
|
||||
.name = "sun3",
|
||||
.lock = __SPIN_LOCK_UNLOCKED(sun3_irq_controller.lock),
|
||||
.startup = m68k_irq_startup,
|
||||
.shutdown = m68k_irq_shutdown,
|
||||
.enable = sun3_enable_irq,
|
||||
.disable = sun3_disable_irq,
|
||||
.irq_startup = m68k_irq_startup,
|
||||
.irq_shutdown = m68k_irq_shutdown,
|
||||
.irq_enable = sun3_irq_enable,
|
||||
.irq_disable = sun3_irq_disable,
|
||||
.irq_mask = sun3_irq_disable,
|
||||
.irq_unmask = sun3_irq_enable,
|
||||
};
|
||||
|
||||
void __init sun3_init_IRQ(void)
|
||||
{
|
||||
*sun3_intreg = 1;
|
||||
|
||||
m68k_setup_auto_interrupt(sun3_inthandle);
|
||||
m68k_setup_irq_controller(&sun3_irq_controller, IRQ_AUTO_1, 7);
|
||||
m68k_setup_user_interrupt(VEC_USER, 128, NULL);
|
||||
m68k_setup_irq_controller(&sun3_irq_chip, handle_level_irq, IRQ_AUTO_1,
|
||||
7);
|
||||
m68k_setup_user_interrupt(VEC_USER, 128);
|
||||
|
||||
if (request_irq(IRQ_AUTO_5, sun3_int5, 0, "int5", NULL))
|
||||
pr_err("Couldn't register %s interrupt\n", "int5");
|
||||
|
|
|
@ -43,7 +43,6 @@
|
|||
/* For SCSI -> ATAPI command conversion */
|
||||
#include <scsi/scsi.h>
|
||||
|
||||
#include <linux/irq.h>
|
||||
#include <linux/io.h>
|
||||
#include <asm/byteorder.h>
|
||||
#include <linux/uaccess.h>
|
||||
|
|
|
@ -35,7 +35,6 @@
|
|||
#include <scsi/scsi_ioctl.h>
|
||||
|
||||
#include <asm/byteorder.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/io.h>
|
||||
#include <asm/unaligned.h>
|
||||
|
|
|
@ -41,7 +41,6 @@
|
|||
#include <scsi/scsi.h>
|
||||
|
||||
#include <asm/byteorder.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/io.h>
|
||||
#include <asm/unaligned.h>
|
||||
|
|
|
@ -159,7 +159,7 @@ int macii_init(void)
|
|||
err = macii_init_via();
|
||||
if (err) goto out;
|
||||
|
||||
err = request_irq(IRQ_MAC_ADB, macii_interrupt, IRQ_FLG_LOCK, "ADB",
|
||||
err = request_irq(IRQ_MAC_ADB, macii_interrupt, 0, "ADB",
|
||||
macii_interrupt);
|
||||
if (err) goto out;
|
||||
|
||||
|
|
|
@ -122,8 +122,8 @@ maciisi_init(void)
|
|||
return err;
|
||||
}
|
||||
|
||||
if (request_irq(IRQ_MAC_ADB, maciisi_interrupt, IRQ_FLG_LOCK | IRQ_FLG_FAST,
|
||||
"ADB", maciisi_interrupt)) {
|
||||
if (request_irq(IRQ_MAC_ADB, maciisi_interrupt, 0, "ADB",
|
||||
maciisi_interrupt)) {
|
||||
printk(KERN_ERR "maciisi_init: can't get irq %d\n", IRQ_MAC_ADB);
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче