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