Resent-Date: Mon, 30 Aug 1999 20:30:25 +0200 (MET DST) Date: Mon, 30 Aug 1999 20:30:01 +0200 (MET DST) From: Roman Zippel X-Sender: zippel@zeus To: Linux/m68k Subject: experimental patch for 2.3.14 Resent-From: linux-m68k@phil.uni-sb.de Hi, This patch implements basically two things - realtime interrupts and a system call stack. The realtime interrupts are not very useful yet, but as a side effect they implement something else - slow interrupts. As Jes version immediatly blows up on my computer with a stack overflow, what is very likely also the reason for Geert's crash. (I'm running a serial console at 56000bps, so it immediatly crashes after mounting root). Anyway, this is a safe version of slow interrupts (I hope), I don't execute them immediatly, instead I'm running them after the fast interrupts. The system call stack patch moves the registers d2-d5 to the switch stack, so that the registers d1-d5 for the arguments only saved for system calls and immediatly dropped after them, so that normal system calls and interrupts are slightly faster now. It's not a realease version yet, so just look at it, try it and tell me what you think. bye, Roman diff -Nur -X /opt/home/roman/src/m68k_nodiff linux-2.3.14/arch/m68k/amiga/amiints.c linux-rtl/arch/m68k/amiga/amiints.c --- linux-2.3.14/arch/m68k/amiga/amiints.c Fri Aug 20 20:46:51 1999 +++ linux-rtl/arch/m68k/amiga/amiints.c Sun Aug 29 20:16:42 1999 @@ -19,31 +19,20 @@ * called again. * The whole interrupt handling for CIAs is moved to cia.c * /Roman Zippel - * - * 07/08/99: rewamp of the interrupt handling - we now have two types of - * interrupts, normal and fast handlers, fast handlers being - * marked with SA_INTERRUPT and runs with all other interrupts - * disabled. Normal interrupts disable their own source but - * run with all other interrupt sources enabled. - * PORTS and EXTER interrupts are always shared even if the - * drivers do not explicitly mark this when calling - * request_irq which they really should do. - * This is similar to the way interrupts are handled on all - * other architectures and makes a ton of sense besides - * having the advantage of making it easier to share - * drivers. - * /Jes */ #include #include #include +#include +#include #include #include #include #include #include +#include #include #include #include @@ -52,26 +41,25 @@ void (*handler)(int, void *, struct pt_regs *), unsigned long flags, const char *devname, void *dev_id); extern void cia_free_irq(struct ciabase *base, unsigned int irq, void *dev_id); -extern void cia_init_IRQ(struct ciabase *base); -extern int cia_get_irq_list(struct ciabase *base, char *buf); - -/* irq node variables for amiga interrupt sources */ -static irq_node_t *ami_irq_list[AMI_STD_IRQS]; +extern void cia_init_IRQ(void); unsigned short ami_intena_vals[AMI_STD_IRQS] = { - IF_VERTB, IF_COPER, IF_AUD0, IF_AUD1, IF_AUD2, IF_AUD3, IF_BLIT, - IF_DSKSYN, IF_DSKBLK, IF_RBF, IF_TBE, IF_SOFT, IF_PORTS, IF_EXTER + IF_TBE, IF_DSKBLK, IF_SOFT, IF_PORTS, IF_COPPER, IF_VERTB, IF_BLIT, + IF_AUD0, IF_AUD1, IF_AUD2, IF_AUD3, IF_RBF, IF_DSKSYN, IF_EXTER }; -static const unsigned char ami_servers[AMI_STD_IRQS] = { - 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1 +static const unsigned char ami_servers[AMI_IRQS] = { + 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; static short ami_ablecount[AMI_IRQS]; -static void ami_badint(int irq, void *dev_id, struct pt_regs *fp) -{ - num_spurious += 1; -} +static void ami_int1(int irq, void *dev_id, struct pt_regs *fp); +static void ami_int2(int irq, void *dev_id, struct pt_regs *fp); +static void ami_int3(int irq, void *dev_id, struct pt_regs *fp); +static void ami_int4(int irq, void *dev_id, struct pt_regs *fp); +static void ami_int5(int irq, void *dev_id, struct pt_regs *fp); +static void ami_int6(int irq, void *dev_id, struct pt_regs *fp); /* * void amiga_init_IRQ(void) @@ -88,22 +76,11 @@ { int i; - /* initialize handlers */ - for (i = 0; i < AMI_STD_IRQS; i++) { - if (ami_servers[i]) { - ami_irq_list[i] = NULL; - } else { - ami_irq_list[i] = new_irq_node(); - ami_irq_list[i]->handler = ami_badint; - ami_irq_list[i]->flags = 0; - ami_irq_list[i]->dev_id = NULL; - ami_irq_list[i]->devname = NULL; - ami_irq_list[i]->next = NULL; - } - } for (i = 0; i < AMI_IRQS; i++) ami_ablecount[i] = 0; + vectors[VEC_INT7] = amiga_nmi_handler; + /* turn off PCMCIA interrupts */ if (AMIGAHW_PRESENT(PCMCIA)) pcmcia_disable_irq(); @@ -113,66 +90,18 @@ custom.intreq = 0x7fff; custom.intena = IF_SETCLR | IF_INTEN; - cia_init_IRQ(&ciaa_base); - cia_init_IRQ(&ciab_base); -} - -static inline void amiga_insert_irq(irq_node_t **list, irq_node_t *node) -{ - unsigned long flags; - irq_node_t *cur; - - if (!node->dev_id) - printk("%s: Warning: dev_id of %s is zero\n", - __FUNCTION__, node->devname); - - save_flags(flags); - cli(); - - cur = *list; - - if (node->flags & SA_INTERRUPT) { - if (node->flags & SA_SHIRQ) - return; - /* - * There should never be more than one - */ - while (cur && cur->flags & SA_INTERRUPT) { - list = &cur->next; - cur = cur->next; - } - } else { - while (cur) { - list = &cur->next; - cur = cur->next; - } - } - - node->next = cur; - *list = node; - - restore_flags(flags); -} - -static inline void amiga_delete_irq(irq_node_t **list, void *dev_id) -{ - unsigned long flags; - irq_node_t *node; - - save_flags(flags); - cli(); +#ifdef CONFIG_RT_INTERRUPT + mach_do_slowirq = amiga_do_slowirq_request; +#endif + + request_irq(IRQ_AMIGA_AUTO_1, ami_int1, IRQ_FLG_REALTIME, "int1 handler", NULL); + request_irq(IRQ_AMIGA_AUTO_2, ami_int2, IRQ_FLG_REALTIME, "int2 handler", NULL); + request_irq(IRQ_AMIGA_AUTO_3, ami_int3, IRQ_FLG_REALTIME, "int3 handler", NULL); + request_irq(IRQ_AMIGA_AUTO_4, ami_int4, IRQ_FLG_REALTIME, "int4 handler", NULL); + request_irq(IRQ_AMIGA_AUTO_5, ami_int5, IRQ_FLG_REALTIME, "int5 handler", NULL); + request_irq(IRQ_AMIGA_AUTO_6, ami_int6, IRQ_FLG_REALTIME, "int6 handler", NULL); - for (node = *list; node; list = &node->next, node = *list) { - if (node->dev_id == dev_id) { - *list = node->next; - /* Mark it as free. */ - node->handler = NULL; - restore_flags(flags); - return; - } - } - restore_flags(flags); - printk ("%s: tried to remove invalid irq\n", __FUNCTION__); + cia_init_IRQ(); } /* @@ -181,18 +110,35 @@ * If the addition was successful, it returns 0. */ -int amiga_request_irq(unsigned int irq, - void (*handler)(int, void *, struct pt_regs *), +int amiga_request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *), unsigned long flags, const char *devname, void *dev_id) { - irq_node_t *node; + unsigned int vec; + int res; if (irq >= AMI_IRQS) { - printk ("%s: Unknown IRQ %d from %s\n", __FUNCTION__, - irq, devname); + printk ("%s: Unknown IRQ %d from %s\n", __FUNCTION__, irq, devname); return -ENXIO; } + flags &= ~IRQ_FLG_LIST; + if (flags & SA_INTERRUPT) + flags |= IRQ_FLG_FAST; +#ifndef CONFIG_RT_INTERRUPT + if (flags & IRQ_FLG_REALTIME) + flags |= IRQ_FLG_FAST; +#endif + + if (irq >= IRQ_AMIGA_AUTO) { + vec = irq - IRQ_AMIGA_AUTO + VEC_SPUR; + + res = sys_request_irq(vec, handler, flags, devname, dev_id); + if (!res) + vectors[vec] = amiga_inthandler; + + return res; + } + if (irq >= IRQ_AMIGA_AUTO) return sys_request_irq(irq - IRQ_AMIGA_AUTO, handler, flags, devname, dev_id); @@ -205,43 +151,43 @@ return cia_request_irq(&ciaa_base, irq - IRQ_AMIGA_CIAA, handler, flags, devname, dev_id); - /* - * IRQ_AMIGA_PORTS & IRQ_AMIGA_EXTER defaults to shared, - * we could add a check here for the SA_SHIRQ flag but all drivers - * should be aware of sharing anyway. - */ - if (ami_servers[irq]) { - if (!(node = new_irq_node())) - return -ENOMEM; - node->handler = handler; - node->flags = flags; - node->dev_id = dev_id; - node->devname = devname; - node->next = NULL; - amiga_insert_irq(&ami_irq_list[irq], node); - } else { - ami_irq_list[irq]->handler = handler; - ami_irq_list[irq]->flags = flags; - ami_irq_list[irq]->dev_id = dev_id; - ami_irq_list[irq]->devname = devname; + vec = irq + VEC_USER; + if (ami_servers[irq]) + flags |= IRQ_FLG_LIST; + + res = sys_request_irq(vec, handler, flags, devname, dev_id); + if (!res) { + if (flags & IRQ_FLG_FASTQUEUE) + amiga_fastintmask |= 1 << irq; + else + amiga_slowintmask |= 1 << irq; + flush_icache_range((unsigned long)&amiga_slowintmask, + ((unsigned long)&amiga_fastintmask)+2); + /* enable the interrupt */ + if (!ami_ablecount[irq]) + custom.intena = IF_SETCLR | ami_intena_vals[irq]; } - /* enable the interrupt */ - if (irq < IRQ_AMIGA_PORTS && !ami_ablecount[irq]) - custom.intena = IF_SETCLR | ami_intena_vals[irq]; - return 0; } void amiga_free_irq(unsigned int irq, void *dev_id) { + unsigned int vec; + if (irq >= AMI_IRQS) { printk ("%s: Unknown IRQ %d\n", __FUNCTION__, irq); return; } - if (irq >= IRQ_AMIGA_AUTO) - sys_free_irq(irq - IRQ_AMIGA_AUTO, dev_id); + if (irq >= IRQ_AMIGA_AUTO) { + vec = irq - IRQ_AMIGA_AUTO + VEC_SPUR; + + sys_free_irq(vec, dev_id); + vectors[vec] = bad_interrupt; + + return; + } if (irq >= IRQ_AMIGA_CIAB) { cia_free_irq(&ciab_base, irq - IRQ_AMIGA_CIAB, dev_id); @@ -253,21 +199,18 @@ return; } - if (ami_servers[irq]) { - amiga_delete_irq(&ami_irq_list[irq], dev_id); - /* if server list empty, disable the interrupt */ - if (!ami_irq_list[irq] && irq < IRQ_AMIGA_PORTS) - custom.intena = ami_intena_vals[irq]; - } else { - if (ami_irq_list[irq]->dev_id != dev_id) - printk("%s: removing probably wrong IRQ %d from %s\n", - __FUNCTION__, irq, ami_irq_list[irq]->devname); - ami_irq_list[irq]->handler = ami_badint; - ami_irq_list[irq]->flags = 0; - ami_irq_list[irq]->dev_id = NULL; - ami_irq_list[irq]->devname = NULL; + vec = irq + VEC_USER; + sys_free_irq(vec, dev_id); + + /* if list empty, disable the interrupt */ + if (!userirq_list[irq]) + amiga_fastintmask &= ~(1 << irq); + if (!userirq_slowlist[irq]) + amiga_slowintmask &= ~(1 << irq); + flush_icache_range((unsigned long)&amiga_slowintmask, + ((unsigned long)&amiga_fastintmask)+2); + if (!userirq_list[irq] && !userirq_slowlist[irq]) custom.intena = ami_intena_vals[irq]; - } } /* @@ -344,79 +287,12 @@ custom.intena = ami_intena_vals[irq]; } -inline void amiga_do_irq(int irq, struct pt_regs *fp) -{ - kstat.irqs[0][SYS_IRQS + irq]++; - ami_irq_list[irq]->handler(irq, ami_irq_list[irq]->dev_id, fp); -} - -void amiga_do_irq_list(int irq, struct pt_regs *fp, struct irq_server *server) -{ - irq_node_t *node, *slow_nodes; - unsigned short flags, intena; - - kstat.irqs[0][SYS_IRQS + irq]++; - if (server->count++) - server->reentrance = 1; - - intena = ami_intena_vals[irq]; - custom.intreq = intena; - - /* serve first fast handlers - there can only be one of these */ - node = ami_irq_list[irq]; - - /* - * Timer interrupts show up like this - */ - if (!node) { - server->count--; - return; - } - - if (node && (node->flags & SA_INTERRUPT)) { - save_flags(flags); - cli(); - node->handler(irq, node->dev_id, fp); - restore_flags(flags); - - server->count--; - return; - } - - /* - * Disable the interrupt source in question and reenable all - * other interrupts. No interrupt handler should ever touch - * the intena flags directly! - */ - custom.intena = intena; - save_flags(flags); - sti(); - - slow_nodes = node; - for (;;) { - for (; node; node = node->next) - node->handler(irq, node->dev_id, fp); - - if (!server->reentrance) { - server->count--; - restore_flags(flags); - custom.intena = IF_SETCLR | intena; - return; - } - - server->reentrance = 0; - node = slow_nodes; - } -} - /* * The builtin Amiga hardware interrupt handlers. */ -static void ami_int1(int irq, void *dev_id, struct pt_regs *fp) +static void ami_int1(int ints, void *dev_id, struct pt_regs *fp) { - unsigned short ints = custom.intreqr & custom.intenar; - /* if serial transmit buffer empty, interrupt */ if (ints & IF_TBE) { custom.intreq = IF_TBE; @@ -436,11 +312,16 @@ } } -static void ami_int3(int irq, void *dev_id, struct pt_regs *fp) +static void ami_int2(int ints, void *dev_id, struct pt_regs *fp) { - unsigned short ints = custom.intreqr & custom.intenar; - static struct irq_server server = {0, 0}; + if (ints & IF_PORTS) { + custom.intreq = IF_PORTS; + amiga_do_irq_list(IRQ_AMIGA_PORTS, fp); + } +} +static void ami_int3(int ints, void *dev_id, struct pt_regs *fp) +{ /* if a blitter interrupt */ if (ints & IF_BLIT) { custom.intreq = IF_BLIT; @@ -448,20 +329,20 @@ } /* if a copper interrupt */ - if (ints & IF_COPER) { - custom.intreq = IF_COPER; + if (ints & IF_COPPER) { + custom.intreq = IF_COPPER; amiga_do_irq(IRQ_AMIGA_COPPER, fp); } /* if a vertical blank interrupt */ - if (ints & IF_VERTB) - amiga_do_irq_list(IRQ_AMIGA_VERTB, fp, &server); + if (ints & IF_VERTB) { + custom.intreq = IF_VERTB; + amiga_do_irq_list(IRQ_AMIGA_VERTB, fp); + } } -static void ami_int4(int irq, void *dev_id, struct pt_regs *fp) +static void ami_int4(int ints, void *dev_id, struct pt_regs *fp) { - unsigned short ints = custom.intreqr & custom.intenar; - /* if audio 0 interrupt */ if (ints & IF_AUD0) { custom.intreq = IF_AUD0; @@ -487,10 +368,8 @@ } } -static void ami_int5(int irq, void *dev_id, struct pt_regs *fp) +static void ami_int5(int ints, void *dev_id, struct pt_regs *fp) { - unsigned short ints = custom.intreqr & custom.intenar; - /* if serial receive buffer full interrupt */ if (ints & IF_RBF) { /* acknowledge of IF_RBF must be done by the serial interrupt */ @@ -504,38 +383,64 @@ } } -static void ami_int7(int irq, void *dev_id, struct pt_regs *fp) +static void ami_int6(int ints, void *dev_id, struct pt_regs *fp) { - panic ("level 7 interrupt received\n"); + if (ints & IF_EXTER) { + custom.intreq = IF_EXTER; + amiga_do_irq_list(IRQ_AMIGA_EXTER, fp); + } } -void (*amiga_default_handler[SYS_IRQS])(int, void *, struct pt_regs *) = { - ami_badint, ami_int1, ami_badint, ami_int3, - ami_int4, ami_int5, ami_badint, ami_int7 -}; - -int amiga_get_irq_list(char *buf) -{ - int i, len = 0; - irq_node_t *node; - - for (i = 0; i < AMI_STD_IRQS; i++) { - if (!(node = ami_irq_list[i])) - continue; - len += sprintf(buf+len, "ami %2d: %10u ", i, - kstat.irqs[0][SYS_IRQS + i]); - do { - if (node->flags & SA_INTERRUPT) - len += sprintf(buf+len, "F "); - else - len += sprintf(buf+len, " "); - len += sprintf(buf+len, "%s\n", node->devname); - if ((node = node->next)) - len += sprintf(buf+len, " "); - } while (node); - } - - len += cia_get_irq_list(&ciaa_base, buf+len); - len += cia_get_irq_list(&ciab_base, buf+len); - return len; +#ifdef CONFIG_RT_INTERRUPT +rt_lockdefine(rtirq_lock); +#endif + +void amiga_do_slowirq_request(void) +{ + int old_mask, old_request, irq; + static struct pt_regs dummy_regs; +#ifdef CONFIG_RT_INTERRUPT + int oldcnt; + rt_flagsdefine; + +again: + rt_exchange(rtirq_lock, &slowirq_request, old_request, 0); +#else + old_request = xchg(&slowirq_request, 0); +#endif + old_mask = old_request; + custom.intreq = old_mask & (0x3fff & ~IF_RBF); + while (old_request) { +#ifdef CONFIG_APUS +#else + asm ("bfffo %1{#0,#32},%0; bfclr %1{%0,#1}" + : "=&d" (irq), "=d" (old_request) + : "1" (old_request): "cc"); + irq = 31 - irq; +#endif + if (ami_servers[irq]) + amiga_do_slowirq_list(irq, &dummy_regs); + else + amiga_do_slowirq(irq, &dummy_regs); + } + custom.intena = IF_SETCLR | (old_mask & 0x3fff); + if ((old_mask >>= AMI_STD_IRQS)) { + cia_able_irq(&ciaa_base, CIA_ICR_SETCLR | (old_mask & CIA_ICR_ALL)); + if ((old_mask >>= CIA_IRQS)) + cia_able_irq(&ciab_base, CIA_ICR_SETCLR | old_mask); + } + if (bh_active & bh_mask) + do_bottom_half(); + +#ifdef CONFIG_RT_INTERRUPT + slowirq_enable = 1; + + /* increment slowirq_busycnt, it must get 1 again */ + rt_exchange(rtirq_lock, &slowirq_busycnt, oldcnt, oldcnt + 1); + if (oldcnt) { + /* set it to 0 and hope no interrupts disturbs us this time */ + slowirq_busycnt = 0; + goto again; + } +#endif } diff -Nur -X /opt/home/roman/src/m68k_nodiff linux-2.3.14/arch/m68k/amiga/cia.c linux-rtl/arch/m68k/amiga/cia.c --- linux-2.3.14/arch/m68k/amiga/cia.c Fri Aug 20 20:46:52 1999 +++ linux-rtl/arch/m68k/amiga/cia.c Sun Aug 29 12:01:13 1999 @@ -18,27 +18,24 @@ #include #include +#include +#include #include #include struct ciabase { volatile struct CIA *cia; - u_char icr_mask, icr_data; + int cia_irq; u_short int_mask; - int handler_irq, cia_irq, server_irq; - char *name; - struct irq_server server; - irq_handler_t irq_list[CIA_IRQS]; + u_char allocmask, pad; + u_char icr_mask, icr_data; + u_char fastmask, slowmask; } ciaa_base = { - &ciaa, 0, 0, IF_PORTS, - IRQ_AMIGA_AUTO_2, IRQ_AMIGA_CIAA, - IRQ_AMIGA_PORTS, - "CIAA handler", {0, 0} + &ciaa, IRQ_AMIGA_CIAA, + IF_PORTS, CIA_ICR_ALL, 0, 0, 0, 0, 0 }, ciab_base = { - &ciab, 0, 0, IF_EXTER, - IRQ_AMIGA_AUTO_6, IRQ_AMIGA_CIAB, - IRQ_AMIGA_EXTER, - "CIAB handler", {0, 0} + &ciab, IRQ_AMIGA_CIAB, + IF_EXTER, CIA_ICR_ALL, 0, 0, 0, 0, 0 }; /* @@ -66,23 +63,17 @@ unsigned char cia_able_irq(struct ciabase *base, unsigned char mask) { - u_char old, tmp; - int i; + u_char old; old = base->icr_mask; base->icr_data |= base->cia->icr; + mask &= CIA_ICR_SETCLR | base->allocmask; base->cia->icr = mask; if (mask & CIA_ICR_SETCLR) base->icr_mask |= mask; else base->icr_mask &= ~mask; base->icr_mask &= CIA_ICR_ALL; - for (i = 0, tmp = 1; i < CIA_IRQS; i++, tmp <<= 1) { - if ((tmp & base->icr_mask) && !base->irq_list[i].handler) { - base->icr_mask &= ~tmp; - base->cia->icr = tmp; - } - } if (base->icr_data & base->icr_mask) custom.intreq = IF_SETCLR | base->int_mask; return old; @@ -92,83 +83,87 @@ void (*handler)(int, void *, struct pt_regs *), unsigned long flags, const char *devname, void *dev_id) { + unsigned int vec; + int res; u_char mask; - base->irq_list[irq].handler = handler; - base->irq_list[irq].flags = flags; - base->irq_list[irq].dev_id = dev_id; - base->irq_list[irq].devname = devname; + vec = VEC_USER + base->cia_irq + irq; + res = sys_request_irq(vec, handler, flags, devname, dev_id); - /* enable the interrupt */ - mask = 1 << irq; - cia_set_irq(base, mask); - cia_able_irq(base, CIA_ICR_SETCLR | mask); + if (!res) { + mask = 1 << irq; + if (flags & IRQ_FLG_FASTQUEUE) + base->fastmask |= mask; + else + base->slowmask |= mask; + /* enable the interrupt */ + base->allocmask |= mask; + cia_set_irq(base, mask); + cia_able_irq(base, CIA_ICR_SETCLR | mask); + } return 0; } void cia_free_irq(struct ciabase *base, unsigned int irq, void *dev_id) { - if (base->irq_list[irq].dev_id != dev_id) - printk("%s: removing probably wrong IRQ %i from %s\n", - __FUNCTION__, base->cia_irq + irq, - base->irq_list[irq].devname); + unsigned int vec; + u_char mask; - base->irq_list[irq].handler = NULL; - base->irq_list[irq].flags = 0; + vec = VEC_USER + base->cia_irq + irq; + sys_free_irq(vec, dev_id); - cia_able_irq(base, 1 << irq); + mask = 1 << irq; + if (!userirq_list[base->cia_irq + irq]) + base->fastmask &= ~mask; + if (!userirq_slowlist[base->cia_irq + irq]) + base->slowmask &= ~mask; + if (!userirq_list[base->cia_irq + irq] && + !userirq_slowlist[base->cia_irq + irq]) { + cia_able_irq(base, mask); + base->allocmask &= ~mask; + } } static void cia_handler(int irq, void *dev_id, struct pt_regs *fp) { struct ciabase *base = (struct ciabase *)dev_id; - int mach_irq, i; - unsigned char ints; + unsigned char ints, slowints; - mach_irq = base->cia_irq; - irq = SYS_IRQS + mach_irq; ints = cia_set_irq(base, CIA_ICR_ALL); + if ((slowints = ints & base->slowmask)) { + set_slowirq_request(slowints << base->cia_irq); + cia_able_irq(base, slowints); + } + ints &= base->fastmask; + custom.intreq = base->int_mask; - for (i = 0; i < CIA_IRQS; i++, irq++, mach_irq++) { - if (ints & 1) { - kstat.irqs[0][irq]++; - base->irq_list[i].handler(mach_irq, base->irq_list[i].dev_id, fp); + if ( ints ) { + unsigned int irq = base->cia_irq + CIA_IRQS - 1; + irq_node_t **list = &userirq_list[irq]; + unsigned int *stat = &kstat.irqs[0][irq + AUTO_IRQ_NR]; + for (ints <<= 3; ints; ints <<= 1) { + if ( ints & 0x80 ) { + (*stat)++; + (*list)->handler(irq, (*list)->dev_id, fp); + } + stat--; list--; irq--; } - ints >>= 1; } - amiga_do_irq_list(base->server_irq, fp, &base->server); } -void __init cia_init_IRQ(struct ciabase *base) +void __init cia_init_IRQ(void) { - int i; - - /* init isr handlers */ - for (i = 0; i < CIA_IRQS; i++) { - base->irq_list[i].handler = NULL; - base->irq_list[i].flags = 0; - } - /* clear any pending interrupt and turn off all interrupts */ - cia_set_irq(base, CIA_ICR_ALL); - cia_able_irq(base, CIA_ICR_ALL); + cia_set_irq(&ciaa_base, CIA_ICR_ALL); + cia_able_irq(&ciaa_base, CIA_ICR_ALL); + cia_set_irq(&ciab_base, CIA_ICR_ALL); + cia_able_irq(&ciab_base, CIA_ICR_ALL); + ciaa_base.allocmask = ciab_base.allocmask = 0; /* install CIA handler */ - request_irq(base->handler_irq, cia_handler, 0, base->name, base); + request_irq(IRQ_AMIGA_PORTS, cia_handler, IRQ_FLG_FAST|IRQ_FLG_REALTIME, + "ciaa handler", &ciaa_base); + request_irq(IRQ_AMIGA_EXTER, cia_handler, IRQ_FLG_FAST|IRQ_FLG_REALTIME, + "ciab handler", &ciab_base); - custom.intena = IF_SETCLR | base->int_mask; -} - -int cia_get_irq_list(struct ciabase *base, char *buf) -{ - int i, j, len = 0; - - j = base->cia_irq; - for (i = 0; i < CIA_IRQS; i++) { - len += sprintf(buf+len, "cia %2d: %10d ", j + i, - kstat.irqs[0][SYS_IRQS + j + i]); - len += sprintf(buf+len, " "); - len += sprintf(buf+len, "%s\n", base->irq_list[i].devname); - } - return len; } diff -Nur -X /opt/home/roman/src/m68k_nodiff linux-2.3.14/arch/m68k/amiga/config.c linux-rtl/arch/m68k/amiga/config.c --- linux-2.3.14/arch/m68k/amiga/config.c Fri Aug 20 20:46:53 1999 +++ linux-rtl/arch/m68k/amiga/config.c Sun Aug 29 20:04:09 1999 @@ -54,7 +54,6 @@ extern int amiga_kbdrate (struct kbd_repeat *); /* amiga specific irq functions */ extern void amiga_init_IRQ (void); -extern void (*amiga_default_handler[]) (int, void *, struct pt_regs *); extern int amiga_request_irq (unsigned int irq, void (*handler)(int, void *, struct pt_regs *), unsigned long flags, const char *devname, @@ -64,7 +63,6 @@ extern void amiga_disable_irq (unsigned int); static void amiga_get_model(char *model); static int amiga_get_hardware_list(char *buffer); -extern int amiga_get_irq_list (char *); /* amiga specific timer functions */ static unsigned long amiga_gettimeoffset (void); static void a3000_gettod (int *, int *, int *, int *, int *, int *); @@ -343,14 +341,12 @@ mach_keyb_init = amiga_keyb_init; mach_kbdrate = amiga_kbdrate; mach_init_IRQ = amiga_init_IRQ; - mach_default_handler = &amiga_default_handler; mach_request_irq = amiga_request_irq; mach_free_irq = amiga_free_irq; enable_irq = amiga_enable_irq; disable_irq = amiga_disable_irq; mach_get_model = amiga_get_model; mach_get_hardware_list = amiga_get_hardware_list; - mach_get_irq_list = amiga_get_irq_list; mach_gettimeoffset = amiga_gettimeoffset; if (AMIGAHW_PRESENT(A3000_CLK)){ mach_gettod = a3000_gettod; diff -Nur -X /opt/home/roman/src/m68k_nodiff linux-2.3.14/arch/m68k/config.in linux-rtl/arch/m68k/config.in --- linux-2.3.14/arch/m68k/config.in Fri Aug 20 20:46:49 1999 +++ linux-rtl/arch/m68k/config.in Sun Aug 29 01:13:55 1999 @@ -72,6 +72,10 @@ if [ "$CONFIG_M68060" = "y" ]; then bool 'Use write-through caching for 68060 supervisor accesses' CONFIG_060_WRITETHROUGH fi + if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then + bool 'Enable realtime interrupts' CONFIG_RT_INTERRUPT + bool 'Enable new system stack' CONFIG_SYS_STACK + fi fi endmenu diff -Nur -X /opt/home/roman/src/m68k_nodiff linux-2.3.14/arch/m68k/fpsp040/skeleton.S linux-rtl/arch/m68k/fpsp040/skeleton.S --- linux-2.3.14/arch/m68k/fpsp040/skeleton.S Tue May 18 16:00:20 1999 +++ linux-rtl/arch/m68k/fpsp040/skeleton.S Thu Aug 26 23:10:17 1999 @@ -70,9 +70,9 @@ frestore (%sp)+ unlk %a6 - SAVE_ALL_INT - GET_CURRENT(%d0) - movel %sp,%sp@- | stack frame pointer argument + save_all_int + get_current + pea %sp@ | stack frame pointer argument bsrl SYMBOL_NAME(trap_c) addql #4,%sp bral SYMBOL_NAME(ret_from_exception) @@ -161,8 +161,8 @@ frestore (%sp)+ unlk %a6 - SAVE_ALL_INT - GET_CURRENT(%d0) + save_all_int + get_current movel %sp,%sp@- | stack frame pointer argument bsrl SYMBOL_NAME(trap_c) addql #4,%sp @@ -187,8 +187,8 @@ frestore (%sp)+ unlk %a6 - SAVE_ALL_INT - GET_CURRENT(%d0) + save_all_int + get_current movel %sp,%sp@- | stack frame pointer argument bsrl SYMBOL_NAME(trap_c) addql #4,%sp @@ -213,8 +213,8 @@ frestore (%sp)+ unlk %a6 - SAVE_ALL_INT - GET_CURRENT(%d0) + save_all_int + get_current movel %sp,%sp@- | stack frame pointer argument bsrl SYMBOL_NAME(trap_c) addql #4,%sp @@ -235,8 +235,8 @@ frestore (%sp)+ unlk %a6 - SAVE_ALL_INT - GET_CURRENT(%d0) + save_all_int + get_current movel %sp,%sp@- | stack frame pointer argument bsrl SYMBOL_NAME(trap_c) addql #4,%sp @@ -257,8 +257,8 @@ frestore (%sp)+ unlk %a6 - SAVE_ALL_INT - GET_CURRENT(%d0) + save_all_int + get_current movel %sp,%sp@- | stack frame pointer argument bsrl SYMBOL_NAME(trap_c) addql #4,%sp @@ -285,8 +285,8 @@ frestore (%sp)+ unlk %a6 - SAVE_ALL_INT - GET_CURRENT(%d0) + save_all_int + get_current movel %sp,%sp@- | stack frame pointer argument bsrl SYMBOL_NAME(trap_c) addql #4,%sp @@ -306,8 +306,8 @@ jmp fpsp_fline real_fline: - SAVE_ALL_INT - GET_CURRENT(%d0) + save_all_int + get_current movel %sp,%sp@- | stack frame pointer argument bsrl SYMBOL_NAME(trap_c) addql #4,%sp @@ -328,8 +328,8 @@ frestore (%sp)+ unlk %a6 - SAVE_ALL_INT - GET_CURRENT(%d0) + save_all_int + get_current movel %sp,%sp@- | stack frame pointer argument bsrl SYMBOL_NAME(trap_c) addql #4,%sp @@ -379,12 +379,12 @@ beq .Lnotkern rte .Lnotkern: - SAVE_ALL_INT - GET_CURRENT(%d0) + save_all_int + get_current tstl %curptr@(TASK_NEEDRESCHED) jne SYMBOL_NAME(ret_from_exception) | deliver signals, | reschedule etc.. - RESTORE_ALL + restore_all | | mem_write --- write to user or supervisor address space diff -Nur -X /opt/home/roman/src/m68k_nodiff linux-2.3.14/arch/m68k/ifpsp060/iskeleton.S linux-rtl/arch/m68k/ifpsp060/iskeleton.S --- linux-2.3.14/arch/m68k/ifpsp060/iskeleton.S Tue May 18 16:00:20 1999 +++ linux-rtl/arch/m68k/ifpsp060/iskeleton.S Wed Aug 25 20:02:00 1999 @@ -73,12 +73,12 @@ beq .Lnotkern rte .Lnotkern: - SAVE_ALL_INT - GET_CURRENT(%d0) + save_all_int + get_current tstl %curptr@(TASK_NEEDRESCHED) jne SYMBOL_NAME(ret_from_exception) | deliver signals, | reschedule etc.. - RESTORE_ALL + restore_all | | _060_real_chk(): diff -Nur -X /opt/home/roman/src/m68k_nodiff linux-2.3.14/arch/m68k/kernel/entry.S linux-rtl/arch/m68k/kernel/entry.S --- linux-2.3.14/arch/m68k/kernel/entry.S Tue Aug 24 01:00:37 1999 +++ linux-rtl/arch/m68k/kernel/entry.S Sun Aug 29 20:18:40 1999 @@ -33,33 +33,34 @@ #include #include #include -#include #include #include #include +#include #include #include "m68k_defs.h" +#include + .globl SYMBOL_NAME(system_call), SYMBOL_NAME(buserr), SYMBOL_NAME(trap) .globl SYMBOL_NAME(resume), SYMBOL_NAME(ret_from_exception) .globl SYMBOL_NAME(ret_from_signal) .globl SYMBOL_NAME(inthandler), SYMBOL_NAME(sys_call_table) .globl SYMBOL_NAME(sys_fork), SYMBOL_NAME(sys_clone), SYMBOL_NAME(sys_vfork) -.globl SYMBOL_NAME(ret_from_interrupt), SYMBOL_NAME(bad_interrupt) .text ENTRY(buserr) - SAVE_ALL_INT - GET_CURRENT(%d0) + save_all_int + get_current movel %sp,%sp@- | stack frame pointer argument bsrl SYMBOL_NAME(buserr_c) addql #4,%sp jra SYMBOL_NAME(ret_from_exception) ENTRY(trap) - SAVE_ALL_INT - GET_CURRENT(%d0) + save_all_int + get_current movel %sp,%sp@- | stack frame pointer argument bsrl SYMBOL_NAME(trap_c) addql #4,%sp @@ -83,40 +84,50 @@ jra SYMBOL_NAME(ret_from_exception) badsys: - movel #-ENOSYS,PT_D0(%sp) + drop_sys_stack + movel #-ENOSYS,%sp@(PT_D0) jra SYMBOL_NAME(ret_from_exception) do_trace: - movel #-ENOSYS,PT_D0(%sp) | needed for strace + drop_sys_stack + + | save top of frame + movel %sp,%curptr@(TASK_THREAD+THREAD_ESP0) + + movel #-ENOSYS,%sp@(PT_D0) | needed for strace subql #4,%sp - SAVE_SWITCH_STACK + save_switch_stack jbsr SYMBOL_NAME(syscall_trace) - RESTORE_SWITCH_STACK + restore_switch_stack addql #4,%sp - jbsr @(SYMBOL_NAME(sys_call_table),%d2:l:4)@(0) - movel %d0,%sp@(PT_D0) | save the return value + rebuild_sys_stack + movel %sp@(SC_SIZEOF+PT_SYSCALL),%d1 + movel #-ENOSYS,%d0 + cmpl #NR_syscalls,%d1 + jcc 1f + jbsr @(SYMBOL_NAME(sys_call_table),%d1:l:4)@(0) +1: movel %d0,%sp@(SC_SIZEOF+PT_D0) | save the return value + drop_sys_stack subql #4,%sp | dummy return address - SAVE_SWITCH_STACK + save_switch_stack jbsr SYMBOL_NAME(syscall_trace) SYMBOL_NAME_LABEL(ret_from_signal) - RESTORE_SWITCH_STACK + restore_switch_stack addql #4,%sp jra SYMBOL_NAME(ret_from_exception) ENTRY(system_call) - SAVE_ALL_SYS - movel %d0,%d2 + save_all_sys + save_sys_stack + get_current %d1 - GET_CURRENT(%d0) - | save top of frame - movel %sp,%curptr@(TASK_THREAD+THREAD_ESP0) - - cmpl #NR_syscalls,%d2 - jcc badsys btst #PF_TRACESYS_BIT,%curptr@(TASK_FLAGS+PF_TRACESYS_OFF) jne do_trace - jbsr @(SYMBOL_NAME(sys_call_table),%d2:l:4)@(0) + cmpl #NR_syscalls,%d0 + jcc badsys + jbsr @(SYMBOL_NAME(sys_call_table),%d0:l:4)@(0) + drop_sys_stack movel %d0,%sp@(PT_D0) | save the return value SYMBOL_NAME_LABEL(ret_from_exception) @@ -128,10 +139,6 @@ andw #ALLOWINT,%sr tstl %curptr@(TASK_NEEDRESCHED) jne SYMBOL_NAME(reschedule) -#if 0 - cmpl #SYMBOL_NAME(task),%curptr | task[0] cannot have signals - jeq 2f -#endif | check for delayed trace bclr #PF_DTRACE_BIT,%curptr@(TASK_FLAGS+PF_DTRACE_OFF) jne do_delayed_trace @@ -140,19 +147,19 @@ jne SYMBOL_NAME(reschedule) tstl %curptr@(TASK_SIGPENDING) - jne Lsignal_return -2: RESTORE_ALL + jne signal_return +2: restore_all -Lsignal_return: +signal_return: subql #4,%sp | dummy return address - SAVE_SWITCH_STACK - pea %sp@(SWITCH_STACK_SIZE) + save_switch_stack + pea %sp@(SW_SIZEOF) clrl %sp@- bsrl SYMBOL_NAME(do_signal) addql #8,%sp - RESTORE_SWITCH_STACK + restore_switch_stack addql #4,%sp - RESTORE_ALL + restore_all do_delayed_trace: bclr #7,%sp@(PT_SR) | clear trace bit in SR @@ -164,139 +171,260 @@ addql #4,%sp jra 5b +/* +** Interrupt construction set. :-) +** You can build your own interrupts with these macros. +*/ -#if 0 -#if CONFIG_AMIGA -SYMBOL_NAME_LABEL(ami_inthandler) +| general interrupt entry +| intnodes - vector of ptr to interrupt nodes +| firstvec, firststatvec - first entry in intnodes/int stats +| -> %a0 contains first int node, %d0 exception vector +.macro int_entry intnodes, firstvec, firststatvec=VEC_SPUR addql #1,SYMBOL_NAME(local_irq_count) - SAVE_ALL_INT - GET_CURRENT(%d0) + save_all_int + get_current +| extract exception vector, do some statistic and get (first) int node bfextu %sp@(PT_VECTOR){#4,#12},%d0 movel %d0,%a0 - addql #1,%a0@(SYMBOL_NAME(kstat)+STAT_IRQ-VECOFF(VEC_SPUR)) - movel %a0@(SYMBOL_NAME(autoirq_list)-VECOFF(VEC_SPUR)),%a0 - -| amiga vector int handler get the req mask instead of irq vector - lea CUSTOMBASE,%a1 - movew %a1@(C_INTREQR),%d0 - andw %a1@(C_INTENAR),%d0 + addql #1,%a0@(SYMBOL_NAME(kstat)+STAT_IRQ-VECOFF(\firststatvec)) + movel %a0@(SYMBOL_NAME(\intnodes)-VECOFF(\firstvec)),%a0 +.endm -| prepare stack (push frame pointer, dev_id & req mask) +| call a single interrupt node +.macro int_callnode exit=SYMBOL_NAME(ret_from_interrupt_cleanup) pea %sp@ movel %a0@(IRQ_DEVID),%sp@- movel %d0,%sp@- - pea %pc@(SYMBOL_NAME(ret_from_interrupt):w) - jbra @(IRQ_HANDLER,%a0)@(0) - -ENTRY(nmi_handler) - rte + pea %pc@(\exit:w) + jra @(IRQ_HANDLER,%a0)@(0) +.endm + +| after int_callnode the stack must be cleaned up +.macro int_cleanup + lea %sp@(12),%sp +.endm + +| call a list of interrupt nodes +.macro int_callnodelist exit=SYMBOL_NAME(ret_from_interrupt) + movel %a0@(IRQ_NEXT),%sp@- + pea %sp@(4) + movel %a0@(IRQ_DEVID),%sp@- + movel %d0,%sp@- +1: jsr @(IRQ_HANDLER,%a0)@(0) + movel %sp@(12),%d0 + jeq 2f + movel %d0,%a0 +| only modify devid on stack, we expect the rest to be unmodified + movel %a0@(IRQ_DEVID),%sp@(4) + movel %a0@(IRQ_NEXT),%sp@(12) + jra 1b +2: lea %sp@(16),%sp + jra \exit +.endm + +| help macro for the two exit macro to check for a nested interrupt. +| For the 060 we can be sure that at least one instruction of an +| exception is executed, so the counter check is sufficient. +.macro int_returncheck dest +#ifndef CPU_M68060_ONLY +#if MAX_NOINT_IPL == 0 + bftst %sp@(PT_SR){#5,#3} + jne \dest +#else + bfextu %sp@(PT_SR){#5,#3},%d0 + cmpiw #MAX_NOINT_IPL,%d0 + jhi \dest #endif #endif +.endm -/* -** This is the main interrupt handler, responsible for calling process_int() -*/ -SYMBOL_NAME_LABEL(inthandler) - SAVE_ALL_INT - GET_CURRENT(%d0) - addql #1,SYMBOL_NAME(local_irq_count) - | put exception # in d0 - bfextu %sp@(PT_VECTOR){#4,#10},%d0 - - movel %sp,%sp@- - 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 SYMBOL_NAME(floppy_hardint) - jbra 3f -1: -#endif - jbsr SYMBOL_NAME(process_int)| process the IRQ -3: addql #8,%sp | pop parameters off stack - -SYMBOL_NAME_LABEL(ret_from_interrupt) +.macro int_return subql #1,SYMBOL_NAME(local_irq_count) - jeq 1f + jeq 2f +1: + restore_all + ALIGN 2: - RESTORE_ALL -1: -#if 1 - bfextu %sp@(PT_SR){#5,#3},%d0 | Check for nested interrupt. -#if MAX_NOINT_IPL > 0 - cmpiw #MAX_NOINT_IPL,%d0 -#endif - jhi 2b -#endif - /* check if we need to do software interrupts */ + int_returncheck 1b + /* check if we need to do software interrupts */ movel SYMBOL_NAME(bh_active),%d0 andl SYMBOL_NAME(bh_mask),%d0 jeq SYMBOL_NAME(ret_from_exception) pea SYMBOL_NAME(ret_from_exception) jra SYMBOL_NAME(do_bottom_half) +.endm +.macro int_slowreturn do_slowrequest + movel SYMBOL_NAME(local_irq_count),%d0 + subql #1,%d0 + jeq 2f +1: movel %d0,SYMBOL_NAME(local_irq_count) + restore_all + ALIGN +2: + int_returncheck 1b +#ifdef CONFIG_RT_INTERRUPT + tstl SYMBOL_NAME(slowirq_enable) + jeq 1b +#endif +3: +#ifdef CONFIG_RT_INTERRUPT + subql #1,SYMBOL_NAME(slowirq_busycnt) + jlt 1b +#endif + andw #0xf8ff,%sr + jsr \do_slowrequest + +#ifndef CONFIG_RT_INTERRUPT + orw #0x0700,%sr + tstl SYMBOL_NAME(slowirq_request) + jne 3b + clrl SYMBOL_NAME(local_irq_count) + jra SYMBOL_NAME(ret_from_exception) +#else + | almost the same as above, but also tries to minimize + | the time where interrupts are disabled + btst #5,%sp@(PT_SR) | check if returning to kernel + jeq 1f + orw #0x0700,%sr + tstl SYMBOL_NAME(slowirq_request) + jne 3b + clrl SYMBOL_NAME(local_irq_count) + restore_all +1: orw #0x0700,%sr + tstl SYMBOL_NAME(slowirq_request) + jne 3b + clrl SYMBOL_NAME(local_irq_count) + andw #0xf8ff,%sr + jra SYMBOL_NAME(ret_from_exception) +#endif +.endm + +#ifdef CONFIG_AMIGA +/* +** Special Amiga interrupt handler +*/ +ENTRY(amiga_inthandler) + int_entry autoirq_list,VEC_SPUR + +| amiga vector int handler get the req mask instead of irq vector + lea CUSTOMBASE,%a1 + movew %a1@(C_INTREQR),%d0 + andw %a1@(C_INTENAR),%d0 + +.globl SYMBOL_NAME(amiga_slowintmask),SYMBOL_NAME(amiga_fastintmask) + +| disable slow ints and modify req mask + movew %d0,%d1 +.equ SYMBOL_NAME(amiga_slowintmask),.+2 + andw #0:w,%d1 + jeq 1f + orw %d1,SYMBOL_NAME(slowirq_request+2) + movew %d1,%a1@(C_INTENA) +.equ SYMBOL_NAME(amiga_fastintmask),.+2 +1: andw #0:w,%d0 + jeq SYMBOL_NAME(amiga_fastret_from_irq) + + int_callnode SYMBOL_NAME(amiga_ret_from_irq) + +ENTRY(amiga_ret_from_irq) + int_cleanup +SYMBOL_NAME_LABEL(amiga_fastret_from_irq) + int_slowreturn SYMBOL_NAME(amiga_do_slowirq_request) + +ENTRY(amiga_nmi_handler) + rte +#endif + +#if defined(CONFIG_HP300) +ENTRY(autoirq_handler) + int_entry autoirq_list,VEC_SPUR + lsrl #2,%d0 + int_callnode SYMBOL_NAME(cleanup_from_interrupt) + +ENTRY(autoirq_listhandler) + int_entry autoirq_list,VEC_SPUR + lsrl #2,%d0 + int_callnodelist SYMBOL_NAME(ret_from_interrupt) + +ENTRY(cleanup_from_interrupt) + int_cleanup +SYMBOL_NAME_LABEL(ret_from_interrupt) + int_return +#endif + +#if defined(CONFIG_APOLLO) +ENTRY(appolloirq_handler) + int_entry userirq_list, 160, 160+VEC_SPUR + lsrl #2,%d0 + int_callnode SYMBOL_NAME(apollo_ret_from_irq) + +ENTRY(appollo_ret_from_irq) + int_cleanup +#warning add something + int_return +#endif /* Handler for uninitialized and spurious interrupts */ -SYMBOL_NAME_LABEL(bad_interrupt) +ENTRY(bad_interrupt) addql #1,SYMBOL_NAME(num_spurious) rte ENTRY(sys_fork) - SAVE_SWITCH_STACK - pea %sp@(SWITCH_STACK_SIZE) + changeto_switch_stack + pea %sp@(SW_SIZEOF) jbsr SYMBOL_NAME(m68k_fork) addql #4,%sp - RESTORE_SWITCH_STACK + changeto_sys_stack rts ENTRY(sys_clone) - SAVE_SWITCH_STACK - pea %sp@(SWITCH_STACK_SIZE) + changeto_switch_stack + pea %sp@(SW_SIZEOF) jbsr SYMBOL_NAME(m68k_clone) addql #4,%sp - RESTORE_SWITCH_STACK + changeto_sys_stack rts ENTRY(sys_vfork) - SAVE_SWITCH_STACK - pea %sp@(SWITCH_STACK_SIZE) + changeto_switch_stack + pea %sp@(SW_SIZEOF) jbsr SYMBOL_NAME(m68k_vfork) addql #4,%sp - RESTORE_SWITCH_STACK + changeto_sys_stack rts ENTRY(sys_sigsuspend) - SAVE_SWITCH_STACK - pea %sp@(SWITCH_STACK_SIZE) + changeto_switch_stack + pea %sp@(SW_SIZEOF) jbsr SYMBOL_NAME(do_sigsuspend) addql #4,%sp - RESTORE_SWITCH_STACK + changeto_sys_stack rts ENTRY(sys_rt_sigsuspend) - SAVE_SWITCH_STACK - pea %sp@(SWITCH_STACK_SIZE) + changeto_switch_stack + pea %sp@(SW_SIZEOF) jbsr SYMBOL_NAME(do_rt_sigsuspend) addql #4,%sp - RESTORE_SWITCH_STACK + changeto_sys_stack rts ENTRY(sys_sigreturn) - SAVE_SWITCH_STACK + changeto_switch_stack jbsr SYMBOL_NAME(do_sigreturn) - RESTORE_SWITCH_STACK + changeto_sys_stack nodrop=1 rts ENTRY(sys_rt_sigreturn) - SAVE_SWITCH_STACK + changeto_switch_stack jbsr SYMBOL_NAME(do_rt_sigreturn) - RESTORE_SWITCH_STACK + changeto_sys_stack nodrop=1 rts SYMBOL_NAME_LABEL(resume) @@ -319,7 +447,7 @@ movel %d0,%a0@(TASK_THREAD+THREAD_USP) /* save non-scratch registers on stack */ - SAVE_SWITCH_STACK + save_switch_stack /* save current kernel stack pointer */ movel %sp,%a0@(TASK_THREAD+THREAD_KSP) @@ -390,7 +518,7 @@ movel %a1@(TASK_THREAD+THREAD_KSP),%sp /* restore non-scratch registers */ - RESTORE_SWITCH_STACK + restore_switch_stack /* restore user stack pointer */ movel %a1@(TASK_THREAD+THREAD_USP),%a0 diff -Nur -X /opt/home/roman/src/m68k_nodiff linux-2.3.14/arch/m68k/kernel/head.S linux-rtl/arch/m68k/kernel/head.S --- linux-2.3.14/arch/m68k/kernel/head.S Fri Aug 20 20:46:57 1999 +++ linux-rtl/arch/m68k/kernel/head.S Sat Aug 28 12:03:29 1999 @@ -259,6 +259,7 @@ #include #include #include +#include #include #include "m68k_defs.h" @@ -386,6 +387,12 @@ #endif #endif +/* The __INITDATA stuff is a no-op when ftrace or kgdb are turned on */ +#ifndef __INITDATA +#define __INITDATA .data +#define __FINIT .previous +#endif + /* Several macros to make the writing of subroutines easier: * - func_start marks the beginning of the routine which setups the frame * register and saves the registers, it also defines another macro @@ -503,18 +510,10 @@ .macro puts string #if defined(CONSOLE) || defined(SERIAL_DEBUG) -/* The __INITDATA stuff is a no-op when ftrace or kgdb are turned on */ -#if defined(CONFIG_FTRACE) || defined(CONFIG_KGDB) - bra 1f -#endif __INITDATA .Lstr\@: .string "\string" __FINIT -#if defined(CONFIG_FTRACE) || defined(CONFIG_KGDB) - .align 2 -1: -#endif pea %pc@(.Lstr\@) func_call puts addql #4,%sp @@ -1352,8 +1351,8 @@ /* * Setup initial stack pointer */ - lea SYMBOL_NAME(init_task_union),%a2 - lea 0x2000(%a2),%sp + lea SYMBOL_NAME(init_task_union),%curptr + lea 0x2000(%curptr),%sp /* jump to the kernel start */ putc '\n' diff -Nur -X /opt/home/roman/src/m68k_nodiff linux-2.3.14/arch/m68k/kernel/ints.c linux-rtl/arch/m68k/kernel/ints.c --- linux-2.3.14/arch/m68k/kernel/ints.c Fri Aug 20 20:46:58 1999 +++ linux-rtl/arch/m68k/kernel/ints.c Sun Aug 29 20:14:33 1999 @@ -23,11 +23,17 @@ * If you want to replace a default handler you should know what * you're doing, since it might handle different other irq sources * which must be served /Roman Zippel + * 01/08/99: new interrupt managemant, that handles user vector interrupts as + * well, sys_request_irq takes now the vector number from traps.h as + * argument, process_int() is gone, every machine has to provide its + * own interrupt entry and insert it into the vector table, examples + * are in entry.S. /Roman Zippel */ #include #include #include +#include #include #include #include @@ -43,23 +49,29 @@ #include #endif -/* table for system interrupt handlers */ -static irq_handler_t irq_list[SYS_IRQS]; - -static const char *default_names[SYS_IRQS] = { - "spurious int", "int1 handler", "int2 handler", "int3 handler", - "int4 handler", "int5 handler", "int6 handler", "int7 handler" -}; - /* The number of spurious interrupts */ volatile unsigned int num_spurious; -#define NUM_IRQ_NODES 100 -static irq_node_t nodes[NUM_IRQ_NODES]; - -unsigned int local_irq_count[NR_CPUS]; +/* static irq nodes used during bootup */ +#define NUM_IRQ_NODES 16 +static irq_node_t boot_nodes[NUM_IRQ_NODES]; + +/* table for auto vector interrupt handlers */ +irq_node_t *autoirq_list[AUTO_IRQ_NR] = { NULL }; +irq_node_t *autoirq_slowlist[AUTO_IRQ_NR] = { NULL }; + +#if USER_IRQ_NR +/* table for user vector interrupt handlers */ +irq_node_t *userirq_list[USER_IRQ_NR] = { NULL }; +irq_node_t *userirq_slowlist[USER_IRQ_NR] = { NULL }; +#endif -unsigned int local_bh_count[NR_CPUS]; +unsigned int local_irq_count[NR_CPUS] = { 0 }; +unsigned int local_bh_count[NR_CPUS] = { 0 }; +unsigned int local_slowirq_count[NR_CPUS] = { 0 }; +volatile int slowirq_enable = 0; +volatile int slowirq_request = 0; +volatile int slowirq_busycnt = 1; static void dummy_enable_irq(unsigned int irq); static void dummy_disable_irq(unsigned int irq); @@ -67,6 +79,7 @@ void (*handler) (int, void *, struct pt_regs *), unsigned long flags, const char *devname, void *dev_id); static void dummy_free_irq(unsigned int irq, void *dev_id); +static void dummy_do_slowirq(void); void (*enable_irq) (unsigned int) = dummy_enable_irq; void (*disable_irq) (unsigned int) = dummy_disable_irq; @@ -74,7 +87,9 @@ int (*mach_request_irq) (unsigned int, void (*)(int, void *, struct pt_regs *), unsigned long, const char *, void *) = dummy_request_irq; void (*mach_free_irq) (unsigned int, void *) = dummy_free_irq; - +#ifdef CONFIG_RT_INTERRUPT +void (*mach_do_slowirq)(void) = dummy_do_slowirq; +#endif /* * void init_IRQ(void) * @@ -90,31 +105,104 @@ { int i; - for (i = 0; i < SYS_IRQS; i++) { - if (mach_default_handler) - irq_list[i].handler = (*mach_default_handler)[i]; - irq_list[i].flags = 0; - irq_list[i].dev_id = NULL; - irq_list[i].devname = default_names[i]; - } + for (i = 0; i < AUTO_IRQ_NR; i++) + autoirq_list[i] = NULL; + +#if USER_IRQ_NR + for (i = 0; i < USER_IRQ_NR; i++) + userirq_list[i] = NULL; +#endif for (i = 0; i < NUM_IRQ_NODES; i++) - nodes[i].handler = NULL; + boot_nodes[i].handler = NULL; - mach_init_IRQ (); + mach_init_IRQ(); } irq_node_t *new_irq_node(void) { irq_node_t *node; - short i; + int i; - for (node = nodes, i = NUM_IRQ_NODES-1; i >= 0; node++, i--) + for (node = boot_nodes, i = 0; i < NUM_IRQ_NODES; node++, i--) if (!node->handler) - return node; + break; + + if (!node) + node = kmalloc(sizeof(irq_node_t), GFP_KERNEL); + + if (node) { + node->handler = NULL; + node->flags = 0; + } + + return node; +} + +void free_irq_node(irq_node_t *node) +{ + if (node >= &boot_nodes[0] || node < &boot_nodes[NUM_IRQ_NODES]) + node->handler = NULL; + else + kfree(node); +} - printk ("new_irq_node: out of nodes\n"); - return NULL; +static irq_node_t **get_irqlist(unsigned int irq, unsigned long flags) +{ + irq_node_t **list = NULL; + + if (irq > VEC_SPUR && irq <= VEC_INT7) { + list = &autoirq_slowlist[irq - VEC_SPUR]; + if (flags & IRQ_FLG_FASTQUEUE) + list = &autoirq_list[irq - VEC_SPUR]; + } + +#if USER_IRQ_NR + if (irq >= VEC_USER && irq <= VEC_USER + USER_IRQ_NR) { + list = &userirq_slowlist[irq - VEC_USER]; + if (flags & IRQ_FLG_FASTQUEUE) + list = &userirq_list[irq - VEC_USER]; + } +#endif + + return list; +} + +static irq_node_t **find_irqnode(unsigned int irq, void *dev_id) +{ + irq_node_t **list = NULL; + irq_node_t **slowlist = NULL; + + if (irq > VEC_SPUR && irq <= VEC_INT7) { + list = &autoirq_list[irq - VEC_SPUR]; + slowlist = &autoirq_slowlist[irq - VEC_SPUR]; + } + +#if USER_IRQ_NR + if (irq >= VEC_USER && irq <= VEC_USER + USER_IRQ_NR) { + list = &userirq_list[irq - VEC_USER]; + slowlist = &userirq_slowlist[irq - VEC_USER]; + } +#endif + + /* First scan fast list and continue with slow list */ + while (list) { + if (!*list) { + list = slowlist; + slowlist = NULL; + continue; + } + + if (!*list) + return NULL; + + if ((*list)->dev_id == dev_id) + break; + + list = &(*list)->next; + } + + return list; } /* @@ -138,49 +226,83 @@ void (*handler)(int, void *, struct pt_regs *), unsigned long flags, const char *devname, void *dev_id) { - if (irq < IRQ1 || irq > IRQ7) { - printk("%s: Incorrect IRQ %d from %s\n", - __FUNCTION__, irq, devname); - return -ENXIO; - } + irq_node_t **list; + irq_node_t *node; -#if 0 - if (!(irq_list[irq].flags & IRQ_FLG_STD)) { - if (irq_list[irq].flags & IRQ_FLG_LOCK) { - printk("%s: IRQ %d from %s is not replaceable\n", - __FUNCTION__, irq, irq_list[irq].devname); + list = find_irqnode(irq, dev_id); + if (list) { + if (!(flags & IRQ_FLG_REPLACE)) { + printk("%s: %s can't replace IRQ %x from %s\n", + __FUNCTION__, devname, irq, (*list)->devname); return -EBUSY; } - if (!(flags & IRQ_FLG_REPLACE)) { - printk("%s: %s can't replace IRQ %d from %s\n", - __FUNCTION__, devname, irq, irq_list[irq].devname); + if ((*list)->flags & IRQ_FLG_LOCK) { + printk("%s: IRQ %x from %s is not replaceable\n", + __FUNCTION__, irq, (*list)->devname); + return -EBUSY; + } + + node = *list; + *list = node->next; + + list = get_irqlist(irq, flags); + } else { + list = get_irqlist(irq, flags); + if (!list) { + printk("%s: Incorrect IRQ %x from %s\n", + __FUNCTION__, irq, devname); + return -ENXIO; + } + + if (*list && !(flags & IRQ_FLG_LIST)) { + printk("%s: IRQ %x is busy (%s)\n", __FUNCTION__, + irq, (*list)->devname); return -EBUSY; } + + node = new_irq_node(); + if (!node) + return -ENOMEM; } -#endif - irq_list[irq].handler = handler; - irq_list[irq].flags = flags; - irq_list[irq].dev_id = dev_id; - irq_list[irq].devname = devname; + node->handler = handler; + node->flags = flags; + node->dev_id = dev_id; + node->devname = devname; + + if (node->flags & IRQ_FLG_SLOW) { + while (*list) + list = &(*list)->next; + } else if (node->flags & IRQ_FLG_FAST) { + node->flags &= ~IRQ_FLG_SLOW; + while (*list && (*list)->flags & IRQ_FLG_FAST) + list = &(*list)->next; + } else { + while (*list && !((*list)->flags & IRQ_FLG_SLOW)) + list = &(*list)->next; + } + + node->next = *list; + *list = node; + return 0; } void sys_free_irq(unsigned int irq, void *dev_id) { - if (irq < IRQ1 || irq > IRQ7) { - printk("%s: Incorrect IRQ %d\n", __FUNCTION__, irq); + irq_node_t **list; + irq_node_t *node; + + list = find_irqnode(irq, dev_id); + if (!list) { + printk("%s: No handler with id 0x%p found for IRQ %x\n", + __FUNCTION__, dev_id, irq); return; } - if (irq_list[irq].dev_id != dev_id) - printk("%s: Removing probably wrong IRQ %d from %s\n", - __FUNCTION__, irq, irq_list[irq].devname); - - irq_list[irq].handler = (*mach_default_handler)[irq]; - irq_list[irq].flags = 0; - irq_list[irq].dev_id = NULL; - irq_list[irq].devname = default_names[irq]; + node = *list; + *list = node->next; + free_irq_node(node); } /* @@ -229,35 +351,88 @@ printk("calling uninitialized disable_irq()\n"); } -asmlinkage void process_int(unsigned long vec, struct pt_regs *fp) +#ifdef CONFIG_RT_INTERRUPT +static void dummy_do_slowirq(void) { - if (vec >= VEC_INT1 && vec <= VEC_INT7 && !MACH_IS_BVME6000) { - vec -= VEC_SPUR; - kstat.irqs[0][vec]++; - irq_list[vec].handler(vec, irq_list[vec].dev_id, fp); - } else { - if (mach_process_int) - mach_process_int(vec, fp); - else - panic("Can't process interrupt vector %ld\n", vec); - return; - } + /* just a dummy */ } +#endif int get_irq_list(char *buf) { - int i, len = 0; + irq_node_t **list; + irq_node_t **slowlist; + int i, len; + + len = sprintf(buf, "auto %2x: %10u spurious int\n", + 0, num_spurious); /* autovector interrupts */ - if (mach_default_handler) { - for (i = 0; i < SYS_IRQS; i++) { - len += sprintf(buf+len, "auto %2d: %10u ", i, - i ? kstat.irqs[0][i] : num_spurious); - len += sprintf(buf+len, " "); - len += sprintf(buf+len, "%s\n", irq_list[i].devname); + for (i = 1; i < AUTO_IRQ_NR; i++) { + list = &autoirq_list[i]; + slowlist = &autoirq_slowlist[i]; + if (!*list && !*slowlist) + continue; + len += sprintf(buf+len, "auto %2d: %10u ", + i, kstat.irqs[0][i]); + if (!*list) { + list = slowlist; + slowlist = NULL; + } + while (1) { + len += sprintf(buf+len, "%c%c%c %s\n", + (*list)->flags & IRQ_FLG_REALTIME ? 'R' : ' ', + (*list)->flags & IRQ_FLG_LOCK ? 'L' : ' ', + (*list)->flags & IRQ_FLG_FAST ? 'F' : + ((*list)->flags & IRQ_FLG_SLOW ? 'S' : ' '), + (*list)->devname); + list = &(*list)->next; + if (!*list) { + if (!(list = slowlist)) + break; + slowlist = NULL; + } + if (!*list) + break; + len += sprintf(buf+len, " "); + } + } + +#if USER_IRQ_NR + /* uservector interrupts */ + for (i = 0; i < USER_IRQ_NR; i++) { + list = &userirq_list[i]; + slowlist = &userirq_slowlist[i]; + if (!*list && !*slowlist) + continue; + len += sprintf(buf+len, "user %2d: %10u ", + i, kstat.irqs[0][AUTO_IRQ_NR+i]); + if (!*list) { + list = slowlist; + slowlist = NULL; + } + while (1) { + len += sprintf(buf+len, "%c%c%c %s\n", + (*list)->flags & IRQ_FLG_REALTIME ? 'R' : ' ', + (*list)->flags & IRQ_FLG_LOCK ? 'L' : ' ', + (*list)->flags & IRQ_FLG_FAST ? 'F' : + ((*list)->flags & IRQ_FLG_SLOW ? 'S' : ' '), + (*list)->devname); + list = &(*list)->next; + if (!*list) { + if (!(list = slowlist)) + break; + slowlist = NULL; + } + if (!*list) + break; + len += sprintf(buf+len, " "); } } +#endif + + if (mach_get_irq_list) + len += mach_get_irq_list(buf+len); - len += mach_get_irq_list(buf+len); return len; } diff -Nur -X /opt/home/roman/src/m68k_nodiff linux-2.3.14/arch/m68k/kernel/m68k_defs.c linux-rtl/arch/m68k/kernel/m68k_defs.c --- linux-2.3.14/arch/m68k/kernel/m68k_defs.c Tue Aug 10 20:14:37 1999 +++ linux-rtl/arch/m68k/kernel/m68k_defs.c Sun Aug 29 02:00:48 1999 @@ -43,19 +43,23 @@ /* offsets into the pt_regs */ DEFINE(PT_D0, offsetof(struct pt_regs, d0)); - DEFINE(PT_ORIG_D0, offsetof(struct pt_regs, orig_d0)); DEFINE(PT_D1, offsetof(struct pt_regs, d1)); - DEFINE(PT_D2, offsetof(struct pt_regs, d2)); - DEFINE(PT_D3, offsetof(struct pt_regs, d3)); - DEFINE(PT_D4, offsetof(struct pt_regs, d4)); - DEFINE(PT_D5, offsetof(struct pt_regs, d5)); DEFINE(PT_A0, offsetof(struct pt_regs, a0)); DEFINE(PT_A1, offsetof(struct pt_regs, a1)); DEFINE(PT_A2, offsetof(struct pt_regs, a2)); + DEFINE(PT_SYSCALL, offsetof(struct pt_regs, syscall)); DEFINE(PT_PC, offsetof(struct pt_regs, pc)); DEFINE(PT_SR, offsetof(struct pt_regs, sr)); /* bitfields are a bit difficult */ DEFINE(PT_VECTOR, offsetof(struct pt_regs, pc) + 4); + + /* size of switchstack and syscall stack */ + DEFINE(SW_SIZEOF, sizeof(struct switch_stack)); +#ifdef CONFIG_SYS_STACK + DEFINE(SC_SIZEOF, sizeof(struct syscall_stack)); +#else + DEFINE(SC_SIZEOF, 0); +#endif /* offsets into the irq_handler struct */ DEFINE(IRQ_HANDLER, offsetof(struct irq_node, handler)); diff -Nur -X /opt/home/roman/src/m68k_nodiff linux-2.3.14/arch/m68k/kernel/process.c linux-rtl/arch/m68k/kernel/process.c --- linux-2.3.14/arch/m68k/kernel/process.c Fri Aug 20 20:47:00 1999 +++ linux-rtl/arch/m68k/kernel/process.c Sun Aug 29 01:51:53 1999 @@ -108,14 +108,12 @@ printk("\n"); printk("Format %02x Vector: %04x PC: %08lx Status: %04x\n", regs->format, regs->vector, regs->pc, regs->sr); - printk("ORIG_D0: %08lx D0: %08lx A2: %08lx A1: %08lx\n", - regs->orig_d0, regs->d0, regs->a2, regs->a1); - printk("A0: %08lx D5: %08lx D4: %08lx\n", - regs->a0, regs->d5, regs->d4); - printk("D3: %08lx D2: %08lx D1: %08lx\n", - regs->d3, regs->d2, regs->d1); + printk("A0: %08lx A1: %08lx A2: %08lx SYS: %08lx\n", + regs->a0, regs->a1, regs->a2, regs->syscall); + printk("D0: %08lx D1: %08lx", regs->d0, regs->d1); if (!(regs->sr & PS_S)) - printk("USP: %08lx\n", rdusp()); + printk(" USP: %08lx", rdusp()); + printk("\n"); } /* @@ -191,7 +189,7 @@ /* syscall2 puts clone_flags in d1 and usp in d2 */ clone_flags = regs->d1; - newsp = regs->d2; + newsp = SW_PTR(regs)->d2; if (!newsp) newsp = rdusp(); return do_fork(clone_flags, newsp, regs); @@ -298,10 +296,17 @@ dump->u_ar0 = (struct user_regs_struct *)((int)&dump->regs - (int)dump); sw = ((struct switch_stack *)regs) - 1; dump->regs.d1 = regs->d1; +#ifdef CONFIG_SYS_STACK + dump->regs.d2 = sw->d2; + dump->regs.d3 = sw->d3; + dump->regs.d4 = sw->d4; + dump->regs.d5 = sw->d5; +#else dump->regs.d2 = regs->d2; dump->regs.d3 = regs->d3; dump->regs.d4 = regs->d4; dump->regs.d5 = regs->d5; +#endif dump->regs.d6 = sw->d6; dump->regs.d7 = sw->d7; dump->regs.a0 = regs->a0; @@ -312,7 +317,7 @@ dump->regs.a5 = sw->a5; dump->regs.a6 = sw->a6; dump->regs.d0 = regs->d0; - dump->regs.orig_d0 = regs->orig_d0; + dump->regs.orig_d0 = regs->syscall; dump->regs.stkadj = regs->stkadj; dump->regs.sr = regs->sr; dump->regs.pc = regs->pc; @@ -328,7 +333,11 @@ { int error; char * filename; - struct pt_regs *regs = (struct pt_regs *) &name; +#ifdef CONFIG_SYS_STACK + struct pt_regs *regs = (struct pt_regs *)(((struct syscall_stack *)&name)+1); +#else + struct pt_regs *regs = (struct pt_regs *)&name; +#endif lock_kernel(); filename = getname(name); diff -Nur -X /opt/home/roman/src/m68k_nodiff linux-2.3.14/arch/m68k/kernel/ptrace.c linux-rtl/arch/m68k/kernel/ptrace.c --- linux-2.3.14/arch/m68k/kernel/ptrace.c Fri Aug 20 20:47:01 1999 +++ linux-rtl/arch/m68k/kernel/ptrace.c Sun Aug 29 01:55:20 1999 @@ -46,11 +46,16 @@ saved. Notice that usp has no stack-slot and needs to be treated specially (see get_reg/put_reg below). */ static int regoff[] = { +#ifdef CONFIG_SYS_STACK + PT_REG(d1), SW_REG(d2), SW_REG(d3), SW_REG(d4), + SW_REG(d5), SW_REG(d6), SW_REG(d7), PT_REG(a0), +#else PT_REG(d1), PT_REG(d2), PT_REG(d3), PT_REG(d4), PT_REG(d5), SW_REG(d6), SW_REG(d7), PT_REG(a0), +#endif PT_REG(a1), PT_REG(a2), SW_REG(a3), SW_REG(a4), SW_REG(a5), SW_REG(a6), PT_REG(d0), -1, - PT_REG(orig_d0), PT_REG(sr), PT_REG(pc), + PT_REG(syscall), PT_REG(sr), PT_REG(pc), }; /* diff -Nur -X /opt/home/roman/src/m68k_nodiff linux-2.3.14/arch/m68k/kernel/signal.c linux-rtl/arch/m68k/kernel/signal.c --- linux-2.3.14/arch/m68k/kernel/signal.c Fri Aug 20 20:47:02 1999 +++ linux-rtl/arch/m68k/kernel/signal.c Sun Aug 29 01:53:58 1999 @@ -74,7 +74,7 @@ */ asmlinkage int do_sigsuspend(struct pt_regs *regs) { - old_sigset_t mask = regs->d3; + old_sigset_t mask = SW_PTR(regs)->d3; sigset_t saveset; mask &= _BLOCKABLE; @@ -95,7 +95,7 @@ do_rt_sigsuspend(struct pt_regs *regs) { sigset_t *unewset = (sigset_t *)regs->d1; - size_t sigsetsize = (size_t)regs->d2; + size_t sigsetsize = (size_t)SW_PTR(regs)->d2; sigset_t saveset, newset; /* XXX: Don't preclude handling different sized sigset_t's. */ @@ -334,7 +334,7 @@ regs->a1 = context.sc_a1; regs->sr = (regs->sr & 0xff00) | (context.sc_sr & 0xff); regs->pc = context.sc_pc; - regs->orig_d0 = -1; /* disable syscall checks */ + regs->syscall = -1; /* disable syscall checks */ wrusp(context.sc_usp); formatvec = context.sc_formatvec; regs->format = formatvec >> 12; @@ -415,10 +415,17 @@ /* restore passed registers */ err |= __get_user(regs->d0, &gregs[0]); err |= __get_user(regs->d1, &gregs[1]); +#ifdef CONFIG_SYS_STACK + err |= __get_user(sw->d2, &gregs[2]); + err |= __get_user(sw->d3, &gregs[3]); + err |= __get_user(sw->d4, &gregs[4]); + err |= __get_user(sw->d5, &gregs[5]); +#else err |= __get_user(regs->d2, &gregs[2]); err |= __get_user(regs->d3, &gregs[3]); err |= __get_user(regs->d4, &gregs[4]); err |= __get_user(regs->d5, &gregs[5]); +#endif err |= __get_user(sw->d6, &gregs[6]); err |= __get_user(sw->d7, &gregs[7]); err |= __get_user(regs->a0, &gregs[8]); @@ -433,7 +440,7 @@ err |= __get_user(regs->pc, &gregs[16]); err |= __get_user(temp, &gregs[17]); regs->sr = (regs->sr & 0xff00) | (temp & 0xff); - regs->orig_d0 = -1; /* disable syscall checks */ + regs->syscall = -1; /* disable syscall checks */ err |= __get_user(temp, &uc->uc_formatvec); regs->format = temp >> 12; regs->vector = temp & 0xfff; @@ -669,10 +676,17 @@ err |= __put_user(MCONTEXT_VERSION, &uc->uc_mcontext.version); err |= __put_user(regs->d0, &gregs[0]); err |= __put_user(regs->d1, &gregs[1]); +#ifdef CONFIG_SYS_STACK + err |= __put_user(sw->d2, &gregs[2]); + err |= __put_user(sw->d3, &gregs[3]); + err |= __put_user(sw->d4, &gregs[4]); + err |= __put_user(sw->d5, &gregs[5]); +#else err |= __put_user(regs->d2, &gregs[2]); err |= __put_user(regs->d3, &gregs[3]); err |= __put_user(regs->d4, &gregs[4]); err |= __put_user(regs->d5, &gregs[5]); +#endif err |= __put_user(sw->d6, &gregs[6]); err |= __put_user(sw->d7, &gregs[7]); err |= __put_user(regs->a0, &gregs[8]); @@ -947,7 +961,7 @@ /* fallthrough */ case -ERESTARTNOINTR: do_restart: - regs->d0 = regs->orig_d0; + regs->d0 = regs->syscall; regs->pc -= 2; break; } @@ -961,7 +975,7 @@ sigset_t *oldset, struct pt_regs *regs) { /* are we from a system call? */ - if (regs->orig_d0 >= 0) + if (regs->syscall >= 0) /* If so, check system call restarting.. */ handle_restart(regs, ka, 1); @@ -1013,7 +1027,7 @@ regs->sr &= ~PS_T; /* Did we come from a system call? */ - if (regs->orig_d0 >= 0) { + if (regs->syscall >= 0) { /* Restart the system call the same way as if the process were not traced. */ struct k_sigaction *ka = @@ -1112,7 +1126,7 @@ } /* Did we come from a system call? */ - if (regs->orig_d0 >= 0) + if (regs->syscall >= 0) /* Restart the system call - no handlers present */ handle_restart(regs, NULL, 0); diff -Nur -X /opt/home/roman/src/m68k_nodiff linux-2.3.14/arch/m68k/kernel/traps.c linux-rtl/arch/m68k/kernel/traps.c --- linux-2.3.14/arch/m68k/kernel/traps.c Fri Aug 20 20:47:03 1999 +++ linux-rtl/arch/m68k/kernel/traps.c Thu Aug 26 21:48:18 1999 @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include @@ -53,19 +54,14 @@ 0, 0, buserr, trap, trap, trap, trap, trap, trap, trap, trap, trap, trap, trap, trap, trap, trap, trap, trap, trap, trap, trap, trap, trap, - inthandler, inthandler, inthandler, inthandler, - inthandler, inthandler, inthandler, inthandler, + bad_interrupt, bad_interrupt, bad_interrupt, bad_interrupt, + bad_interrupt, bad_interrupt, bad_interrupt, bad_interrupt, /* TRAP #0-15 */ system_call, trap, trap, trap, trap, trap, trap, trap, trap, trap, trap, trap, trap, trap, trap, trap, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, }; -/* nmi handler for the Amiga */ -asm(".text\n" - __ALIGN_STR "\n" - SYMBOL_NAME_STR(nmihandler) ": rte"); - void __init base_trap_init(void) { /* setup the exception vector table */ @@ -132,17 +128,12 @@ vectors[i] = trap; for (i = 64; i < 256; i++) - vectors[i] = inthandler; + vectors[i] = bad_interrupt; #ifdef CONFIG_M68KFPU_EMU if (FPU_IS_EMU) vectors[VEC_LINE11] = fpu_emu; #endif - - /* if running on an amiga, make the NMI interrupt do nothing */ - if (MACH_IS_AMIGA) { - vectors[VEC_INT7] = nmihandler; - } } @@ -893,10 +884,8 @@ printk("%s: %08x\n",str,nr); printk("PC: [<%08lx>]\nSR: %04x SP: %p a2: %08lx\n", fp->pc, fp->sr, fp, fp->a2); - printk("d0: %08lx d1: %08lx d2: %08lx d3: %08lx\n", - fp->d0, fp->d1, fp->d2, fp->d3); - printk("d4: %08lx d5: %08lx a0: %08lx a1: %08lx\n", - fp->d4, fp->d5, fp->a0, fp->a1); + printk("d0: %08lx d1: %08lx a0: %08lx a1: %08lx\n", + fp->d0, fp->d1, fp->a0, fp->a1); printk("Process %s (pid: %d, stackpage=%08lx)\n", current->comm, current->pid, PAGE_SIZE+(unsigned long)current); diff -Nur -X /opt/home/roman/src/m68k_nodiff linux-2.3.14/arch/m68k/math-emu/fp_entry.S linux-rtl/arch/m68k/math-emu/fp_entry.S --- linux-2.3.14/arch/m68k/math-emu/fp_entry.S Fri Aug 20 20:47:14 1999 +++ linux-rtl/arch/m68k/math-emu/fp_entry.S Wed Aug 25 20:02:40 1999 @@ -47,8 +47,8 @@ .text SYMBOL_NAME_LABEL(fpu_emu) - SAVE_ALL_INT - GET_CURRENT(%d0) + save_all_int + get_current #if defined(CPU_M68020_OR_M68030) && defined(CPU_M68040_OR_M68060) tst.l SYMBOL_NAME(m68k_is040or060) diff -Nur -X /opt/home/roman/src/m68k_nodiff linux-2.3.14/drivers/video/amifb.c linux-rtl/drivers/video/amifb.c --- linux-2.3.14/drivers/video/amifb.c Sun Aug 29 20:24:13 1999 +++ linux-rtl/drivers/video/amifb.c Sun Aug 29 20:27:15 1999 @@ -599,8 +599,8 @@ #define arraysize(x) (sizeof(x)/sizeof(*(x))) -#define VBlankOn() custom.intena = IF_SETCLR|IF_COPER -#define VBlankOff() custom.intena = IF_COPER +#define VBlankOn() custom.intena = IF_SETCLR|IF_COPPER +#define VBlankOff() custom.intena = IF_COPPER /* @@ -1785,13 +1785,10 @@ ami_init_copper(); - if (request_irq(IRQ_AMIGA_AUTO_3, amifb_interrupt, 0, + if (request_irq(IRQ_AMIGA_COPPER, amifb_interrupt, + IRQ_FLG_REALTIME|IRQ_FLG_LOCK, "fb vertb handler", NULL)) panic("Couldn't add vblank interrupt\n"); - ami_intena_vals[IRQ_AMIGA_VERTB] = IF_COPER; - ami_intena_vals[IRQ_AMIGA_COPPER] = 0; - custom.intena = IF_VERTB; - custom.intena = IF_SETCLR | IF_COPER; amifb_set_var(&var, -1, &fb_info); @@ -1876,57 +1873,41 @@ static void amifb_interrupt(int irq, void *dev_id, struct pt_regs *fp) { - u_short ints = custom.intreqr & custom.intenar; - static struct irq_server server = {0, 0}; unsigned long flags; - if (ints & IF_BLIT) { - custom.intreq = IF_BLIT; - amiga_do_irq(IRQ_AMIGA_BLIT, fp); - } - - if (ints & IF_COPER) { - custom.intreq = IF_COPER; - if (do_vmode_pan || do_vmode_full) - ami_update_display(); - - if (do_vmode_full) - ami_init_display(); - - if (do_vmode_pan) { - flash_cursor(); - ami_rebuild_copper(); - do_cursor = do_vmode_pan = 0; - } else if (do_cursor) { - flash_cursor(); - ami_set_sprite(); - do_cursor = 0; - } else { - if (flash_cursor()) - ami_set_sprite(); - } + if (do_vmode_pan || do_vmode_full) + ami_update_display(); - save_flags(flags); - cli(); - if (get_vbpos() < down2(currentpar.diwstrt_v - 6)) - custom.copjmp2 = 0; - restore_flags(flags); + if (do_vmode_full) + ami_init_display(); - if (do_blank) { - ami_do_blank(); - do_blank = 0; - } + if (do_vmode_pan) { + flash_cursor(); + ami_rebuild_copper(); + do_cursor = do_vmode_pan = 0; + } else if (do_cursor) { + flash_cursor(); + ami_set_sprite(); + do_cursor = 0; + } else { + if (flash_cursor()) + ami_set_sprite(); + } - if (do_vmode_full) { - ami_reinit_copper(); - do_vmode_full = 0; - } - amiga_do_irq_list(IRQ_AMIGA_VERTB, fp, &server); + r_save_flags(flags); + r_cli(); + if (get_vbpos() < down2(currentpar.diwstrt_v - 6)) + custom.copjmp2 = 0; + r_restore_flags(flags); + + if (do_blank) { + ami_do_blank(); + do_blank = 0; } - if (ints & IF_VERTB) { - printk("%s: Warning: IF_VERTB was enabled\n", __FUNCTION__); - custom.intena = IF_VERTB; + if (do_vmode_full) { + ami_reinit_copper(); + do_vmode_full = 0; } } @@ -3182,7 +3163,7 @@ (cop++)->l = CMOVE2(loww(p), sprpt[i]); } - (cop++)->l = CMOVE(IF_SETCLR | IF_COPER, intreq); + (cop++)->l = CMOVE(IF_SETCLR | IF_COPPER, intreq); copdisplay.wait = cop; (cop++)->l = CEND; (cop++)->l = CMOVE(0, copjmp2); diff -Nur -X /opt/home/roman/src/m68k_nodiff linux-2.3.14/include/asm-i386/rt.h linux-rtl/include/asm-i386/rt.h --- linux-2.3.14/include/asm-i386/rt.h Thu Jan 1 01:00:00 1970 +++ linux-rtl/include/asm-i386/rt.h Wed Aug 4 21:19:50 1999 @@ -0,0 +1,151 @@ +#ifndef _ASM_I386_ATOMIC_H +#define _ASM_I386_ATOMIC_H + +#ifdef __SMP__ +#else +#define __LOCK +#endif + +#define __has_bit_instr + +#if 0 + +#define rt_lockdefine( lock ) unsigned long lock +#define rt_define unsigned long __rt_flags +#define rt_enter( lock ) asm volatile ("cli": : :"memory") +#define rt_leave( lock ) asm volatile ("sti": : :"memory") + +#else + +#define __has_rt_instr + +#define __rt_init( ptr, old ) ({ old = *(ptr); }) + +#define __rt_reserve( ptr, old ) + +#define __rt_update( ptr, old, new ) ({ \ + unsigned char res; \ + asm volatile (__LOCK "cmpxchg %3,%1; sete %0" \ + : "=q" (res), "=m" (*(ptr)), "=&a" (old) \ + : "r" (new), "1" (*(ptr)), "2" (old)); \ + res; \ +}) + +#define rt_do_exchange( lock, ptr, old, new ) ({ \ + old = *(ptr); \ + asm volatile ("1:" \ + : "=&a" (old), "=m" (*(ptr)) \ + : "0" (old), "1" (*(ptr))); \ + asm volatile (__LOCK "cmpxchg %2,%0; jne 1b" \ + : "=m" (*(ptr)), "=&a" (old) \ + : "r" (new), "0" (*(ptr)), "1" (old)); \ +}) + +#define rt_inserthead( lock, ptr, old, new ) ({ \ + typeof(*(ptr)) __val = *(ptr); \ + asm volatile ("1:" \ + : "=&r" (__val), "=m" (*(ptr)) \ + : "0" (__val), "1" (*(ptr))); \ + old = __val; \ + asm volatile (__LOCK "cmpxchg %2,%0; jne 1b" \ + : "=m" (*(ptr)), "=&a" (__val) \ + : "r" (new), "0" (*(ptr)), "1" (__val)); \ +}) + +#endif + +/* Note: no "lock" prefix even on SMP: xchg always implies lock anyway */ + +#define rt_do_exchange_const( lock, ptr, old, new ) ({ \ + asm volatile ("xchg.l %1,%0" \ + : "=m" (*(ptr)), "=r" (old) \ + : "0" (*(ptr)), "1" (new)); \ +}) + +#define rt_inc( lock, ptr ) ({ \ + asm volatile (__LOCK "incl %0" \ + : "=m" (*(ptr)) : "0" (*(ptr))); \ +}) + +#define rt_dec( lock, ptr ) ({ \ + asm volatile (__LOCK "decl %0" \ + : "=m" (*(ptr)) : "0" (*(ptr))); \ +}) + +#define rt_dec_test( lock, ptr ) ({ \ + unsigned char __res; \ + \ + asm volatile (__LOCK "decl %0; sete %1" \ + : "=m" (*(ptr)), "=qm" (__res) \ + : "1" (*(ptr))); \ + __res != 0; \ +}) + +#define rt_add( lock, ptr, val ) ({ \ + asm volatile (__LOCK "addl %1,%0" \ + : "=m" (*(ptr)) : "ir" (val), "0" (*(ptr))); \ +}) + +#define rt_sub( lock, ptr, val ) ({ \ + asm volatile (__LOCK "subl %1,%0" \ + : "=m" (*(ptr)) : "ir" (val), "0" (*(ptr))); \ +}) + +#define rt_do_setmask( lock, ptr, mask ) ({ \ + asm volatile (__LOCK "orl %1,%0" \ + : "=m" (*(ptr)) : "ir" (val), "0" (*(ptr))); \ +}) + +#define rt_do_clrmask( lock, ptr, mask ) ({ \ + asm volatile (__LOCK "andl %1,%0" \ + : "=m" (*(ptr)) : "ir" (~(val)), "0" (*(ptr))); \ +}) + +#define rt_do_chgmask( lock, ptr, mask ) ({ \ + asm volatile (__LOCK "xorl %1,%0" \ + : "=m" (*(ptr)) : "ir" (~(val)), "0" (*(ptr))); \ +}) + +#define rt_do_setbit( lock, ptr, bit ) ({ \ + asm volatile (__LOCK "btsl %1,%0" \ + : "=m" (*(ptr)) : "Ir" (bit), "0" (*(ptr))); \ +}) + +#define rt_do_clrbit( lock, ptr, bit ) ({ \ + asm volatile (__LOCK "btrl %1,%0" \ + : "=m" (*(ptr)) : "Ir" (bit), "0" (*(ptr))); \ +}) + +#define rt_do_chgbit( lock, ptr, bit ) ({ \ + asm volatile (__LOCK "btcl %1,%0" \ + : "=m" (*(ptr)) : "Ir" (bit), "0" (*(ptr))); \ +}) + +#define rt_do_test_setbit( lock, ptr, bit ) ({ \ + int __res; \ + \ + asm volatile (__LOCK "btsl %2,%1; tsbbl %0,%0" \ + : "=r" (__res), "=m" (*(ptr)) \ + : "Ir" (bit), "1" (*(ptr))); \ + __res; \ +}) + +#define rt_do_test_clrbit( lock, ptr, bit ) ({ \ + int __res; \ + \ + asm volatile (__LOCK "btrl %2,%1; tsbbl %0,%0" \ + : "=r" (__res),"=m" (*(ptr)) \ + : "Ir" (bit), "1" (*(ptr))); \ + __res; \ +}) + +#define rt_do_test_chgbit( lock, ptr, bit ) ({ \ + int __res; \ + \ + asm volatile (__LOCK "btcl %2,%1; tsbbl %0,%0" \ + : "=r" (__res),"=m" (*(ptr)) \ + : "Ir" (bit), "1" (*(ptr))); \ + __res; \ +}) + +#endif /* _ASM_I386_ATOMIC_H */ diff -Nur -X /opt/home/roman/src/m68k_nodiff linux-2.3.14/include/asm-m68k/amigaints.h linux-rtl/include/asm-m68k/amigaints.h --- linux-2.3.14/include/asm-m68k/amigaints.h Tue May 18 16:01:03 1999 +++ linux-rtl/include/asm-m68k/amigaints.h Sun Aug 29 20:33:49 1999 @@ -10,8 +10,12 @@ ** Created 10/2/92 by Greg Harp */ -#ifndef _ASMm68k_AMIGAINTS_H_ -#define _ASMm68k_AMIGAINTS_H_ +#ifndef _M68K_AMIGAINTS_H_ +#define _M68K_AMIGAINTS_H_ + +#include +#include +#include /* ** Amiga Interrupt sources. @@ -23,35 +27,21 @@ #define CIA_IRQS (5) #define AMI_IRQS (32) /* AUTO_IRQS+AMI_STD_IRQS+2*CIA_IRQS */ -/* vertical blanking interrupt */ -#define IRQ_AMIGA_VERTB 0 - -/* copper interrupt */ -#define IRQ_AMIGA_COPPER 1 - -/* Audio interrupts */ -#define IRQ_AMIGA_AUD0 2 -#define IRQ_AMIGA_AUD1 3 -#define IRQ_AMIGA_AUD2 4 -#define IRQ_AMIGA_AUD3 5 - -/* Blitter done interrupt */ -#define IRQ_AMIGA_BLIT 6 - -/* floppy disk interrupts */ -#define IRQ_AMIGA_DSKSYN 7 -#define IRQ_AMIGA_DSKBLK 8 - -/* builtin serial port interrupts */ -#define IRQ_AMIGA_RBF 9 -#define IRQ_AMIGA_TBE 10 - -/* software interrupts */ -#define IRQ_AMIGA_SOFT 11 - -/* interrupts from external hardware */ -#define IRQ_AMIGA_PORTS 12 -#define IRQ_AMIGA_EXTER 13 +/* Amiga standard interrupt sources */ +#define IRQ_AMIGA_TBE 0 +#define IRQ_AMIGA_DSKBLK 1 +#define IRQ_AMIGA_SOFT 2 +#define IRQ_AMIGA_PORTS 3 +#define IRQ_AMIGA_COPPER 4 +#define IRQ_AMIGA_VERTB 5 +#define IRQ_AMIGA_BLIT 6 +#define IRQ_AMIGA_AUD0 7 +#define IRQ_AMIGA_AUD1 8 +#define IRQ_AMIGA_AUD2 9 +#define IRQ_AMIGA_AUD3 10 +#define IRQ_AMIGA_RBF 11 +#define IRQ_AMIGA_DSKSYN 12 +#define IRQ_AMIGA_EXTER 13 /* CIA interrupt sources */ #define IRQ_AMIGA_CIAA 14 @@ -78,8 +68,6 @@ #define IRQ_AMIGA_AUTO_6 30 #define IRQ_AMIGA_AUTO_7 31 -#define IRQ_FLOPPY IRQ_AMIGA_DSKBLK - /* INTREQR masks */ #define IRQ1_MASK 0x0007 /* INTREQR mask for IRQ 1 */ #define IRQ2_MASK 0x0008 /* INTREQR mask for IRQ 2 */ @@ -100,21 +88,54 @@ #define IF_AUD0 0x0080 /* audio channel 0 done interrupt */ #define IF_BLIT 0x0040 /* blitter done interrupt */ #define IF_VERTB 0x0020 /* vertical blanking interrupt */ -#define IF_COPER 0x0010 /* copper interrupt */ +#define IF_COPPER 0x0010 /* copper interrupt */ #define IF_PORTS 0x0008 /* external level 2 and CIA A interrupt */ #define IF_SOFT 0x0004 /* software initiated interrupt */ #define IF_DSKBLK 0x0002 /* diskblock DMA finished */ #define IF_TBE 0x0001 /* serial transmit buffer empty interrupt */ -struct irq_server { - unsigned short count, reentrance; -}; +extern unsigned short amiga_slowintmask, amiga_fastintmask; -extern void amiga_do_irq(int irq, struct pt_regs *fp); -extern void amiga_do_irq_list(int irq, struct pt_regs *fp, struct irq_server *server); +asmlinkage void amiga_inthandler(void); +asmlinkage void amiga_nmi_handler(void); +asmlinkage void amiga_do_slowirq_request(void); + +extern inline void amiga_do_irq(int irq, struct pt_regs *fp) +{ + kstat.irqs[0][AUTO_IRQ_NR + irq]++; + userirq_list[irq]->handler(irq, userirq_list[irq]->dev_id, fp); +} + +extern inline void amiga_do_irq_list(int irq, struct pt_regs *fp) +{ + irq_node_t *node; + + kstat.irqs[0][AUTO_IRQ_NR + irq]++; + /* serve handlers */ + for (node = userirq_list[irq]; node; node = node->next) + node->handler(irq, node->dev_id, fp); +} + +extern inline void amiga_do_slowirq(int irq, struct pt_regs *fp) +{ + kstat.irqs[0][AUTO_IRQ_NR + irq]++; + userirq_slowlist[irq]->handler(irq, userirq_slowlist[irq]->dev_id, fp); +} + +extern inline void amiga_do_slowirq_list(int irq, struct pt_regs *fp) +{ + irq_node_t *node; + + /* serve handlers */ + for (node = userirq_slowlist[irq]; node; node = node->next) + node->handler(irq, node->dev_id, fp); +} -/* CIA interrupt control register bits */ +/* + * CIA specific definitions + */ +/* CIA interrupt control register bits */ #define CIA_ICR_TA 0x01 #define CIA_ICR_TB 0x02 #define CIA_ICR_ALRM 0x04 @@ -132,4 +153,4 @@ extern unsigned char cia_set_irq(struct ciabase *base, unsigned char mask); extern unsigned char cia_able_irq(struct ciabase *base, unsigned char mask); -#endif /* asm-m68k/amigaints.h */ +#endif /* _M68K_AMIGAINTS_H_ */ diff -Nur -X /opt/home/roman/src/m68k_nodiff linux-2.3.14/include/asm-m68k/elf.h linux-rtl/include/asm-m68k/elf.h --- linux-2.3.14/include/asm-m68k/elf.h Tue May 18 16:01:03 1999 +++ linux-rtl/include/asm-m68k/elf.h Sun Aug 29 16:00:50 1999 @@ -42,31 +42,57 @@ #define ELF_ET_DYN_BASE 0xD0000000UL +#ifdef CONFIG_SYS_STACK #define ELF_CORE_COPY_REGS(pr_reg, regs) \ - /* Bleech. */ \ - pr_reg[0] = regs->d1; \ - pr_reg[1] = regs->d2; \ - pr_reg[2] = regs->d3; \ - pr_reg[3] = regs->d4; \ - pr_reg[4] = regs->d5; \ - pr_reg[7] = regs->a0; \ - pr_reg[8] = regs->a1; \ - pr_reg[9] = regs->a2; \ - pr_reg[14] = regs->d0; \ - pr_reg[15] = rdusp(); \ - pr_reg[16] = regs->orig_d0; \ - pr_reg[17] = regs->sr; \ - pr_reg[18] = regs->pc; \ - pr_reg[19] = (regs->format << 12) | regs->vector; \ - { \ - struct switch_stack *sw = ((struct switch_stack *)regs) - 1; \ - pr_reg[5] = sw->d6; \ - pr_reg[6] = sw->d7; \ - pr_reg[10] = sw->a3; \ - pr_reg[11] = sw->a4; \ - pr_reg[12] = sw->a5; \ - pr_reg[13] = sw->a6; \ - } +{ \ + struct switch_stack *sw = ((struct switch_stack *)regs) - 1; \ + pr_reg[PT_D0] = regs->d0; \ + pr_reg[PT_D1] = regs->d1; \ + pr_reg[PT_D2] = sw->d2; \ + pr_reg[PT_D3] = sw->d3; \ + pr_reg[PT_D4] = sw->d4; \ + pr_reg[PT_D5] = sw->d5; \ + pr_reg[PT_D6] = sw->d6; \ + pr_reg[PT_D7] = sw->d7; \ + pr_reg[PT_A0] = regs->a0; \ + pr_reg[PT_A1] = regs->a1; \ + pr_reg[PT_A2] = regs->a2; \ + pr_reg[PT_A3] = sw->a3; \ + pr_reg[PT_A4] = sw->a4; \ + pr_reg[PT_A5] = sw->a5; \ + pr_reg[PT_A6] = sw->a6; \ + pr_reg[PT_USP] = rdusp(); \ + pr_reg[PT_ORIG_D0] = regs->syscall; \ + pr_reg[PT_SR] = regs->sr; \ + pr_reg[PT_PC] = regs->pc; \ + pr_reg[PT_VEC] = (regs->format << 12) | regs->vector; \ +} +#else +#define ELF_CORE_COPY_REGS(pr_reg, regs) \ +{ \ + struct switch_stack *sw = ((struct switch_stack *)regs) - 1; \ + pr_reg[PT_D0] = regs->d0; \ + pr_reg[PT_D1] = regs->d1; \ + pr_reg[PT_D2] = regs->d2; \ + pr_reg[PT_D3] = regs->d3; \ + pr_reg[PT_D4] = regs->d4; \ + pr_reg[PT_D5] = regs->d5; \ + pr_reg[PT_D6] = sw->d6; \ + pr_reg[PT_D7] = sw->d7; \ + pr_reg[PT_A0] = regs->a0; \ + pr_reg[PT_A1] = regs->a1; \ + pr_reg[PT_A2] = regs->a2; \ + pr_reg[PT_A3] = sw->a3; \ + pr_reg[PT_A4] = sw->a4; \ + pr_reg[PT_A5] = sw->a5; \ + pr_reg[PT_A6] = sw->a6; \ + pr_reg[PT_USP] = rdusp(); \ + pr_reg[PT_ORIG_D0] = regs->syscall; \ + pr_reg[PT_SR] = regs->sr; \ + pr_reg[PT_PC] = regs->pc; \ + pr_reg[PT_VEC] = (regs->format << 12) | regs->vector; \ +} +#endif /* This yields a mask that user programs can use to figure out what instruction set this cpu supports. */ diff -Nur -X /opt/home/roman/src/m68k_nodiff linux-2.3.14/include/asm-m68k/entry.h linux-rtl/include/asm-m68k/entry.h --- linux-2.3.14/include/asm-m68k/entry.h Tue May 18 16:01:03 1999 +++ linux-rtl/include/asm-m68k/entry.h Sun Aug 29 16:02:41 1999 @@ -59,13 +59,10 @@ PF_DTRACE_OFF = 1 PF_DTRACE_BIT = 5 -#define SAVE_ALL_INT save_all_int -#define SAVE_ALL_SYS save_all_sys -#define RESTORE_ALL restore_all /* * This defines the normal kernel pt-regs layout. * - * regs a3-a6 and d6-d7 are preserved by C code + * regs a3-a6 and d2-d7 are preserved by C code * the kernel doesn't mess with usp unless it needs to */ #ifndef CONFIG_KGDB @@ -75,62 +72,108 @@ */ .macro save_all_int clrl %sp@- | stk_adj - pea -1:w | orig d0 + pea -1:w | syscall +#ifdef CONFIG_SYS_STACK + moveml %d0/%d1/%a0/%a1/%curptr,%sp@- +#else movel %d0,%sp@- | d0 moveml %d1-%d5/%a0-%a1/%curptr,%sp@- +#endif .endm .macro save_all_sys clrl %sp@- | stk_adj - movel %d0,%sp@- | orig d0 + movel %d0,%sp@- | syscall +#ifdef CONFIG_SYS_STACK + moveml %d0/%d1/%a0/%a1/%curptr,%sp@- +#else movel %d0,%sp@- | d0 moveml %d1-%d5/%a0-%a1/%curptr,%sp@- +#endif .endm + #else /* Need to save the "missing" registers for kgdb... */ .macro save_all_int clrl %sp@- | stk_adj - pea -1:w | orig d0 - movel %d0,%sp@- | d0 - moveml %d1-%d5/%a0-%a1/%curptr,%sp@- + moveml %d0/%d1/%a0/%a1/%curptr,%sp@- moveml %d6-%d7,kgdb_registers+GDBOFFA_D6 moveml %a3-%a6,kgdb_registers+GDBOFFA_A3 .endm -.macro save_all_sys - clrl %sp@- | stk_adj - movel %d0,%sp@- | orig d0 - movel %d0,%sp@- | d0 - moveml %d1-%d5/%a0-%a1/%curptr,%sp@- - moveml %d6-%d7,kgdb_registers+GDBOFFA_D6 - moveml %a3-%a6,kgdb_registers+GDBOFFA_A3 -.endm #endif -.macro restore_all - moveml %sp@+,%a0-%a1/%curptr/%d1-%d5 - movel %sp@+,%d0 - addql #4,%sp | orig d0 - addl %sp@+,%sp | stk adj - rte +.macro save_sys_stack +#ifdef CONFIG_SYS_STACK + moveml %d1-%d5,%sp@- +#endif .endm -#define SWITCH_STACK_SIZE (6*4+4) /* includes return address */ +.macro rebuild_sys_stack +#ifdef CONFIG_SYS_STACK + movel %sp@(PT_D1),%d1 + moveml %d1-%d5,%sp@- +#endif +.endm -#define SAVE_SWITCH_STACK save_switch_stack -#define RESTORE_SWITCH_STACK restore_switch_stack -#define GET_CURRENT(tmp) get_current tmp +.macro drop_sys_stack +#ifdef CONFIG_SYS_STACK + lea %sp@(20),%sp +#endif +.endm .macro save_switch_stack - moveml %a3-%a6/%d6-%d7,%sp@- +#ifdef CONFIG_SYS_STACK + moveml %d2-%d7/%a3-%a6,%sp@- +#else + moveml %d6-%d7/%a3-%a6,%sp@- +#endif .endm .macro restore_switch_stack - moveml %sp@+,%a3-%a6/%d6-%d7 +#ifdef CONFIG_SYS_STACK + moveml %sp@+,%d2-%d7/%a3-%a6 +#else + moveml %sp@+,%d6-%d7/%a3-%a6 +#endif +.endm + +.macro changeto_switch_stack +#ifdef CONFIG_SYS_STACK + movel %sp@+,%d1 + drop_sys_stack + movel %d1,%sp@- +#endif + save_switch_stack +.endm + +.macro changeto_sys_stack nodrop=0 + .if \nodrop + restore_switch_stack + .else + lea %sp@(SW_SIZEOF-4),%sp + .endif +#ifdef CONFIG_SYS_STACK + movel %sp@+,%d1 + lea %sp@(-SC_SIZEOF),%sp + movel %d1,%sp@- +#endif +.endm + +.macro restore_all +#ifdef CONFIG_SYS_STACK + moveml %sp@+,%d0/%d1/%a0/%a1/%curptr +#else + moveml %sp@+,%d1-%d5/%a0-%a1/%curptr + movel %sp@+,%d0 +#endif + addql #4,%sp | syscall + addl %sp@+,%sp | stk adj + rte .endm -.macro get_current reg=%d0 +.macro get_current reg=%d1 movel %sp,\reg andw #-8192,\reg movel \reg,%curptr diff -Nur -X /opt/home/roman/src/m68k_nodiff linux-2.3.14/include/asm-m68k/hardirq.h linux-rtl/include/asm-m68k/hardirq.h --- linux-2.3.14/include/asm-m68k/hardirq.h Tue Aug 10 20:24:42 1999 +++ linux-rtl/include/asm-m68k/hardirq.h Wed Aug 25 21:19:53 1999 @@ -7,7 +7,11 @@ #define in_interrupt() (local_irq_count[smp_processor_id()] + local_bh_count[smp_processor_id()] != 0) -#define hardirq_trylock(cpu) (local_irq_count[cpu] == 0) +/* the bottomhalf is already protected by softirq_trylock() and + * the interrupt exit guarantees already that do_bottom_half() + * is only called from the last interrupt + */ +#define hardirq_trylock(cpu) (1) #define hardirq_endlock(cpu) do { } while (0) #define hardirq_enter(cpu) (local_irq_count[cpu]++) diff -Nur -X /opt/home/roman/src/m68k_nodiff linux-2.3.14/include/asm-m68k/irq.h linux-rtl/include/asm-m68k/irq.h --- linux-2.3.14/include/asm-m68k/irq.h Fri Aug 20 20:56:31 1999 +++ linux-rtl/include/asm-m68k/irq.h Sun Aug 29 20:17:41 1999 @@ -4,46 +4,32 @@ #include /* - * # of m68k interrupts + * # of auto and user vector m68k interrupts. This number is used for kstat, so + * the first 8 are always the autovector interrupts, the rest is machine + * specific. It can be either the # of used vector interrupts or the # of other + * interrupt sources. The highest value wins if compiled for several machines. */ -#define SYS_IRQS 8 +#define AUTO_IRQ_NR 8 -/* - * This should be the same as the max(NUM_X_SOURCES) for all the - * different m68k hosts compiled into the kernel. - * Currently the Atari has 72 and the Amiga 24, but if both are - * supported in the kernel it is better to make room for 72. - */ #if defined(CONFIG_ATARI) -#define NR_IRQS (72+SYS_IRQS) +#define USER_IRQ_NR 72 +#elif defined(CONFIG_AMIGA) +#define USER_IRQ_NR 24 +#elif defined(CONFIG_APOLLO) +#define USER_IRQ_NR 16 #else -#define NR_IRQS (24+SYS_IRQS) +#define USER_IRQ_NR 0 #endif /* - * Interrupt source definitions - * General interrupt sources are the level 1-7. - * Adding an interrupt service routine for one of these sources - * results in the addition of that routine to a chain of routines. - * Each one is called in succession. Each individual interrupt - * service routine should determine if the device associated with - * that routine requires service. - */ - -#define IRQ1 (1) /* level 1 interrupt */ -#define IRQ2 (2) /* level 2 interrupt */ -#define IRQ3 (3) /* level 3 interrupt */ -#define IRQ4 (4) /* level 4 interrupt */ -#define IRQ5 (5) /* level 5 interrupt */ -#define IRQ6 (6) /* level 6 interrupt */ -#define IRQ7 (7) /* level 7 interrupt (non-maskable) */ - -/* - * "Generic" interrupt sources + * This should be the same as the max(NUM_X_SOURCES) for all the + * different m68k hosts compiled into the kernel. */ -#define IRQ_SCHED_TIMER (8) /* interrupt source for scheduling timer */ +#define NR_IRQS (AUTO_IRQ_NR+USER_IRQ_NR) + +#ifndef __ASSEMBLY__ static __inline__ int irq_cannonicalize(int irq) { @@ -83,12 +69,20 @@ * mechanism like all other architectures - SA_INTERRUPT and SA_SHIRQ * are your friends. */ -#ifndef CONFIG_AMIGA #define IRQ_FLG_LOCK (0x0001) /* handler is not replaceable */ #define IRQ_FLG_REPLACE (0x0002) /* replace existing handler */ #define IRQ_FLG_FAST (0x0004) #define IRQ_FLG_SLOW (0x0008) -#define IRQ_FLG_STD (0x8000) /* internally used */ +#define IRQ_FLG_LIST (0x0010) +#define IRQ_FLG_REALTIME (0x0020) + +/* only used by the interrupt management! depending on the config option + * IRQ_FLG_FASTQUEUE decides about on which queue a handler is put on. + */ +#ifdef CONFIG_RT_INTERRUPT +#define IRQ_FLG_FASTQUEUE IRQ_FLG_REALTIME +#else +#define IRQ_FLG_FASTQUEUE IRQ_FLG_FAST #endif /* @@ -103,22 +97,34 @@ struct irq_node *next; } irq_node_t; -/* - * This structure has only 4 elements for speed reasons - */ -typedef struct irq_handler { - void (*handler)(int, void *, struct pt_regs *); - unsigned long flags; - void *dev_id; - const char *devname; -} irq_handler_t; +extern int sys_request_irq(unsigned int, void (*)(int, void *, struct pt_regs *), + unsigned long, const char *, void *); +extern int sys_request_listirq(unsigned int, void (*)(int, void *, struct pt_regs *), + unsigned long, const char *, void *); +extern void sys_free_irq(unsigned int, void *); + +extern irq_node_t *autoirq_list[]; +extern irq_node_t *userirq_list[]; +extern irq_node_t *autoirq_slowlist[]; +extern irq_node_t *userirq_slowlist[]; +extern volatile int slowirq_busycnt; /* count of spurious interrupts */ extern volatile unsigned int num_spurious; +extern volatile int slowirq_request; + +/* standard interrupt handlers */ +asmlinkage void autoirq_handler(void); +asmlinkage void autoirq_listhandler(void); +asmlinkage void userirq_handler(void); +asmlinkage void bad_interrupt(void); /* * This function returns a new irq_node_t */ extern irq_node_t *new_irq_node(void); +extern void free_irq_node(irq_node_t *); + +#endif /* __ASSEMBLY__ */ #endif /* _M68K_IRQ_H_ */ diff -Nur -X /opt/home/roman/src/m68k_nodiff linux-2.3.14/include/asm-m68k/m68kserial.h linux-rtl/include/asm-m68k/m68kserial.h --- linux-2.3.14/include/asm-m68k/m68kserial.h Fri Aug 20 21:14:08 1999 +++ linux-rtl/include/asm-m68k/m68kserial.h Sun Aug 29 20:30:34 1999 @@ -337,7 +337,7 @@ int ch, int err ) { struct tty_struct *tty = info->tty; - + if (tty->flip.count >= TTY_FLIPBUF_SIZE) return; tty->flip.count++; diff -Nur -X /opt/home/roman/src/m68k_nodiff linux-2.3.14/include/asm-m68k/machdep.h linux-rtl/include/asm-m68k/machdep.h --- linux-2.3.14/include/asm-m68k/machdep.h Tue May 18 16:01:03 1999 +++ linux-rtl/include/asm-m68k/machdep.h Wed Aug 25 21:29:44 1999 @@ -15,14 +15,12 @@ extern void (*mach_kbd_leds) (unsigned int); /* machine dependent irq functions */ extern void (*mach_init_IRQ) (void); -extern void (*(*mach_default_handler)[]) (int, void *, struct pt_regs *); extern int (*mach_request_irq) (unsigned int irq, void (*handler)(int, void *, struct pt_regs *), unsigned long flags, const char *devname, void *dev_id); extern void (*mach_free_irq) (unsigned int irq, void *dev_id); extern void (*mach_get_model) (char *model); extern int (*mach_get_hardware_list) (char *buffer); extern int (*mach_get_irq_list) (char *buf); -extern void (*mach_process_int) (int irq, struct pt_regs *fp); /* machine dependent timer functions */ extern unsigned long (*mach_gettimeoffset)(void); extern void (*mach_gettod)(int *year, int *mon, int *day, int *hour, diff -Nur -X /opt/home/roman/src/m68k_nodiff linux-2.3.14/include/asm-m68k/ptrace.h linux-rtl/include/asm-m68k/ptrace.h --- linux-2.3.14/include/asm-m68k/ptrace.h Tue May 18 16:01:03 1999 +++ linux-rtl/include/asm-m68k/ptrace.h Sun Aug 29 15:57:06 1999 @@ -1,6 +1,8 @@ #ifndef _M68K_PTRACE_H #define _M68K_PTRACE_H +#include + #define PT_D1 0 #define PT_D2 1 #define PT_D3 2 @@ -20,28 +22,37 @@ #define PT_ORIG_D0 16 #define PT_SR 17 #define PT_PC 18 +#define PT_VEC 19 #ifndef __ASSEMBLY__ /* this struct defines the way the registers are stored on the - stack during a system call. */ + stack during an exception. */ struct pt_regs { - long d1; - long d2; - long d3; - long d4; - long d5; - long a0; - long a1; - long a2; - long d0; - long orig_d0; - long stkadj; - unsigned short sr; - unsigned long pc; - unsigned format : 4; /* frame format specifier */ - unsigned vector : 12; /* vector offset */ +#ifdef CONFIG_SYS_STACK + unsigned long d0; + unsigned long d1; + unsigned long a0; + unsigned long a1; + unsigned long a2; +#else + unsigned long d1; + unsigned long d2; + unsigned long d3; + unsigned long d4; + unsigned long d5; + unsigned long a0; + unsigned long a1; + unsigned long a2; + unsigned long d0; +#endif + unsigned long syscall; + unsigned long stkadj; + unsigned short sr; + unsigned long pc; + unsigned format : 4; /* frame format specifier */ + unsigned vector : 12; /* vector offset */ }; /* @@ -49,6 +60,12 @@ * switcher: it's pushed after the normal "struct pt_regs". */ struct switch_stack { +#ifdef CONFIG_SYS_STACK + unsigned long d2; + unsigned long d3; + unsigned long d4; + unsigned long d5; +#endif unsigned long d6; unsigned long d7; unsigned long a3; @@ -57,6 +74,24 @@ unsigned long a6; unsigned long retpc; }; + +#ifdef CONFIG_SYS_STACK +/* this macro can be used to get access to the switch_stack in front of pt_regs */ +#define SW_PTR(pt_ptr) ((struct switch_stack *)(pt_ptr)-1) + +/* + * This is the stack used during system calls for the arguments + */ +struct syscall_stack { + unsigned long d1; + unsigned long d2; + unsigned long d3; + unsigned long d4; + unsigned long d5; +}; +#else +#define SW_PTR(pt_ptr) (pt_ptr) +#endif /* Arbitrarily choose the same ptrace numbers as used by the Sparc code. */ #define PTRACE_GETREGS 12 diff -Nur -X /opt/home/roman/src/m68k_nodiff linux-2.3.14/include/asm-m68k/rt.h linux-rtl/include/asm-m68k/rt.h --- linux-2.3.14/include/asm-m68k/rt.h Thu Jan 1 01:00:00 1970 +++ linux-rtl/include/asm-m68k/rt.h Sun Aug 29 01:32:35 1999 @@ -0,0 +1,163 @@ +#ifndef _ASM_M68K_ATOMIC_H +#define _ASM_M68K_ATOMIC_H + +#include + +#ifndef CONFIG_RMW_INSNS + +#define __has_bit_instr + +#define rt_lockdeclare(lock) +#define rt_lockdefine(lock) +#define rt_flagsdefine unsigned long __rt_flags +#define rt_enter(lock) \ + asm volatile ("movew %%sr,%0; oriw #0x0700,%%sr" : "=d" (__rt_flags) : :"memory") +#define rt_leave(lock) \ + asm volatile ("movew %0,%%sr": : "d" (__rt_flags) :"memory") + +#else + +#define __has_rt_instr + +#define __rt_init( ptr , data ) ((data) = *(ptr)) + +#define __rt_reserve( ptr, data ) + +#define __rt_update( ptr, data, new ) ({ \ + unsigned char res; \ + \ + asm volatile ( "cas.l %3,%4,%5; seq %0" \ + : "=d" (res), "=&d" (data), "=m" (*(ptr)) \ + : "1" (data), "d" (new), "2" (*(ptr))); \ + res; \ +}) + +#define rt_do_exchange( lock, ptr, old, new ) ({ \ + old = *(ptr); \ + asm volatile ("1:" \ + : "=&d" (old), "=m" (*(ptr)) \ + : "0" (old), "1" (*(ptr))); \ + asm volatile ("cas.l %2,%3,%4; jne 1b" \ + : "=&d" (old), "=m" (*(ptr)) \ + : "0" (old), "d" (new), "1" (*(ptr))); \ +}) + +#define rt_do_exchange_const( lock, ptr, old, new ) ({ \ + asm volatile ("1: cas.l %2,%3,%4; jne 1b" \ + : "=&d" (old), "=m" (*(ptr)) \ + : "0" (*(ptr)), "d" (new), "1" (*(ptr))); \ +}) + +#define rt_inserthead( lock, ptr, old, new ) ({ \ + typeof(*(ptr)) __val = *(ptr); \ + \ + asm volatile ( "1:" \ + : "=&d" (__val), "=m" (*(ptr)) \ + : "0" (__val), "1" (*(ptr))); \ + old = __val; \ + asm volatile ( "cas.l %2,%3,%4; jne 1b" \ + : "=&d" (__val), "=m" (*(ptr)) \ + : "0" (__val), "d" (new), "1" (*(ptr)) ); \ +}) + +#endif + +#define rt_inc( lock, ptr ) ({ \ + asm volatile ("addq.l #1,%0" \ + : "=m" (*(ptr)): "0" (*(ptr))); \ +}) + +#define rt_dec( lock, ptr ) ({ \ + asm volatile ("subq.l #1,%0" \ + : "=m" (*(ptr)): "0" (*(ptr))); \ +}) + +#define rt_dec_test( lock, ptr ) ({ \ + unsigned char res; \ + \ + asm volatile ( "subq.l #1,%1; sne %0" \ + : "=d" (res), "=m" (*(ptr)) : "1" (*(ptr)) ); \ + res != 0; \ +}) + + +#define rt_add( lock, ptr, val ) ({ \ + asm volatile ( "add.l %1,%0": "=m" (*(ptr)) \ + : "d" (val), "0" (*(ptr)) ); \ +}) + +#define rt_sub( lock, ptr, val ) ({ \ + asm volatile ( "sub.l %1,%0": "=m" (*(ptr)) \ + : "d" (val), "0" (*(ptr)) ); \ +}) + +#define rt_do_setmask( lock, ptr, mask ) ({ \ + asm volatile ( "or.l %1,%0": "=m" (*(ptr)) \ + : "d" (mask), "0" (*(ptr)) ); \ +}) + +#define rt_do_clrmask( lock, ptr, mask ) ({ \ + asm volatile ( "and.l %1,%0": "=m" (*(ptr)) \ + : "d" (~(mask)), "0" (*(ptr)) ); \ +}) + +#define rt_do_chgmask( lock, ptr, mask ) ({ \ + asm volatile ( "xor.l %1,%0": "=m" (*(ptr)) \ + : "d" (mask), "0" (*(ptr)) ); \ +}) + +#define rt_do_setbit( lock, ptr, bit ) ({ \ + unsigned char *__ptr; \ + \ + __ptr = (unsigned char *)(ptr) + (3 - (bit >> 3)); \ + asm volatile ( "bset %1,%0": "=m" (*(__ptr)) \ + : "id" (bit & 7), "0" (*(__ptr)) ); \ +}) + +#define rt_do_clrbit( lock, ptr, bit ) ({ \ + unsigned char *__ptr; \ + \ + __ptr = (unsigned char *)(ptr) + (3 - (bit >> 3)); \ + asm volatile ( "bclr %1,%0": "=m" (*(__ptr)) \ + : "id" (bit & 7), "0" (*(__ptr)) ); \ +}) + +#define rt_do_chgbit( lock, ptr, bit ) ({ \ + unsigned char *__ptr; \ + \ + __ptr = (unsigned char *)(ptr) + (3 - (bit >> 3)); \ + asm volatile ( "bchg %1,%0": "=m" (*(__ptr)) \ + : "id" (bit & 7), "0" (*(__ptr)) ); \ +}) + +#define rt_do_test_setbit( lock, ptr, bit ) ({ \ + unsigned char *__ptr, __res; \ + \ + __ptr = (unsigned char *)(ptr) + (3 - (bit >> 3)); \ + asm volatile ( "bset %2,%1; sne %0" \ + : "=r" (__res), "=m" (*(__ptr)) \ + : "id" (bit & 7), "1" (*(__ptr)) ); \ + __res; \ +}) + +#define rt_do_test_clrbit( lock, ptr, bit ) ({ \ + unsigned char *__ptr, __res; \ + \ + __ptr = (unsigned char *)(ptr) + (3 - (bit >> 3)); \ + asm volatile ( "bclr %2,%1; sne %0" \ + : "=r" (__res), "=m" (*(__ptr)) \ + : "id" (bit & 7), "1" (*(__ptr)) ); \ + __res; \ +}) + +#define rt_do_test_chgbit( lock, ptr, bit ) ({ \ + unsigned char *__ptr, __res; \ + \ + __ptr = (unsigned char *)(ptr) + (3 - (bit >> 3)); \ + asm volatile ( "bchg %2,%1; sne %0" \ + : "=r" (__res), "=m" (*(__ptr)) \ + : "id" (bit & 7), "1" (*(__ptr)) ); \ + __res; \ +}) + +#endif /* _ASM_M68K_ATOMIC_H */ diff -Nur -X /opt/home/roman/src/m68k_nodiff linux-2.3.14/include/asm-m68k/system.h linux-rtl/include/asm-m68k/system.h --- linux-2.3.14/include/asm-m68k/system.h Tue Aug 10 20:24:53 1999 +++ linux-rtl/include/asm-m68k/system.h Sun Aug 29 12:36:19 1999 @@ -3,7 +3,9 @@ #include /* get configuration macros */ #include +#include #include +#include #define prepare_to_switch() do { } while(0) @@ -34,6 +36,17 @@ * the mm structures are shared in d2 (to avoid atc flushing). */ asmlinkage void resume(void); +#ifdef CONFIG_SYS_STACK +#define switch_to(prev,next,last) { \ + register void *_prev __asm__ ("a0") = (prev); \ + register void *_next __asm__ ("a1") = (next); \ + register void *_last __asm__ ("d1"); \ + __asm__ __volatile__("jbsr " SYMBOL_NAME_STR(resume) \ + : "=d" (_last) : "a" (_prev), "a" (_next) \ + : "d0", "d1", "a0", "a1"); \ + (last) = _last; \ +} +#else #define switch_to(prev,next,last) { \ register void *_prev __asm__ ("a0") = (prev); \ register void *_next __asm__ ("a1") = (next); \ @@ -43,6 +56,7 @@ : "d0", "d1", "d2", "d3", "d4", "d5", "a0", "a1"); \ (last) = _last; \ } +#endif #define xchg(ptr,x) ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr)))) #define tas(ptr) (xchg((ptr),1)) @@ -51,28 +65,78 @@ #define __xg(x) ((volatile struct __xchg_dummy *)(x)) #if defined(MACH_ATARI_ONLY) && !defined(CONFIG_HADES) -/* block out HSYNC on the atari */ -#define __sti() __asm__ __volatile__ ("andiw #0xfbff,%/sr": : : "memory") +#define r_sti() ({ \ + if (local_irq_count[smp_processor_id()] <= 1) \ + /* block out HSYNC on the atari */ \ + asm volatile ("andiw #0xfbff,%%sr": : : "memory"); \ +}) #else /* portable version */ -#define __sti() __asm__ __volatile__ ("andiw #0xf8ff,%/sr": : : "memory") -#endif /* machine compilation types */ -#define __cli() __asm__ __volatile__ ("oriw #0x0700,%/sr": : : "memory") +#define r_sti() ({ \ + if (local_irq_count[smp_processor_id()] <= 1) \ + asm volatile ("andiw #0xf8ff,%%sr": : : "memory"); \ +}) +#endif /* machine compilation types */ +#define r_cli() asm volatile ("oriw #0x0700,%%sr": : : "memory") + +#define r_save_flags(x) \ + asm volatile ("movew %%sr,%0":"=d" (x) : :"memory") +#define r_restore_flags(x) \ + asm volatile ("movew %0,%%sr": :"d" (x) : "memory") + +#ifdef CONFIG_RT_INTERRUPT +extern volatile int slowirq_enable; +extern volatile int slowirq_busycnt; +extern void (*mach_do_slowirq)(void); + +#define __sti() ({ \ + rt_flagsdefine; \ + slowirq_enable = 1; \ + if (!rt_dec_test(rtirq_lock, &slowirq_busycnt)) \ + mach_do_slowirq(); \ +}) +#define __cli() ({ \ + slowirq_enable = 0; \ +}) +#define __save_flags(x) ({ \ + (x) = slowirq_enable; \ +}) +#define __restore_flags(x) ({ \ + if (x) \ + __sti(); \ + else \ + __cli(); \ +}) + +rt_lockdeclare(rtirq_lock); + +#define set_slowirq_request(mask) ({ \ + rt_flagsdefine; \ + rt_setmask(rtirq_lock, &slowirq_request, (mask)); \ +}) + +#else /* CONFIG_RT_INTERRUPT */ + +#define __sti() r_sti() +#define __cli() r_cli() +#define __save_flags(x) r_save_flags(x) +#define __restore_flags(x) r_restore_flags(x) + +#define set_slowirq_request(mask) \ + asm volatile ("orl %2,%1" : "=m" (slowirq_request) \ + : "0" (slowirq_request), "id" (mask)) + +#endif /* CONFIG_RT_INTERRUPT */ + #define nop() __asm__ __volatile__ ("nop"::) #define mb() __asm__ __volatile__ ("" : : :"memory") #define rmb() __asm__ __volatile__ ("" : : :"memory") #define wmb() __asm__ __volatile__ ("" : : :"memory") -#define __save_flags(x) \ -__asm__ __volatile__("movew %/sr,%0":"=d" (x) : /* no input */ :"memory") - -#define __restore_flags(x) \ -__asm__ __volatile__("movew %0,%/sr": /* no outputs */ :"d" (x) : "memory") - -#define cli() __cli() -#define sti() __sti() -#define save_flags(x) __save_flags(x) -#define restore_flags(x) __restore_flags(x) -#define save_and_cli(flags) do { save_flags(flags); cli(); } while(0) +#define cli() __cli() +#define sti() __sti() +#define save_flags(x) __save_flags(x) +#define restore_flags(x) __restore_flags(x) +#define save_and_cli(flags) ({ save_flags(flags); cli(); }) #ifndef CONFIG_RMW_INSNS static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int size) diff -Nur -X /opt/home/roman/src/m68k_nodiff linux-2.3.14/include/asm-ppc/rt.h linux-rtl/include/asm-ppc/rt.h --- linux-2.3.14/include/asm-ppc/rt.h Thu Jan 1 01:00:00 1970 +++ linux-rtl/include/asm-ppc/rt.h Wed Aug 4 21:19:50 1999 @@ -0,0 +1,42 @@ +#ifndef _ASM_PPC_ATOMIC_H +#define _ASM_PPC_ATOMIC_H + +#define __has_rt_instr + +#ifdef __SMP__ +#define __SYNC "sync; " +#endif + +#define __rt_init( ptr, old ) + +#define __rt_reserve( ptr, old ) ({ \ + asm volatile ( "lwarx %0,0,%1" \ + : "=r" (old) : "m" (*(ptr)) ); \ +}) + +#define __rt_update( ptr, old, new ) ({ \ + unsigned int __res; \ + asm volatile ( __SYNC "stwcx. %2,0,%1; mfcr %0" \ + : "=r" (__res), "=m" (*(ptr)) \ + : "r" (new) : "cc" ); \ + __res & 0x20000000; \ +}) + +#define rt_exchange( ptr, old, new ) ({ \ + asm volatile ( "1: lwarx %0,0,%1" \ + : "=r" (old) : "m" (*(ptr)) ); \ + asm volatile ( __SYNC "stwcx. %1,0,%0; bne- 1b" \ + : "=m" (*(ptr)) : "r" ((new)) : "cc" ); \ +}) + +#define rt_inserthead( ptr, old, new ) ({ \ + typeof(*(ptr)) __val; \ + \ + asm volatile ( "1: lwarx %0,0,%1" \ + : "=r" (__val) : "m" (*(ptr)) ); \ + (old) = __val; \ + asm volatile ( __SYNC "stwcx. %1,0,%0; bne- 1b" \ + : "=m" (*(ptr)) : "r" ((new)) : "cc" ); \ +}) + +#endif /* _ASM_PPC_ATOMIC_H */ diff -Nur -X /opt/home/roman/src/m68k_nodiff linux-2.3.14/include/linux/rt.h linux-rtl/include/linux/rt.h --- linux-2.3.14/include/linux/rt.h Thu Jan 1 01:00:00 1970 +++ linux-rtl/include/linux/rt.h Sun Aug 29 01:32:35 1999 @@ -0,0 +1,426 @@ +/* + * linux/include/linux/atomic.h + * + * Copyright (C) 1998, Roman Zippel + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file COPYING in the main directory of this archive + * for more details. + * + * For a more detailed documentation about this, see .... + */ + +#ifndef _LINUX_ATOMIC_H +#define _LINUX_ATOMIC_H + +#ifdef __KERNEL__ + +#include + +#ifdef __has_rt_instr + +/* atomic instructions are available, so no need for synchronization with an + * atomic lock. + */ + +#define rt_lockdeclare( dummylock ) +#define rt_lockdefine( dummylock ) +#define rt_flagsdefine +#define rt_enter( dummylock ) +#define rt_leave( dummylock ) + +#define __rt_exchange( ptr, old, new ) rt_exchange( dummylock, ptr, old, new ) +#define __rt_inserthead( ptr, old, new ) rt_inserthead( dummylock, ptr, old, new ) + +#define __rt_inc( ptr ) rt_inc( dummylock, ptr ) +#define __rt_dec( ptr ) rt_dec( dummylock, ptr ) +#define __rt_dec_test( ptr ) rt_dec_test( dummylock, ptr ) +#define __rt_add( ptr, val ) rt_add( dummylock, ptr, val ) +#define __rt_sub( ptr, val ) rt_sub( dummylock, ptr, val ) + +#define __rt_setmask( ptr, val ) rt_setmask( dummylock, ptr, val ) +#define __rt_clrmask( ptr, val ) rt_clrmask( dummylock, ptr, val ) +#define __rt_chgmask( ptr, val ) rt_chgmask( dummylock, ptr, val ) +#define __rt_test_setmask( ptr, val ) rt_test_setmask( dummylock, ptr, val ) +#define __rt_test_clrmask( ptr, val ) rt_test_clrmask( dummylock, ptr, val ) +#define __rt_test_chgmask( ptr, val ) rt_test_chgmask( dummylock, ptr, val ) + +#define __rt_setbit( ptr, val ) rt_setbit( dummylock, ptr, val ) +#define __rt_clrbit( ptr, val ) rt_clrbit( dummylock, ptr, val ) +#define __rt_chgbit( ptr, val ) rt_chgbit( dummylock, ptr, val ) +#define __rt_test_setbit( ptr, val ) rt_test_setbit( dummylock, ptr, val ) +#define __rt_test_clrbit( ptr, val ) rt_test_clrbit( dummylock, ptr, val ) +#define __rt_test_chgbit( ptr, val ) rt_test_chgbit( dummylock, ptr, val ) + +#else + +/* synchronization with an atomic lock is needed, that is done by atomic_enter() + * and atomic_leave(), between them we can let the compiler do the work + */ + +#define __rt_init( ptr, old ) ({ (old) = *(ptr); }) +#define __rt_reserve( ptr, old ) +#define __rt_update( ptr, old, new ) ({ *(ptr) = (new); 1; }) + +#define __rt_exchange( ptr, old, new ) \ + ({ (old) = *(ptr); *(ptr) = (new); (void)0; }) +#define __rt_inserthead( ptr, old, new ) \ + ({ (old) = *(ptr); *(ptr) = (new); (void)0; }) +#define __rt_inc( ptr ) ( (void)(*(ptr)++) ) +#define __rt_dec( ptr ) ( (void)(*(ptr)--) ) +#define __rt_dec_test( ptr ) ( --*(ptr) ) +#define __rt_add( ptr, val ) ( (void)(*(ptr) += (val)) ) +#define __rt_sub( ptr, val ) ( (void)(*(ptr) -= (val)) ) +#define __rt_setmask( ptr, mask ) ( (void)(*(ptr) |= (mask)) ) +#define __rt_clrmask( ptr, mask ) ( (void)(*(ptr) &= ~(mask)) ) +#define __rt_chgmask( ptr, mask ) ( (void)(*(ptr) ^= (mask)) ) + +/* for the following macros the C version is ugly, see if there is a more + * efficient version available. + */ + +#ifdef __has_bit_instr + +#define __rt_test_setmask( ptr, mask ) rt_test_setmask( dummylock, ptr, mask ) +#define __rt_test_clrmask( ptr, mask ) rt_test_clrmask( dummylock, ptr, mask ) +#define __rt_test_chgmask( ptr, mask ) rt_test_chgmask( dummylock, ptr, mask ) + +#else + +#define __rt_test_setmask( ptr, mask ) ({ \ + typeof(*(ptr)) __oldval = *(ptr); \ + \ + *(ptr) |= (mask); \ + __oldval & (mask); \ +}) + +#define __rt_test_clrmask( ptr, val ) ({ \ + typeof(*(ptr)) __oldval = *(ptr); \ + \ + *(ptr) &= ~(val); \ + __oldval & (mask); \ +}) + +#define __rt_test_chgmask( ptr, val ) ({ \ + typeof(*(ptr)) __oldval = *(ptr); \ + \ + *(ptr) ^= (mask); \ + __oldval & (mask); \ +}) + +#endif + +#endif + +/* atomically exchange a memory value and return the old value, if is + * constant, a more efficient macro might be available. + */ + +#ifndef rt_do_exchange +#define rt_do_exchange( lock, ptr, old, new ) ({ \ + rt_define; \ + \ + rt_enter( lock ); \ + __rt_init( ptr, old ); \ + do { \ + __rt_reserve( ptr, old ); \ + } while ( !__rt_update(ptr, old, (new)) ); \ + rt_leave( lock ); \ +}) +#endif + +#ifndef rt_do_exchange_const +#define rt_do_exchange_const( lock, ptr, old, new ) rt_do_exchange( lock, ptr, old, new ) +#endif + +#ifndef rt_exchange +#define rt_exchange( lock, ptr, old, new ) ({ \ + if ( __builtin_constant_p(new) ) \ + rt_do_exchange_const( lock, ptr, old, new );\ + else \ + rt_do_exchange( lock, ptr, old, new ); \ +}) +#endif + +#ifndef rt_inserthead +#define rt_inserthead( lock, ptr, old, new ) ({ \ + typeof(*(ptr)) __val; \ + rt_define; \ + \ + rt_enter( lock ); \ + __rt_init( ptr, __val ); \ + do { \ + __rt_reserve( ptr, __val ); \ + old = __val; \ + } while ( !__rt_update(ptr, __val, (new)) ); \ + rt_leave( lock ); \ +}) +#endif + +/* atomically increment the value */ +#ifndef rt_inc +#define rt_inc( lock, ptr ) ({ \ + typeof(*(ptr)) __val; \ + \ + rt_exchange( lock, ptr, __val, __val + 1 ); \ +}) +#endif + +/* atomically decrement the value */ +#ifndef rt_dec +#define rt_dec( lock, ptr ) ({ \ + typeof(*(ptr)) __val; \ + \ + rt_exchange( lock, ptr, __val, __val - 1 ); \ +}) +#endif + +/* atomically decrement the value and test the result */ +#ifndef rt_dec_test +#define rt_dec_test( lock, ptr ) ({ \ + typeof(*(ptr)) __val; \ + \ + rt_exchange( lock, ptr, __val, __val - 1 ); \ + __val != 0; \ +}) +#endif + +/* atomically add a value */ +#ifndef rt_add +#define rt_add( lock, ptr, val ) ({ \ + typeof(*(ptr)) __val; \ + \ + rt_exchange( lock, ptr, __val, __val + (val) ); \ +}) +#endif + +/* atomically subtract a value */ +#ifndef rt_sub +#define rt_sub( lock, ptr, val ) ({ \ + typeof(*(ptr)) __val; \ + \ + rt_exchange( lock, ptr, __val, __val - (val) ); \ +}) +#endif + +#define __getbitnr( mask ) ({ \ + int bit = -1; \ + \ + if ( __builtin_constant_p(mask) ) { \ + switch ( mask ) { \ + case 1 << 0: bit = 0; break; \ + case 1 << 1: bit = 1; break; \ + case 1 << 2: bit = 2; break; \ + case 1 << 3: bit = 3; break; \ + case 1 << 4: bit = 4; break; \ + case 1 << 5: bit = 5; break; \ + case 1 << 6: bit = 6; break; \ + case 1 << 7: bit = 7; break; \ + case 1 << 8: bit = 8; break; \ + case 1 << 9: bit = 9; break; \ + case 1 << 10: bit = 10; break; \ + case 1 << 11: bit = 11; break; \ + case 1 << 12: bit = 12; break; \ + case 1 << 13: bit = 13; break; \ + case 1 << 14: bit = 14; break; \ + case 1 << 15: bit = 15; break; \ + case 1 << 16: bit = 16; break; \ + case 1 << 17: bit = 17; break; \ + case 1 << 18: bit = 18; break; \ + case 1 << 19: bit = 19; break; \ + case 1 << 20: bit = 20; break; \ + case 1 << 21: bit = 21; break; \ + case 1 << 22: bit = 22; break; \ + case 1 << 23: bit = 23; break; \ + case 1 << 24: bit = 24; break; \ + case 1 << 25: bit = 25; break; \ + case 1 << 26: bit = 26; break; \ + case 1 << 27: bit = 27; break; \ + case 1 << 28: bit = 28; break; \ + case 1 << 29: bit = 29; break; \ + case 1 << 30: bit = 30; break; \ + case 1 << 31: bit = 31; break; \ + } \ + } \ + bit; \ +}) + +#define __getmask( bit ) ( 1 << bit ) + +/* atomically set a mask/bit, if the mask has only a single bit set, + * try a bit operation if available + */ + +#ifndef rt_do_setmask +#define rt_do_setmask( lock, ptr, mask ) ({ \ + typeof(*(ptr)) __val; \ + \ + rt_exchange( lock, ptr, __val, __val | (mask) ); \ +}) +#endif + +#ifndef rt_do_setbit +#define rt_do_setbit( lock, ptr, bit ) rt_do_setmask( lock, ptr, __getmask(bit) ); +#endif + +#ifndef rt_setmask +#define rt_setmask( lock, ptr, mask ) ({ \ + int bit = __getbitnr( mask ); \ + \ + if ( bit < 0 ) \ + rt_do_setmask( lock, ptr, mask ); \ + else \ + rt_do_setbit( lock, ptr, bit ); \ +}) +#endif + +#define rt_setbit( lock, ptr, bit ) rt_do_setbit( lock, ptr, bit ) + +/* atomically clear a mask/bit, if the mask has only a single bit set, + * try a bit operation if available + */ + +#ifndef rt_do_clrmask +#define rt_do_clrmask( lock, ptr, mask ) ({ \ + typeof(*(ptr)) __val; \ + \ + rt_exchange( lock, ptr, __val, __val & ~(mask) ); \ +}) +#endif + +#ifndef rt_do_clrbit +#define rt_do_clrbit( lock, ptr, bit ) rt_do_clrmask( lock, ptr, __getmask(bit) ); +#endif + +#ifndef rt_clrmask +#define rt_clrmask( lock, ptr, mask ) ({ \ + int bit = __getbitnr( mask ); \ + \ + if ( bit < 0 ) \ + rt_do_clrmask( lock, ptr, mask ); \ + else \ + rt_do_clrbit( lock, ptr, bit ); \ +}) +#endif + +#define rt_clrbit( lock, ptr, bit ) rt_do_clrbit( lock, ptr, bit ) + +/* atomically change a mask/bit, if the mask has only a single bit set, + * try a bit operation if available + */ + +#ifndef rt_do_chgmask +#define rt_do_chgmask( lock, ptr, mask ) ({ \ + typeof(*(ptr)) __val; \ + \ + rt_exchange( lock, ptr, __val, __val ^ (mask) ); \ +}) +#endif + +#ifndef rt_do_chgbit +#define rt_do_chgbit( lock, ptr, bit ) rt_do_chgmask( lock, ptr, __getmask(bit) ); +#endif + +#ifndef rt_chgmask +#define rt_chgmask( lock, ptr, mask ) ({ \ + int bit = __getbitnr( mask ); \ + \ + if ( bit < 0 ) \ + rt_do_chgmask( lock, ptr, mask ); \ + else \ + rt_do_chgbit( lock, ptr, bit ); \ +}) +#endif + +#define rt_chgbit( lock, ptr, bit ) rt_do_chgbit( lock, ptr, bit ) + +/* atomically set a mask/bit and test it against the old value */ + +#ifndef rt_do_test_setmask +#define rt_do_test_setmask( lock, ptr, mask ) ({ \ + typeof(*(ptr)) __oldval; \ + \ + rt_exchange( lock, ptr, __oldval, __oldval | (mask) );\ + __oldval & (mask); \ +}) +#endif + +#ifndef rt_do_test_setbit +#define rt_do_test_setbit( lock, ptr, bit ) rt_do_test_setmask( lock, ptr, __getmask(bit) ); +#endif + +#ifndef rt_test_setmask +#define rt_test_setmask( lock, ptr, mask ) ({ \ + int res, bit = __getbitnr( mask ); \ + \ + if ( bit < 0 ) \ + res = rt_do_test_setmask( lock, ptr, mask );\ + else \ + res = rt_do_test_setbit( lock, ptr, bit ); \ + res; \ +}) +#endif + +#define rt_test_setbit( lock, ptr, bit ) rt_do_test_setbit( lock, ptr, bit ) + +/* atomically clear a mask/bit and test it against the old value */ + +#ifndef rt_do_test_clrmask +#define rt_do_test_clrmask( lock, ptr, mask ) ({ \ + typeof(*(ptr)) __val; \ + \ + rt_exchange( lock, ptr, __val, __val & ~(mask) ); \ + __val & (mask); \ +}) +#endif + +#ifndef rt_do_test_clrbit +#define rt_do_test_clrbit( lock, ptr, bit ) rt_do_test_clrmask( lock, ptr, __getmask(bit) ); +#endif + +#ifndef rt_test_clrmask +#define rt_test_clrmask( lock, ptr, mask ) ({ \ + int res, bit = __getbitnr( mask ); \ + \ + if ( bit < 0 ) \ + res = rt_do_test_clrmask( lock, ptr, mask );\ + else \ + res = rt_do_test_clrbit( lock, ptr, bit ); \ + res; \ +}) +#endif + +#define rt_test_clrbit( lock, ptr, bit ) rt_do_test_clrbit( lock, ptr, bit ) + +/* atomically change a mask/bit and test it against the old value */ + +#ifndef rt_do_test_chgmask +#define rt_do_test_chgmask( lock, ptr, mask ) ({ \ + typeof(*(ptr)) __val; \ + \ + rt_exchange( lock, ptr, __val, __val ^ (mask) ); \ + __val & (mask); \ +}) +#endif + +#ifndef rt_do_test_chgbit +#define rt_do_test_chgbit( lock, ptr, bit ) rt_do_test_chgmask( lock, ptr, __getmask(bit) ); +#endif + +#ifndef rt_test_chgmask +#define rt_test_chgmask( lock, ptr, mask ) ({ \ + int res, bit = __getbitnr( mask ); \ + \ + if ( bit < 0 ) \ + res = rt_do_test_chgmask( lock, ptr, mask );\ + else \ + res = rt_do_test_chgbit( lock, ptr, bit ); \ + res; \ +}) +#endif + +#define rt_test_chgbit( lock, ptr, bit ) rt_do_test_chgbit( lock, ptr, bit ) + +#endif /* __KERNEL__ */ + +#endif /* _LINUX_ATOMIC_H */ diff -Nur -X /opt/home/roman/src/m68k_nodiff linux-2.3.14/include/linux/tqueue.h linux-rtl/include/linux/tqueue.h --- linux-2.3.14/include/linux/tqueue.h Tue May 18 16:01:05 1999 +++ linux-rtl/include/linux/tqueue.h Sun Aug 29 12:36:19 1999 @@ -13,9 +13,8 @@ #ifndef _LINUX_TQUEUE_H #define _LINUX_TQUEUE_H -#include +#include #include -#include /* * New proposed "bottom half" handlers: @@ -75,7 +74,7 @@ * interrupt. */ -extern spinlock_t tqueue_lock; +rt_lockdeclare(tqueue_lock); /* * queue_task @@ -83,13 +82,12 @@ extern __inline__ void queue_task(struct tq_struct *bh_pointer, task_queue *bh_list) { - if (!test_and_set_bit(0,&bh_pointer->sync)) { - unsigned long flags; - spin_lock_irqsave(&tqueue_lock, flags); - bh_pointer->next = *bh_list; - *bh_list = bh_pointer; - spin_unlock_irqrestore(&tqueue_lock, flags); - } + rt_flagsdefine; + + rt_enter(tqueue_lock); + if (!__rt_test_setbit(&bh_pointer->sync, 0)) + __rt_inserthead(bh_list, bh_pointer->next, bh_pointer); + rt_leave(tqueue_lock); } /* @@ -98,14 +96,11 @@ extern __inline__ void run_task_queue(task_queue *list) { if (*list) { - unsigned long flags; struct tq_struct *p; + rt_flagsdefine; + + rt_exchange(tqueue_lock, list, p, NULL); - spin_lock_irqsave(&tqueue_lock, flags); - p = *list; - *list = NULL; - spin_unlock_irqrestore(&tqueue_lock, flags); - while (p) { void *arg; void (*f) (void *); diff -Nur -X /opt/home/roman/src/m68k_nodiff linux-2.3.14/init/main.c linux-rtl/init/main.c --- linux-2.3.14/init/main.c Fri Aug 20 21:14:08 1999 +++ linux-rtl/init/main.c Wed Aug 25 21:48:04 1999 @@ -499,6 +499,9 @@ } memory_start = kmem_cache_init(memory_start, memory_end); +#ifdef CONFIG_RT_INTERRUPT + r_sti(); +#endif sti(); calibrate_delay(); #ifdef CONFIG_BLK_DEV_INITRD diff -Nur -X /opt/home/roman/src/m68k_nodiff linux-2.3.14/kernel/printk.c linux-rtl/kernel/printk.c --- linux-2.3.14/kernel/printk.c Fri Aug 20 20:58:10 1999 +++ linux-rtl/kernel/printk.c Thu Aug 26 22:59:07 1999 @@ -344,8 +344,9 @@ char buf[16]; signed char msg_level = -1; char *q; + long flags; - spin_lock_irq(&console_lock); + spin_lock_irqsave(&console_lock, flags); /* * See if we want to use this console driver. If we * didn't select a console we take the first one @@ -422,7 +423,7 @@ j = 0; } out: - spin_unlock_irq(&console_lock); + spin_unlock_irqrestore(&console_lock, flags); }