From 1d34167488e56e36ad702627b17be7ac18a9db9c Mon Sep 17 00:00:00 2001 From: Damien Zammit Date: Sun, 10 Nov 2019 16:27:42 +0100 Subject: simplify interrupt handling We have removed spl levels, now remove the machinery to manage different PIC masks according to levels. Only keep machinery to disable interrupts whatever the level. * i386/i386/pic.c (pic_mask): Remove array. (picinit): Do not form PIC mask. Set initial PIC mask to 0. (form_pic_mask): Remove function. * i386/i386/pic.h (form_pic_mask, pic_mask): Remove declarations. * i386/i386/spl.S (SETMASK): Remove macro. (XEN_SETMASK): Add macro, containing the Xen version of SETMASK. (spl0, splx_cli, spl) [MACH_XEN]: Call XEN_SETMASK instead of SETMASK. * i386/i386/pit.c (clkstart): Do not call form_pic_mask. * i386/i386at/autoconf.c (take_dev_irq, take_ctlr_irq): Likewise. * i386/i386at/kd_mouse.c (kd_mouse_open, kd_mouse_close): Likewise. * linux/dev/arch/i386/kernel/irq.c (mask_irq, unmask_irq): Directly update curr_pic_mask without using pic_mask array. (init_IRQ, restore_IRQ): do not call form_pic_mask. * linux/dev/include/asm-i386/system.h: Include . (__save_flags, __restore_flags): Use curr_ipl and splx instead of hardware flags. * linux/dev/init/main.c (linux_init): Do not call cli. * linux/dev/kernel/sched.c (linux_timer_intr): Do not use pic_mask. * linux/src/drivers/block/ide.c (try_to_identify): Disable irq probing. * linux/src/drivers/scsi/NCR53c406a.c (NCR53c406a_detect): Disable irq probing. --- i386/i386/pic.c | 89 +++++-------------------------------- i386/i386/pic.h | 2 - i386/i386/pit.c | 1 - i386/i386/spl.S | 47 +++++++++----------- i386/i386at/autoconf.c | 2 - i386/i386at/kd_mouse.c | 2 - linux/dev/arch/i386/kernel/irq.c | 26 +++++------ linux/dev/include/asm-i386/system.h | 8 ++-- linux/dev/init/main.c | 1 - linux/dev/kernel/sched.c | 2 +- linux/src/drivers/block/ide.c | 2 + linux/src/drivers/scsi/NCR53c406a.c | 2 +- 12 files changed, 51 insertions(+), 133 deletions(-) diff --git a/i386/i386/pic.c b/i386/i386/pic.c index e8c881af..0c2e2bc8 100644 --- a/i386/i386/pic.c +++ b/i386/i386/pic.c @@ -57,7 +57,6 @@ WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include spl_t curr_ipl; -int pic_mask[NSPL]; int curr_pic_mask; int iunit[NINTR] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}; @@ -72,33 +71,18 @@ u_short PICM_ICW4, PICS_ICW4 ; /* ** picinit() - This routine ** * Establishes a table of interrupt vectors -** * Establishes a table of interrupt priority levels -** * Establishes a table of interrupt masks to be put -** in the PICs. ** * Establishes location of PICs in the system +** * Unmasks all interrupts in the PICs ** * Initialises them ** ** At this stage the interrupt functionality of this system should be -** coplete. -** +** complete. */ - /* -** 1. First we form a table of PIC masks - rather then calling form_pic_mask() -** each time there is a change of interrupt level - we will form a table -** of pic masks, as there are only 7 interrupt priority levels. -** -** 2. The next thing we must do is to determine which of the PIC interrupt -** request lines have to be masked out, this is done by calling -** form_pic_mask() with a (int_lev) of zero, this will find all the -** interrupt lines that have priority 0, (ie to be ignored). -** Then we split this up for the master/slave PICs. -** -** 2. Initialise the PICs , master first, then the slave. -** All the register field definitions are described in pic_jh.h, also -** the settings of these fields for the various registers are selected. -** +** Initialise the PICs , master first, then the slave. +** All the register field definitions are described in pic.h also +** the settings of these fields for the various registers are selected. */ void @@ -108,23 +92,14 @@ picinit(void) asm("cli"); /* - ** 1. Form pic mask table - */ -#if 0 - printf (" Let the console driver screw up this line ! \n"); -#endif - - form_pic_mask(); - - /* - ** 1a. Select current SPL. + ** 0. Initialise the current level to match cli() */ curr_ipl = SPLHI; - curr_pic_mask = pic_mask[SPLHI]; + curr_pic_mask = 0; /* - ** 2. Generate addresses to each PIC port. + ** 1. Generate addresses to each PIC port. */ master_icw = PIC_MASTER_ICW; @@ -133,7 +108,7 @@ picinit(void) slaves_ocw = PIC_SLAVE_OCW; /* - ** 3. Select options for each ICW and each OCW for each PIC. + ** 2. Select options for each ICW and each OCW for each PIC. */ PICM_ICW1 = @@ -164,9 +139,8 @@ picinit(void) PICM_OCW3 = (OCW_TEMPLATE | READ_NEXT_RD | READ_IR_ONRD ); PICS_OCW3 = (OCW_TEMPLATE | READ_NEXT_RD | READ_IR_ONRD ); - /* - ** 4. Initialise master - send commands to master PIC + ** 3. Initialise master - send commands to master PIC */ outb ( master_icw, PICM_ICW1 ); @@ -178,7 +152,7 @@ picinit(void) outb ( master_icw, PICM_OCW3 ); /* - ** 5. Initialise slave - send commands to slave PIC + ** 4. Initialise slave - send commands to slave PIC */ outb ( slaves_icw, PICS_ICW1 ); @@ -191,49 +165,10 @@ picinit(void) outb ( slaves_icw, PICS_OCW3 ); /* - ** 6. Initialise interrupts + ** 5. Initialise interrupts */ outb ( master_ocw, PICM_OCW1 ); -#if 0 - printf(" spl set to %x \n", curr_pic_mask); -#endif - -} - - -/* -** form_pic_mask(int_lvl) -** -** For a given interrupt priority level (int_lvl), this routine goes out -** and scans through the interrupt level table, and forms a mask based on the -** entries it finds there that have the same or lower interrupt priority level -** as (int_lvl). It returns a 16-bit mask which will have to be split up between -** the 2 pics. -** -*/ - -#if defined(AT386) -#define SLAVEMASK (0xFFFF ^ SLAVE_ON_IR2) -#endif /* defined(AT386) */ - -#define SLAVEACTV 0xFF00 - -void -form_pic_mask(void) -{ - unsigned int i, j, bit, mask; - - for (i=SPL0; i < NSPL; i++) { - for (j=0x00, bit=0x01, mask = 0; j < NINTR; j++, bit<<=1) - if (intpri[j] <= i) - mask |= bit; - - if ((mask & SLAVEACTV) != SLAVEACTV ) - mask &= SLAVEMASK; - - pic_mask[i] = mask; - } } void diff --git a/i386/i386/pic.h b/i386/i386/pic.h index 80bf65d6..1d224a44 100644 --- a/i386/i386/pic.h +++ b/i386/i386/pic.h @@ -177,10 +177,8 @@ WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #define READ_IS_ONRD 0x01 #ifndef __ASSEMBLER__ -extern void form_pic_mask (void); extern void picinit (void); extern int curr_pic_mask; -extern int pic_mask[]; extern void prtnull(int unit); extern void intnull(int unit); #endif /* __ASSEMBLER__ */ diff --git a/i386/i386/pit.c b/i386/i386/pit.c index f0978088..bb6a4f79 100644 --- a/i386/i386/pit.c +++ b/i386/i386/pit.c @@ -76,7 +76,6 @@ clkstart(void) return; intpri[0] = SPLHI; - form_pic_mask(); s = sploff(); /* disable interrupts */ diff --git a/i386/i386/spl.S b/i386/i386/spl.S index 20a80766..215142c9 100644 --- a/i386/i386/spl.S +++ b/i386/i386/spl.S @@ -19,7 +19,6 @@ #include #include -#include #include #include @@ -30,20 +29,9 @@ #endif /* - * Program PICs with mask in %eax. + * Program XEN evt masks from %eax. */ -#ifndef MACH_XEN -#define SETMASK() \ - cmpl EXT(curr_pic_mask),%eax; \ - je 9f; \ - outb %al,$(PIC_MASTER_OCW); \ - movl %eax,EXT(curr_pic_mask); \ - movb %ah,%al; \ - outb %al,$(PIC_SLAVE_OCW); \ -9: -#else /* MACH_XEN */ -#define pic_mask int_mask -#define SETMASK() \ +#define XEN_SETMASK() \ pushl %ebx; \ movl %eax,%ebx; \ xchgl %eax,hyp_shared_info+EVTMASK; \ @@ -55,7 +43,6 @@ lock orl $1,hyp_shared_info+CPU_PENDING_SEL; /* Yes, activate it */ \ movb $1,hyp_shared_info+CPU_PENDING; \ 9: -#endif /* MACH_XEN */ ENTRY(spl0) mb; @@ -90,9 +77,11 @@ ENTRY(spl0) cmpl $(SPL0),EXT(curr_ipl) /* are we at spl0? */ je 1f /* yes, all done */ movl $(SPL0),EXT(curr_ipl) /* set ipl */ - movl EXT(pic_mask)+SPL0*4,%eax - /* get PIC mask */ - SETMASK() /* program PICs with new mask */ +#ifdef MACH_XEN + movl EXT(int_mask)+SPL0*4,%eax + /* get xen mask */ + XEN_SETMASK() /* program xen evts */ +#endif 1: sti /* enable interrupts */ popl %eax /* return previous mask */ @@ -129,9 +118,9 @@ Entry(splhi) ENTRY(spl7) mb; /* just clear IF */ - movl $SPL7,%eax - xchgl EXT(curr_ipl),%eax cli + movl $SPL7,%eax + xchgl EXT(curr_ipl),%eax ret ENTRY(splx) @@ -202,9 +191,11 @@ splx_cli: cmpl EXT(curr_ipl),%edx /* same ipl as current? */ je 1f /* yes, all done */ movl %edx,EXT(curr_ipl) /* set ipl */ - movl EXT(pic_mask)(,%edx,4),%eax - /* get PIC mask */ - SETMASK() /* program PICs with new mask */ +#ifdef MACH_XEN + movl EXT(int_mask)(,%edx,4),%eax + /* get int mask */ + XEN_SETMASK() /* program xen evts with new mask */ +#endif 1: ret @@ -229,11 +220,15 @@ spl: #endif /* (MACH_KDB || MACH_TTD) && !MACH_XEN */ cmpl $SPL7,%edx /* spl7? */ je EXT(spl7) /* yes, handle specially */ - movl EXT(pic_mask)(,%edx,4),%eax - /* get PIC mask */ +#ifdef MACH_XEN + movl EXT(int_mask)(,%edx,4),%eax + /* get int mask */ +#endif cli /* disable interrupts */ xchgl EXT(curr_ipl),%edx /* set ipl */ - SETMASK() /* program PICs with new mask */ +#ifdef MACH_XEN + XEN_SETMASK() /* program PICs with new mask */ +#endif sti /* enable interrupts */ movl %edx,%eax /* return previous ipl */ ret diff --git a/i386/i386at/autoconf.c b/i386/i386at/autoconf.c index 908c3ec0..6ed2270c 100644 --- a/i386/i386at/autoconf.c +++ b/i386/i386at/autoconf.c @@ -130,7 +130,6 @@ void take_dev_irq( iunit[pic] = dev->unit; ivect[pic] = dev->intr; intpri[pic] = (int)dev->sysdep; - form_pic_mask(); } else { printf("The device below will clobber IRQ %d.\n", pic); printf("You have two devices at the same IRQ.\n"); @@ -151,7 +150,6 @@ void take_ctlr_irq( iunit[pic] = ctlr->unit; ivect[pic] = ctlr->intr; intpri[pic] = (int)ctlr->sysdep; - form_pic_mask(); } else { printf("The device below will clobber IRQ %d.\n", pic); printf("You have two devices at the same IRQ. This won't work.\n"); diff --git a/i386/i386at/kd_mouse.c b/i386/i386at/kd_mouse.c index 20a8c88c..05280055 100644 --- a/i386/i386at/kd_mouse.c +++ b/i386/i386at/kd_mouse.c @@ -228,7 +228,6 @@ kd_mouse_open( ivect[mouse_pic] = kdintr; oldspl = intpri[mouse_pic]; intpri[mouse_pic] = SPL6; - form_pic_mask(); splx(s); } @@ -291,7 +290,6 @@ kd_mouse_close( ivect[mouse_pic] = oldvect; intpri[mouse_pic] = oldspl; - form_pic_mask(); splx(s); } diff --git a/linux/dev/arch/i386/kernel/irq.c b/linux/dev/arch/i386/kernel/irq.c index a02e9582..596dae6b 100644 --- a/linux/dev/arch/i386/kernel/irq.c +++ b/linux/dev/arch/i386/kernel/irq.c @@ -128,18 +128,15 @@ linux_intr (int irq) static inline void mask_irq (unsigned int irq_nr) { - int i; - - for (i = 0; i < intpri[irq_nr]; i++) - pic_mask[i] |= 1 << irq_nr; + int new_pic_mask = curr_pic_mask | 1 << irq_nr; - if (curr_pic_mask != pic_mask[curr_ipl]) + if (curr_pic_mask != new_pic_mask) { - curr_pic_mask = pic_mask[curr_ipl]; + curr_pic_mask = new_pic_mask; if (irq_nr < 8) - outb (curr_pic_mask & 0xff, PIC_MASTER_OCW); + outb (curr_pic_mask & 0xff, PIC_MASTER_OCW); else - outb (curr_pic_mask >> 8, PIC_SLAVE_OCW); + outb (curr_pic_mask >> 8, PIC_SLAVE_OCW); } } @@ -149,18 +146,18 @@ mask_irq (unsigned int irq_nr) static inline void unmask_irq (unsigned int irq_nr) { - int mask, i; + int mask; + int new_pic_mask; mask = 1 << irq_nr; if (irq_nr >= 8) mask |= 1 << 2; - for (i = 0; i < intpri[irq_nr]; i++) - pic_mask[i] &= ~mask; + new_pic_mask = curr_pic_mask & ~mask; - if (curr_pic_mask != pic_mask[curr_ipl]) + if (curr_pic_mask != new_pic_mask) { - curr_pic_mask = pic_mask[curr_ipl]; + curr_pic_mask = new_pic_mask; if (irq_nr < 8) outb (curr_pic_mask & 0xff, PIC_MASTER_OCW); else @@ -737,8 +734,6 @@ init_IRQ (void) } } - form_pic_mask (); - /* * Enable interrupts. */ @@ -777,6 +772,5 @@ restore_IRQ (void) */ ivect[0] = old_clock_handler; intpri[0] = old_clock_pri; - form_pic_mask (); } diff --git a/linux/dev/include/asm-i386/system.h b/linux/dev/include/asm-i386/system.h index f26a33e7..41eb65a4 100644 --- a/linux/dev/include/asm-i386/system.h +++ b/linux/dev/include/asm-i386/system.h @@ -1,6 +1,8 @@ #ifndef __ASM_SYSTEM_H #define __ASM_SYSTEM_H +#include /* curr_ipl, splx */ + #include /* @@ -223,10 +225,8 @@ static inline unsigned long __xchg(unsigned long x, void * ptr, int size) #define mb() __asm__ __volatile__ ("" : : :"memory") #define __sti() __asm__ __volatile__ ("sti": : :"memory") #define __cli() __asm__ __volatile__ ("cli": : :"memory") -#define __save_flags(x) \ -__asm__ __volatile__("pushf ; pop %0" : "=r" (x): /* no input */ :"memory") -#define __restore_flags(x) \ -__asm__ __volatile__("push %0 ; popf": /* no output */ :"g" (x):"memory") +#define __save_flags(x) (x = ((curr_ipl > 0) ? 0 : (1 << 9))) +#define __restore_flags(x) splx((x & (1 << 9)) ? 0 : 7) #ifdef __SMP__ diff --git a/linux/dev/init/main.c b/linux/dev/init/main.c index 3740c12c..6d853957 100644 --- a/linux/dev/init/main.c +++ b/linux/dev/init/main.c @@ -151,7 +151,6 @@ linux_init (void) linux_net_emulation_init (); #endif - cli (); device_setup (); #ifdef CONFIG_PCMCIA diff --git a/linux/dev/kernel/sched.c b/linux/dev/kernel/sched.c index 87906a45..2a9eeb3f 100644 --- a/linux/dev/kernel/sched.c +++ b/linux/dev/kernel/sched.c @@ -622,6 +622,6 @@ linux_timer_intr (void) mark_bh (TQUEUE_BH); #if 0 if (linux_timer_print) - printf ("linux_timer_intr: pic_mask[0] %x\n", pic_mask[0]); + printf ("linux_timer_intr: hello\n"); #endif } diff --git a/linux/src/drivers/block/ide.c b/linux/src/drivers/block/ide.c index 43b12f1f..170e4e13 100644 --- a/linux/src/drivers/block/ide.c +++ b/linux/src/drivers/block/ide.c @@ -2703,6 +2703,8 @@ static int try_to_identify (ide_drive_t *drive, byte cmd) int irq_off; if (!HWIF(drive)->irq) { /* already got an IRQ? */ + printk("%s: Not probing legacy IRQs)\n", drive->name); + return 2; probe_irq_off(probe_irq_on()); /* clear dangling irqs */ irqs_on = probe_irq_on(); /* start monitoring irqs */ OUT_BYTE(drive->ctl,IDE_CONTROL_REG); /* enable device irq */ diff --git a/linux/src/drivers/scsi/NCR53c406a.c b/linux/src/drivers/scsi/NCR53c406a.c index 9f2de9a0..7745f5ad 100644 --- a/linux/src/drivers/scsi/NCR53c406a.c +++ b/linux/src/drivers/scsi/NCR53c406a.c @@ -525,7 +525,7 @@ NCR53c406a_detect(Scsi_Host_Template * tpnt){ #ifndef IRQ_LEV if (irq_level < 0) { /* LILO override if >= 0*/ - irq_level=irq_probe(); + irq_level = -1; // XXX No probing irq_probe(); if (irq_level < 0) { /* Trouble */ printk("NCR53c406a: IRQ problem, irq_level=%d, giving up\n", irq_level); return 0; -- cgit v1.2.3