Module Name: src
Committed By: macallan
Date: Thu Apr 18 16:42:46 UTC 2013
Modified Files:
src/sys/arch/macppc/conf: files.macppc
src/sys/arch/macppc/include: intr.h
src/sys/arch/macppc/macppc: interrupts.c
Added Files:
src/sys/arch/macppc/macppc: pic_u3_ht.c
Log Message:
support OpenPIC variant found in PowerMac G5s
from Phileas Fogg
To generate a diff of this commit:
cvs rdiff -u -r1.99 -r1.100 src/sys/arch/macppc/conf/files.macppc
cvs rdiff -u -r1.30 -r1.31 src/sys/arch/macppc/include/intr.h
cvs rdiff -u -r1.4 -r1.5 src/sys/arch/macppc/macppc/interrupts.c
cvs rdiff -u -r0 -r1.1 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/conf/files.macppc
diff -u src/sys/arch/macppc/conf/files.macppc:1.99 src/sys/arch/macppc/conf/files.macppc:1.100
--- src/sys/arch/macppc/conf/files.macppc:1.99 Tue Jan 24 04:33:11 2012
+++ src/sys/arch/macppc/conf/files.macppc Thu Apr 18 16:42:46 2013
@@ -1,4 +1,4 @@
-# $NetBSD: files.macppc,v 1.99 2012/01/24 04:33:11 macallan Exp $
+# $NetBSD: files.macppc,v 1.100 2013/04/18 16:42:46 macallan Exp $
#
# macppc-specific configuration info
@@ -25,13 +25,16 @@ file arch/macppc/dev/dbdma.c
# interrupt controllers
define pic_ohare
define pic_heathrow
+define pic_u3_ht
defflag opt_interrupt.h PIC_OHARE: pic_ohare
defflag opt_interrupt.h OHARE_DEBUG
defflag opt_interrupt.h PIC_HEATHROW: pic_heathrow
+defflag opt_interrupt.h PIC_U3_HT: pic_u3_ht
file arch/macppc/macppc/pic_ohare.c pic_ohare needs-flag
file arch/macppc/macppc/pic_heathrow.c pic_heathrow needs-flag
+file arch/macppc/macppc/pic_u3_ht.c pic_u3_ht needs-flag
# IPI interface
define ipi_hammerhead
@@ -108,7 +111,7 @@ device grackle: pcibus, pic_heathrow
attach grackle at mainbus
file arch/macppc/pci/grackle.c grackle
-device uninorth: pcibus, pic_openpic, ipi_openpic
+device uninorth: pcibus, pic_openpic, ipi_openpic, pic_u3_ht
attach uninorth at mainbus
file arch/macppc/pci/uninorth.c uninorth
@@ -121,7 +124,7 @@ file arch/macppc/dev/uni-n.c uni_n
include "dev/usb/files.usb"
include "dev/bluetooth/files.bluetooth"
-device ibmcpc: pcibus, pic_openpic, ipi_openpic
+device ibmcpc: pcibus, pic_openpic, ipi_openpic, pic_u3_ht
attach ibmcpc at mainbus
file arch/macppc/pci/u3.c ibmcpc
Index: src/sys/arch/macppc/include/intr.h
diff -u src/sys/arch/macppc/include/intr.h:1.30 src/sys/arch/macppc/include/intr.h:1.31
--- src/sys/arch/macppc/include/intr.h:1.30 Fri Jun 17 23:36:17 2011
+++ src/sys/arch/macppc/include/intr.h Thu Apr 18 16:42:46 2013
@@ -1,4 +1,4 @@
-/* $NetBSD: intr.h,v 1.30 2011/06/17 23:36:17 matt Exp $ */
+/* $NetBSD: intr.h,v 1.31 2013/04/18 16:42:46 macallan Exp $ */
/*-
* Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -52,6 +52,7 @@ struct cpu_info;
/* probe for a PIC and set it up, return TRUE on success */
int init_ohare(void);
int init_heathrow(void);
+int init_u3_ht(void);
int init_grandcentral(void);
void setup_hammerhead_ipi(void);
#endif
Index: src/sys/arch/macppc/macppc/interrupts.c
diff -u src/sys/arch/macppc/macppc/interrupts.c:1.4 src/sys/arch/macppc/macppc/interrupts.c:1.5
--- src/sys/arch/macppc/macppc/interrupts.c:1.4 Sun Nov 14 03:57:17 2010
+++ src/sys/arch/macppc/macppc/interrupts.c Thu Apr 18 16:42:46 2013
@@ -1,4 +1,4 @@
-/* $NetBSD: interrupts.c,v 1.4 2010/11/14 03:57:17 uebayasi Exp $ */
+/* $NetBSD: interrupts.c,v 1.5 2013/04/18 16:42:46 macallan Exp $ */
/*-
* Copyright (c) 2007 Michael Lorenz
@@ -27,7 +27,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: interrupts.c,v 1.4 2010/11/14 03:57:17 uebayasi Exp $");
+__KERNEL_RCSID(0, "$NetBSD: interrupts.c,v 1.5 2013/04/18 16:42:46 macallan Exp $");
#include "opt_multiprocessor.h"
@@ -47,6 +47,7 @@ __KERNEL_RCSID(0, "$NetBSD: interrupts.c
#include "pic_openpic.h"
#include "pic_ohare.h"
#include "pic_heathrow.h"
+#include "pic_u3_ht.h"
#include "opt_ipi.h"
#include "ipi_openpic.h"
#include "ipi_hammerhead.h"
@@ -119,6 +120,10 @@ init_interrupt(void)
if (init_heathrow())
goto done;
#endif
+#if NPIC_U3_HT > 0
+ if (init_u3_ht())
+ goto done;
+#endif
#if NPIC_OPENPIC > 0
if (init_openpic(0))
goto done;
Added files:
Index: src/sys/arch/macppc/macppc/pic_u3_ht.c
diff -u /dev/null src/sys/arch/macppc/macppc/pic_u3_ht.c:1.1
--- /dev/null Thu Apr 18 16:42:46 2013
+++ src/sys/arch/macppc/macppc/pic_u3_ht.c Thu Apr 18 16:42:46 2013
@@ -0,0 +1,522 @@
+/*-
+ * Copyright (c) 2013 Phileas Fogg
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+
+#include "opt_openpic.h"
+#include "opt_interrupt.h"
+
+#include <sys/param.h>
+#include <sys/kmem.h>
+#include <sys/kernel.h>
+
+#include <machine/pio.h>
+#include <powerpc/openpic.h>
+
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_pci.h>
+#include <dev/pci/pcireg.h>
+
+#include <machine/autoconf.h>
+#include <arch/powerpc/pic/picvar.h>
+
+struct u3_ht_irqmap {
+ int im_index;
+ int im_level;
+ volatile uint8_t *im_base;
+ volatile uint8_t *im_apple_base;
+ uint32_t im_data;
+};
+
+struct u3_ht_ops {
+ struct pic_ops pic;
+
+ volatile uint8_t *ht_base;
+
+ struct u3_ht_irqmap ht_irqmap[128];
+
+ uint32_t (*ht_read)(struct u3_ht_ops *, u_int);
+ void (*ht_write)(struct u3_ht_ops *, u_int, uint32_t);
+};
+
+#define u3_ht_read(ptr,reg) (ptr)->ht_read(ptr, reg)
+#define u3_ht_write(ptr,reg,val) (ptr)->ht_write(ptr, reg, val)
+
+static struct u3_ht_ops *setup_u3_ht(uint32_t, uint32_t, int);
+static int setup_u3_ht_workarounds(struct u3_ht_ops *);
+
+static void u3_ht_enable_irq(struct pic_ops *, int, int);
+static void u3_ht_disable_irq(struct pic_ops *, int);
+static int u3_ht_get_irq(struct pic_ops *, int);
+static void u3_ht_ack_irq(struct pic_ops *, int);
+static void u3_ht_establish_irq(struct pic_ops *, int, int, int);
+static void u3_ht_finish_setup(struct pic_ops *);
+
+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_ack_ht_irq(struct u3_ht_ops *, int);
+
+static void u3_ht_set_priority(struct u3_ht_ops *, int, int);
+static int u3_ht_read_irq(struct u3_ht_ops *, int);
+static void u3_ht_eoi(struct u3_ht_ops *, int);
+
+static uint32_t u3_ht_read_be(struct u3_ht_ops *, u_int);
+static void u3_ht_write_be(struct u3_ht_ops *, u_int, uint32_t);
+static uint32_t u3_ht_read_le(struct u3_ht_ops *, u_int);
+static void u3_ht_write_le(struct u3_ht_ops *, u_int, uint32_t);
+
+static const char *u3_compat[] = {
+ "u3",
+ NULL
+};
+
+const char *pic_compat[] = {
+ "chrp,open-pic",
+ "open-pic",
+ "openpic",
+ NULL
+};
+
+int init_u3_ht(void)
+{
+ int u4, pic;
+ uint32_t reg[2];
+ uint32_t base, len, tmp;
+ int bigendian;
+ volatile uint8_t *unin_reg;
+
+ u4 = OF_finddevice("/u4");
+ if (u4 == -1)
+ return FALSE;
+
+ if (of_compatible(u4, u3_compat) == -1)
+ return FALSE;
+
+ pic = OF_child(u4);
+ while ((pic != 0) && (of_compatible(pic, pic_compat) == -1))
+ pic = OF_peer(pic);
+
+ if ((pic == -1) || (pic == 0))
+ return FALSE;
+
+ if (OF_getprop(u4, "reg", reg, sizeof(reg)) != 8)
+ return FALSE;
+
+ base = reg[1];
+
+ /* Enable and reset PIC */
+
+ unin_reg = mapiodev(base, PAGE_SIZE, false);
+ KASSERT(unin_reg != NULL);
+ tmp = in32(unin_reg + 0xe0);
+ tmp |= 0x06;
+ out32(unin_reg + 0xe0, tmp);
+
+ bigendian = 0;
+ if (OF_getprop(pic, "big-endian", reg, 4) > -1)
+ bigendian = 1;
+
+ if (OF_getprop(pic, "reg", reg, 8) != 8)
+ return FALSE;
+
+ base = reg[0];
+ len = reg[1];
+
+ aprint_normal("found U3/U4 HT PIC at %08x\n", base);
+
+ setup_u3_ht(base, len, bigendian);
+
+ return TRUE;
+}
+
+static struct u3_ht_ops *
+setup_u3_ht(uint32_t addr, uint32_t len, int bigendian)
+{
+ struct u3_ht_ops *u3_ht;
+ struct pic_ops *pic;
+ int irq;
+ u_int x;
+
+ u3_ht = kmem_alloc(sizeof(struct u3_ht_ops), KM_SLEEP);
+ KASSERT(u3_ht != NULL);
+ bzero(u3_ht, sizeof(struct u3_ht_ops));
+ pic = &u3_ht->pic;
+
+ u3_ht->ht_base = mapiodev(addr, len, false);
+ KASSERT(u3_ht->ht_base != NULL);
+
+ if (bigendian) {
+ u3_ht->ht_read = u3_ht_read_be;
+ u3_ht->ht_write = u3_ht_write_be;
+ } else {
+ u3_ht->ht_read = u3_ht_read_le;
+ u3_ht->ht_write = u3_ht_write_le;
+ }
+
+ setup_u3_ht_workarounds(u3_ht);
+
+ /* Reset PIC */
+
+ x = u3_ht_read(u3_ht, OPENPIC_CONFIG);
+ u3_ht_write(u3_ht, OPENPIC_CONFIG, x | OPENPIC_CONFIG_RESET);
+ do {
+ x = u3_ht_read(u3_ht, OPENPIC_CONFIG);
+ } while (x & OPENPIC_CONFIG_RESET);
+
+ x = u3_ht_read(u3_ht, OPENPIC_FEATURE);
+
+ aprint_normal("OpenPIC Version 1.%d: "
+ "Supports %d CPUs and %d interrupt sources.\n",
+ x & 0xff, ((x & 0x1f00) >> 8) + 1, ((x & 0x07ff0000) >> 16) + 1);
+
+ pic->pic_numintrs = ((x & 0x07ff0000) >> 16) + 1;
+ pic->pic_cookie = (void *) addr;
+ pic->pic_enable_irq = u3_ht_enable_irq;
+ pic->pic_reenable_irq = u3_ht_enable_irq;
+ pic->pic_disable_irq = u3_ht_disable_irq;
+ pic->pic_get_irq = u3_ht_get_irq;
+ pic->pic_ack_irq = u3_ht_ack_irq;
+ pic->pic_establish_irq = u3_ht_establish_irq;
+ pic->pic_finish_setup = u3_ht_finish_setup;
+ strcpy(pic->pic_name, "openpic");
+ pic_add(pic);
+
+ u3_ht_set_priority(u3_ht, 0, 15);
+
+ for (irq = 0; irq < pic->pic_numintrs; irq++) {
+ x = irq;
+ x |= OPENPIC_IMASK;
+ x |= OPENPIC_POLARITY_NEGATIVE;
+ x |= OPENPIC_SENSE_LEVEL;
+ 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;
+ u3_ht_write(u3_ht, OPENPIC_CONFIG, x);
+
+ u3_ht_write(u3_ht, OPENPIC_SPURIOUS_VECTOR, 0xff);
+
+ u3_ht_set_priority(u3_ht, 0, 0);
+
+ for (irq = 0; irq < pic->pic_numintrs; irq++) {
+ u3_ht_read_irq(u3_ht, 0);
+ u3_ht_eoi(u3_ht, 0);
+ }
+
+ return u3_ht;
+}
+
+static int
+setup_u3_ht_workarounds(struct u3_ht_ops *u3_ht)
+{
+ struct u3_ht_irqmap *irqmap = u3_ht->ht_irqmap;
+ int parent, child;
+ uint32_t reg[5], tmp;
+ uint8_t pos;
+ uint16_t cr, ht_cr;
+ int nirq, irq, i;
+ volatile uint8_t *ht_reg, *dev_reg, *base;
+
+ parent = OF_finddevice("/ht");
+ if (parent == -1)
+ return FALSE;
+
+ if (OF_getprop(parent, "reg", reg, 12) != 12)
+ return FALSE;
+
+ ht_reg = mapiodev(reg[1], reg[2], false);
+ KASSERT(ht_reg != NULL);
+
+ for (child = OF_child(parent); child != 0; child = OF_peer(child)) {
+ if (OF_getprop(child, "reg", reg, 4) != 4)
+ continue;
+
+ dev_reg = ht_reg + (reg[0] & (OFW_PCI_PHYS_HI_DEVICEMASK |
+ OFW_PCI_PHYS_HI_FUNCTIONMASK));
+
+ tmp = in32rb(dev_reg + PCI_COMMAND_STATUS_REG);
+ if ((tmp & PCI_STATUS_CAPLIST_SUPPORT) == 0)
+ continue;
+
+ for (pos = in8rb(dev_reg + PCI_CAPLISTPTR_REG);
+ pos != 0; pos = in8rb(dev_reg + pos + 0x01)) {
+ cr = in16rb(dev_reg + pos);
+ if (PCI_CAPLIST_CAP(cr) != 0x08)
+ continue;
+
+ ht_cr = in16rb(dev_reg + pos + 0x02);
+ if ((ht_cr & 0xf800) == 0x8000)
+ break;
+ }
+
+ if (pos == 0)
+ continue;
+
+ base = dev_reg + pos;
+
+ out8rb(base + 0x02, 0x01);
+ nirq = in32rb(base + 0x04);
+ nirq = (nirq >> 16) & 0xff;
+
+ for (i = 0; i <= nirq; i++) {
+ out8rb(base + 0x02, 0x10 + (i << 1));
+ tmp = in32rb(base + 0x04);
+ irq = (tmp >> 16) & 0xff;
+ tmp |= 0x01;
+ out32rb(base + 0x04, tmp);
+
+ irqmap[irq].im_index = i;
+ irqmap[irq].im_level = 0;
+ irqmap[irq].im_base = base;
+
+ tmp = in32rb(dev_reg + PCI_ID_REG);
+ if (PCI_VENDOR(tmp) == 0x106b)
+ irqmap[irq].im_apple_base = dev_reg + 0x60;
+ else
+ irqmap[irq].im_apple_base = NULL;
+
+ out8rb(base + 0x02, 0x11 + (i << 1));
+ irqmap[irq].im_data = in32rb(base + 0x04);
+ irqmap[irq].im_data |= (1 << 31);
+ }
+ }
+
+ return TRUE;
+}
+
+static void
+u3_ht_enable_irq(struct pic_ops *pic, int irq, int type)
+{
+ struct u3_ht_ops *u3_ht = (struct u3_ht_ops *)pic;
+ u_int x;
+
+ 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_enable_ht_irq(u3_ht, irq);
+}
+
+static void
+u3_ht_disable_irq(struct pic_ops *pic, int irq)
+{
+ struct u3_ht_ops *u3_ht = (struct u3_ht_ops *)pic;
+ u_int x;
+
+ x = u3_ht_read(u3_ht, OPENPIC_SRC_VECTOR(irq));
+ x |= OPENPIC_IMASK;
+ u3_ht_write(u3_ht, OPENPIC_SRC_VECTOR(irq), x);
+}
+
+static int
+u3_ht_get_irq(struct pic_ops *pic, int mode)
+{
+ struct u3_ht_ops *u3_ht = (struct u3_ht_ops *)pic;
+
+ return u3_ht_read_irq(u3_ht, curcpu()->ci_index);
+}
+
+static void
+u3_ht_ack_irq(struct pic_ops *pic, int irq)
+{
+ struct u3_ht_ops *u3_ht = (struct u3_ht_ops *)pic;
+
+ if (u3_ht_is_ht_irq(u3_ht, irq))
+ u3_ht_ack_ht_irq(u3_ht, irq);
+
+ u3_ht_eoi(u3_ht, curcpu()->ci_index);
+}
+
+static void
+u3_ht_establish_irq(struct pic_ops *pic, int irq, int type, int pri)
+{
+ struct u3_ht_ops *u3_ht = (struct u3_ht_ops *)pic;
+ int realpri = max(1, min(15, pri));
+ uint32_t x;
+
+ x = irq;
+ x |= OPENPIC_IMASK;
+
+ if (u3_ht_is_ht_irq(u3_ht, irq)) {
+ x |= OPENPIC_POLARITY_POSITIVE |
+ OPENPIC_SENSE_EDGE;
+ } else {
+ if (irq == 0 || type == IST_EDGE_RISING || type == IST_LEVEL_HIGH)
+ x |= OPENPIC_POLARITY_POSITIVE;
+ else
+ x |= OPENPIC_POLARITY_NEGATIVE;
+
+ if (type == IST_EDGE_FALLING || type == IST_EDGE_RISING)
+ x |= OPENPIC_SENSE_EDGE;
+ else
+ x |= OPENPIC_SENSE_LEVEL;
+ }
+
+ x |= realpri << OPENPIC_PRIORITY_SHIFT;
+ u3_ht_write(u3_ht, OPENPIC_SRC_VECTOR(irq), x);
+
+ 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);
+}
+
+static void
+u3_ht_finish_setup(struct pic_ops *pic)
+{
+ struct u3_ht_ops *u3_ht = (struct u3_ht_ops *)pic;
+ uint32_t cpumask = 0;
+ int i;
+
+#ifdef OPENPIC_DISTRIBUTE
+ for (i = 0; i < ncpu; i++)
+ cpumask |= (1 << cpu_info[i].ci_cpuid);
+#else
+ cpumask = 1;
+#endif
+
+ for (i = 0; i < pic->pic_numintrs; i++)
+ u3_ht_write(u3_ht, OPENPIC_IDEST(i), cpumask);
+}
+
+static int
+u3_ht_is_ht_irq(struct u3_ht_ops *u3_ht, int irq)
+{
+ return (irq < 128) && (u3_ht->ht_irqmap[irq].im_base != NULL);
+}
+
+static void
+u3_ht_establish_ht_irq(struct u3_ht_ops *u3_ht, int irq, int type)
+{
+ 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 &= ~0x23;
+
+ if (type == IST_LEVEL_HIGH || type == IST_LEVEL_LOW) {
+ irqmap->im_level = 1;
+ x |= 0x22;
+ } else {
+ irqmap->im_level = 0;
+ }
+
+ out32rb(irqmap->im_base + 0x04, x);
+}
+
+static void
+u3_ht_enable_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);
+
+ u3_ht_ack_ht_irq(u3_ht, irq);
+}
+
+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];
+
+ if (irqmap->im_level != 0) {
+ if (irqmap->im_apple_base != NULL) {
+ out32rb(irqmap->im_apple_base + ((irqmap->im_index >> 3) & ~0x03),
+ 1 << (irqmap->im_index & 0x1f));
+ } else {
+ out8rb(irqmap->im_base + 0x02, 0x11 + (irqmap->im_index << 1));
+ out32rb(irqmap->im_base + 0x04, irqmap->im_data);
+ }
+ }
+}
+
+static void
+u3_ht_set_priority(struct u3_ht_ops *u3_ht, int cpu, int pri)
+{
+ u_int x;
+
+ x = u3_ht_read(u3_ht, OPENPIC_CPU_PRIORITY(cpu));
+ x &= ~OPENPIC_CPU_PRIORITY_MASK;
+ x |= pri;
+ u3_ht_write(u3_ht, OPENPIC_CPU_PRIORITY(cpu), x);
+}
+
+static int
+u3_ht_read_irq(struct u3_ht_ops *u3_ht, int cpu)
+{
+ return u3_ht_read(u3_ht, OPENPIC_IACK(cpu)) & OPENPIC_VECTOR_MASK;
+}
+
+static void
+u3_ht_eoi(struct u3_ht_ops *u3_ht, int cpu)
+{
+ u3_ht_write(u3_ht, OPENPIC_EOI(cpu), 0);
+ u3_ht_read(u3_ht, OPENPIC_EOI(cpu));
+}
+
+static uint32_t
+u3_ht_read_be(struct u3_ht_ops *u3_ht, u_int reg)
+{
+ volatile uint8_t *addr = u3_ht->ht_base + reg;
+
+ return in32(addr);
+}
+
+static void
+u3_ht_write_be(struct u3_ht_ops *u3_ht, u_int reg, uint32_t val)
+{
+ volatile uint8_t *addr = u3_ht->ht_base + reg;
+
+ out32(addr, val);
+}
+
+static uint32_t
+u3_ht_read_le(struct u3_ht_ops *u3_ht, u_int reg)
+{
+ volatile uint8_t *addr = u3_ht->ht_base + reg;
+
+ return in32rb(addr);
+}
+
+static void
+u3_ht_write_le(struct u3_ht_ops *u3_ht, u_int reg, uint32_t val)
+{
+ volatile uint8_t *addr = u3_ht->ht_base + reg;
+
+ out32rb(addr, val);
+}