DOSBox-X
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines
src/cpu/callback.cpp
00001 /*
00002  *  Copyright (C) 2002-2015  The DOSBox Team
00003  *
00004  *  This program is free software; you can redistribute it and/or modify
00005  *  it under the terms of the GNU General Public License as published by
00006  *  the Free Software Foundation; either version 2 of the License, or
00007  *  (at your option) any later version.
00008  *
00009  *  This program is distributed in the hope that it will be useful,
00010  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  *  GNU General Public License for more details.
00013  *
00014  *  You should have received a copy of the GNU General Public License
00015  *  along with this program; if not, write to the Free Software
00016  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00017  */
00018 
00019 
00020 #include <stdlib.h>
00021 #include <string.h>
00022 
00023 #include "dosbox.h"
00024 #include "callback.h"
00025 #include "logging.h"
00026 #include "bios.h"
00027 #include "mem.h"
00028 #include "cpu.h"
00029 
00030 #if C_EMSCRIPTEN
00031 # include <emscripten.h>
00032 #endif
00033 
00034 Bit16u CB_SEG=0,CB_SOFFSET=0;
00035 extern Bitu vm86_fake_io_seg;
00036 extern Bitu vm86_fake_io_off;
00037 
00038 unsigned int last_callback = 0;
00039 
00040 /* CallBack are located at 0xF000:0x1000  (see CB_SEG and CB_SOFFSET in callback.h)
00041    And they are 16 bytes each and you can define them to behave in certain ways like a
00042    far return or and IRET
00043 */
00044 
00045 CallBack_Handler CallBack_Handlers[CB_MAX] = {NULL};
00046 char* CallBack_Description[CB_MAX] = {NULL};
00047 
00048 Bitu call_stop,call_idle,call_default,call_default2;
00049 Bitu call_priv_io;
00050 
00051 static Bitu illegal_handler(void) {
00052         E_Exit("Illegal CallBack #%u Called",last_callback);
00053         return 1;
00054 }
00055 
00056 void DBG_CALLBACK_Dump(void) {
00057         LOG_MSG("Callbacks");
00058     for (Bitu i=0;i < CB_MAX;i++) {
00059         if (CallBack_Handlers[i] == &illegal_handler)
00060             continue;
00061 
00062         LOG_MSG("  [%u] func=%p desc='%s'",
00063             (unsigned int)i,
00064             (void*)((uintptr_t)CallBack_Handlers[i]), /* shut the compiler up by func -> uintptr_t -> void* conversion */
00065             CallBack_Description[i] != NULL ? CallBack_Description[i] : "");
00066     }
00067         LOG_MSG("--------------");
00068 }
00069 
00070 void CALLBACK_Dump(void) {
00071         LOG(LOG_CPU,LOG_DEBUG)("Callback dump");
00072     for (Bitu i=0;i < CB_MAX;i++) {
00073         if (CallBack_Handlers[i] == &illegal_handler)
00074             continue;
00075 
00076         LOG(LOG_CPU,LOG_DEBUG)("  [%u] func=%p desc='%s'",
00077             (unsigned int)i,
00078             (void*)((uintptr_t)CallBack_Handlers[i]), /* shut the compiler up by func -> uintptr_t -> void* conversion */
00079             CallBack_Description[i] != NULL ? CallBack_Description[i] : "");
00080     }
00081         LOG(LOG_CPU,LOG_DEBUG)("--------------");
00082 }
00083 
00084 void CALLBACK_Shutdown(void) {
00085         for (Bitu i=1;(i<CB_MAX);i++) {
00086                 CallBack_Handlers[i] = &illegal_handler;
00087                 CALLBACK_SetDescription(i,NULL);
00088         }
00089 }
00090 
00091 Bitu CALLBACK_Allocate(void) {
00092         for (Bitu i=1;(i<CB_MAX);i++) {
00093                 if (CallBack_Handlers[i]==&illegal_handler) {
00094                         if (CallBack_Description[i] != NULL) LOG_MSG("CALLBACK_Allocate() warning: empty slot still has description string!\n");
00095                         CallBack_Handlers[i]=0;
00096                         return i;
00097                 }
00098         }
00099         E_Exit("CALLBACK:Can't allocate handler.");
00100         return 0;
00101 }
00102 
00103 void CALLBACK_DeAllocate(Bitu in) {
00104     assert(in != 0);
00105     assert(in < CB_MAX);
00106 
00107         CallBack_Handlers[in]=&illegal_handler;
00108         CALLBACK_SetDescription(in,NULL);
00109 }
00110 
00111 
00112 void CALLBACK_Idle(void) {
00113 #if C_EMSCRIPTEN
00114     void GFX_Events();
00115     GFX_Events();
00116 #endif
00117 
00118 /* this makes the cpu execute instructions to handle irq's and then come back */
00119         Bitu oldIF=GETFLAG(IF);
00120         SETFLAGBIT(IF,true);
00121         Bit16u oldcs=SegValue(cs);
00122         Bit32u oldeip=reg_eip;
00123         SegSet16(cs,CB_SEG);
00124         reg_eip=CB_SOFFSET+call_idle*CB_SIZE;
00125         DOSBOX_RunMachine();
00126         reg_eip=oldeip;
00127         SegSet16(cs,oldcs);
00128         SETFLAGBIT(IF,oldIF);
00129         if (!CPU_CycleAutoAdjust && CPU_Cycles>0)
00130                 CPU_Cycles=0;
00131 }
00132 
00133 static Bitu default_handler(void) {
00134         LOG(LOG_CPU,LOG_ERROR)("Illegal Unhandled Interrupt Called %X",lastint);
00135         return CBRET_NONE;
00136 }
00137 
00138 static Bitu stop_handler(void) {
00139         return CBRET_STOP;
00140 }
00141 
00142 Bitu FillFlags(void);
00143 
00144 void CALLBACK_RunRealFarInt(Bit16u seg,Bit16u off) {
00145         FillFlags();
00146 
00147         reg_sp-=6;
00148         mem_writew(SegPhys(ss)+reg_sp,RealOff(CALLBACK_RealPointer(call_stop)));
00149         mem_writew(SegPhys(ss)+reg_sp+2,RealSeg(CALLBACK_RealPointer(call_stop)));
00150         mem_writew(SegPhys(ss)+reg_sp+4,reg_flags);
00151         Bit32u oldeip=reg_eip;
00152         Bit16u oldcs=SegValue(cs);
00153         reg_eip=off;
00154         SegSet16(cs,seg);
00155         DOSBOX_RunMachine();
00156         reg_eip=oldeip;
00157         SegSet16(cs,oldcs);
00158 }
00159 
00160 void CALLBACK_RunRealFar(Bit16u seg,Bit16u off) {
00161         reg_sp-=4;
00162         mem_writew(SegPhys(ss)+reg_sp,RealOff(CALLBACK_RealPointer(call_stop)));
00163         mem_writew(SegPhys(ss)+reg_sp+2,RealSeg(CALLBACK_RealPointer(call_stop)));
00164         Bit32u oldeip=reg_eip;
00165         Bit16u oldcs=SegValue(cs);
00166         reg_eip=off;
00167         SegSet16(cs,seg);
00168         DOSBOX_RunMachine();
00169         reg_eip=oldeip;
00170         SegSet16(cs,oldcs);
00171 }
00172 
00173 void CALLBACK_RunRealInt_retcsip(Bit8u intnum,Bitu &rcs,Bitu &rip) {
00174         Bit32u oldeip=reg_eip;
00175         Bit16u oldcs=SegValue(cs);
00176         reg_eip=CB_SOFFSET+(CB_MAX*CB_SIZE)+(intnum*6U);
00177         SegSet16(cs,CB_SEG);
00178         DOSBOX_RunMachine();
00179         rcs = SegValue(cs);
00180         rip = reg_ip;
00181         reg_eip=oldeip;
00182         SegSet16(cs,oldcs);
00183 }
00184 
00185 void CALLBACK_RunRealInt(Bit8u intnum) {
00186         Bit32u oldeip=reg_eip;
00187         Bit16u oldcs=SegValue(cs);
00188         reg_eip=CB_SOFFSET+(CB_MAX*CB_SIZE)+(intnum*6U);
00189         SegSet16(cs,CB_SEG);
00190         DOSBOX_RunMachine();
00191         reg_eip=oldeip;
00192         SegSet16(cs,oldcs);
00193 }
00194 
00195 void CALLBACK_SZF(bool val) {
00196     Bitu tempf;
00197 
00198     if (cpu.stack.big)
00199         tempf = mem_readd(SegPhys(ss)+reg_esp+8); // first word past FAR 32:32
00200     else
00201         tempf = mem_readw(SegPhys(ss)+reg_sp+4); // first word past FAR 16:16
00202 
00203     if (val) tempf |= FLAG_ZF;
00204     else tempf &= ~FLAG_ZF;
00205 
00206     if (cpu.stack.big)
00207         mem_writed(SegPhys(ss)+reg_esp+8,tempf);
00208     else
00209         mem_writew(SegPhys(ss)+reg_sp+4,tempf);
00210 }
00211 
00212 void CALLBACK_SCF(bool val) {
00213     Bitu tempf;
00214 
00215     if (cpu.stack.big)
00216         tempf = mem_readd(SegPhys(ss)+reg_esp+8); // first word past FAR 32:32
00217     else
00218         tempf = mem_readw(SegPhys(ss)+reg_sp+4); // first word past FAR 16:16
00219 
00220     if (val) tempf |= FLAG_CF;
00221     else tempf &= ~FLAG_CF;
00222 
00223     if (cpu.stack.big)
00224         mem_writed(SegPhys(ss)+reg_esp+8,tempf);
00225     else
00226         mem_writew(SegPhys(ss)+reg_sp+4,tempf);
00227 }
00228 
00229 void CALLBACK_SIF(bool val) {
00230     Bitu tempf;
00231 
00232     if (cpu.stack.big)
00233         tempf = mem_readd(SegPhys(ss)+reg_esp+8); // first word past FAR 32:32
00234     else
00235         tempf = mem_readw(SegPhys(ss)+reg_sp+4); // first word past FAR 16:16
00236 
00237     if (val) tempf |= FLAG_IF;
00238     else tempf &= ~FLAG_IF;
00239 
00240     if (cpu.stack.big)
00241         mem_writed(SegPhys(ss)+reg_esp+8,tempf);
00242     else
00243         mem_writew(SegPhys(ss)+reg_sp+4,tempf);
00244 }
00245 
00246 void CALLBACK_SetDescription(Bitu nr, const char* descr) {
00247         if (CallBack_Description[nr]) delete[] CallBack_Description[nr];
00248         CallBack_Description[nr] = 0;
00249 
00250         if (descr != NULL) {
00251                 CallBack_Description[nr] = new char[strlen(descr)+1];
00252                 strcpy(CallBack_Description[nr],descr);
00253         }
00254 }
00255 
00256 const char* CALLBACK_GetDescription(Bitu nr) {
00257         if (nr>=CB_MAX) return 0;
00258         return CallBack_Description[nr];
00259 }
00260 
00261 Bitu CALLBACK_SetupExtra(Bitu callback, Bitu type, PhysPt physAddress, bool use_cb=true) {
00262         if (callback>=CB_MAX)
00263                 return 0;
00264         switch (type) {
00265         case CB_RETN:
00266                 if (use_cb) {
00267                         phys_writeb(physAddress+0x00,(Bit8u)0xFE);      //GRP 4
00268                         phys_writeb(physAddress+0x01,(Bit8u)0x38);      //Extra Callback instruction
00269                         phys_writew(physAddress+0x02,(Bit16u)callback); //The immediate word
00270                         physAddress+=4;
00271                 }
00272                 phys_writeb(physAddress+0x00,(Bit8u)0xC3);              //A RETN Instruction
00273                 return (use_cb?5:1);
00274         case CB_RETF:
00275                 if (use_cb) {
00276                         phys_writeb(physAddress+0x00,(Bit8u)0xFE);      //GRP 4
00277                         phys_writeb(physAddress+0x01,(Bit8u)0x38);      //Extra Callback instruction
00278                         phys_writew(physAddress+0x02,(Bit16u)callback); //The immediate word
00279                         physAddress+=4;
00280                 }
00281                 phys_writeb(physAddress+0x00,(Bit8u)0xCB);              //A RETF Instruction
00282                 return (use_cb?5:1);
00283         case CB_RETF8:
00284                 if (use_cb) {
00285                         phys_writeb(physAddress+0x00,(Bit8u)0xFE);      //GRP 4
00286                         phys_writeb(physAddress+0x01,(Bit8u)0x38);      //Extra Callback instruction
00287                         phys_writew(physAddress+0x02,(Bit16u)callback); //The immediate word
00288                         physAddress+=4;
00289                 }
00290                 phys_writeb(physAddress+0x00,(Bit8u)0xCA);              //A RETF 8 Instruction
00291                 phys_writew(physAddress+0x01,(Bit16u)0x0008);
00292                 return (use_cb?7:3);
00293         case CB_IRET:
00294                 if (use_cb) {
00295                         phys_writeb(physAddress+0x00,(Bit8u)0xFE);      //GRP 4
00296                         phys_writeb(physAddress+0x01,(Bit8u)0x38);      //Extra Callback instruction
00297                         phys_writew(physAddress+0x02,(Bit16u)callback);         //The immediate word
00298                         physAddress+=4;
00299                 }
00300                 phys_writeb(physAddress+0x00,(Bit8u)0xCF);              //An IRET Instruction
00301                 return (use_cb?5:1);
00302         case CB_IRETD:
00303                 if (use_cb) {
00304                         phys_writeb(physAddress+0x00,(Bit8u)0xFE);      //GRP 4
00305                         phys_writeb(physAddress+0x01,(Bit8u)0x38);      //Extra Callback instruction
00306                         phys_writew(physAddress+0x02,(Bit16u)callback);         //The immediate word
00307                         physAddress+=4;
00308                 }
00309                 phys_writeb(physAddress+0x00,(Bit8u)0x66);              //An IRETD Instruction
00310                 phys_writeb(physAddress+0x01,(Bit8u)0xCF);
00311                 return (use_cb?6:2);
00312         case CB_IRET_STI:
00313                 phys_writeb(physAddress+0x00,(Bit8u)0xFB);              //STI
00314                 if (use_cb) {
00315                         phys_writeb(physAddress+0x01,(Bit8u)0xFE);      //GRP 4
00316                         phys_writeb(physAddress+0x02,(Bit8u)0x38);      //Extra Callback instruction
00317                         phys_writew(physAddress+0x03,(Bit16u)callback); //The immediate word
00318                         physAddress+=4;
00319                 }
00320                 phys_writeb(physAddress+0x01,(Bit8u)0xCF);              //An IRET Instruction
00321                 return (use_cb?6:2);
00322         case CB_IRET_EOI_PIC1:
00323                 if (use_cb) {
00324                         phys_writeb(physAddress+0x00,(Bit8u)0xFE);      //GRP 4
00325                         phys_writeb(physAddress+0x01,(Bit8u)0x38);      //Extra Callback instruction
00326                         phys_writew(physAddress+0x02,(Bit16u)callback);         //The immediate word
00327                         physAddress+=4;
00328                 }
00329                 phys_writeb(physAddress+0x00,(Bit8u)0x50);              // push ax
00330                 phys_writeb(physAddress+0x01,(Bit8u)0xb0);              // mov al, 0x20
00331                 phys_writeb(physAddress+0x02,(Bit8u)0x20);
00332                 phys_writeb(physAddress+0x03,(Bit8u)0xe6);              // out 0x20, al (IBM) / out 0x00, al (PC-98)
00333                 phys_writeb(physAddress+0x04,(Bit8u)(IS_PC98_ARCH ? 0x00 : 0x20));
00334                 phys_writeb(physAddress+0x05,(Bit8u)0x58);              // pop ax
00335                 phys_writeb(physAddress+0x06,(Bit8u)0xcf);              //An IRET Instruction
00336                 return (use_cb?0x0b:0x07);
00337         case CB_IRQ0:   // timer int8
00338                 phys_writeb(physAddress+0x00,(Bit8u)0xFB);              //STI
00339                 if (use_cb) {
00340                         phys_writeb(physAddress+0x01,(Bit8u)0xFE);      //GRP 4
00341                         phys_writeb(physAddress+0x02,(Bit8u)0x38);      //Extra Callback instruction
00342                         phys_writew(physAddress+0x03,(Bit16u)callback);         //The immediate word
00343                         physAddress+=4;
00344                 }
00345                 phys_writeb(physAddress+0x01,(Bit8u)0x1e);              // push ds
00346                 phys_writeb(physAddress+0x02,(Bit8u)0x50);              // push ax
00347                 phys_writeb(physAddress+0x03,(Bit8u)0x52);              // push dx
00348                 phys_writew(physAddress+0x04,(Bit16u)0x1ccd);   // int 1c
00349                 phys_writeb(physAddress+0x06,(Bit8u)0xfa);              // cli
00350                 phys_writew(physAddress+0x07,(Bit16u)0x20b0);   // mov al, 0x20
00351                 phys_writew(physAddress+0x09,(Bit16u)(IS_PC98_ARCH ? 0x00e6 : 0x20e6)); // out 0x20, al / out 0x00, al (PC-98) (FIXME: PC-98 does not have INT 1Ch)
00352                 phys_writeb(physAddress+0x0b,(Bit8u)0x5a);              // pop dx
00353                 phys_writeb(physAddress+0x0c,(Bit8u)0x58);              // pop ax
00354                 phys_writeb(physAddress+0x0d,(Bit8u)0x1f);              // pop ds
00355                 phys_writeb(physAddress+0x0e,(Bit8u)0xcf);              //An IRET Instruction
00356                 return (use_cb?0x13:0x0f);
00357         case CB_IRQ1:   // keyboard int9
00358                 phys_writeb(physAddress+0x00,(Bit8u)0x50);                      // push ax
00359         if (machine == MCH_PCJR || IS_PC98_ARCH) {
00360             /* NTS: NEC PC-98 does not have keyboard input on port 60h, it's a 8251 UART elsewhere.
00361              *
00362              *      IBM PCjr reads the infared input on NMI interrupt, which then calls INT 48h to
00363              *      translate to IBM PC/XT scan codes before passing AL directly to IRQ1 (INT 9).
00364              *      PCjr keyboard handlers, including games made for the PCjr, assume the scan code
00365              *      is in AL and do not read the I/O port */
00366             phys_writew(physAddress+0x01,(Bit16u)0x9090);               // nop, nop
00367         }
00368         else {
00369             phys_writew(physAddress+0x01,(Bit16u)0x60e4);               // in al, 0x60
00370         }
00371         if (IS_PC98_ARCH || IS_TANDY_ARCH) {
00372             phys_writew(physAddress+0x03,(Bit16u)0x9090);               // nop, nop
00373             phys_writeb(physAddress+0x05,(Bit8u)0x90);                  // nop
00374             phys_writew(physAddress+0x06,(Bit16u)0x9090);               // nop, nop (PC-98 does not have INT 15h keyboard hook)
00375         }
00376         else {
00377             phys_writew(physAddress+0x03,(Bit16u)0x4fb4);               // mov ah, 0x4f
00378             phys_writeb(physAddress+0x05,(Bit8u)0xf9);                  // stc
00379             phys_writew(physAddress+0x06,(Bit16u)0x15cd);               // int 15
00380         }
00381 
00382                 if (use_cb) {
00383             if (IS_PC98_ARCH || IS_TANDY_ARCH)
00384                 phys_writew(physAddress+0x08,(Bit16u)0x9090);   // nop nop
00385             else
00386                 phys_writew(physAddress+0x08,(Bit16u)0x0473);   // jc skip
00387 
00388                         phys_writeb(physAddress+0x0a,(Bit8u)0xFE);              //GRP 4
00389                         phys_writeb(physAddress+0x0b,(Bit8u)0x38);              //Extra Callback instruction
00390                         phys_writew(physAddress+0x0c,(Bit16u)callback);                 //The immediate word
00391                         // jump here to (skip):
00392                         physAddress+=6;
00393                 }
00394                 phys_writeb(physAddress+0x08,(Bit8u)0xfa);                      // cli
00395                 phys_writew(physAddress+0x09,(Bit16u)0x20b0);           // mov al, 0x20
00396                 phys_writew(physAddress+0x0b,(Bit16u)(IS_PC98_ARCH ? 0x00e6 : 0x20e6));         // out 0x20, al
00397                 phys_writeb(physAddress+0x0d,(Bit8u)0x58);                      // pop ax
00398                 phys_writeb(physAddress+0x0e,(Bit8u)0xcf);                      //An IRET Instruction
00399                 return (use_cb?0x15:0x0f);
00400         case CB_IRQ1_BREAK:     // return from int9, when Ctrl-Break is detected; invokes int 1b
00401                 phys_writew(physAddress+0x00,(Bit16u)0x1bcd);           // int 1b
00402                 phys_writeb(physAddress+0x02,(Bit8u)0xfa);              // cli
00403                 if (use_cb) {
00404                         phys_writeb(physAddress+0x03,(Bit8u)0xFE);      //GRP 4
00405                         phys_writeb(physAddress+0x04,(Bit8u)0x38);      //Extra Callback instruction
00406                         phys_writew(physAddress+0x05,(Bit16u)callback);         //The immediate word
00407                         physAddress+=4;
00408                 }
00409                 phys_writew(physAddress+0x03,(Bit16u)0x20b0);           // mov al, 0x20
00410                 phys_writew(physAddress+0x05,(Bit16u)(IS_PC98_ARCH ? 0x00e6 : 0x20e6));         // out 0x20, al
00411                 phys_writeb(physAddress+0x07,(Bit8u)0x58);                      // pop ax
00412                 phys_writeb(physAddress+0x08,(Bit8u)0xcf);                      //An IRET Instruction
00413                 return (use_cb?0x0d:0x09);
00414         case CB_IRQ9:   // pic cascade interrupt
00415                 if (use_cb) {
00416                         phys_writeb(physAddress+0x00,(Bit8u)0xFE);      //GRP 4
00417                         phys_writeb(physAddress+0x01,(Bit8u)0x38);      //Extra Callback instruction
00418                         phys_writew(physAddress+0x02,(Bit16u)callback);         //The immediate word
00419                         physAddress+=4;
00420                 }
00421                 phys_writeb(physAddress+0x00,(Bit8u)0x50);              // push ax
00422                 phys_writew(physAddress+0x01,(Bit16u)0x61b0);   // mov al, 0x61
00423                 phys_writew(physAddress+0x03,(Bit16u)0xa0e6);   // out 0xa0, al
00424                 phys_writew(physAddress+0x05,(Bit16u)0x0acd);   // int a
00425                 phys_writeb(physAddress+0x07,(Bit8u)0xfa);              // cli
00426                 phys_writeb(physAddress+0x08,(Bit8u)0x58);              // pop ax
00427                 phys_writeb(physAddress+0x09,(Bit8u)0xcf);              //An IRET Instruction
00428                 return (use_cb?0x0e:0x0a);
00429         case CB_IRQ12:  // ps2 mouse int74
00430                 if (!use_cb) E_Exit("int74 callback must implement a callback handler!");
00431                 phys_writeb(physAddress++,(Bit8u)0x1e);         // push ds
00432                 phys_writeb(physAddress++,(Bit8u)0x06);         // push es
00433                 if (CPU_ArchitectureType>=CPU_ARCHTYPE_386) {
00434                         phys_writew(physAddress,(Bit16u)0x6066);// pushad
00435                         physAddress += 2;
00436                 }
00437                 else if (CPU_ArchitectureType>=CPU_ARCHTYPE_80186) {
00438                         phys_writeb(physAddress++,(Bit8u)0x60); // pusha
00439                 }
00440                 else {
00441                         // 8086-level tedium, PUSHA not available
00442                         phys_writeb(physAddress++,(Bit8u)0x50); // push ax
00443                         phys_writeb(physAddress++,(Bit8u)0x51); // push cx
00444                         phys_writeb(physAddress++,(Bit8u)0x52); // push dx
00445                         phys_writeb(physAddress++,(Bit8u)0x53); // push bx
00446                         phys_writeb(physAddress++,(Bit8u)0x55); // push bp
00447                         phys_writeb(physAddress++,(Bit8u)0x56); // push si
00448                         phys_writeb(physAddress++,(Bit8u)0x57); // push di
00449                 }
00450                 phys_writeb(physAddress++,(Bit8u)0xfc);         // cld
00451                 phys_writeb(physAddress++,(Bit8u)0xfb);         // sti
00452                 phys_writeb(physAddress++,(Bit8u)0xFE);         //GRP 4
00453                 phys_writeb(physAddress++,(Bit8u)0x38);         //Extra Callback instruction
00454                 phys_writew(physAddress,(Bit16u)callback);                      //The immediate word
00455                 physAddress += 2;
00456                 return 0x0a;
00457         case CB_IRQ12_RET:      // ps2 mouse int74 return
00458                 if (use_cb) {
00459                         phys_writeb(physAddress++,(Bit8u)0xFE); //GRP 4
00460                         phys_writeb(physAddress++,(Bit8u)0x38); //Extra Callback instruction
00461                         phys_writew(physAddress,(Bit16u)callback);              //The immediate word
00462                         physAddress+=2;
00463                 }
00464                 phys_writeb(physAddress++,(Bit8u)0xfa);         // cli
00465                 phys_writew(physAddress,(Bit16u)0x20b0);        // mov al, 0x20
00466                 physAddress += 2;
00467                 phys_writew(physAddress,(Bit16u)0xa0e6);        // out 0xa0, al
00468                 physAddress += 2;
00469                 phys_writew(physAddress,(Bit16u)0x20e6);        // out 0x20, al
00470                 physAddress += 2;
00471                 if (CPU_ArchitectureType>=CPU_ARCHTYPE_386) {
00472                         phys_writew(physAddress,(Bit16u)0x6166);// popad
00473                         physAddress += 2;
00474                 }
00475                 else if (CPU_ArchitectureType>=CPU_ARCHTYPE_80186) {
00476                         phys_writeb(physAddress++,(Bit8u)0x61); // popa
00477                 }
00478                 else {
00479                         // 8086-level tedium, POPA not available
00480                         phys_writeb(physAddress++,(Bit8u)0x5F); // pop di
00481                         phys_writeb(physAddress++,(Bit8u)0x5E); // pop si
00482                         phys_writeb(physAddress++,(Bit8u)0x5D); // pop bp
00483                         phys_writeb(physAddress++,(Bit8u)0x5B); // pop bx
00484                         phys_writeb(physAddress++,(Bit8u)0x5A); // pop dx
00485                         phys_writeb(physAddress++,(Bit8u)0x59); // pop cx
00486                         phys_writeb(physAddress++,(Bit8u)0x58); // pop ax
00487                 }
00488                 phys_writeb(physAddress++,(Bit8u)0x07);         // pop es
00489                 phys_writeb(physAddress++,(Bit8u)0x1f);         // pop ds
00490                 phys_writeb(physAddress++,(Bit8u)0xcf);         //An IRET Instruction
00491                 return (use_cb?0x10:0x0c);
00492         case CB_IRQ6_PCJR:      // pcjr keyboard interrupt
00493                 phys_writeb(physAddress+0x00,(Bit8u)0x50);                      // push ax
00494                 phys_writew(physAddress+0x01,(Bit16u)0x60e4);           // in al, 0x60
00495                 phys_writew(physAddress+0x03,(Bit16u)0xe03c);           // cmp al, 0xe0
00496                 if (use_cb) {
00497                         phys_writew(physAddress+0x05,(Bit16u)0x0b74);   // je skip
00498                         phys_writeb(physAddress+0x07,(Bit8u)0xFE);              //GRP 4
00499                         phys_writeb(physAddress+0x08,(Bit8u)0x38);              //Extra Callback instruction
00500                         phys_writew(physAddress+0x09,(Bit16u)callback);                 //The immediate word
00501                         physAddress+=4;
00502                 } else {
00503                         phys_writew(physAddress+0x05,(Bit16u)0x0774);   // je skip
00504                 }
00505                 phys_writeb(physAddress+0x07,(Bit8u)0x1e);                      // push ds
00506                 phys_writew(physAddress+0x08,(Bit16u)0x406a);           // push 0x0040
00507                 phys_writeb(physAddress+0x0a,(Bit8u)0x1f);                      // pop ds
00508                 phys_writew(physAddress+0x0b,(Bit16u)0x09cd);           // int 9
00509                 phys_writeb(physAddress+0x0d,(Bit8u)0x1f);                      // pop ds
00510                 // jump here to (skip):
00511                 phys_writeb(physAddress+0x0e,(Bit8u)0xfa);                      // cli
00512                 phys_writew(physAddress+0x0f,(Bit16u)0x20b0);           // mov al, 0x20
00513                 phys_writew(physAddress+0x11,(Bit16u)0x20e6);           // out 0x20, al
00514                 phys_writeb(physAddress+0x13,(Bit8u)0x58);                      // pop ax
00515                 phys_writeb(physAddress+0x14,(Bit8u)0xcf);                      //An IRET Instruction
00516                 return (use_cb?0x19:0x15);
00517         case CB_MOUSE:
00518                 phys_writew(physAddress+0x00,(Bit16u)0x07eb);           // jmp i33hd
00519                 physAddress+=9;
00520                 // jump here to (i33hd):
00521                 if (use_cb) {
00522                         phys_writeb(physAddress+0x00,(Bit8u)0xFE);      //GRP 4
00523                         phys_writeb(physAddress+0x01,(Bit8u)0x38);      //Extra Callback instruction
00524                         phys_writew(physAddress+0x02,(Bit16u)callback);         //The immediate word
00525                         physAddress+=4;
00526                 }
00527                 phys_writeb(physAddress+0x00,(Bit8u)0xCF);              //An IRET Instruction
00528                 return (use_cb?0x0e:0x0a);
00529         case CB_INT16:
00530                 phys_writeb(physAddress+0x00,(Bit8u)0xFB);              //STI
00531                 if (use_cb) {
00532                         phys_writeb(physAddress+0x01,(Bit8u)0xFE);      //GRP 4
00533                         phys_writeb(physAddress+0x02,(Bit8u)0x38);      //Extra Callback instruction
00534                         phys_writew(physAddress+0x03,(Bit16u)callback); //The immediate word
00535                         physAddress+=4;
00536                 }
00537                 phys_writeb(physAddress+0x01,(Bit8u)0xCF);              //An IRET Instruction
00538                 for (Bitu i=0;i<=0x0b;i++) phys_writeb(physAddress+0x02+i,0x90);
00539                 phys_writew(physAddress+0x0e,(Bit16u)0xedeb);   //jmp callback
00540                 return (use_cb?0x10:0x0c);
00541         /*case CB_INT28:        // DOS idle
00542                 phys_writeb(physAddress+0x00,(Bit8u)0xFB);              // STI
00543                 phys_writeb(physAddress+0x01,(Bit8u)0xF4);              // HLT
00544                 phys_writeb(physAddress+0x02,(Bit8u)0xcf);              // An IRET Instruction
00545                 return (0x04);*/
00546         case CB_INT29:  // fast console output
00547         if (IS_PC98_ARCH) LOG_MSG("WARNING: CB_INT29 callback setup not appropriate for PC-98 mode (INT 10h no longer BIOS call)");
00548                 if (use_cb) {
00549                         phys_writeb(physAddress+0x00,(Bit8u)0xFE);      //GRP 4
00550                         phys_writeb(physAddress+0x01,(Bit8u)0x38);      //Extra Callback instruction
00551                         phys_writew(physAddress+0x02,(Bit16u)callback);         //The immediate word
00552                         physAddress+=4;
00553                 }
00554                 phys_writeb(physAddress+0x00,(Bit8u)0x50);      // push ax
00555                 phys_writeb(physAddress+0x01,(Bit8u)0x53);      // push bx
00556                 phys_writew(physAddress+0x02,(Bit16u)0x0eb4);   // mov ah, 0x0e
00557                 phys_writeb(physAddress+0x04,(Bit8u)0xbb);      // mov bx,
00558                 phys_writew(physAddress+0x05,(Bit16u)0x0007);   // 0x0007
00559                 phys_writew(physAddress+0x07,(Bit16u)0x10cd);   // int 10
00560                 phys_writeb(physAddress+0x09,(Bit8u)0x5b);      // pop bx
00561                 phys_writeb(physAddress+0x0a,(Bit8u)0x58);      // pop ax
00562                 phys_writeb(physAddress+0x0b,(Bit8u)0xcf);      //An IRET Instruction
00563                 return (use_cb?0x10:0x0c);
00564         case CB_HOOKABLE:
00565                 phys_writeb(physAddress+0x00,(Bit8u)0xEB);              //jump near
00566                 phys_writeb(physAddress+0x01,(Bit8u)0x03);              //offset
00567                 phys_writeb(physAddress+0x02,(Bit8u)0x90);              //NOP
00568                 phys_writeb(physAddress+0x03,(Bit8u)0x90);              //NOP
00569                 phys_writeb(physAddress+0x04,(Bit8u)0x90);              //NOP
00570                 if (use_cb) {
00571                         phys_writeb(physAddress+0x05,(Bit8u)0xFE);      //GRP 4
00572                         phys_writeb(physAddress+0x06,(Bit8u)0x38);      //Extra Callback instruction
00573                         phys_writew(physAddress+0x07,(Bit16u)callback);         //The immediate word
00574                         physAddress+=4;
00575                 }
00576                 phys_writeb(physAddress+0x05,(Bit8u)0xCB);              //A RETF Instruction
00577                 return (use_cb?0x0a:0x06);
00578         case CB_TDE_IRET:       // TandyDAC end transfer
00579                 if (use_cb) {
00580                         phys_writeb(physAddress+0x00,(Bit8u)0xFE);      //GRP 4
00581                         phys_writeb(physAddress+0x01,(Bit8u)0x38);      //Extra Callback instruction
00582                         phys_writew(physAddress+0x02,(Bit16u)callback);         //The immediate word
00583                         physAddress+=4;
00584                 }
00585                 phys_writeb(physAddress+0x00,(Bit8u)0x50);              // push ax
00586                 phys_writeb(physAddress+0x01,(Bit8u)0xb8);              // mov ax, 0x91fb
00587                 phys_writew(physAddress+0x02,(Bit16u)0x91fb);
00588                 phys_writew(physAddress+0x04,(Bit16u)0x15cd);   // int 15
00589                 phys_writeb(physAddress+0x06,(Bit8u)0xfa);              // cli
00590                 phys_writew(physAddress+0x07,(Bit16u)0x20b0);   // mov al, 0x20
00591                 phys_writew(physAddress+0x09,(Bit16u)0x20e6);   // out 0x20, al
00592                 phys_writeb(physAddress+0x0b,(Bit8u)0x58);              // pop ax
00593                 phys_writeb(physAddress+0x0c,(Bit8u)0xcf);              //An IRET Instruction
00594                 return (use_cb?0x11:0x0d);
00595 /*      case CB_IPXESR:         // IPX ESR
00596                 if (!use_cb) E_Exit("ipx esr must implement a callback handler!");
00597                 phys_writeb(physAddress+0x00,(Bit8u)0x1e);              // push ds
00598                 phys_writeb(physAddress+0x01,(Bit8u)0x06);              // push es
00599                 phys_writew(physAddress+0x02,(Bit16u)0xa00f);   // push fs
00600                 phys_writew(physAddress+0x04,(Bit16u)0xa80f);   // push gs
00601                 phys_writeb(physAddress+0x06,(Bit8u)0x60);              // pusha
00602                 phys_writeb(physAddress+0x07,(Bit8u)0xFE);              //GRP 4
00603                 phys_writeb(physAddress+0x08,(Bit8u)0x38);              //Extra Callback instruction
00604                 phys_writew(physAddress+0x09,(Bit16u)callback); //The immediate word
00605                 phys_writeb(physAddress+0x0b,(Bit8u)0xCB);              //A RETF Instruction
00606                 return 0x0c;
00607         case CB_IPXESR_RET:             // IPX ESR return
00608                 if (use_cb) E_Exit("ipx esr return must not implement a callback handler!");
00609                 phys_writeb(physAddress+0x00,(Bit8u)0xfa);              // cli
00610                 phys_writew(physAddress+0x01,(Bit16u)0x20b0);   // mov al, 0x20
00611                 phys_writew(physAddress+0x03,(Bit16u)0xa0e6);   // out 0xa0, al
00612                 phys_writew(physAddress+0x05,(Bit16u)0x20e6);   // out 0x20, al
00613                 phys_writeb(physAddress+0x07,(Bit8u)0x61);              // popa
00614                 phys_writew(physAddress+0x08,(Bit16u)0xA90F);   // pop gs
00615                 phys_writew(physAddress+0x0a,(Bit16u)0xA10F);   // pop fs
00616                 phys_writeb(physAddress+0x0c,(Bit8u)0x07);              // pop es
00617                 phys_writeb(physAddress+0x0d,(Bit8u)0x1f);              // pop ds
00618                 phys_writeb(physAddress+0x0e,(Bit8u)0xcf);              //An IRET Instruction
00619                 return 0x0f; */
00620         case CB_VESA_START: {
00621                 // pseudocode: if(reg_bl==0x80) while(!(inportb(0x3da)&0x8));
00622                 phys_writes(physAddress,
00623                         "\xFE\x38\x90\x90"      // GRP4 CB      ####
00624                         "\x80\xFB\x80"          // cmp          bl,80h
00625                         "\x75\x11"                      // jne          NOVRET
00626                         "\x66\x50"                      // push         ax
00627                         "\x66\x52"                      // push         dx
00628                         "\x66\xBA\xDA\x03"      // mov          dx,3DAh 
00629                                                                 // AGAIN:
00630                         "\xEC"                          // in           al,dx
00631                         "\x24\x08"                      // and          al,8
00632                         "\x74\xFB"                      // je           AGAIN
00633                         "\x66\x5A"                      // pop          dx
00634                         "\x66\x58"                      // pop          ax
00635                                                                 // NOVRET:
00636                         "\xC3"                          // retn
00637                         ,27);
00638                 phys_writew(physAddress+2, callback); // callback number
00639                 return 27;
00640         }
00641         case CB_INT21:
00642                 phys_writeb(physAddress+0x00,(Bit8u)0xFB);              //STI
00643                 if (use_cb) {
00644                         phys_writeb(physAddress+0x01,(Bit8u)0xFE);      //GRP 4
00645                         phys_writeb(physAddress+0x02,(Bit8u)0x38);      //Extra Callback instruction
00646                         phys_writew(physAddress+0x03,(Bit16u)callback); //The immediate word
00647                         physAddress+=4;
00648                 }
00649                 phys_writeb(physAddress+0x01,(Bit8u)0xCF);              //An IRET Instruction
00650                 phys_writeb(physAddress+0x02,(Bit8u)0xCB);              //A RETF Instruction
00651                 phys_writeb(physAddress+0x03,(Bit8u)0x51);              // push cx
00652                 phys_writeb(physAddress+0x04,(Bit8u)0xB9);              // mov cx,
00653                 phys_writew(physAddress+0x05,(Bit16u)0x0140);           // 0x140
00654                 phys_writew(physAddress+0x07,(Bit16u)0xFEE2);           // loop $-2
00655                 phys_writeb(physAddress+0x09,(Bit8u)0x59);              // pop cx
00656                 phys_writeb(physAddress+0x0A,(Bit8u)0xCF);              //An IRET Instruction
00657                 return (use_cb?15:11);
00658         case CB_INT13:
00659                 phys_writeb(physAddress+0x00,(Bit8u)0xFB);              //STI
00660                 if (use_cb) {
00661                         phys_writeb(physAddress+0x01,(Bit8u)0xFE);      //GRP 4
00662                         phys_writeb(physAddress+0x02,(Bit8u)0x38);      //Extra Callback instruction
00663                         phys_writew(physAddress+0x03,(Bit16u)callback); //The immediate word
00664                         physAddress+=4;
00665                 }
00666                 phys_writeb(physAddress+0x01,(Bit8u)0xCF);              //An IRET Instruction
00667                 phys_writew(physAddress+0x02,(Bit16u)0x0ECD);           // int 0e
00668                 phys_writeb(physAddress+0x04,(Bit8u)0xCF);              //An IRET Instruction
00669                 return (use_cb?9:5);
00670         case CB_IRET_EOI_PIC2:
00671                 if (use_cb) {
00672                         phys_writeb(physAddress+0x00,(Bit8u)0xFE);      //GRP 4
00673                         phys_writeb(physAddress+0x01,(Bit8u)0x38);      //Extra Callback instruction
00674                         phys_writew(physAddress+0x02,(Bit16u)callback);         //The immediate word
00675                         physAddress+=4;
00676                 }
00677                 phys_writeb(physAddress+0x00,(Bit8u)0x50);              // push ax
00678                 phys_writeb(physAddress+0x01,(Bit8u)0xb0);              // mov al, 0x20
00679                 phys_writeb(physAddress+0x02,(Bit8u)0x20);
00680                 phys_writeb(physAddress+0x03,(Bit8u)0xe6);              // out 0xA0, al (IBM) / out 0x08, al (PC-98)
00681                 phys_writeb(physAddress+0x04,(Bit8u)(IS_PC98_ARCH ? 0x08 : 0xA0));
00682                 phys_writeb(physAddress+0x05,(Bit8u)0xe6);              // out 0x20, al (IBM) / out 0x00, al (PC-98)
00683                 phys_writeb(physAddress+0x06,(Bit8u)(IS_PC98_ARCH ? 0x00 : 0x20));
00684                 phys_writeb(physAddress+0x07,(Bit8u)0x58);              // pop ax
00685                 phys_writeb(physAddress+0x08,(Bit8u)0xcf);              //An IRET Instruction
00686                 return (use_cb?0x0d:0x09);
00687         case CB_CPM:
00688                 phys_writeb(physAddress+0x00,(Bit8u)0x9C);              //PUSHF
00689                 return CALLBACK_SetupExtra(callback,CB_INT21,physAddress+1,use_cb)+1;
00690         default:
00691                 E_Exit("CALLBACK:Setup:Illegal type %u",(unsigned int)type);
00692         }
00693         return 0;
00694 }
00695 
00696 bool CALLBACK_Setup(Bitu callback,CallBack_Handler handler,Bitu type,const char* descr) {
00697         if (callback>=CB_MAX) return false;
00698         CALLBACK_SetupExtra(callback,type,CALLBACK_PhysPointer(callback)+0,(handler!=NULL));
00699         CallBack_Handlers[callback]=handler;
00700         CALLBACK_SetDescription(callback,descr);
00701         return true;
00702 }
00703 
00704 Bitu CALLBACK_Setup(Bitu callback,CallBack_Handler handler,Bitu type,PhysPt addr,const char* descr) {
00705         if (callback>=CB_MAX) return 0;
00706         Bitu csize=CALLBACK_SetupExtra(callback,type,addr,(handler!=NULL));
00707         if (csize>0) {
00708                 CallBack_Handlers[callback]=handler;
00709                 CALLBACK_SetDescription(callback,descr);
00710         }
00711         return csize;
00712 }
00713 
00714 void CALLBACK_RemoveSetup(Bitu callback) {
00715         if (MemBase == NULL) {
00716                 /* avoid crash */
00717                 return;
00718         }
00719 
00720         for (Bitu i = 0;i < CB_SIZE;i++) {
00721                 phys_writeb(CALLBACK_PhysPointer(callback)+i ,(Bit8u) 0x00);
00722         }
00723 }
00724 
00725 void CALLBACK_HandlerObject::Uninstall(){
00726         if(!installed) return;
00727         if(m_type == CALLBACK_HandlerObject::SETUP) {
00728                 if(vectorhandler.installed && MemBase != NULL){
00729                         //See if we are the current handler. if so restore the old one
00730                         if(RealGetVec(vectorhandler.interrupt) == Get_RealPointer()) {
00731                                 RealSetVec(vectorhandler.interrupt,vectorhandler.old_vector);
00732                         } else
00733                                 LOG(LOG_MISC,LOG_WARN)("Interrupt vector changed on %X %s",vectorhandler.interrupt,CALLBACK_GetDescription(m_callback));
00734                 }
00735                 CALLBACK_RemoveSetup(m_callback);
00736         } else if(m_type == CALLBACK_HandlerObject::SETUPAT){
00737                 E_Exit("Callback:SETUP at not handled yet.");
00738         } else if(m_type == CALLBACK_HandlerObject::NONE){
00739                 //Do nothing. Merely DeAllocate the callback
00740         } else E_Exit("what kind of callback is this!");
00741         if(CallBack_Description[m_callback]) delete [] CallBack_Description[m_callback];
00742         CallBack_Description[m_callback] = 0;
00743         CALLBACK_DeAllocate(m_callback);
00744         installed=false;
00745 }
00746 
00747 CALLBACK_HandlerObject::~CALLBACK_HandlerObject(){
00748         Uninstall();
00749 }
00750 
00751 void CALLBACK_HandlerObject::Install(CallBack_Handler handler,Bitu type,const char* description){
00752         if(!installed) {
00753                 installed=true;
00754                 m_type=SETUP;
00755                 m_callback=CALLBACK_Allocate();
00756                 CALLBACK_Setup(m_callback,handler,type,description);
00757         } else E_Exit("Callback handler object already installed");
00758 }
00759 void CALLBACK_HandlerObject::Install(CallBack_Handler handler,Bitu type,PhysPt addr,const char* description){
00760         if(!installed) {
00761                 installed=true;
00762                 m_type=SETUP;
00763                 m_callback=CALLBACK_Allocate();
00764                 CALLBACK_Setup(m_callback,handler,type,addr,description);
00765         } else E_Exit("Callback handler object already installed");
00766 }
00767 
00768 void CALLBACK_HandlerObject::Allocate(CallBack_Handler handler,const char* description) {
00769         if(!installed) {
00770                 installed=true;
00771                 m_type=NONE;
00772                 m_callback=CALLBACK_Allocate();
00773                 CALLBACK_SetDescription(m_callback,description);
00774                 CallBack_Handlers[m_callback]=handler;
00775         } else E_Exit("Callback handler object already installed");
00776 }
00777 
00778 void CALLBACK_HandlerObject::Set_RealVec(Bit8u vec,bool reinstall){
00779         if(!vectorhandler.installed || reinstall) {
00780                 vectorhandler.installed=true;
00781                 vectorhandler.interrupt=vec;
00782                 RealSetVec(vec,Get_RealPointer(),vectorhandler.old_vector);
00783         } else E_Exit ("double usage of vector handler");
00784 }
00785 
00786 extern bool custom_bios;
00787 
00788 void CALLBACK_Init() {
00789         {
00790                 /* NTS: Layout of the callback area:
00791                  *
00792                  * CB_MAX entries CB_SIZE each, where executable x86 code is written per callback,
00793                  * followed by 256 entries 6 bytes each corresponding to an interrupt call */
00794                 Bitu o;
00795 
00796                 LOG(LOG_MISC,LOG_DEBUG)("Initializing DOSBox callback instruction system");
00797 
00798                 o = ROMBIOS_GetMemory((CB_MAX*CB_SIZE)+(256*6),"DOSBox callback area",/*align*/4);
00799                 if (o == 0) E_Exit("Cannot allocate callback area");
00800                 CB_SOFFSET = o&0xFFFF;
00801                 CB_SEG = (o>>4)&0xF000;
00802                 if (((Bitu)CB_SOFFSET + (CB_MAX*CB_SIZE) + (256*6)) > 0x10000) E_Exit("Callback area spans 64KB segment");
00803 
00804                 o = ROMBIOS_GetMemory(14/*2+2+3+2+2+3*/,"DOSBox vm86 hack",/*align*/4);
00805                 if (o == 0) E_Exit("Cannot allocate vm86 hack");
00806                 vm86_fake_io_off = o&0xFFFF;
00807                 vm86_fake_io_seg = (o>>4)&0xF000;
00808                 if ((vm86_fake_io_off+14) > 0x1000000) E_Exit("vm86 area spans 64KB segment");
00809         }
00810 
00811         LOG(LOG_CPU,LOG_DEBUG)("Callback area starts at %04x:%04x",CB_SEG,CB_SOFFSET);
00812 
00813         Bitu i;
00814         for (i=0;i<CB_MAX;i++) {
00815                 CallBack_Handlers[i]=&illegal_handler;
00816                 CallBack_Description[i]=NULL;
00817         }
00818 
00819         /* Setup the Stop Handler */
00820         call_stop=CALLBACK_Allocate();
00821         CallBack_Handlers[call_stop]=stop_handler;
00822         CALLBACK_SetDescription(call_stop,"stop");
00823         phys_writeb(CALLBACK_PhysPointer(call_stop)+0,0xFE);
00824         phys_writeb(CALLBACK_PhysPointer(call_stop)+1,0x38);
00825         phys_writew(CALLBACK_PhysPointer(call_stop)+2,(Bit16u)call_stop);
00826 
00827         /* Setup the idle handler */
00828         call_idle=CALLBACK_Allocate();
00829         CallBack_Handlers[call_idle]=stop_handler;
00830         CALLBACK_SetDescription(call_idle,"idle");
00831         for (i=0;i<=11;i++) phys_writeb(CALLBACK_PhysPointer(call_idle)+i,0x90);
00832         phys_writeb(CALLBACK_PhysPointer(call_idle)+12,0xFE);
00833         phys_writeb(CALLBACK_PhysPointer(call_idle)+13,0x38);
00834         phys_writew(CALLBACK_PhysPointer(call_idle)+14,(Bit16u)call_idle);
00835 
00836         /* Default handlers for unhandled interrupts that have to be non-null */
00837         call_default=CALLBACK_Allocate();
00838         CALLBACK_Setup(call_default,&default_handler,CB_IRET,"default");
00839         call_default2=CALLBACK_Allocate();
00840         CALLBACK_Setup(call_default2,&default_handler,CB_IRET,"default");
00841 
00842         /* Setup block of 0xCD 0xxx instructions */
00843         PhysPt rint_base=CALLBACK_GetBase()+CB_MAX*CB_SIZE;
00844         for (i=0;i<=0xff;i++) {
00845                 phys_writeb(rint_base,0xCD);
00846                 phys_writeb(rint_base+1,(Bit8u)i);
00847                 phys_writeb(rint_base+2,0xFE);
00848                 phys_writeb(rint_base+3,0x38);
00849                 phys_writew(rint_base+4,(Bit16u)call_stop);
00850                 rint_base+=6;
00851 
00852         }
00853 
00854         call_priv_io=CALLBACK_Allocate();
00855 
00856         // virtualizable in-out opcodes
00857         phys_writeb(CALLBACK_PhysPointer(call_priv_io)+0x00,(Bit8u)0xec);       // in al, dx
00858         phys_writeb(CALLBACK_PhysPointer(call_priv_io)+0x01,(Bit8u)0xcb);       // retf
00859         phys_writeb(CALLBACK_PhysPointer(call_priv_io)+0x02,(Bit8u)0xed);       // in ax, dx
00860         phys_writeb(CALLBACK_PhysPointer(call_priv_io)+0x03,(Bit8u)0xcb);       // retf
00861         phys_writeb(CALLBACK_PhysPointer(call_priv_io)+0x04,(Bit8u)0x66);       // in eax, dx
00862         phys_writeb(CALLBACK_PhysPointer(call_priv_io)+0x05,(Bit8u)0xed);
00863         phys_writeb(CALLBACK_PhysPointer(call_priv_io)+0x06,(Bit8u)0xcb);       // retf
00864 
00865         phys_writeb(CALLBACK_PhysPointer(call_priv_io)+0x08,(Bit8u)0xee);       // out dx, al
00866         phys_writeb(CALLBACK_PhysPointer(call_priv_io)+0x09,(Bit8u)0xcb);       // retf
00867         phys_writeb(CALLBACK_PhysPointer(call_priv_io)+0x0a,(Bit8u)0xef);       // out dx, ax
00868         phys_writeb(CALLBACK_PhysPointer(call_priv_io)+0x0b,(Bit8u)0xcb);       // retf
00869         phys_writeb(CALLBACK_PhysPointer(call_priv_io)+0x0c,(Bit8u)0x66);       // out dx, eax
00870         phys_writeb(CALLBACK_PhysPointer(call_priv_io)+0x0d,(Bit8u)0xef);
00871         phys_writeb(CALLBACK_PhysPointer(call_priv_io)+0x0e,(Bit8u)0xcb);       // retf
00872 }