Commit 77dda339 authored by Roman Zippel's avatar Roman Zippel Committed by Linus Torvalds
Browse files

[PATCH] m68k: convert q40 irq code

parent 9c5f4afd
Loading
Loading
Loading
Loading
+1 −10
Original line number Original line Diff line number Diff line
@@ -205,18 +205,9 @@ ENTRY(auto_inthandler)


	movel	%sp,%sp@-
	movel	%sp,%sp@-
	movel	%d0,%sp@-		|  put vector # on stack
	movel	%d0,%sp@-		|  put vector # on stack
#if defined(MACH_Q40_ONLY) && defined(CONFIG_BLK_DEV_FD)
	btstb	#4,0xff000000		| Q40 floppy needs very special treatment ...
	jbeq	1f
	btstb	#3,0xff000004
	jbeq	1f
	jbsr	floppy_hardint
	jbra	3f
1:
#endif
auto_irqhandler_fixup = . + 2
auto_irqhandler_fixup = . + 2
	jsr	m68k_handle_int		|  process the IRQ
	jsr	m68k_handle_int		|  process the IRQ
3:	addql	#8,%sp			|  pop parameters off stack
	addql	#8,%sp			|  pop parameters off stack


ret_from_interrupt:
ret_from_interrupt:
	subqb	#1,%curptr@(TASK_INFO+TINFO_PREEMPT+1)
	subqb	#1,%curptr@(TASK_INFO+TINFO_PREEMPT+1)
+0 −11
Original line number Original line Diff line number Diff line
@@ -38,13 +38,8 @@


extern irqreturn_t q40_process_int (int level, struct pt_regs *regs);
extern irqreturn_t q40_process_int (int level, struct pt_regs *regs);
extern void q40_init_IRQ (void);
extern void q40_init_IRQ (void);
extern void q40_free_irq (unsigned int, void *);
extern int  show_q40_interrupts (struct seq_file *, void *);
extern void q40_enable_irq (unsigned int);
extern void q40_disable_irq (unsigned int);
static void q40_get_model(char *model);
static void q40_get_model(char *model);
static int  q40_get_hardware_list(char *buffer);
static int  q40_get_hardware_list(char *buffer);
extern int  q40_request_irq(unsigned int irq, irqreturn_t (*handler)(int, void *, struct pt_regs *), unsigned long flags, const char *devname, void *dev_id);
extern void q40_sched_init(irqreturn_t (*handler)(int, void *, struct pt_regs *));
extern void q40_sched_init(irqreturn_t (*handler)(int, void *, struct pt_regs *));


extern unsigned long q40_gettimeoffset (void);
extern unsigned long q40_gettimeoffset (void);
@@ -174,12 +169,6 @@ void __init config_q40(void)
    mach_set_clock_mmss	 = q40_set_clock_mmss;
    mach_set_clock_mmss	 = q40_set_clock_mmss;


    mach_reset		 = q40_reset;
    mach_reset		 = q40_reset;
    mach_free_irq	 = q40_free_irq;
    mach_process_int	 = q40_process_int;
    mach_get_irq_list	 = show_q40_interrupts;
    mach_request_irq	 = q40_request_irq;
    enable_irq		 = q40_enable_irq;
    disable_irq          = q40_disable_irq;
    mach_get_model       = q40_get_model;
    mach_get_model       = q40_get_model;
    mach_get_hardware_list = q40_get_hardware_list;
    mach_get_hardware_list = q40_get_hardware_list;


+168 −296
Original line number Original line Diff line number Diff line
@@ -14,13 +14,8 @@
#include <linux/types.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/errno.h>
#include <linux/string.h>
#include <linux/sched.h>
#include <linux/seq_file.h>
#include <linux/interrupt.h>
#include <linux/interrupt.h>
#include <linux/hardirq.h>


#include <asm/rtc.h>
#include <asm/ptrace.h>
#include <asm/ptrace.h>
#include <asm/system.h>
#include <asm/system.h>
#include <asm/irq.h>
#include <asm/irq.h>
@@ -39,28 +34,37 @@
 *
 *
*/
*/


extern int ints_inited;
static void q40_irq_handler(unsigned int, struct pt_regs *fp);
static void q40_enable_irq(unsigned int);
static void q40_disable_irq(unsigned int);


unsigned short q40_ablecount[35];
unsigned short q40_state[35];


irqreturn_t q40_irq2_handler (int, void *, struct pt_regs *fp);
static int q40_irq_startup(unsigned int irq)

{

	/* test for ISA ints not implemented by HW */
static irqreturn_t q40_defhand (int irq, void *dev_id, struct pt_regs *fp);
	switch (irq) {

	case 1: case 2: case 8: case 9:

	case 11: case 12: case 13:
#define DEVNAME_SIZE 24
		printk("%s: ISA IRQ %d not implemented by HW\n", __FUNCTION__, irq);
		return -ENXIO;
	}
	return 0;
}


static struct q40_irq_node {
static void q40_irq_shutdown(unsigned int irq)
	irqreturn_t	(*handler)(int, void *, struct pt_regs *);
{
	unsigned long	flags;
}
	void		*dev_id;
  /*        struct q40_irq_node *next;*/
        char	        devname[DEVNAME_SIZE];
	unsigned	count;
        unsigned short  state;
} irq_tab[Q40_IRQ_MAX+1];


short unsigned q40_ablecount[Q40_IRQ_MAX+1];
static struct irq_controller q40_irq_controller = {
	.name		= "q40",
	.lock		= SPIN_LOCK_UNLOCKED,
	.startup	= q40_irq_startup,
	.shutdown	= q40_irq_shutdown,
	.enable		= q40_enable_irq,
	.disable	= q40_disable_irq,
};


/*
/*
 * void q40_init_IRQ (void)
 * void q40_init_IRQ (void)
@@ -73,27 +77,17 @@ short unsigned q40_ablecount[Q40_IRQ_MAX+1];
 * the q40 IRQ handling routines.
 * the q40 IRQ handling routines.
 */
 */


static int disabled=0;
static int disabled;


void q40_init_IRQ(void)
void q40_init_IRQ(void)
{
{
	int i;
	m68k_setup_irq_controller(&q40_irq_controller, 1, Q40_IRQ_MAX);

	disabled=0;
	for (i = 0; i <= Q40_IRQ_MAX; i++) {
		irq_tab[i].handler = q40_defhand;
		irq_tab[i].flags = 0;
		irq_tab[i].dev_id = NULL;
		/*		irq_tab[i].next = NULL;*/
		irq_tab[i].devname[0] = 0;
		irq_tab[i].count = 0;
		irq_tab[i].state =0;
		q40_ablecount[i]=0;   /* all enabled */
	}


	/* setup handler for ISA ints */
	/* setup handler for ISA ints */
	cpu_request_irq(IRQ_AUTO_2, q40_irq2_handler, 0,
	m68k_setup_auto_interrupt(q40_irq_handler);
			"q40 ISA and master chip", NULL);

	m68k_irq_startup(IRQ_AUTO_2);
	m68k_irq_startup(IRQ_AUTO_4);


	/* now enable some ints.. */
	/* now enable some ints.. */
	master_outb(1, EXT_ENABLE_REG);  /* ISA IRQ 5-15 */
	master_outb(1, EXT_ENABLE_REG);  /* ISA IRQ 5-15 */
@@ -102,106 +96,6 @@ void q40_init_IRQ (void)
	master_outb(0, KEY_IRQ_ENABLE_REG);
	master_outb(0, KEY_IRQ_ENABLE_REG);
}
}


int q40_request_irq(unsigned int irq,
		irqreturn_t (*handler)(int, void *, struct pt_regs *),
                unsigned long flags, const char *devname, void *dev_id)
{
  /*printk("q40_request_irq %d, %s\n",irq,devname);*/

	if (irq > Q40_IRQ_MAX || (irq>15 && irq<32)) {
		printk("%s: Incorrect IRQ %d from %s\n", __FUNCTION__, irq, devname);
		return -ENXIO;
	}

	/* test for ISA ints not implemented by HW */
	switch (irq)
	  {
	  case 1: case 2: case 8: case 9:
	  case 12: case 13:
	    printk("%s: ISA IRQ %d from %s not implemented by HW\n", __FUNCTION__, irq, devname);
	    return -ENXIO;
	  case 11:
	    printk("warning IRQ 10 and 11 not distinguishable\n");
	    irq=10;
	  default:
	    ;
	  }

	if (irq<Q40_IRQ_SAMPLE)
	  {
	    if (irq_tab[irq].dev_id != NULL)
		  {
		    printk("%s: IRQ %d from %s is not replaceable\n",
			   __FUNCTION__, irq, irq_tab[irq].devname);
		    return -EBUSY;
		  }
	    /*printk("IRQ %d set to handler %p\n",irq,handler);*/
	    if (dev_id==NULL)
		  {
		printk("WARNING: dev_id == NULL in request_irq\n");
		dev_id=(void*)1;
	      }
	    irq_tab[irq].handler = handler;
	    irq_tab[irq].flags   = flags;
	    irq_tab[irq].dev_id  = dev_id;
	    strlcpy(irq_tab[irq].devname,devname,sizeof(irq_tab[irq].devname));
	    irq_tab[irq].state = 0;
	    return 0;
	  }
	else {
	  /* Q40_IRQ_SAMPLE :somewhat special actions required here ..*/
	  cpu_request_irq(4, handler, flags, devname, dev_id);
	  cpu_request_irq(6, handler, flags, devname, dev_id);
	  return 0;
	}
}

void q40_free_irq(unsigned int irq, void *dev_id)
{
	if (irq > Q40_IRQ_MAX || (irq>15 && irq<32)) {
		printk("%s: Incorrect IRQ %d, dev_id %x \n", __FUNCTION__, irq, (unsigned)dev_id);
		return;
	}

	/* test for ISA ints not implemented by HW */
	switch (irq)
	  {
	  case 1: case 2: case 8: case 9:
	  case 12: case 13:
	    printk("%s: ISA IRQ %d from %x invalid\n", __FUNCTION__, irq, (unsigned)dev_id);
	    return;
	  case 11: irq=10;
	  default:
	    ;
	  }

	if (irq<Q40_IRQ_SAMPLE)
	  {
	    if (irq_tab[irq].dev_id != dev_id)
	      printk("%s: Removing probably wrong IRQ %d from %s\n",
		     __FUNCTION__, irq, irq_tab[irq].devname);

	    irq_tab[irq].handler = q40_defhand;
	    irq_tab[irq].flags   = 0;
	    irq_tab[irq].dev_id  = NULL;
	    /* irq_tab[irq].devname = NULL; */
	    /* do not reset state !! */
	  }
	else
	  { /* == Q40_IRQ_SAMPLE */
	    cpu_free_irq(4, dev_id);
	    cpu_free_irq(6, dev_id);
	  }
}


irqreturn_t q40_process_int (int level, struct pt_regs *fp)
{
  printk("unexpected interrupt vec=%x, pc=%lx, d0=%lx, d0_orig=%lx, d1=%lx, d2=%lx\n",
          level, fp->pc, fp->d0, fp->orig_d0, fp->d1, fp->d2);
  printk("\tIIRQ_REG = %x, EIRQ_REG = %x\n",master_inb(IIRQ_REG),master_inb(EIRQ_REG));
  return IRQ_HANDLED;
}


/*
/*
 * this stuff doesn't really belong here..
 * this stuff doesn't really belong here..
@@ -216,8 +110,7 @@ void q40_mksound(unsigned int hz, unsigned int ticks)
{
{
	/* for now ignore hz, except that hz==0 switches off sound */
	/* for now ignore hz, except that hz==0 switches off sound */
	/* simply alternate the ampl (128-SVOL)-(128+SVOL)-..-.. at 200Hz */
	/* simply alternate the ampl (128-SVOL)-(128+SVOL)-..-.. at 200Hz */
  if (hz==0)
	if (hz == 0) {
    {
		if (sound_ticks)
		if (sound_ticks)
			sound_ticks = 1;
			sound_ticks = 1;


@@ -227,7 +120,8 @@ void q40_mksound(unsigned int hz, unsigned int ticks)
		return;
		return;
	}
	}
	/* sound itself is done in q40_timer_int */
	/* sound itself is done in q40_timer_int */
  if (sound_ticks == 0) sound_ticks=1000; /* pretty long beep */
	if (sound_ticks == 0)
		sound_ticks = 1000; /* pretty long beep */
	sound_ticks = ticks << 1;
	sound_ticks = ticks << 1;
}
}


@@ -236,8 +130,7 @@ static irqreturn_t (*q40_timer_routine)(int, void *, struct pt_regs *);
static irqreturn_t q40_timer_int (int irq, void * dev, struct pt_regs * regs)
static irqreturn_t q40_timer_int (int irq, void * dev, struct pt_regs * regs)
{
{
	ql_ticks = ql_ticks ? 0 : 1;
	ql_ticks = ql_ticks ? 0 : 1;
    if (sound_ticks)
	if (sound_ticks) {
      {
		unsigned char sval=(sound_ticks & 1) ? 128-SVOL : 128+SVOL;
		unsigned char sval=(sound_ticks & 1) ? 128-SVOL : 128+SVOL;
		sound_ticks--;
		sound_ticks--;
		*DAC_LEFT=sval;
		*DAC_LEFT=sval;
@@ -307,23 +200,35 @@ static int mext_disabled=0; /* ext irq disabled by master chip? */
static int aliased_irq=0;  /* how many times inside handler ?*/
static int aliased_irq=0;  /* how many times inside handler ?*/




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


//repeat:
//repeat:
	mir = master_inb(IIRQ_REG);
	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:
		m68k_handle_int(Q40_IRQ_SAMPLE, fp);
		return;
	}
	if (mir & Q40_IRQ_FRAME_MASK) {
	if (mir & Q40_IRQ_FRAME_MASK) {
	  irq_tab[Q40_IRQ_FRAME].count++;
		m68k_handle_int(Q40_IRQ_FRAME, fp);
	  irq_tab[Q40_IRQ_FRAME].handler(Q40_IRQ_FRAME,irq_tab[Q40_IRQ_FRAME].dev_id,fp);
		master_outb(-1, FRAME_CLEAR_REG);
		master_outb(-1, FRAME_CLEAR_REG);
	}
	}
	if ((mir & Q40_IRQ_SER_MASK) || (mir & Q40_IRQ_EXT_MASK)) {
	if ((mir & Q40_IRQ_SER_MASK) || (mir & Q40_IRQ_EXT_MASK)) {
		mer = master_inb(EIRQ_REG);
		mer = master_inb(EIRQ_REG);
		for (i = 0; eirqs[i].mask; i++) {
		for (i = 0; eirqs[i].mask; i++) {
		  if (mer&(eirqs[i].mask)) {
			if (mer & eirqs[i].mask) {
				irq = eirqs[i].irq;
				irq = eirqs[i].irq;
/*
/*
 * There is a little mess wrt which IRQ really caused this irq request. The
 * There is a little mess wrt which IRQ really caused this irq request. The
@@ -335,11 +240,7 @@ irqreturn_t q40_irq2_handler (int vec, void *devname, struct pt_regs *fp)
					/*aliased_irq++;*/
					/*aliased_irq++;*/
					goto iirq;
					goto iirq;
				}
				}
			  if (irq_tab[irq].handler == q40_defhand ) {
				if (q40_state[irq] & IRQ_INPROGRESS) {
				  printk("handler for IRQ %d not defined\n",irq);
				  continue; /* ignore uninited INTs :-( */
			  }
			  if ( irq_tab[irq].state & IRQ_INPROGRESS ) {
					/* some handlers do local_irq_enable() for irq latency reasons, */
					/* some handlers do local_irq_enable() for irq latency reasons, */
					/* however reentering an active irq handler is not permitted */
					/* however reentering an active irq handler is not permitted */
#ifdef IP_USE_DISABLE
#ifdef IP_USE_DISABLE
@@ -348,16 +249,16 @@ irqreturn_t q40_irq2_handler (int vec, void *devname, struct pt_regs *fp)
					disable_irq(irq);
					disable_irq(irq);
					disabled = 1;
					disabled = 1;
#else
#else
				  /*printk("IRQ_INPROGRESS detected for irq %d, disabling - %s disabled\n",irq,disabled ? "already" : "not yet"); */
					/*printk("IRQ_INPROGRESS detected for irq %d, disabling - %s disabled\n",
						irq, disabled ? "already" : "not yet"); */
					fp->sr = (((fp->sr) & (~0x700))+0x200);
					fp->sr = (((fp->sr) & (~0x700))+0x200);
					disabled = 1;
					disabled = 1;
#endif
#endif
					goto iirq;
					goto iirq;
				}
				}
			  irq_tab[irq].count++;
				q40_state[irq] |= IRQ_INPROGRESS;
			  irq_tab[irq].state |= IRQ_INPROGRESS;
				m68k_handle_int(irq, fp);
			  irq_tab[irq].handler(irq,irq_tab[irq].dev_id,fp);
				q40_state[irq] &= ~IRQ_INPROGRESS;
			  irq_tab[irq].state &= ~IRQ_INPROGRESS;


				/* naively enable everything, if that fails than    */
				/* naively enable everything, if that fails than    */
				/* this function will be reentered immediately thus */
				/* this function will be reentered immediately thus */
@@ -367,59 +268,34 @@ irqreturn_t q40_irq2_handler (int vec, void *devname, struct pt_regs *fp)
#ifdef IP_USE_DISABLE
#ifdef IP_USE_DISABLE
					if (irq > 4) {
					if (irq > 4) {
						disabled = 0;
						disabled = 0;
					  enable_irq(irq);}
						enable_irq(irq);
					}
#else
#else
					disabled = 0;
					disabled = 0;
					/*printk("reenabling irq %d\n", irq); */
					/*printk("reenabling irq %d\n", irq); */
#endif
#endif
				}
				}
// used to do 'goto repeat;' here, this delayed bh processing too long
// used to do 'goto repeat;' here, this delayed bh processing too long
			  return IRQ_HANDLED;
				return;
			}
		}
		}
		if (mer && ccleirq > 0 && !aliased_irq) {
			printk("ISA interrupt from unknown source? EIRQ_REG = %x\n",mer);
			ccleirq--;
		}
		}
	  if (mer && ccleirq>0 && !aliased_irq)
		  printk("ISA interrupt from unknown source? EIRQ_REG = %x\n",mer),ccleirq--;
	}
	}
 iirq:
 iirq:
	mir = master_inb(IIRQ_REG);
	mir = master_inb(IIRQ_REG);
	/* should test whether keyboard irq is really enabled, doing it in defhand */
	/* should test whether keyboard irq is really enabled, doing it in defhand */
  if (mir&Q40_IRQ_KEYB_MASK) {
	if (mir & Q40_IRQ_KEYB_MASK)
	  irq_tab[Q40_IRQ_KEYBOARD].count++;
		m68k_handle_int(Q40_IRQ_KEYBOARD, fp);
	  irq_tab[Q40_IRQ_KEYBOARD].handler(Q40_IRQ_KEYBOARD,irq_tab[Q40_IRQ_KEYBOARD].dev_id,fp);
  }
  return IRQ_HANDLED;
}

int show_q40_interrupts (struct seq_file *p, void *v)
{
	int i;


	for (i = 0; i <= Q40_IRQ_MAX; i++) {
	return;
		if (irq_tab[i].count)
		      seq_printf(p, "%sIRQ %02d: %8d  %s%s\n",
			      (i<=15) ? "ISA-" : "    " ,
			    i, irq_tab[i].count,
			    irq_tab[i].devname[0] ? irq_tab[i].devname : "?",
			    irq_tab[i].handler == q40_defhand ?
					" (now unassigned)" : "");
	}
	return 0;
}


static irqreturn_t q40_defhand (int irq, void *dev_id, struct pt_regs *fp)
{
        if (irq!=Q40_IRQ_KEYBOARD)
	     printk ("Unknown q40 interrupt %d\n", irq);
	else master_outb(-1,KEYBOARD_UNLOCK_REG);
	return IRQ_NONE;
}
}



void q40_enable_irq(unsigned int irq)
void q40_enable_irq(unsigned int irq)
{
{
  if ( irq>=5 && irq<=15 )
	if (irq >= 5 && irq <= 15) {
  {
		mext_disabled--;
		mext_disabled--;
		if (mext_disabled > 0)
		if (mext_disabled > 0)
			printk("q40_enable_irq : nested disable/enable\n");
			printk("q40_enable_irq : nested disable/enable\n");
@@ -439,7 +315,8 @@ void q40_disable_irq (unsigned int irq)
	if (irq >= 5 && irq <= 15) {
	if (irq >= 5 && irq <= 15) {
		master_outb(0, EXT_ENABLE_REG);
		master_outb(0, EXT_ENABLE_REG);
		mext_disabled++;
		mext_disabled++;
    if (mext_disabled>1) printk("disable_irq nesting count %d\n",mext_disabled);
		if (mext_disabled > 1)
			printk("disable_irq nesting count %d\n",mext_disabled);
	}
	}
}
}


@@ -452,8 +329,3 @@ int q40_probe_irq_off (unsigned long irqs)
{
{
	return -1;
	return -1;
}
}
/*
 * Local variables:
 * compile-command: "m68k-linux-gcc -D__KERNEL__ -I/home/rz/lx/linux-2.2.6/include -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -pipe -fno-strength-reduce -ffixed-a2 -m68040   -c -o q40ints.o q40ints.c"
 * End:
 */