···1414#include <linux/types.h>1515#include <linux/kernel.h>1616#include <linux/errno.h>1717-#include <linux/string.h>1818-#include <linux/sched.h>1919-#include <linux/seq_file.h>2017#include <linux/interrupt.h>2121-#include <linux/hardirq.h>22182323-#include <asm/rtc.h>2419#include <asm/ptrace.h>2520#include <asm/system.h>2621#include <asm/irq.h>···3439 *3540*/36413737-extern int ints_inited;4242+static void q40_irq_handler(unsigned int, struct pt_regs *fp);4343+static void q40_enable_irq(unsigned int);4444+static void q40_disable_irq(unsigned int);38454646+unsigned short q40_ablecount[35];4747+unsigned short q40_state[35];39484040-irqreturn_t q40_irq2_handler (int, void *, struct pt_regs *fp);4949+static int q40_irq_startup(unsigned int irq)5050+{5151+ /* test for ISA ints not implemented by HW */5252+ switch (irq) {5353+ case 1: case 2: case 8: case 9:5454+ case 11: case 12: case 13:5555+ printk("%s: ISA IRQ %d not implemented by HW\n", __FUNCTION__, irq);5656+ return -ENXIO;5757+ }5858+ return 0;5959+}41606161+static void q40_irq_shutdown(unsigned int irq)6262+{6363+}42644343-static irqreturn_t q40_defhand (int irq, void *dev_id, struct pt_regs *fp);4444-4545-4646-#define DEVNAME_SIZE 244747-4848-static struct q40_irq_node {4949- irqreturn_t (*handler)(int, void *, struct pt_regs *);5050- unsigned long flags;5151- void *dev_id;5252- /* struct q40_irq_node *next;*/5353- char devname[DEVNAME_SIZE];5454- unsigned count;5555- unsigned short state;5656-} irq_tab[Q40_IRQ_MAX+1];5757-5858-short unsigned q40_ablecount[Q40_IRQ_MAX+1];6565+static struct irq_controller q40_irq_controller = {6666+ .name = "q40",6767+ .lock = SPIN_LOCK_UNLOCKED,6868+ .startup = q40_irq_startup,6969+ .shutdown = q40_irq_shutdown,7070+ .enable = q40_enable_irq,7171+ .disable = q40_disable_irq,7272+};59736074/*6175 * void q40_init_IRQ (void)···7773 * the q40 IRQ handling routines.7874 */79758080-static int disabled=0;7676+static int disabled;81778282-void q40_init_IRQ (void)7878+void q40_init_IRQ(void)8379{8484- int i;8585-8686- disabled=0;8787- for (i = 0; i <= Q40_IRQ_MAX; i++) {8888- irq_tab[i].handler = q40_defhand;8989- irq_tab[i].flags = 0;9090- irq_tab[i].dev_id = NULL;9191- /* irq_tab[i].next = NULL;*/9292- irq_tab[i].devname[0] = 0;9393- irq_tab[i].count = 0;9494- irq_tab[i].state =0;9595- q40_ablecount[i]=0; /* all enabled */9696- }8080+ m68k_setup_irq_controller(&q40_irq_controller, 1, Q40_IRQ_MAX);97819882 /* setup handler for ISA ints */9999- cpu_request_irq(IRQ_AUTO_2, q40_irq2_handler, 0,100100- "q40 ISA and master chip", NULL);8383+ m68k_setup_auto_interrupt(q40_irq_handler);8484+8585+ m68k_irq_startup(IRQ_AUTO_2);8686+ m68k_irq_startup(IRQ_AUTO_4);1018710288 /* now enable some ints.. */103103- master_outb(1,EXT_ENABLE_REG); /* ISA IRQ 5-15 */8989+ master_outb(1, EXT_ENABLE_REG); /* ISA IRQ 5-15 */1049010591 /* make sure keyboard IRQ is disabled */106106- master_outb(0,KEY_IRQ_ENABLE_REG);9292+ master_outb(0, KEY_IRQ_ENABLE_REG);10793}10894109109-int q40_request_irq(unsigned int irq,110110- irqreturn_t (*handler)(int, void *, struct pt_regs *),111111- unsigned long flags, const char *devname, void *dev_id)112112-{113113- /*printk("q40_request_irq %d, %s\n",irq,devname);*/114114-115115- if (irq > Q40_IRQ_MAX || (irq>15 && irq<32)) {116116- printk("%s: Incorrect IRQ %d from %s\n", __FUNCTION__, irq, devname);117117- return -ENXIO;118118- }119119-120120- /* test for ISA ints not implemented by HW */121121- switch (irq)122122- {123123- case 1: case 2: case 8: case 9:124124- case 12: case 13:125125- printk("%s: ISA IRQ %d from %s not implemented by HW\n", __FUNCTION__, irq, devname);126126- return -ENXIO;127127- case 11:128128- printk("warning IRQ 10 and 11 not distinguishable\n");129129- irq=10;130130- default:131131- ;132132- }133133-134134- if (irq<Q40_IRQ_SAMPLE)135135- {136136- if (irq_tab[irq].dev_id != NULL)137137- {138138- printk("%s: IRQ %d from %s is not replaceable\n",139139- __FUNCTION__, irq, irq_tab[irq].devname);140140- return -EBUSY;141141- }142142- /*printk("IRQ %d set to handler %p\n",irq,handler);*/143143- if (dev_id==NULL)144144- {145145- printk("WARNING: dev_id == NULL in request_irq\n");146146- dev_id=(void*)1;147147- }148148- irq_tab[irq].handler = handler;149149- irq_tab[irq].flags = flags;150150- irq_tab[irq].dev_id = dev_id;151151- strlcpy(irq_tab[irq].devname,devname,sizeof(irq_tab[irq].devname));152152- irq_tab[irq].state = 0;153153- return 0;154154- }155155- else {156156- /* Q40_IRQ_SAMPLE :somewhat special actions required here ..*/157157- cpu_request_irq(4, handler, flags, devname, dev_id);158158- cpu_request_irq(6, handler, flags, devname, dev_id);159159- return 0;160160- }161161-}162162-163163-void q40_free_irq(unsigned int irq, void *dev_id)164164-{165165- if (irq > Q40_IRQ_MAX || (irq>15 && irq<32)) {166166- printk("%s: Incorrect IRQ %d, dev_id %x \n", __FUNCTION__, irq, (unsigned)dev_id);167167- return;168168- }169169-170170- /* test for ISA ints not implemented by HW */171171- switch (irq)172172- {173173- case 1: case 2: case 8: case 9:174174- case 12: case 13:175175- printk("%s: ISA IRQ %d from %x invalid\n", __FUNCTION__, irq, (unsigned)dev_id);176176- return;177177- case 11: irq=10;178178- default:179179- ;180180- }181181-182182- if (irq<Q40_IRQ_SAMPLE)183183- {184184- if (irq_tab[irq].dev_id != dev_id)185185- printk("%s: Removing probably wrong IRQ %d from %s\n",186186- __FUNCTION__, irq, irq_tab[irq].devname);187187-188188- irq_tab[irq].handler = q40_defhand;189189- irq_tab[irq].flags = 0;190190- irq_tab[irq].dev_id = NULL;191191- /* irq_tab[irq].devname = NULL; */192192- /* do not reset state !! */193193- }194194- else195195- { /* == Q40_IRQ_SAMPLE */196196- cpu_free_irq(4, dev_id);197197- cpu_free_irq(6, dev_id);198198- }199199-}200200-201201-202202-irqreturn_t q40_process_int (int level, struct pt_regs *fp)203203-{204204- printk("unexpected interrupt vec=%x, pc=%lx, d0=%lx, d0_orig=%lx, d1=%lx, d2=%lx\n",205205- level, fp->pc, fp->d0, fp->orig_d0, fp->d1, fp->d2);206206- printk("\tIIRQ_REG = %x, EIRQ_REG = %x\n",master_inb(IIRQ_REG),master_inb(EIRQ_REG));207207- return IRQ_HANDLED;208208-}2099521096/*21197 * this stuff doesn't really belong here..212212-*/9898+ */21399214100int ql_ticks; /* 200Hz ticks since last jiffie */215101static int sound_ticks;···108214109215void q40_mksound(unsigned int hz, unsigned int ticks)110216{111111- /* for now ignore hz, except that hz==0 switches off sound */112112- /* simply alternate the ampl (128-SVOL)-(128+SVOL)-..-.. at 200Hz */113113- if (hz==0)114114- {115115- if (sound_ticks)116116- sound_ticks=1;217217+ /* for now ignore hz, except that hz==0 switches off sound */218218+ /* simply alternate the ampl (128-SVOL)-(128+SVOL)-..-.. at 200Hz */219219+ if (hz == 0) {220220+ if (sound_ticks)221221+ sound_ticks = 1;117222118118- *DAC_LEFT=128;119119- *DAC_RIGHT=128;223223+ *DAC_LEFT = 128;224224+ *DAC_RIGHT = 128;120225121121- return;122122- }123123- /* sound itself is done in q40_timer_int */124124- if (sound_ticks == 0) sound_ticks=1000; /* pretty long beep */125125- sound_ticks=ticks<<1;226226+ return;227227+ }228228+ /* sound itself is done in q40_timer_int */229229+ if (sound_ticks == 0)230230+ sound_ticks = 1000; /* pretty long beep */231231+ sound_ticks = ticks << 1;126232}127233128234static irqreturn_t (*q40_timer_routine)(int, void *, struct pt_regs *);129235130236static irqreturn_t q40_timer_int (int irq, void * dev, struct pt_regs * regs)131237{132132- ql_ticks = ql_ticks ? 0 : 1;133133- if (sound_ticks)134134- {135135- unsigned char sval=(sound_ticks & 1) ? 128-SVOL : 128+SVOL;136136- sound_ticks--;137137- *DAC_LEFT=sval;138138- *DAC_RIGHT=sval;139139- }238238+ ql_ticks = ql_ticks ? 0 : 1;239239+ if (sound_ticks) {240240+ unsigned char sval=(sound_ticks & 1) ? 128-SVOL : 128+SVOL;241241+ sound_ticks--;242242+ *DAC_LEFT=sval;243243+ *DAC_RIGHT=sval;244244+ }140245141141- if (!ql_ticks)142142- q40_timer_routine(irq, dev, regs);143143- return IRQ_HANDLED;246246+ if (!ql_ticks)247247+ q40_timer_routine(irq, dev, regs);248248+ return IRQ_HANDLED;144249}145250146251void q40_sched_init (irqreturn_t (*timer_routine)(int, void *, struct pt_regs *))147252{148148- int timer_irq;253253+ int timer_irq;149254150150- q40_timer_routine = timer_routine;151151- timer_irq=Q40_IRQ_FRAME;255255+ q40_timer_routine = timer_routine;256256+ timer_irq = Q40_IRQ_FRAME;152257153153- if (request_irq(timer_irq, q40_timer_int, 0,258258+ if (request_irq(timer_irq, q40_timer_int, 0,154259 "timer", q40_timer_int))155155- panic ("Couldn't register timer int");260260+ panic("Couldn't register timer int");156261157157- master_outb(-1,FRAME_CLEAR_REG);158158- master_outb( 1,FRAME_RATE_REG);262262+ master_outb(-1, FRAME_CLEAR_REG);263263+ master_outb( 1, FRAME_RATE_REG);159264}160265161266···200307static int aliased_irq=0; /* how many times inside handler ?*/201308202309203203-/* got level 2 interrupt, dispatch to ISA or keyboard/timer IRQs */204204-irqreturn_t q40_irq2_handler (int vec, void *devname, struct pt_regs *fp)310310+/* got interrupt, dispatch to ISA or keyboard/timer IRQs */311311+static void q40_irq_handler(unsigned int irq, struct pt_regs *fp)205312{206206- unsigned mir, mer;207207- int irq,i;313313+ unsigned mir, mer;314314+ int i;208315209316//repeat:210210- mir=master_inb(IIRQ_REG);211211- if (mir&Q40_IRQ_FRAME_MASK) {212212- irq_tab[Q40_IRQ_FRAME].count++;213213- irq_tab[Q40_IRQ_FRAME].handler(Q40_IRQ_FRAME,irq_tab[Q40_IRQ_FRAME].dev_id,fp);214214- master_outb(-1,FRAME_CLEAR_REG);215215- }216216- if ((mir&Q40_IRQ_SER_MASK) || (mir&Q40_IRQ_EXT_MASK)) {217217- mer=master_inb(EIRQ_REG);218218- for (i=0; eirqs[i].mask; i++) {219219- if (mer&(eirqs[i].mask)) {220220- irq=eirqs[i].irq;317317+ mir = master_inb(IIRQ_REG);318318+#ifdef CONFIG_BLK_DEV_FD319319+ if ((mir & Q40_IRQ_EXT_MASK) &&320320+ (master_inb(EIRQ_REG) & Q40_IRQ6_MASK)) {321321+ floppy_hardint();322322+ return;323323+ }324324+#endif325325+ switch (irq) {326326+ case 4:327327+ case 6:328328+ m68k_handle_int(Q40_IRQ_SAMPLE, fp);329329+ return;330330+ }331331+ if (mir & Q40_IRQ_FRAME_MASK) {332332+ m68k_handle_int(Q40_IRQ_FRAME, fp);333333+ master_outb(-1, FRAME_CLEAR_REG);334334+ }335335+ if ((mir & Q40_IRQ_SER_MASK) || (mir & Q40_IRQ_EXT_MASK)) {336336+ mer = master_inb(EIRQ_REG);337337+ for (i = 0; eirqs[i].mask; i++) {338338+ if (mer & eirqs[i].mask) {339339+ irq = eirqs[i].irq;221340/*222341 * There is a little mess wrt which IRQ really caused this irq request. The223342 * main problem is that IIRQ_REG and EIRQ_REG reflect the state when they224343 * are read - which is long after the request came in. In theory IRQs should225344 * not just go away but they occassionally do226345 */227227- if (irq>4 && irq<=15 && mext_disabled) {228228- /*aliased_irq++;*/229229- goto iirq;230230- }231231- if (irq_tab[irq].handler == q40_defhand ) {232232- printk("handler for IRQ %d not defined\n",irq);233233- continue; /* ignore uninited INTs :-( */234234- }235235- if ( irq_tab[irq].state & IRQ_INPROGRESS ) {236236- /* some handlers do local_irq_enable() for irq latency reasons, */237237- /* however reentering an active irq handler is not permitted */346346+ if (irq > 4 && irq <= 15 && mext_disabled) {347347+ /*aliased_irq++;*/348348+ goto iirq;349349+ }350350+ if (q40_state[irq] & IRQ_INPROGRESS) {351351+ /* some handlers do local_irq_enable() for irq latency reasons, */352352+ /* however reentering an active irq handler is not permitted */238353#ifdef IP_USE_DISABLE239239- /* in theory this is the better way to do it because it still */240240- /* lets through eg the serial irqs, unfortunately it crashes */241241- disable_irq(irq);242242- disabled=1;354354+ /* in theory this is the better way to do it because it still */355355+ /* lets through eg the serial irqs, unfortunately it crashes */356356+ disable_irq(irq);357357+ disabled = 1;243358#else244244- /*printk("IRQ_INPROGRESS detected for irq %d, disabling - %s disabled\n",irq,disabled ? "already" : "not yet"); */245245- fp->sr = (((fp->sr) & (~0x700))+0x200);246246- disabled=1;359359+ /*printk("IRQ_INPROGRESS detected for irq %d, disabling - %s disabled\n",360360+ irq, disabled ? "already" : "not yet"); */361361+ fp->sr = (((fp->sr) & (~0x700))+0x200);362362+ disabled = 1;247363#endif248248- goto iirq;249249- }250250- irq_tab[irq].count++;251251- irq_tab[irq].state |= IRQ_INPROGRESS;252252- irq_tab[irq].handler(irq,irq_tab[irq].dev_id,fp);253253- irq_tab[irq].state &= ~IRQ_INPROGRESS;364364+ goto iirq;365365+ }366366+ q40_state[irq] |= IRQ_INPROGRESS;367367+ m68k_handle_int(irq, fp);368368+ q40_state[irq] &= ~IRQ_INPROGRESS;254369255255- /* naively enable everything, if that fails than */256256- /* this function will be reentered immediately thus */257257- /* getting another chance to disable the IRQ */370370+ /* naively enable everything, if that fails than */371371+ /* this function will be reentered immediately thus */372372+ /* getting another chance to disable the IRQ */258373259259- if ( disabled ) {374374+ if (disabled) {260375#ifdef IP_USE_DISABLE261261- if (irq>4){262262- disabled=0;263263- enable_irq(irq);}376376+ if (irq > 4) {377377+ disabled = 0;378378+ enable_irq(irq);379379+ }264380#else265265- disabled=0;266266- /*printk("reenabling irq %d\n",irq); */381381+ disabled = 0;382382+ /*printk("reenabling irq %d\n", irq); */267383#endif268268- }384384+ }269385// used to do 'goto repeat;' here, this delayed bh processing too long270270- return IRQ_HANDLED;271271- }272272- }273273- if (mer && ccleirq>0 && !aliased_irq)274274- printk("ISA interrupt from unknown source? EIRQ_REG = %x\n",mer),ccleirq--;275275- }276276- iirq:277277- mir=master_inb(IIRQ_REG);278278- /* should test whether keyboard irq is really enabled, doing it in defhand */279279- if (mir&Q40_IRQ_KEYB_MASK) {280280- irq_tab[Q40_IRQ_KEYBOARD].count++;281281- irq_tab[Q40_IRQ_KEYBOARD].handler(Q40_IRQ_KEYBOARD,irq_tab[Q40_IRQ_KEYBOARD].dev_id,fp);282282- }283283- return IRQ_HANDLED;284284-}285285-286286-int show_q40_interrupts (struct seq_file *p, void *v)287287-{288288- int i;289289-290290- for (i = 0; i <= Q40_IRQ_MAX; i++) {291291- if (irq_tab[i].count)292292- seq_printf(p, "%sIRQ %02d: %8d %s%s\n",293293- (i<=15) ? "ISA-" : " " ,294294- i, irq_tab[i].count,295295- irq_tab[i].devname[0] ? irq_tab[i].devname : "?",296296- irq_tab[i].handler == q40_defhand ?297297- " (now unassigned)" : "");386386+ return;387387+ }388388+ }389389+ if (mer && ccleirq > 0 && !aliased_irq) {390390+ printk("ISA interrupt from unknown source? EIRQ_REG = %x\n",mer);391391+ ccleirq--;392392+ }298393 }299299- return 0;394394+ iirq:395395+ mir = master_inb(IIRQ_REG);396396+ /* should test whether keyboard irq is really enabled, doing it in defhand */397397+ if (mir & Q40_IRQ_KEYB_MASK)398398+ m68k_handle_int(Q40_IRQ_KEYBOARD, fp);399399+400400+ return;300401}301402302302-303303-static irqreturn_t q40_defhand (int irq, void *dev_id, struct pt_regs *fp)403403+void q40_enable_irq(unsigned int irq)304404{305305- if (irq!=Q40_IRQ_KEYBOARD)306306- printk ("Unknown q40 interrupt %d\n", irq);307307- else master_outb(-1,KEYBOARD_UNLOCK_REG);308308- return IRQ_NONE;405405+ if (irq >= 5 && irq <= 15) {406406+ mext_disabled--;407407+ if (mext_disabled > 0)408408+ printk("q40_enable_irq : nested disable/enable\n");409409+ if (mext_disabled == 0)410410+ master_outb(1, EXT_ENABLE_REG);411411+ }309412}310413311414312312-void q40_enable_irq (unsigned int irq)415415+void q40_disable_irq(unsigned int irq)313416{314314- if ( irq>=5 && irq<=15 )315315- {316316- mext_disabled--;317317- if (mext_disabled>0)318318- printk("q40_enable_irq : nested disable/enable\n");319319- if (mext_disabled==0)320320- master_outb(1,EXT_ENABLE_REG);321321- }417417+ /* disable ISA iqs : only do something if the driver has been418418+ * verified to be Q40 "compatible" - right now IDE, NE2K419419+ * Any driver should not attempt to sleep across disable_irq !!420420+ */421421+422422+ if (irq >= 5 && irq <= 15) {423423+ master_outb(0, EXT_ENABLE_REG);424424+ mext_disabled++;425425+ if (mext_disabled > 1)426426+ printk("disable_irq nesting count %d\n",mext_disabled);427427+ }322428}323429324324-325325-void q40_disable_irq (unsigned int irq)430430+unsigned long q40_probe_irq_on(void)326431{327327- /* disable ISA iqs : only do something if the driver has been328328- * verified to be Q40 "compatible" - right now IDE, NE2K329329- * Any driver should not attempt to sleep across disable_irq !!330330- */331331-332332- if ( irq>=5 && irq<=15 ) {333333- master_outb(0,EXT_ENABLE_REG);334334- mext_disabled++;335335- if (mext_disabled>1) printk("disable_irq nesting count %d\n",mext_disabled);336336- }432432+ printk("irq probing not working - reconfigure the driver to avoid this\n");433433+ return -1;337434}338338-339339-unsigned long q40_probe_irq_on (void)435435+int q40_probe_irq_off(unsigned long irqs)340436{341341- printk("irq probing not working - reconfigure the driver to avoid this\n");342342- return -1;437437+ return -1;343438}344344-int q40_probe_irq_off (unsigned long irqs)345345-{346346- return -1;347347-}348348-/*349349- * Local variables:350350- * compile-command: "m68k-linux-gcc -D__KERNEL__ -I/home/rz/lx/linux-2.2.6/include -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -pipe -fno-strength-reduce -ffixed-a2 -m68040 -c -o q40ints.o q40ints.c"351351- * End:352352- */