Module Name:    src
Committed By:   macallan
Date:           Wed Oct 18 12:55:14 UTC 2017

Modified Files:
        src/sys/arch/macppc/macppc: pic_u3_ht.c

Log Message:
do what freebsd does:
- when disabling an interrupt, disable it on the HT PIC as well
- when establishing an interrupt, don't enable it right away
- program IRQs 0-3 as level, like freebsd does
Now svwsata is almost usable. We still get an interrupt storm but it doesn't
eat up all CPU cycles anymore.


To generate a diff of this commit:
cvs rdiff -u -r1.2 -r1.3 src/sys/arch/macppc/macppc/pic_u3_ht.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/arch/macppc/macppc/pic_u3_ht.c
diff -u src/sys/arch/macppc/macppc/pic_u3_ht.c:1.2 src/sys/arch/macppc/macppc/pic_u3_ht.c:1.3
--- src/sys/arch/macppc/macppc/pic_u3_ht.c:1.2	Thu Jun  1 02:45:06 2017
+++ src/sys/arch/macppc/macppc/pic_u3_ht.c	Wed Oct 18 12:55:14 2017
@@ -43,6 +43,12 @@
 #include <machine/autoconf.h>
 #include <arch/powerpc/pic/picvar.h>
 
+#ifdef U3_HT_PIC_DEPUG
+#define DPRINTF aprint_error
+#else
+#define DPRINTF if (0) printf
+#endif
+
 struct u3_ht_irqmap {
 	int im_index;
 	int im_level;
@@ -78,6 +84,7 @@ static void u3_ht_finish_setup(struct pi
 static int u3_ht_is_ht_irq(struct u3_ht_ops *, int);
 static void u3_ht_establish_ht_irq(struct u3_ht_ops *, int, int);
 static void u3_ht_enable_ht_irq(struct u3_ht_ops *, int);
+static void u3_ht_disable_ht_irq(struct u3_ht_ops *, int);
 static void u3_ht_ack_ht_irq(struct u3_ht_ops *, int);
 
 static void u3_ht_set_priority(struct u3_ht_ops *, int, int);
@@ -206,7 +213,7 @@ setup_u3_ht(uint32_t addr, uint32_t len,
 
 	u3_ht_set_priority(u3_ht, 0, 15);
 
-	for (irq = 0; irq < pic->pic_numintrs; irq++) {
+	for (irq = 0; irq < 4; irq++) {
 		x = irq;
 		x |= OPENPIC_IMASK;
 		x |= OPENPIC_POLARITY_NEGATIVE;
@@ -215,6 +222,15 @@ setup_u3_ht(uint32_t addr, uint32_t len,
 		u3_ht_write(u3_ht, OPENPIC_SRC_VECTOR(irq), x);
 		u3_ht_write(u3_ht, OPENPIC_IDEST(irq), 1 << 0);
 	}
+	for (irq = 4; irq < pic->pic_numintrs; irq++) {
+		x = irq;
+		x |= OPENPIC_IMASK;
+		x |= OPENPIC_POLARITY_NEGATIVE;
+		x |= OPENPIC_SENSE_EDGE;
+		x |= 8 << OPENPIC_PRIORITY_SHIFT;
+		u3_ht_write(u3_ht, OPENPIC_SRC_VECTOR(irq), x);
+		u3_ht_write(u3_ht, OPENPIC_IDEST(irq), 1 << 0);
+	}
 
 	x = u3_ht_read(u3_ht, OPENPIC_CONFIG);
 	x |= OPENPIC_CONFIG_8259_PASSTHRU_DISABLE;
@@ -253,6 +269,8 @@ setup_u3_ht_workarounds(struct u3_ht_ops
 	ht_reg = mapiodev(reg[1], reg[2], false);
 	KASSERT(ht_reg != NULL);
 
+	memset(irqmap, 0, sizeof(u3_ht->ht_irqmap));
+
 	for (child = OF_child(parent); child != 0; child = OF_peer(child)) {
 		if (OF_getprop(child, "reg", reg, 4) != 4) 
 			continue;
@@ -284,6 +302,8 @@ setup_u3_ht_workarounds(struct u3_ht_ops
 		nirq = in32rb(base + 0x04);
 		nirq = (nirq >> 16) & 0xff;
 
+		DPRINTF("dev %08x nirq %d pos %08x\n", (uint32_t)base, nirq, (uint32_t)pos);
+		DPRINTF("devreg %08x\n", in32rb(dev_reg + PCI_ID_REG));
 		for (i = 0; i <= nirq; i++) {
 			out8rb(base + 0x02, 0x10 + (i << 1));
 			tmp = in32rb(base + 0x04);
@@ -333,6 +353,9 @@ u3_ht_disable_irq(struct pic_ops *pic, i
  	x = u3_ht_read(u3_ht, OPENPIC_SRC_VECTOR(irq));
  	x |= OPENPIC_IMASK;
  	u3_ht_write(u3_ht, OPENPIC_SRC_VECTOR(irq), x);
+
+	if (u3_ht_is_ht_irq(u3_ht, irq))
+		u3_ht_disable_ht_irq(u3_ht, irq);
 }
 
 static int
@@ -385,8 +408,8 @@ u3_ht_establish_irq(struct pic_ops *pic,
 	if (u3_ht_is_ht_irq(u3_ht, irq))
 		u3_ht_establish_ht_irq(u3_ht, irq, type);
 
-	aprint_debug("%s: setting IRQ %d to priority %d\n", __func__, irq,
-	    realpri);
+	aprint_error("%s: setting IRQ %d %d to priority %d %x\n", __func__, irq,
+	    type, realpri, x);
 }
 
 static void
@@ -422,10 +445,15 @@ u3_ht_establish_ht_irq(struct u3_ht_ops 
 	out8rb(irqmap->im_base + 0x02, 0x10 + (irqmap->im_index << 1));
 
 	x = in32rb(irqmap->im_base + 0x04);
-	x &= ~0x23;
+	/* mask interrupt */
+	out32rb(irqmap->im_base + 0x04, x | 1);
+
+	/* mask out EOI and LEVEL bits */
+	x &= ~0x22;
 
 	if (type == IST_LEVEL_HIGH || type == IST_LEVEL_LOW) {
 		irqmap->im_level = 1;
+		DPRINTF("level\n");
 		x |= 0x22;
 	} else {
 		irqmap->im_level = 0;
@@ -449,6 +477,18 @@ u3_ht_enable_ht_irq(struct u3_ht_ops *u3
 }
 
 static void
+u3_ht_disable_ht_irq(struct u3_ht_ops *u3_ht, int irq)
+{
+	struct u3_ht_irqmap *irqmap = &u3_ht->ht_irqmap[irq];
+	u_int x;
+
+	out8rb(irqmap->im_base + 0x02, 0x10 + (irqmap->im_index << 1));
+	x = in32rb(irqmap->im_base + 0x04);
+	x |= 0x01;
+	out32rb(irqmap->im_base + 0x04, x);
+}
+
+static void
 u3_ht_ack_ht_irq(struct u3_ht_ops *u3_ht, int irq)
 {
 	struct u3_ht_irqmap *irqmap = &u3_ht->ht_irqmap[irq];

Reply via email to