Hello.
The purpose of this patch is to fix a crash when mouse moves under X.
It prevents reentering to the mouse handler by using a standart PIC model
of handling interrupts. This should work for every program including dpmi apps.
I beleave that other internal drivers should also be changed to this model
for better stability.
The patch changes alot and needs some testing.
If it does bad things or doesn't fix the problem, please let me know.
--- src/include/pic.h Wed May 2 15:22:52 2001
+++ src/include/pic.h Thu Sep 6 21:59:00 2001
@@ -65,8 +65,6 @@
#define PIC_IMOUSE 17 /* internal mouse driver */
#define PIC_IPX 18 /* IPX Signal */
-#define PIC_IRQALL 0xfffe /* bits for all IRQs set. This never changes */
-
/* pic_irq_list translates irq numbers to pic_ilevels. This is not used
by pic routines; it is simply made available for configuration ease */
EXTERN unsigned long pic_irq_list[] INIT({PIC_IRQ0, PIC_IRQ1, PIC_IRQ9, PIC_IRQ3,
@@ -87,6 +85,7 @@
EXTERN unsigned long pic_isr; /* interrupt in-service register */
EXTERN unsigned long pic_iflag; /* interrupt enable flag: en-/dis- =0/0xfffe */
EXTERN unsigned long pic_icount; /* iret counter (to avoid filling stack) */
+EXTERN unsigned long pic_irqall; /* bits for all IRQs set. */
EXTERN unsigned long pic_ilevel INIT(32); /* current interrupt level */
EXTERN unsigned long pic0_imr INIT(0xf800); /* interrupt mask register, pic0 */
@@ -108,6 +107,7 @@
struct lvldef {
void (*func)();
+ void (*callback)();
int ivec;
};
@@ -120,7 +120,7 @@
Bit8u read_pic1(ioport_t port); /* read from PIC 1 */
void pic_unmaski(int level); /* clear dosemu's irq mask bit */
void pic_maski(int level); /* set dosemu's irq mask bit */
-void pic_seti(unsigned int level, void (*func), unsigned int ivec);
+void pic_seti(unsigned int, void (*), unsigned int, void (*));
/* set function and interrupt vector */
void run_irqs(); /* run requested irqs */
#define pic_run() if(pic_irr)run_irqs() /* the right way to call run_irqs */
@@ -141,7 +141,7 @@
#define pic_set_mask pic_imr=(pic0_imr|pic1_imr|pice_imr|pic_iflag)
#define pic_sti() (pic_iflag=0,pic_set_mask, (void)0) /* emulate STI
*/
-#define pic_cli() (pic_iflag=PIC_IRQALL,pic_set_mask, (void)0) /* emulate CLI
*/
+#define pic_cli() (pic_iflag=pic_irqall,pic_set_mask, (void)0) /* emulate CLI
+*/
/* Experimental TIMER-IRQ CHAIN code */
extern void timer_int_engine(void);
--- src/include/mouse.h Sun Nov 12 20:02:07 2000
+++ src/include/mouse.h Tue Sep 4 16:57:16 2001
@@ -160,6 +160,7 @@
extern void DOSEMUMouseEvents(void);
extern void mouse_event(void);
+extern void do_mouse_irq(void);
extern void mouse_move_buttons(int lbutton, int mbutton, int rbutton);
extern void mouse_move_relative(int dx, int dy);
--- src/base/dev/pic/pic.c Tue Sep 4 19:56:47 2001
+++ src/base/dev/pic/pic.c Thu Sep 6 22:21:56 2001
@@ -191,6 +191,7 @@
static unsigned long pic_wirr; /* watchdog timer for pic_pirr */
static unsigned long pic_wcount = 0; /* watchdog for pic_icount */
unsigned long pic_icount_od = 1; /* overdrive for pic_icount_od */
+unsigned long pic_irqall = 0xfffe;
#if 0
unsigned long pic0_imr = 0xf800; /* IRQs 3-7 on pic0 start out disabled */
unsigned long pic1_imr = 0x07f8; /* IRQs 8-15 on pic1 start out disabled */
@@ -216,15 +217,16 @@
NEVER};
#define PNULL (void *) 0
-static struct lvldef pic_iinfo[32] =
- {{PNULL,0x02}, {PNULL,0x08}, {PNULL,0x09}, {PNULL,0x70},
- {PNULL,0x71}, {PNULL,0x72}, {PNULL,0x73}, {PNULL,0x74},
- {PNULL,0x75}, {PNULL,0x76}, {PNULL,0x77}, {PNULL,0x0b},
- {PNULL,0x0c}, {PNULL,0x0d}, {PNULL,0x0e}, {PNULL,0x0f},
- {PNULL,0x00}, {PNULL,0x00}, {PNULL,0x00}, {PNULL,0x00},
- {PNULL,0x00}, {PNULL,0x00}, {PNULL,0x00}, {PNULL,0x00},
- {PNULL,0x00}, {PNULL,0x00}, {PNULL,0x00}, {PNULL,0x00},
- {PNULL,0x00}, {PNULL,0x00}, {PNULL,0x00}, {PNULL,0x00}};
+static struct lvldef pic_iinfo[32] = {
+{PNULL,PNULL,0x02}, {PNULL,PNULL,0x08}, {PNULL,PNULL,0x09}, {PNULL,PNULL,0x70},
+{PNULL,PNULL,0x71}, {PNULL,PNULL,0x72}, {PNULL,PNULL,0x73}, {PNULL,PNULL,0x74},
+{PNULL,PNULL,0x75}, {PNULL,PNULL,0x76}, {PNULL,PNULL,0x77}, {PNULL,PNULL,0x0b},
+{PNULL,PNULL,0x0c}, {PNULL,PNULL,0x0d}, {PNULL,PNULL,0x0e}, {PNULL,PNULL,0x0f},
+{PNULL,PNULL,0x00}, {PNULL,PNULL,0x00}, {PNULL,PNULL,0x00}, {PNULL,PNULL,0x00},
+{PNULL,PNULL,0x00}, {PNULL,PNULL,0x00}, {PNULL,PNULL,0x00}, {PNULL,PNULL,0x00},
+{PNULL,PNULL,0x00}, {PNULL,PNULL,0x00}, {PNULL,PNULL,0x00}, {PNULL,PNULL,0x00},
+{PNULL,PNULL,0x00}, {PNULL,PNULL,0x00}, {PNULL,PNULL,0x00}, {PNULL,PNULL,0x00}
+};
/*
* run_irq() checks for and runs any interrupts requested in pic_irr
@@ -592,22 +594,32 @@
/* DANG_BEGIN_FUNCTION pic_seti
*
* pic_seti is used to initialize an interrupt for dosemu. It requires
- * three parameters. The first parameter is the interrupt level, which
- * man select the NMI, any of the IRQs, or any of the 16 extra levels
+ * four parameters. The first parameter is the interrupt level, which
+ * may select the NMI, any of the IRQs, or any of the 16 extra levels
* (16 - 31). The second parameter is the dosemu function to be called
* when the interrupt is activated. This function should call do_irq()
- * if the DOS interruptis really to be activated. If there is no special
+ * if the DOS interrupt is really to be activated. If there is no special
* dosemu code to call, the second parameter can specify do_irq(), but
- * see that description for some special considerations.
+ * see that description for some special considerations.
+ * The third parameter is a number of an interrupt to activate if there is
+ * no default interrupt for this ilevel.
+ * The fourth parameter is the dosemu function to be called from do_irq().
+ * Required by some internal dosemu drivers that needs some additional code
+ * before calling an actual handler. This function MUST provide a EOI at
+ * the end of a callback.
*
* DANG_END_FUNCTION
*/
-void pic_seti(level,func,ivec)
+void pic_seti(level,func,ivec,callback)
unsigned int level,ivec;
-void (*func);
+void (*func),(*callback);
{
if(level>=32) return;
pic_iinfo[level].func = func;
+ if(callback) {
+ pic_iinfo[level].callback = callback;
+ set_bit(level, &pic_irqall);
+ }
if(level>15) pic_iinfo[level].ivec = ivec;
if(func == (void*)0) pic_maski(level);
}
@@ -799,9 +807,10 @@
*/
g_printf("+%d",(int)pic_ilevel);
#endif
- if(pic_ilevel < 16) pic_push(pic_ilevel);
+ if(test_bit(pic_ilevel, &pic_irqall)) pic_push(pic_ilevel);
if (in_dpmi) {
- run_pm_int(intr);
+ if (!pic_iinfo[pic_ilevel].callback) run_pm_int(intr);
+ else pic_iinfo[pic_ilevel].callback();
} else {
#ifndef USE_NEW_INT
pic_cli();
@@ -820,7 +829,8 @@
LWORD(eip) = PIC_OFF;
/* schedule the requested interrupt, then enter the vm86() loop */
- run_int(intr);
+ if (!pic_iinfo[pic_ilevel].callback) run_int(intr);
+ else pic_iinfo[pic_ilevel].callback();
}
pic_icount++;
pic_wcount++;
@@ -841,7 +851,7 @@
pic_print(2, "Initiating VM86 irq lvl ", pic_ilevel, " in do_irq");
run_vm86();
}
- pic_isr &= PIC_IRQALL; /* levels 0 and 16-31 are Auto-EOI */
+ pic_isr &= pic_irqall; /* levels 0 and 16-31 are Auto-EOI */
serial_run(); /* delete when moved to timer stuff */
pic_run();
#if 0
@@ -1218,22 +1228,22 @@
}
/* PIC reset on reboot and at bootup */
- pic_seti(PIC_IRQ0, timer_int_engine, 0); /* do_irq0 in pic.c */
+ pic_seti(PIC_IRQ0, timer_int_engine, 0, NULL); /* do_irq0 in pic.c */
pic_unmaski(PIC_IRQ0);
pic_request(PIC_IRQ0); /* start timer */
if (mice->intdrv || mice->type == MOUSE_PS2 || mice->type == MOUSE_IMPS2) {
- pic_seti(PIC_IMOUSE, DOSEMUMouseEvents, 0);
+ pic_seti(PIC_IMOUSE, DOSEMUMouseEvents, 0, do_mouse_irq);
pic_unmaski(PIC_IMOUSE);
}
#ifdef USING_NET
#ifdef CONFIG_IPX
- pic_seti(PIC_IPX, IPXRelinquishControl, 0);
+ pic_seti(PIC_IPX, IPXRelinquishControl, 0, NULL);
pic_unmaski(PIC_IPX);
#endif
#ifdef CONFIG_IPXPICPKT
- pic_seti(PIC_NET, pkt_check_receive_quick, 0x61);
+ pic_seti(PIC_NET, pkt_check_receive_quick, 0x61, NULL);
#else
- pic_seti(PIC_NET, pkt_check_receive_quick, 0);
+ pic_seti(PIC_NET, pkt_check_receive_quick, 0, NULL);
#endif
pic_unmaski(PIC_NET);
#endif
--- src/base/mouse/mouseint.c Sun Nov 12 20:04:26 2000
+++ src/base/mouse/mouseint.c Thu Sep 6 20:41:45 2001
@@ -173,7 +173,7 @@
m_printf("MOUSE: INIT complete\n");
}
-void
+int
DOSEMUMouseProtocol(rBuf, nBytes)
unsigned char *rBuf;
int nBytes;
@@ -364,13 +364,12 @@
*/
mouse_move_buttons(buttons & 0x04, buttons & 0x02, buttons & 0x01);
mouse_move_relative(dx, dy);
- /*
- * check if user events need to be processed
- */
- mouse_event();
+
pBufP = 0;
+ return (i + 1);
} /* assembly full package */
} /* !config.usesX */
+ return nBytes;
}
void DOSEMUSetMouseSpeed(int old, int new, unsigned cflag)
@@ -459,12 +458,27 @@
{
/* We define a large buffer, because of high overheads with other processes */
#define MOUSE_BUFFER 1024
- unsigned char rBuf[MOUSE_BUFFER];
- int nBytes;
-
- nBytes = RPT_SYSCALL(read(mice->fd, (char *)rBuf, sizeof(rBuf)));
- if (nBytes>0 && !config.usesX) {
- m_printf("MOUSE: Read %d bytes\n", nBytes);
- DOSEMUMouseProtocol(rBuf, nBytes);
+ static unsigned char rBuf[MOUSE_BUFFER];
+ static int qBeg = 0, qEnd = 0;
+ int nBytes, nBytesProc;
+
+ nBytes = RPT_SYSCALL(read(mice->fd, (char *)(rBuf+qEnd),
+ sizeof(rBuf)-qEnd));
+ if (nBytes>0 && !config.usesX)
+ qEnd += nBytes;
+ if (qBeg < qEnd) {
+ m_printf("MOUSE: Read %d bytes. %d bytes in queue\n",
+ nBytes>0 ? nBytes : 0, qEnd-qBeg);
+ nBytesProc = DOSEMUMouseProtocol(rBuf+qBeg, qEnd-qBeg);
+ qBeg += nBytesProc;
+ m_printf("MOUSE: Processed %d bytes. %d bytes still in queue\n",
+ nBytesProc, qEnd-qBeg);
+ if (qBeg >= qEnd)
+ qBeg = qEnd = 0;
+ }
+ mouse_event();
+ if (qBeg < qEnd) {
+ m_printf("MOUSE: Requesting for the next event\n");
+ pic_request(PIC_IMOUSE);
}
}
--- src/base/mouse/mouse.c Sun Nov 12 20:02:07 2000
+++ src/base/mouse/mouse.c Tue Sep 4 21:52:30 2001
@@ -1437,18 +1437,18 @@
}
void
-fake_int(void)
+fake_int(int cs, int ip)
{
unsigned char *ssp;
unsigned long sp;
- m_printf("MOUSE: fake_int: CS:IP %04x:%04x\n",LWORD(cs),LWORD(eip));
+ m_printf("MOUSE: fake_int: CS:IP %04x:%04x\n", cs, ip);
ssp = (unsigned char *)(LWORD(ss)<<4);
sp = (unsigned long) LWORD(esp);
pushw(ssp, sp, vflags);
- pushw(ssp, sp, LWORD(cs));
- pushw(ssp, sp, LWORD(eip));
+ pushw(ssp, sp, cs);
+ pushw(ssp, sp, ip);
LWORD(esp) -= 6;
#if 0
do_hard_int(0x74);
@@ -1508,17 +1508,20 @@
* call user event handler
*/
void
-mouse_event()
+do_mouse_irq()
{
- if (mouse.mask & mouse_events && (mouse.cs || mouse.ip)) {
if(in_dpmi && !in_dpmi_dos_int
&& !((mouse.cs == DPMI_SEG) &&
((Bit32u)mouse.ip == (DPMI_OFF+HLT_OFF(DPMI_mouse_callback)))))
fake_pm_int();
- /* push iret frame on _SS:_SP. At F000:20F7 (bios.S) we get an
+ /* push iret frame on _SS:_SP. At F000:2146 (bios.S) we get an
* iret and return to _CS:_IP */
- fake_int();
+ fake_int(LWORD(cs), LWORD(eip));
+
+ /* push iret frame. At F000:20F7 (bios.S) we get an
+ * iret and return to F000:2140 for EOI */
+ fake_int(Mouse_SEG, Mouse_ROUTINE_OFF);
/* push all 16-bit regs plus _DS,_ES. At F000:20F4 (bios.S) we find
* 'pop es; pop ds; popa' */
@@ -1553,11 +1556,16 @@
"should call %04x:%04x (actually %04x:%04x)"
".........jumping to %04x:%04x\n",
mouse.cs, mouse.ip, *mouse.csp, *mouse.ipp,
- LWORD(cs), LWORD(eip));
- }
- mouse_events = 0;
+ LWORD(cs), LWORD(eip));
}
+void
+mouse_event()
+{
+ if (mouse.mask & mouse_events && (mouse.cs || mouse.ip))
+ do_irq();
+ mouse_events = 0;
+}
/* unconditional mouse cursor update */
static void
--- src/emu.c Mon Oct 16 00:42:52 2000
+++ src/emu.c Fri Sep 7 01:07:49 2001
@@ -259,7 +259,7 @@
sg->irq = irq;
g_printf("SIG: IRQ%d, enabling PIC-level %ld\n", irq,
pic_irq_list[irq]);
{ extern int SillyG_do_irq(void);
- pic_seti(pic_irq_list[irq], SillyG_do_irq, 0);
+ pic_seti(pic_irq_list[irq], SillyG_do_irq, 0, NULL);
}
pic_unmaski(pic_irq_list[irq]);
sg++;
--- src/dosext/sound/sound.c Thu Sep 6 21:53:30 2001
+++ src/dosext/sound/sound.c Thu Sep 6 21:51:10 2001
@@ -2408,7 +2408,7 @@
SB_info.irq.irq8 = pic_irq_list[config.sb_irq];
/* We let DOSEMU handle the interrupt */
- pic_seti(SB_info.irq.irq8, sb_irq_trigger, 0);
+ pic_seti(SB_info.irq.irq8, sb_irq_trigger, 0, NULL);
pic_unmaski(SB_info.irq.irq8);
S_printf ("SB: Initialisation - Base 0x%03x, IRQ %d, DMA %d\n",
--- src/base/serial/ser_init.c Sat Jul 8 23:37:18 2000
+++ src/base/serial/ser_init.c Thu Sep 6 21:54:25 2001
@@ -394,7 +394,7 @@
if(com[num].interrupt < 16) {
com[num].interrupt = pic_irq_list[com[num].interrupt];
s_printf("SER%d: enabling interrupt %d\n", num, com[num].interrupt);
- pic_seti(com[num].interrupt,pic_serial_run,0);
+ pic_seti(com[num].interrupt, pic_serial_run, 0, NULL);
pic_unmaski(com[num].interrupt);
}
irq_source_num[com[num].interrupt] = num; /* map interrupt to port */
--- src/base/keyboard/serv_8042.c Sun Mar 5 15:57:37 2000
+++ src/base/keyboard/serv_8042.c Thu Sep 6 21:54:52 2001
@@ -369,7 +369,7 @@
io_device.end_addr = 0x0061;
port_register_handler(io_device, config.speaker==SPKR_NATIVE? PORT_FAST:0);
if (config.keybint) {
- pic_seti(PIC_IRQ1, do_irq1, 0); /* init keyboard interrupt */
+ pic_seti(PIC_IRQ1, do_irq1, 0, NULL); /* init keyboard interrupt */
pic_unmaski(PIC_IRQ1);
}
}
--- src/base/init/init.c Sun Nov 12 20:02:07 2000
+++ src/base/init/init.c Thu Sep 6 21:56:39 2001
@@ -201,26 +201,26 @@
extern void do_irq1(void);
extern void rtc_int8(void);
/* PIC init */
- pic_seti(PIC_IRQ0, timer_int_engine, 0); /* do_irq0 in pic.c */
+ pic_seti(PIC_IRQ0, timer_int_engine, 0, NULL); /* do_irq0 in pic.c */
pic_unmaski(PIC_IRQ0);
pic_request(PIC_IRQ0); /* start timer */
- pic_seti(PIC_IRQ1, do_irq1, 0); /* do_irq1 in dosio.c */
+ pic_seti(PIC_IRQ1, do_irq1, 0, NULL); /* do_irq1 in dosio.c */
pic_unmaski(PIC_IRQ1);
- pic_seti(PIC_IRQ8, rtc_int8, 0);
+ pic_seti(PIC_IRQ8, rtc_int8, 0, NULL);
pic_unmaski(PIC_IRQ8);
if (mice->intdrv || mice->type == MOUSE_PS2 || mice->type == MOUSE_IMPS2) {
- pic_seti(PIC_IMOUSE, DOSEMUMouseEvents, 0);
+ pic_seti(PIC_IMOUSE, DOSEMUMouseEvents, 0, do_mouse_irq);
pic_unmaski(PIC_IMOUSE);
}
#ifdef USING_NET
#ifdef IPX
- pic_seti(PIC_IPX, IPXCallRel, 0);
+ pic_seti(PIC_IPX, IPXCallRel, 0, NULL);
pic_unmaski(PIC_IPX);
#endif
#ifdef PICPKT
- pic_seti(PIC_NET, pkt_check_receive_quick, 0x61);
+ pic_seti(PIC_NET, pkt_check_receive_quick, 0x61, NULL);
#else
- pic_seti(PIC_NET, pkt_check_receive_quick, 0);
+ pic_seti(PIC_NET, pkt_check_receive_quick, 0, NULL);
#endif
pic_unmaski(PIC_NET);
#endif
--- src/env/video/X.c Sun Oct 8 00:33:40 2000
+++ src/env/video/X.c Thu Sep 6 22:19:32 2001
@@ -1531,7 +1531,7 @@
busy = 0;
#if CONFIG_X_MOUSE
- mouse_event();
+ pic_request(PIC_IMOUSE);
#endif
#if 0