From: hollis@austin.ibm.com
To: linuxppc-dev@lists.linuxppc.org
Subject: Re: patch: i8259.c & PCI int ack
Date: Tue, 4 Dec 2001 10:29:58 -0600 [thread overview]
Message-ID: <20011204102958.L421@austin.ibm.com> (raw)
In-Reply-To: <20011204094600.K421@austin.ibm.com>
[-- Attachment #1: Type: text/plain, Size: 14 bytes --]
Ugh.
-Hollis
[-- Attachment #2: i8259-full.diff --]
[-- Type: text/plain, Size: 15754 bytes --]
===== kernel/i8259.c 1.11 vs edited =====
--- 1.11/arch/ppc/kernel/i8259.c Sun Nov 25 21:32:25 2001
+++ edited/arch/ppc/kernel/i8259.c Mon Dec 3 16:45:31 2001
@@ -4,11 +4,15 @@
#include <linux/stddef.h>
#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/ioport.h>
#include <linux/sched.h>
#include <linux/signal.h>
#include <asm/io.h>
#include <asm/i8259.h>
+static volatile char *pci_intack; /* RO, gives us the irq vector */
+
unsigned char cached_8259[2] = { 0xff, 0xff };
#define cached_A1 (cached_8259[0])
#define cached_21 (cached_8259[1])
@@ -17,35 +21,58 @@
int i8259_pic_irq_offset;
-int i8259_irq(int cpu)
+/* Acknowledge the irq using the PCI host bridge's interrupt acknowledge
+ * feature. (Polling is somehow broken on some IBM and Motorola PReP boxes.)
+ */
+int i8259_irq(void)
{
int irq;
-
+
spin_lock/*_irqsave*/(&i8259_lock/*, flags*/);
- /*
- * Perform an interrupt acknowledge cycle on controller 1
- */
- outb(0x0C, 0x20);
- irq = inb(0x20) & 7;
- if (irq == 2)
- {
- /*
- * Interrupt is cascaded so perform interrupt
- * acknowledge on controller 2
- */
- outb(0x0C, 0xA0);
- irq = (inb(0xA0) & 7) + 8;
- }
- else if (irq==7)
- {
- /*
- * This may be a spurious interrupt
- *
- * Read the interrupt status register. If the most
- * significant bit is not set then there is no valid
+
+ irq = *pci_intack & 0xff;
+ if (irq==7) {
+ /*
+ * This may be a spurious interrupt.
+ *
+ * Read the interrupt status register (ISR). If the most
+ * significant bit is not set then there is no valid
+ * interrupt.
+ */
+ if(~inb(0x20)&0x80) {
+ irq = -1;
+ }
+ }
+ spin_unlock/*_irqrestore*/(&i8259_lock/*, flags*/);
+ return irq;
+}
+
+/* Poke the 8259's directly using poll commands. */
+int i8259_poll(void)
+{
+ int irq;
+
+ spin_lock/*_irqsave*/(&i8259_lock/*, flags*/);
+ /*
+ * Perform an interrupt acknowledge cycle on controller 1
+ */
+ outb(0x0C, 0x20); /* prepare for poll */
+ irq = inb(0x20) & 7;
+ if (irq == 2) {
+ /*
+ * Interrupt is cascaded so perform interrupt
+ * acknowledge on controller 2
+ */
+ outb(0x0C, 0xA0); /* prepare for poll */
+ irq = (inb(0xA0) & 7) + 8;
+ } else if (irq==7) {
+ /*
+ * This may be a spurious interrupt
+ *
+ * Read the interrupt status register. If the most
+ * significant bit is not set then there is no valid
* interrupt
*/
- outb(0x0b, 0x20);
if(~inb(0x20)&0x80) {
spin_unlock/*_irqrestore*/(&i8259_lock/*, flags*/);
return -1;
@@ -58,30 +85,30 @@
static void i8259_mask_and_ack_irq(unsigned int irq_nr)
{
unsigned long flags;
-
+
spin_lock_irqsave(&i8259_lock, flags);
- if ( irq_nr >= i8259_pic_irq_offset )
- irq_nr -= i8259_pic_irq_offset;
+ if ( irq_nr >= i8259_pic_irq_offset )
+ irq_nr -= i8259_pic_irq_offset;
- if (irq_nr > 7) {
- cached_A1 |= 1 << (irq_nr-8);
- inb(0xA1); /* DUMMY */
- outb(cached_A1,0xA1);
- outb(0x20,0xA0); /* Non-specific EOI */
- outb(0x20,0x20); /* Non-specific EOI to cascade */
- } else {
- cached_21 |= 1 << irq_nr;
- inb(0x21); /* DUMMY */
- outb(cached_21,0x21);
- outb(0x20,0x20); /* Non-specific EOI */
- }
+ if (irq_nr > 7) {
+ cached_A1 |= 1 << (irq_nr-8);
+ inb(0xA1); /* DUMMY */
+ outb(cached_A1,0xA1);
+ outb(0x20,0xA0); /* Non-specific EOI */
+ outb(0x20,0x20); /* Non-specific EOI to cascade */
+ } else {
+ cached_21 |= 1 << irq_nr;
+ inb(0x21); /* DUMMY */
+ outb(cached_21,0x21);
+ outb(0x20,0x20); /* Non-specific EOI */
+ }
spin_unlock_irqrestore(&i8259_lock, flags);
}
static void i8259_set_irq_mask(int irq_nr)
{
- outb(cached_A1,0xA1);
- outb(cached_21,0x21);
+ outb(cached_A1,0xA1);
+ outb(cached_21,0x21);
}
static void i8259_mask_irq(unsigned int irq_nr)
@@ -89,13 +116,13 @@
unsigned long flags;
spin_lock_irqsave(&i8259_lock, flags);
- if ( irq_nr >= i8259_pic_irq_offset )
- irq_nr -= i8259_pic_irq_offset;
- if ( irq_nr < 8 )
- cached_21 |= 1 << irq_nr;
- else
- cached_A1 |= 1 << (irq_nr-8);
- i8259_set_irq_mask(irq_nr);
+ if ( irq_nr >= i8259_pic_irq_offset )
+ irq_nr -= i8259_pic_irq_offset;
+ if ( irq_nr < 8 )
+ cached_21 |= 1 << irq_nr;
+ else
+ cached_A1 |= 1 << (irq_nr-8);
+ i8259_set_irq_mask(irq_nr);
spin_unlock_irqrestore(&i8259_lock, flags);
}
@@ -104,13 +131,13 @@
unsigned long flags;
spin_lock_irqsave(&i8259_lock, flags);
- if ( irq_nr >= i8259_pic_irq_offset )
- irq_nr -= i8259_pic_irq_offset;
- if ( irq_nr < 8 )
- cached_21 &= ~(1 << irq_nr);
- else
- cached_A1 &= ~(1 << (irq_nr-8));
- i8259_set_irq_mask(irq_nr);
+ if ( irq_nr >= i8259_pic_irq_offset )
+ irq_nr -= i8259_pic_irq_offset;
+ if ( irq_nr < 8 )
+ cached_21 &= ~(1 << irq_nr);
+ else
+ cached_A1 &= ~(1 << (irq_nr-8));
+ i8259_set_irq_mask(irq_nr);
spin_unlock_irqrestore(&i8259_lock, flags);
}
@@ -121,36 +148,62 @@
}
struct hw_interrupt_type i8259_pic = {
- " i8259 ",
- NULL,
- NULL,
- i8259_unmask_irq,
- i8259_mask_irq,
- i8259_mask_and_ack_irq,
- i8259_end_irq,
- NULL
+ " i8259 ",
+ NULL,
+ NULL,
+ i8259_unmask_irq,
+ i8259_mask_irq,
+ i8259_mask_and_ack_irq,
+ i8259_end_irq,
+ NULL
};
-void __init i8259_init(void)
+static struct resource pic1_iores = {
+ "8259 (master)", 0x20, 0x21, IORESOURCE_BUSY
+};
+
+static struct resource pic2_iores = {
+ "8259 (slave)", 0xa0, 0xa1, IORESOURCE_BUSY
+};
+
+static struct resource pic_edgectrl_iores = {
+ "8259 edge control", 0x4d0, 0x4d1, IORESOURCE_BUSY
+};
+
+void __init i8259_init(long intack_addr)
{
unsigned long flags;
-
+
spin_lock_irqsave(&i8259_lock, flags);
- /* init master interrupt controller */
- outb(0x11, 0x20); /* Start init sequence */
- outb(0x00, 0x21); /* Vector base */
- outb(0x04, 0x21); /* edge tiggered, Cascade (slave) on IRQ2 */
- outb(0x01, 0x21); /* Select 8086 mode */
- outb(0xFF, 0x21); /* Mask all */
- /* init slave interrupt controller */
- outb(0x11, 0xA0); /* Start init sequence */
- outb(0x08, 0xA1); /* Vector base */
- outb(0x02, 0xA1); /* edge triggered, Cascade (slave) on IRQ2 */
- outb(0x01, 0xA1); /* Select 8086 mode */
- outb(0xFF, 0xA1); /* Mask all */
- outb(cached_A1, 0xA1);
- outb(cached_21, 0x21);
+ /* init master interrupt controller */
+ outb(0x11, 0x20); /* Start init sequence */
+ outb(0x00, 0x21); /* Vector base */
+ outb(0x04, 0x21); /* edge tiggered, Cascade (slave) on IRQ2 */
+ outb(0x01, 0x21); /* Select 8086 mode */
+
+ /* init slave interrupt controller */
+ outb(0x11, 0xA0); /* Start init sequence */
+ outb(0x08, 0xA1); /* Vector base */
+ outb(0x02, 0xA1); /* edge triggered, Cascade (slave) on IRQ2 */
+ outb(0x01, 0xA1); /* Select 8086 mode */
+
+ /* always read ISR */
+ outb(0x0B, 0x20);
+ outb(0x0B, 0xA0);
+
+ /* Mask all interrupts */
+ outb(cached_A1, 0xA1);
+ outb(cached_21, 0x21);
+
spin_unlock_irqrestore(&i8259_lock, flags);
- request_irq( i8259_pic_irq_offset + 2, no_action, SA_INTERRUPT,
- "82c59 secondary cascade", NULL );
+
+ /* reserve our resources */
+ request_irq( i8259_pic_irq_offset + 2, no_action, SA_INTERRUPT,
+ "82c59 secondary cascade", NULL );
+ request_resource(&ioport_resource, &pic1_iores);
+ request_resource(&ioport_resource, &pic2_iores);
+ request_resource(&ioport_resource, &pic_edgectrl_iores);
+
+ if (intack_addr)
+ pci_intack = ioremap(intack_addr, 1);
}
===== kernel/open_pic.c 1.42 vs edited =====
--- 1.42/arch/ppc/kernel/open_pic.c Sun Nov 4 06:02:40 2001
+++ edited/arch/ppc/kernel/open_pic.c Mon Dec 3 14:16:51 2001
@@ -19,6 +19,7 @@
#include <linux/irq.h>
#include <asm/ptrace.h>
#include <asm/signal.h>
+#include <asm/i8259.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/prom.h>
@@ -825,9 +826,6 @@
/*
* Clean up needed. -VAL
*/
-#ifndef CONFIG_GEMINI
- extern int i8259_irq(int cpu);
-#endif
int irq = openpic_irq();
/* Management of the cascade should be moved out of here */
@@ -842,7 +840,7 @@
irq = *chrp_int_ack_special;
#ifndef CONFIG_GEMINI
else
- irq = i8259_irq( smp_processor_id() );
+ irq = i8259_poll();
#endif
openpic_eoi();
}
===== platforms/adir_pic.c 1.6 vs edited =====
--- 1.6/arch/ppc/platforms/adir_pic.c Mon Nov 26 23:30:58 2001
+++ edited/arch/ppc/platforms/adir_pic.c Tue Dec 4 08:47:49 2001
@@ -102,7 +102,7 @@
/* Initialize the cascaded 8259's on the VT82C686 */
for (i=0; i<16; i++)
irq_desc[i].handler = &i8259_pic;
- i8259_init();
+ i8259_init(NULL);
/* Initialize Adirondack CPLD PIC and enable 8259 interrupt cascade */
for (i=16; i<32; i++)
@@ -126,7 +126,7 @@
return irq;
if (irq == ADIR_IRQ_VT82C686_INTR)
- irq = i8259_irq(0);
+ irq = i8259_poll();
return irq;
}
===== platforms/chrp_setup.c 1.49 vs edited =====
--- 1.49/arch/ppc/platforms/chrp_setup.c Wed Nov 28 22:43:34 2001
+++ edited/arch/ppc/platforms/chrp_setup.c Mon Dec 3 14:04:25 2001
@@ -370,7 +370,7 @@
openpic_init(1, NUM_8259_INTERRUPTS, chrp_int_ack_special, nmi_irq);
for ( i = 0 ; i < NUM_8259_INTERRUPTS ; i++ )
irq_desc[i].handler = &i8259_pic;
- i8259_init();
+ i8259_init(NULL);
#if defined(CONFIG_VT) && defined(CONFIG_ADB_KEYBOARD) && defined(XMON)
/* see if there is a keyboard in the device tree
with a parent of type "adb" */
===== platforms/k2_setup.c 1.21 vs edited =====
--- 1.21/arch/ppc/platforms/k2_setup.c Tue Nov 27 16:44:21 2001
+++ edited/arch/ppc/platforms/k2_setup.c Tue Dec 4 08:49:04 2001
@@ -334,13 +334,13 @@
for ( i = 0 ; i < 16 ; i++ )
irq_desc[i].handler = &i8259_pic;
- i8259_init();
+ i8259_init(NULL);
}
static int
k2_get_irq(struct pt_regs *regs)
{
- return i8259_irq(0);
+ return i8259_poll();
}
void __init platform_init(unsigned long r3, unsigned long r4,
===== platforms/lopec_setup.c 1.13 vs edited =====
--- 1.13/arch/ppc/platforms/lopec_setup.c Tue Nov 27 15:37:17 2001
+++ edited/arch/ppc/platforms/lopec_setup.c Tue Dec 4 08:49:38 2001
@@ -98,7 +98,7 @@
irq = openpic_irq();
if (irq == LOPEC_SIO_IRQ) {
- cascade_irq = i8259_irq(0);
+ cascade_irq = i8259_poll();
if (cascade_irq != -1) {
irq = cascade_irq;
@@ -229,7 +229,7 @@
LOPEC_SIO_IRQ);
}
- i8259_init();
+ i8259_init(NULL);
}
static void __init
===== platforms/mcpn765_setup.c 1.21 vs edited =====
--- 1.21/arch/ppc/platforms/mcpn765_setup.c Tue Nov 27 15:06:46 2001
+++ edited/arch/ppc/platforms/mcpn765_setup.c Tue Dec 4 08:50:11 2001
@@ -194,7 +194,7 @@
for(i=0; i < NUM_8259_INTERRUPTS; i++)
irq_desc[i].handler = &i8259_pic;
- i8259_init();
+ i8259_init(NULL);
if ( ppc_md.progress )
ppc_md.progress("init_irq: exit", 0);
===== platforms/menf1_setup.c 1.16 vs edited =====
--- 1.16/arch/ppc/platforms/menf1_setup.c Tue Nov 27 15:06:46 2001
+++ edited/arch/ppc/platforms/menf1_setup.c Tue Dec 4 08:50:40 2001
@@ -146,12 +146,12 @@
for ( i = 0 ; i < NUM_8259_INTERRUPTS ; i++ )
irq_desc[i].handler = &i8259_pic;
- i8259_init();
+ i8259_init(NULL);
}
static int menf1_get_irq(struct pt_regs *regs)
{
- return i8259_irq(0);
+ return i8259_poll();
}
/*
===== platforms/mvme5100_setup.c 1.22 vs edited =====
--- 1.22/arch/ppc/platforms/mvme5100_setup.c Tue Nov 27 17:22:04 2001
+++ edited/arch/ppc/platforms/mvme5100_setup.c Tue Dec 4 08:51:17 2001
@@ -143,7 +143,7 @@
for(i=0; i < NUM_8259_INTERRUPTS; i++)
irq_desc[i].handler = &i8259_pic;
- i8259_init();
+ i8259_init(NULL);
#else
openpic_init(1, 0, NULL, -1);
#endif
===== platforms/pcore_setup.c 1.16 vs edited =====
--- 1.16/arch/ppc/platforms/pcore_setup.c Tue Nov 27 15:06:46 2001
+++ edited/arch/ppc/platforms/pcore_setup.c Tue Dec 4 08:52:31 2001
@@ -166,13 +166,13 @@
for ( i = 0 ; i < 16 ; i++ )
irq_desc[i].handler = &i8259_pic;
- i8259_init();
+ i8259_init(NULL);
}
static int
pcore_get_irq(struct pt_regs *regs)
{
- return i8259_irq(0);
+ return i8259_poll();
}
/*
===== platforms/powerpmc250.c 1.12 vs edited =====
--- 1.12/arch/ppc/platforms/powerpmc250.c Tue Nov 27 17:22:04 2001
+++ edited/arch/ppc/platforms/powerpmc250.c Tue Dec 4 08:53:19 2001
@@ -192,7 +192,7 @@
}
/* Resolves the open_pic.c build without including i8259.c */
-int i8259_irq(int cpu)
+int i8259_poll(void)
{
return 0;
}
===== platforms/pplus_setup.c 1.4 vs edited =====
--- 1.4/arch/ppc/platforms/pplus_setup.c Wed Nov 21 15:27:27 2001
+++ edited/arch/ppc/platforms/pplus_setup.c Tue Dec 4 08:54:04 2001
@@ -261,7 +261,7 @@
static int
pplus_get_irq(struct pt_regs *regs)
{
- return i8259_irq(smp_processor_id());
+ return i8259_poll();
}
static void __init
@@ -273,7 +273,7 @@
openpic_init(1, NUM_8259_INTERRUPTS, 0, -1);
for ( i = 0 ; i < NUM_8259_INTERRUPTS ; i++ )
irq_desc[i].handler = &i8259_pic;
- i8259_init();
+ i8259_init(NULL);
}
#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
===== platforms/prep_setup.c 1.59 vs edited =====
--- 1.59/arch/ppc/platforms/prep_setup.c Thu Nov 29 08:55:58 2001
+++ edited/arch/ppc/platforms/prep_setup.c Mon Dec 3 13:48:45 2001
@@ -667,7 +667,7 @@
static int __prep
prep_get_irq(struct pt_regs *regs)
{
- return i8259_irq(smp_processor_id());
+ return i8259_irq();
}
static void __init
@@ -679,7 +679,7 @@
openpic_init(1, NUM_8259_INTERRUPTS, 0, -1);
for ( i = 0 ; i < NUM_8259_INTERRUPTS ; i++ )
irq_desc[i].handler = &i8259_pic;
- i8259_init();
+ i8259_init(0xbffffff0); /* PCI interrupt ack address for MPC105 and 106 */
}
#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
===== platforms/prpmc750_setup.c 1.17 vs edited =====
--- 1.17/arch/ppc/platforms/prpmc750_setup.c Tue Nov 27 17:22:04 2001
+++ edited/arch/ppc/platforms/prpmc750_setup.c Tue Dec 4 08:56:18 2001
@@ -201,7 +201,7 @@
}
/* Resolves the open_pic.c build without including i8259.c */
-int i8259_irq(int cpu)
+int i8259_poll(void)
{
return 0;
}
===== platforms/prpmc800_setup.c 1.12 vs edited =====
--- 1.12/arch/ppc/platforms/prpmc800_setup.c Tue Nov 27 17:22:04 2001
+++ edited/arch/ppc/platforms/prpmc800_setup.c Tue Dec 4 08:57:00 2001
@@ -195,7 +195,7 @@
}
/* Resolves the open_pic.c build without including i8259.c */
-int i8259_irq(int cpu)
+int i8259_poll()
{
return 0;
}
===== platforms/sandpoint_setup.c 1.20 vs edited =====
--- 1.20/arch/ppc/platforms/sandpoint_setup.c Tue Nov 27 15:06:47 2001
+++ edited/arch/ppc/platforms/sandpoint_setup.c Tue Dec 4 08:58:55 2001
@@ -327,7 +327,7 @@
SANDPOINT_SIO_IRQ);
}
- i8259_init();
+ i8259_init(NULL);
}
static int
@@ -338,7 +338,7 @@
irq = openpic_irq();
if (irq == SANDPOINT_SIO_IRQ) {
- cascade_irq = i8259_irq(smp_processor_id());
+ cascade_irq = i8259_poll();
if (cascade_irq != -1) {
irq = cascade_irq;
===== ./i8259.h 1.9 vs edited =====
--- 1.9/include/asm-ppc/i8259.h Sun Nov 4 04:07:38 2001
+++ edited/include/asm-ppc/i8259.h Mon Dec 3 14:09:08 2001
@@ -5,11 +5,10 @@
#ifndef _PPC_KERNEL_i8259_H
#define _PPC_KERNEL_i8259_H
-#include <linux/irq.h>
-
extern struct hw_interrupt_type i8259_pic;
-void i8259_init(void);
-int i8259_irq(int);
+void i8259_init(long);
+int i8259_irq(void);
+int i8259_poll(void);
#endif /* _PPC_KERNEL_i8259_H */
next prev parent reply other threads:[~2001-12-04 16:29 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2001-12-03 22:09 RFC: i8259.c & PCI int ack hollis
2001-12-04 15:46 ` patch: " hollis
2001-12-04 16:29 ` hollis [this message]
2001-12-06 14:00 ` Mathias von Essen
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20011204102958.L421@austin.ibm.com \
--to=hollis@austin.ibm.com \
--cc=linuxppc-dev@lists.linuxppc.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.