Re: Math Coprocessor !

Linus Torvalds (torvalds@cs.helsinki.fi)
Sun, 17 Mar 1996 09:10:04 +0200 (EET)


On Sun, 17 Mar 1996, Amitay B Isaacs wrote:
>
> After applying the patches 74 and 75 the kernel does not set the math
> coprocessor properly. It gives following message.
>
> Checking 386/387 coupling... 387 failed: trying to reset
>
> While 1.3.72 does not give any problem, report normal ! (no info on 73)
>
> Checking 386/387 coupling... Ok, fpu using old IRQ13 error reporting

Thanks, this was a silly thinko on my part. Surprising that it worked at
all - here is a patch that hopefully fixes it (untested, please do tell
if it works for you)

Linus
-----
diff -u --recursive --new-file v1.3.75/linux/arch/i386/kernel/irq.c linux/arch/i386/kernel/irq.c
--- v1.3.75/linux/arch/i386/kernel/irq.c Sun Mar 17 09:04:04 1996
+++ linux/arch/i386/kernel/irq.c Sun Mar 17 09:01:02 1996
@@ -212,16 +212,15 @@
#endif

/*
- * IRQ0 is timer, IRQ2 is cascade interrupt to second interrupt controller
+ * IRQ2 is cascade interrupt to second interrupt controller
*/
-extern struct irqaction irq0;
static struct irqaction irq2 = { no_action, 0, 0, "cascade", NULL, NULL};

static struct irqaction *irq_action[16] = {
- &irq0, NULL, &irq2, NULL,
NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL,
- NULL, &irq13 , NULL, NULL
+ NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL
};

int get_irq_list(char *buf)
@@ -385,59 +384,39 @@
}
}

-int request_irq(unsigned int irq,
- void (*handler)(int, void *, struct pt_regs *),
- unsigned long irqflags,
- const char * devname,
- void *dev_id)
+int setup_x86_irq(int irq, struct irqaction * new)
{
int shared = 0;
- struct irqaction * action, **p;
+ struct irqaction *old, **p;
unsigned long flags;

- if (irq > 15)
- return -EINVAL;
- if (!handler)
- return -EINVAL;
p = irq_action + irq;
- action = *p;
- if (action) {
+ if ((old = *p) != NULL) {
/* Can't share interrupts unless both agree to */
- if (!(action->flags & irqflags & SA_SHIRQ))
+ if (!(old->flags & new->flags & SA_SHIRQ))
return -EBUSY;

/* Can't share interrupts unless both are same type */
- if ((action->flags ^ irqflags) & SA_INTERRUPT)
+ if ((old->flags ^ new->flags) & SA_INTERRUPT)
return -EBUSY;

/* add new interrupt at end of irq queue */
do {
- p = &action->next;
- action = *p;
- } while (action);
+ p = &old->next;
+ old = *p;
+ } while (old);
shared = 1;
}

- action = (struct irqaction *)kmalloc(sizeof(struct irqaction), GFP_KERNEL);
- if (!action)
- return -ENOMEM;
-
- if (irqflags & SA_SAMPLE_RANDOM)
+ if (new->flags & SA_SAMPLE_RANDOM)
rand_initialize_irq(irq);

- action->handler = handler;
- action->flags = irqflags;
- action->mask = 0;
- action->name = devname;
- action->next = NULL;
- action->dev_id = dev_id;
-
save_flags(flags);
cli();
- *p = action;
+ *p = new;

if (!shared) {
- if (action->flags & SA_INTERRUPT)
+ if (new->flags & SA_INTERRUPT)
set_intr_gate(0x20+irq,fast_interrupt[irq]);
else
set_intr_gate(0x20+irq,interrupt[irq]);
@@ -446,6 +425,38 @@
restore_flags(flags);
return 0;
}
+
+int request_irq(unsigned int irq,
+ void (*handler)(int, void *, struct pt_regs *),
+ unsigned long irqflags,
+ const char * devname,
+ void *dev_id)
+{
+ int retval;
+ struct irqaction * action;
+
+ if (irq > 15)
+ return -EINVAL;
+ if (!handler)
+ return -EINVAL;
+
+ action = (struct irqaction *)kmalloc(sizeof(struct irqaction), GFP_KERNEL);
+ if (!action)
+ return -ENOMEM;
+
+ action->handler = handler;
+ action->flags = irqflags;
+ action->mask = 0;
+ action->name = devname;
+ action->next = NULL;
+ action->dev_id = dev_id;
+
+ retval = setup_x86_irq(irq, action);
+
+ if (retval)
+ kfree(action);
+ return retval;
+}

void free_irq(unsigned int irq, void *dev_id)
{
@@ -535,6 +546,6 @@
#endif
request_region(0x20,0x20,"pic1");
request_region(0xa0,0x20,"pic2");
- enable_irq(2);
- enable_irq(13);
+ setup_x86_irq(2, &irq2);
+ setup_x86_irq(13, &irq13);
}
diff -u --recursive --new-file v1.3.75/linux/arch/i386/kernel/time.c linux/arch/i386/kernel/time.c
--- v1.3.75/linux/arch/i386/kernel/time.c Wed Mar 13 10:09:12 1996
+++ linux/arch/i386/kernel/time.c Sun Mar 17 08:54:33 1996
@@ -27,6 +27,8 @@
#include <linux/timex.h>
#include <linux/config.h>

+extern int setup_x86_irq(int, struct irqaction *);
+
/* Cycle counter value at the previous timer interrupt.. */
static unsigned long long last_timer_cc = 0;
static unsigned long long init_timer_cc = 0;
@@ -353,7 +355,7 @@
return mktime(year, mon, day, hour, min, sec);
}

-struct irqaction irq0 = { timer_interrupt, 0, 0, "timer", NULL, NULL};
+static struct irqaction irq0 = { timer_interrupt, 0, 0, "timer", NULL, NULL};

void time_init(void)
{
@@ -374,5 +376,5 @@
irq0.handler = pentium_timer_interrupt;
}
#endif
- enable_irq(0);
+ setup_x86_irq(0, &irq0);
}
diff -u --recursive --new-file v1.3.75/linux/drivers/block/floppy.c linux/drivers/block/floppy.c
--- v1.3.75/linux/drivers/block/floppy.c Fri Mar 15 16:03:10 1996
+++ linux/drivers/block/floppy.c Sat Mar 16 23:13:55 1996
@@ -175,7 +175,7 @@
{
int order;

- size >>= (PAGE_SHIFT-1);
+ size = (size-1) >> (PAGE_SHIFT-1);
order = -1;
do {
size >>= 1;
diff -u --recursive --new-file v1.3.75/linux/drivers/char/ftape/kernel-interface.c linux/drivers/char/ftape/kernel-interface.c
--- v1.3.75/linux/drivers/char/ftape/kernel-interface.c Sun Mar 17 09:04:06 1996
+++ linux/drivers/char/ftape/kernel-interface.c Sat Mar 16 23:13:55 1996
@@ -89,7 +89,7 @@
{
int order;

- size >>= (PAGE_SHIFT-1);
+ size = (size-1) >> (PAGE_SHIFT-1);
order = -1;
do {
size >>= 1;
----------