r1952 - trunk/src/host/qemu-neo1973/hw
andrew at sita.openmoko.org
andrew at sita.openmoko.org
Mon May 14 01:32:36 CEST 2007
Author: andrew
Date: 2007-05-14 01:32:35 +0200 (Mon, 14 May 2007)
New Revision: 1952
Modified:
trunk/src/host/qemu-neo1973/hw/s3c2410.c
trunk/src/host/qemu-neo1973/hw/usb.h
Log:
Optimise the PIC, make interrupt arbitration optional. Add missing definitions.
Modified: trunk/src/host/qemu-neo1973/hw/s3c2410.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/s3c2410.c 2007-05-12 16:21:11 UTC (rev 1951)
+++ trunk/src/host/qemu-neo1973/hw/s3c2410.c 2007-05-13 23:32:35 UTC (rev 1952)
@@ -27,11 +27,21 @@
static void s3c_pic_update(struct s3c_pic_state_s *s)
{
qemu_set_irq(s->parent_pic[ARM_PIC_CPU_FIQ],
- s->srcpnd & ~s->intmsk & s->intmod);
+ s->srcpnd & s->intmod);
qemu_set_irq(s->parent_pic[ARM_PIC_CPU_IRQ],
s->intpnd & ~s->intmsk & ~s->intmod);
}
+/*
+ * Performs interrupt arbitration and notifies the CPU.
+ *
+ * Since it's a complex logic which cannot be relied on by the OS
+ * anyway - first because real hardware doesn't do it accurately,
+ * second because it only matters when interrupts occur at the
+ * same time which normally can't be predicted - we use a simpler
+ * version for non-debug runs.
+ */
+#ifdef DEBUG
static const uint32_t s3c_arbmsk[6] = {
0x0000000f,
0x000003f0,
@@ -41,25 +51,18 @@
0xf0000000,
};
-#define S3C_ARB_SEL(i) ((s->priority >> (7 + (i << 1))) & 3)
-#define S3C_ARB_MODE(i) ((s->priority >> i) & 1)
-#define S3C_ARB_SEL_SET(i, v) \
+# define S3C_ARB_SEL(i) ((s->priority >> (7 + (i << 1))) & 3)
+# define S3C_ARB_MODE(i) ((s->priority >> i) & 1)
+# define S3C_ARB_SEL_SET(i, v) \
s->priority &= ~(3 << (7 + (i << 1))); \
s->priority |= v << (7 + (i << 1));
-/*
- * Performs interrupt arbitration without notifying the CPU.
- *
- * XXX: Perhaps we should replace this with something much simpler
- * and faster and not 100% compliant. It's unlikely that any OS
- * relies on accurate arbitration.
- */
static void s3c_pic_arbitrate(struct s3c_pic_state_s *s)
{
uint32_t pnd = s->srcpnd & ~s->intmsk & ~s->intmod;
int offset, i, arb;
- if (!pnd) {
- s->intoffset = 0;
+ if (s->intpnd || !pnd) {
+ s3c_pic_update(s);
return;
}
@@ -103,8 +106,18 @@
offset += i & 3;
known_offset:
s->intoffset = offset;
- s->intpnd = 1 << offset; /* Note: |= breaks Linux */
+ s->intpnd = 1 << offset;
+ s3c_pic_update(s);
}
+#else
+inline static void s3c_pic_arbitrate(struct s3c_pic_state_s *s)
+{
+ uint32_t pnd = s->srcpnd & ~s->intmsk & ~s->intmod;
+ if (pnd && !s->intpnd)
+ s->intpnd = 1 << (s->intoffset = ffs(pnd) - 1);
+ s3c_pic_update(s);
+}
+#endif
static const int s3c_sub_src_map[] = {
[S3C_PICS_RXD0 & 31] = S3C_PIC_UART0,
@@ -123,6 +136,7 @@
static void s3c_pic_set_irq(void *opaque, int irq, int req)
{
struct s3c_pic_state_s *s = (struct s3c_pic_state_s *) opaque;
+ uint32_t mask;
/* This interrupt controller doesn't clear any request signals
* or register bits automatically. */
if (!req)
@@ -132,14 +146,24 @@
irq &= 31;
s->subsrcpnd |= 1 << irq;
if (~s->intsubmsk & (1 << irq))
- s->srcpnd |= 1 << s3c_sub_src_map[irq];
+ irq = s3c_sub_src_map[irq];
else
return;
- } else
- s->srcpnd |= 1 << irq;
+ }
+ s->srcpnd |= (mask = 1 << irq);
- s3c_pic_arbitrate(s);
- s3c_pic_update(s);
+ /* A FIQ */
+ if (s->intmod & mask)
+ qemu_irq_raise(s->parent_pic[ARM_PIC_CPU_FIQ]);
+ else if (!s->intpnd && !(s->intmsk & mask)) {
+#ifdef DEBUG
+ s3c_pic_arbitrate(s);
+#else
+ s->intpnd = mask;
+ s->intoffset = irq;
+ qemu_irq_raise(s->parent_pic[ARM_PIC_CPU_IRQ]);
+#endif
+ }
}
static void s3c_pic_reset(struct s3c_pic_state_s *s)
@@ -202,15 +226,23 @@
switch (addr) {
case S3C_SRCPND:
s->srcpnd &= ~value;
+ if (value & s->intmod)
+ s3c_pic_update(s);
break;
case S3C_INTPND:
- s->intpnd &= ~value;
- s3c_pic_arbitrate(s);
- s3c_pic_update(s);
+ if (s->intpnd & value) {
+ s->intpnd = 0;
+ s->intoffset = 0;
+ s3c_pic_arbitrate(s);
+ }
break;
case S3C_INTMSK:
s->intmsk = value;
- s3c_pic_update(s);
+ if (s->intpnd & value) {
+ s->intpnd = 0;
+ s->intoffset = 0;
+ }
+ s3c_pic_arbitrate(s);
break;
case S3C_INTMOD:
s->intmod = value;
Modified: trunk/src/host/qemu-neo1973/hw/usb.h
===================================================================
--- trunk/src/host/qemu-neo1973/hw/usb.h 2007-05-12 16:21:11 UTC (rev 1951)
+++ trunk/src/host/qemu-neo1973/hw/usb.h 2007-05-13 23:32:35 UTC (rev 1952)
@@ -225,3 +225,6 @@
/* usb-msd.c */
USBDevice *usb_msd_init(const char *filename);
+
+/* usb-net.c */
+USBDevice *usb_net_init(NICInfo *nd);
More information about the commitlog
mailing list