M bitsy/io.h => bitsy/io.h +74 -0
@@ 3,3 3,77 @@
*/
typedef struct Uartregs Uartregs;
Uartregs *uart3regs;
+
+/*
+ * IRQ's defined by SA1100
+ */
+enum
+{
+ IRQgpio0= 0,
+ IRQgpio1= 1,
+ IRQgpio2= 2,
+ IRQgpio3= 3,
+ IRQgpio4= 4,
+ IRQgpio5= 5,
+ IRQgpio6= 6,
+ IRQgpio7= 7,
+ IRQgpio8= 8,
+ IRQgpio9= 9,
+ IRQgpio10= 10,
+ IRQgpiohi= 11,
+ IRQlcd= 12,
+ IRQudc= 13,
+ IRQuart1b= 15,
+ IRQuart2= 16,
+ IRQuart3= 17,
+ IRQmcp= 18,
+ IRQssp= 19,
+ IRQdma0= 20,
+ IRQdma1= 21,
+ IRQdma2= 22,
+ IRQdma3= 23,
+ IRQdma4= 24,
+ IRQdma5= 25,
+ IRQtimer0= 26,
+ IRQtimer1= 27,
+ IRQtimer2= 28,
+ IRQtimer3= 29,
+ IRQsecond= 30,
+ IRQrtc= 31,
+};
+
+/*
+ * GPIO lines (signal names from compaq document). _i indicates input
+ * and _o output.
+ */
+enum
+{
+ PWR_ON_i= 1<<0, /* power button */
+ UP_IRQ_i= 1<<1, /* microcontroller interrupts */
+ LDD8_o= 1<<2, /* LCD data 8-15 */
+ LDD9_o= 1<<3,
+ LDD10_o= 1<<4,
+ LDD11_o= 1<<5,
+ LDD12_o= 1<<6,
+ LDD13_o= 1<<7,
+ LDD14_o= 1<<8,
+ LDD15_o= 1<<9,
+ CARD_IND1_i= 1<<10, /* card inserted in PCMCIA socket 1 */
+ CARD_IRQ1_i= 1<<11, /* PCMCIA socket 1 interrupt */
+ CLK_SET0_o= 1<<12, /* clock selects for audio codec */
+ CLK_SET1_o= 1<<13,
+ L3_SDA_io= 1<<14, /* UDA1341 interface */
+ L3_MODE_o= 1<<15,
+ L3_SCLK_o= 1<<16,
+ CARD_IND0_i= 1<<17, /* card inserted in PCMCIA socket 0 */
+ KEY_ACT_i= 1<<18, /* hot key from cradle */
+ SYS_CLK_i= 1<<19, /* clock from codec */
+ BAT_FAULT_i= 1<<20, /* battery fault */
+ CARD_IRQ0_i= 1<<21, /* PCMCIA socket 0 interrupt */
+ LOCK_i= 1<<22, /* expansion pack lock/unlock */
+ COM_DCD_i= 1<<23, /* DCD from UART3 */
+ OPT_IRQ_i= 1<<24, /* expansion pack IRQ */
+ COM_CTS_i= 1<<25, /* CTS from UART3 */
+ COM_RTS_oi= 1<<26, /* RTS to UART3 */
+ OPT_IND_i= 1<<27, /* expansion pack inserted */
+};
M bitsy/l.s => bitsy/l.s +13 -15
@@ 143,16 143,19 @@ TEXT exceptionvectors(SB), $-4
MOVW 0x18(R15), R15 /* reserved */
MOVW 0x18(R15), R15 /* IRQ */
MOVW 0x18(R15), R15 /* FIQ */
- WORD $_vsvc(SB) /* reset, in svc mode already */
+ WORD $_vrst(SB) /* reset, in svc mode already */
WORD $_vund(SB) /* undefined, switch to svc mode */
WORD $_vsvc(SB) /* swi, in svc mode already */
- WORD $_vpab(SB) /* prefetch abort, switch to svc mode */
- WORD $_vdab(SB) /* data abort, switch to svc mode */
- WORD $_vsvc(SB) /* reserved */
+ WORD $_vabt(SB) /* prefetch abort, switch to svc mode */
+ WORD $_vabt(SB) /* data abort, switch to svc mode */
+ WORD $_vrst(SB) /* reserved, shouldn't happen */
WORD $_virq(SB) /* IRQ, switch to svc mode */
WORD $_vfiq(SB) /* FIQ, switch to svc mode */
-TEXT _vsvc(SB), $-4 /* reset or SWI or reserved */
+TEXT _vrst(SB), $-4
+ BL reset
+
+TEXT _vsvc(SB), $-4 /* SWI */
SUB $12, R13 /* make room for pc, psr, & type */
MOVW R14, 8(R13) /* ureg->pc = interupted PC */
MOVW SPSR, R14 /* ureg->psr = SPSR */
@@ 167,16 170,11 @@ TEXT _vund(SB), $-4 /* undefined */
MOVW $PsrMund, R0
B _vswitch
-TEXT _vpab(SB), $-4 /* prefetch abort */
+TEXT _vabt(SB), $-4 /* prefetch abort */
MOVM.IA [R0-R3], (R13) /* free some working space */
MOVW $PsrMabt, R0 /* r0 = type */
B _vswitch
-TEXT _vdab(SB), $-4 /* data abort */
- MOVM.IA [R0-R3], (R13) /* free some working space */
- MOVW $(PsrMabt+1), R0 /* r0 = type */
- B _vswitch
-
TEXT _virq(SB), $-4 /* IRQ */
MOVM.IA [R0-R3], (R13) /* free some working space */
MOVW $PsrMirq, R0 /* r0 = type */
@@ 204,13 202,13 @@ _vswitch: /* switch to svc, type in R0 */
* R13 and R14 are no longer accessible. That's why R3 was left to point to where
* the old [r0-r3] are stored.
*/
- MOVM.DB.W [R0-R2], (R13) /* set ureg->{pc, psr, type}; r13 points to ureg->type */
+ MOVM.DB.W [R0-R2], (R13) /* set ureg->{type, psr, pc}; r13 points to ureg->type */
MOVM.IA (R3), [R0-R3] /* restore [R0-R3] from previous mode's stack */
MOVM.DB.W.S [R0-R14], (R13) /* save user level registers, at end r13 points to ureg */
/*
- * if the original interrupt happened while executing SVC mode, the User R14 in the Ureg is
- * wrong. We need to save the SVC one there.
+ * if the original interrupt happened while executing SVC mode,
+ * the User R14 in the Ureg is wrong. We need to save the SVC one there.
*/
MOVW 0x40(R13), R1
AND.S $0xf, R1
@@ 231,7 229,7 @@ _vrfe:
MOVW 8(R13), R14 /* restore link */
MOVW 4(R13), R0 /* restore SPSR */
MOVW R0, SPSR /* ... */
- MOVM.DB.S (R13), [R0-R14] /* restore registers */
+ MOVM.DB.W.S (R13), [R0-R14] /* restore registers */
ADD $8, R13 /* pop past ureg->{type+psr} */
RFE /* MOVM.IA.S.W (R13), [R15] */
M bitsy/mem.h => bitsy/mem.h +1 -0
@@ 91,6 91,7 @@
#define SSPREGS 0x80070060 /* serial port 4 - synchronous serial port */
#define PPCREGS 0x90060000 /* peripheral pin controller */
#define GPIOREGS 0x90040000 /* 28 general purpose IO pins */
+#define INTRREGS 0x90050000 /* interrupt registers */
/*
* Program Status Registers
M bitsy/trap.c => bitsy/trap.c +70 -10
@@ 7,17 7,32 @@
#include "ureg.h"
#include "../port/error.h"
-/*
- * called in sysfile.c
- */
-void
-evenaddr(ulong addr)
+struct Intrregs
{
- if(addr & 3){
- postnote(up, 1, "sys: odd address", NDebug);
- error(Ebadarg);
- }
-}
+ ulong icip; /* pending IRQs */
+ ulong icmr; /* IRQ mask */
+ ulong iclr; /* IRQ if bit == 0, FRIQ if 1 */
+ ulong iccr; /* control register */
+ ulong icfp; /* pending FIQs */
+ ulong dummy1[3]
+ ulong icpr; /* pending interrupts */
+
+};
+
+struct Intrregs *intrregs;
+
+typedef struct Vctl {
+ Vctl* next; /* handlers on this vector */
+
+ char name[NAMELEN]; /* of driver */
+ int irq;
+
+ void (*f)(Ureg*, void*); /* handler to call */
+ void* a; /* argument to call it with */
+} Vctl;
+
+static Lock vctllock;
+static Vctl *vctl[32];
/*
* set up for exceptioons
@@ 35,6 50,35 @@ trapinit(void)
*/
memmove((void*)KZERO, exceptionvectors, 2*4*8);
wbflush();
+
+ /* map in interrupt registers */
+ intrregs = mapspecial(INTRREGS, sizeof(*intrregs));
+
+ /* make all interrupts irq and disable all interrupts */
+ intrregs->iclr = 0;
+ intrregs->icmr = 0;
+}
+
+/*
+ * enable an interrupt and attach a function to i
+ */
+void
+intrenable(int irq, void (*f)(Ureg*, void*), void* a, char *name)
+{
+ int vno;
+ Vctl *v;
+
+ v = xalloc(sizeof(Vctl));
+ v->irq = irq;
+ v->f = f;
+ v->a = a;
+ strncpy(v->name, name, NAMELEN-1);
+ v->name[NAMELEN-1] = 0;
+
+ lock(&vctllock);
+ v->next = vctl[irq];
+ vctl[irq] = v;
+ unlock(&vctllock);
}
/*
@@ 43,6 87,22 @@ trapinit(void)
void
trap(Ureg *ureg)
{
+ switch(ureg->type){
+ case PsrMfiq: /* fast interrupt */
+ panic("fiq can't happen");
+ break;
+ case PsrMabt: /* fault */
+ case PsrMabt+1: /* fault */
+ panic("faults not implemented");
+ break;
+ case PsrMund: /* undefined instruction */
+ panic("undefined instruction");
+ break;
+ case PsrMirq: /* device interrupt */
+ break;
+ case PsrMsvc: /* system call */
+ break;
+ }
}
/* Give enough context in the ureg to produce a kernel stack for