arch/m68k/q40/q40ints.c

Source file repositories/reference/linux-study-clean/arch/m68k/q40/q40ints.c

File Facts

System
Linux kernel
Corpus path
arch/m68k/q40/q40ints.c
Extension
.c
Size
8121 bytes
Lines
335
Domain
Architecture Layer
Bucket
arch/m68k
Inferred role
Architecture Layer: implementation source
Status
source implementation candidate

Why This File Exists

CPU and platform-specific kernel glue: boot entry, traps, syscall entry, interrupts, page tables, context switch, and low-level barriers.

Dependency Surface

Detected Declarations

Annotated Snippet

struct IRQ_TABLE{ unsigned mask; int irq ;};
#if 0
static struct IRQ_TABLE iirqs[]={
  {Q40_IRQ_FRAME_MASK,Q40_IRQ_FRAME},
  {Q40_IRQ_KEYB_MASK,Q40_IRQ_KEYBOARD},
  {0,0}};
#endif
static struct IRQ_TABLE eirqs[] = {
  { .mask = Q40_IRQ3_MASK,	.irq = 3 },	/* ser 1 */
  { .mask = Q40_IRQ4_MASK,	.irq = 4 },	/* ser 2 */
  { .mask = Q40_IRQ14_MASK,	.irq = 14 },	/* IDE 1 */
  { .mask = Q40_IRQ15_MASK,	.irq = 15 },	/* IDE 2 */
  { .mask = Q40_IRQ6_MASK,	.irq = 6 },	/* floppy, handled elsewhere */
  { .mask = Q40_IRQ7_MASK,	.irq = 7 },	/* par */
  { .mask = Q40_IRQ5_MASK,	.irq = 5 },
  { .mask = Q40_IRQ10_MASK,	.irq = 10 },
  {0,0}
};

/* complain only this many times about spurious ints : */
static int ccleirq=60;    /* ISA dev IRQs*/
/*static int cclirq=60;*/     /* internal */

/* FIXME: add shared ints,mask,unmask,probing.... */

#define IRQ_INPROGRESS 1
/*static unsigned short saved_mask;*/
//static int do_tint=0;

#define DEBUG_Q40INT
/*#define IP_USE_DISABLE *//* would be nice, but crashes ???? */

static int mext_disabled;	/* ext irq disabled by master chip? */
static int aliased_irq;		/* how many times inside handler ?*/


/* got interrupt, dispatch to ISA or keyboard/timer IRQs */
static void q40_irq_handler(unsigned int irq, struct pt_regs *fp)
{
	unsigned mir, mer;
	int i;

//repeat:
	mir = master_inb(IIRQ_REG);
#ifdef CONFIG_BLK_DEV_FD
	if ((mir & Q40_IRQ_EXT_MASK) &&
	    (master_inb(EIRQ_REG) & Q40_IRQ6_MASK)) {
		floppy_hardint();
		return;
	}
#endif
	switch (irq) {
	case 4:
	case 6:
		do_IRQ(Q40_IRQ_SAMPLE, fp);
		return;
	}
	if (mir & Q40_IRQ_FRAME_MASK) {
		do_IRQ(Q40_IRQ_FRAME, fp);
		master_outb(-1, FRAME_CLEAR_REG);
	}
	if ((mir & Q40_IRQ_SER_MASK) || (mir & Q40_IRQ_EXT_MASK)) {
		mer = master_inb(EIRQ_REG);
		for (i = 0; eirqs[i].mask; i++) {
			if (mer & eirqs[i].mask) {
				irq = eirqs[i].irq;
/*
 * There is a little mess wrt which IRQ really caused this irq request. The
 * main problem is that IIRQ_REG and EIRQ_REG reflect the state when they
 * are read - which is long after the request came in. In theory IRQs should
 * not just go away but they occasionally do
 */
				if (irq > 4 && irq <= 15 && mext_disabled) {
					/*aliased_irq++;*/
					goto iirq;
				}
				if (q40_state[irq] & IRQ_INPROGRESS) {
					/* some handlers do local_irq_enable() for irq latency reasons, */
					/* however reentering an active irq handler is not permitted */
#ifdef IP_USE_DISABLE
					/* in theory this is the better way to do it because it still */
					/* lets through eg the serial irqs, unfortunately it crashes */
					disable_irq(irq);
					disabled = 1;
#else
					/*pr_warn("IRQ_INPROGRESS detected for irq %d, disabling - %s disabled\n",
						irq, disabled ? "already" : "not yet"); */
					fp->sr = (((fp->sr) & (~0x700))+0x200);
					disabled = 1;
#endif

Annotation

Implementation Notes