Main Page | Data Structures | Directories | File List | Data Fields | Globals | Related Pages

vice_comm.c

Go to the documentation of this file.
00001 /*
00002  *      This program is free software; you can redistribute it and/or
00003  *      modify it under the terms of the GNU General Public License
00004  *      as published by the Free Software Foundation; either version
00005  *      2 of the License, or (at your option) any later version.
00006  *
00007  *  Copyright 2005 Spiro Trikaliotis
00008  *
00009 */
00010 
00020 #include <windows.h>
00021 #include <windowsx.h>
00022 
00023 #include "viceremote.h"
00024 
00026 #define DBG_USERMODE
00027 
00029 #define DBG_PROGNAME "OPENCBM.DLL"
00030 
00031 #include "debug.h"
00032 
00033 #include <winioctl.h>
00034 #include "cbmioctl.h"
00035 
00036 #include <stdlib.h>
00037 
00039 #define DLL
00040 #include "i_opencbm.h"
00041 #include "archlib.h"
00042 
00043 #include "arch.h"
00044 #include "vice_comm.h"
00045 
00046 static REMOTECONTROL *ptr_mappedfile = 0;
00047 static HANDLE handle_mappedfile = 0;
00048 
00049 static UINT buffernotowrite = -1;
00050 
00051 static REMOTECONTROL_ONEMEMBUFFER *membuffertowrite = 0;
00052 static REMOTECONTROL_ONEREGBUFFER *regbuffertowrite = 0;
00053 
00054 static REMOTECONTROL_ONEMEMBUFFER *membuffertoread = 0;
00055 static REMOTECONTROL_ONEREGBUFFER *regbuffertoread = 0;
00056 
00057 int vicereadregister(viceregs which)
00058 {
00059     unsigned int value;
00060 
00061     switch (which)
00062     {
00063         case reg_pc:    value = regbuffertoread->OutRegs.PC;    break;
00064         case reg_a:     value = regbuffertoread->OutRegs.AC;    break;
00065         case reg_x:     value = regbuffertoread->OutRegs.XR;    break;
00066         case reg_y:     value = regbuffertoread->OutRegs.YR;    break;
00067         case reg_sp:    value = regbuffertoread->OutRegs.SP;    break;
00068         case reg_flags: value = regbuffertoread->OutRegs.FLAGS; break;
00069     }
00070 
00071     return value;
00072 }
00073 
00074 void vicewriteregister(viceregs which, unsigned int value)
00075 {
00076     switch (which)
00077     {
00078         case reg_pc:    regbuffertowrite->InRegsValid.PC    = 1; regbuffertowrite->InRegs.PC    = value; break;
00079         case reg_a:     regbuffertowrite->InRegsValid.AC    = 1; regbuffertowrite->InRegs.AC    = value; break;
00080         case reg_x:     regbuffertowrite->InRegsValid.XR    = 1; regbuffertowrite->InRegs.XR    = value; break;
00081         case reg_y:     regbuffertowrite->InRegsValid.YR    = 1; regbuffertowrite->InRegs.YR    = value; break;
00082         case reg_sp:    regbuffertowrite->InRegsValid.SP    = 1; regbuffertowrite->InRegs.SP    = value; break;
00083         case reg_flags: regbuffertowrite->InRegsValid.FLAGS = 1; regbuffertowrite->InRegs.FLAGS = value; break;
00084     }
00085 }
00086 
00087 void vicewriteregister_when_at(unsigned int value)
00088 {
00089     ptr_mappedfile->regupdateaddress = value;
00090 }
00091 
00092 void vicereadmemory(unsigned int address, unsigned int size, char *buffer)
00093 {
00094     if (ptr_mappedfile)
00095     {
00096         DBG_ASSERT(membuffertoread->read.perform == 0); // make sure the read was executed
00097         DBG_ASSERT(membuffertoread->read.address == address);
00098         DBG_ASSERT(membuffertoread->read.size    == size);
00099 
00100         memcpy(buffer, ptr_mappedfile->data, size);
00101     }
00102 }
00103 
00104 void vicepreparereadmemory(unsigned int address, unsigned int size)
00105 {
00106     if (ptr_mappedfile)
00107     {
00108         DBG_ASSERT(membuffertowrite->read.perform == 0);
00109 
00110         membuffertowrite->read.perform = 1;
00111         membuffertowrite->read.address = address;
00112         membuffertowrite->read.size    = size;
00113     }
00114 }
00115 
00116 void vicewritememory(unsigned int address, unsigned int size, const char *buffer)
00117 {
00118     if (ptr_mappedfile)
00119     {
00120         DBG_ASSERT(membuffertowrite->write.perform == 0);
00121 
00122         membuffertowrite->write.perform = 1;
00123         membuffertowrite->write.address = address;
00124         membuffertowrite->write.size    = size;
00125 
00126         memcpy(ptr_mappedfile->data, buffer, size);
00127     }
00128 }
00129 
00130 void vicepause()
00131 {
00132     if (ptr_mappedfile)
00133     {
00134         membuffertoread = 0;
00135         regbuffertoread = 0;
00136 
00137         buffernotowrite = (ptr_mappedfile->remotecontrollerbuffer + 1) & 1;
00138         membuffertowrite = &ptr_mappedfile->memorybuffer[buffernotowrite];
00139         regbuffertowrite = &ptr_mappedfile->regbuffer[buffernotowrite];
00140 
00141         // delete the complete data which we might want to set
00142         memset(membuffertowrite, 0, sizeof(*membuffertowrite));
00143         memset(regbuffertowrite, 0, sizeof(*regbuffertowrite));
00144 
00145         ptr_mappedfile->trapaddress = -1;
00146         ptr_mappedfile->regupdateaddress = -1;
00147     }
00148 }
00149 
00150 void viceresume()
00151 {
00152     if (ptr_mappedfile)
00153     {
00154         DBG_ASSERT(ptr_mappedfile->remotecontrollerbuffer == ptr_mappedfile->vicebuffer);
00155 
00156         // make the new buffer active
00157         InterlockedIncrement(&ptr_mappedfile->remotecontrollerbuffer);
00158 
00159         buffernotowrite = -1;
00160 
00161         membuffertoread = membuffertowrite;
00162         regbuffertoread = regbuffertowrite;
00163 
00164         membuffertowrite = 0;
00165         regbuffertowrite = 0;
00166     }
00167 }
00168 
00169 void vicetrap(UINT address)
00170 {
00171     if (ptr_mappedfile)
00172     {
00173         ptr_mappedfile->trapaddress = address;
00174     }
00175 }
00176 
00177 void vicereset(void)
00178 {
00179     if (ptr_mappedfile)
00180     {
00181         ptr_mappedfile->reset = 1;
00182     }
00183 }
00184 
00185 void vicewaittrap(void)
00186 {
00187     if (ptr_mappedfile)
00188     {
00189         while (InterlockedExchangeAdd(&ptr_mappedfile->vicebuffer, 0)
00190             != InterlockedExchangeAdd(&ptr_mappedfile->remotecontrollerbuffer, 0))
00191             arch_usleep(1);
00192     }
00193 }
00194 
00195 void vicerelease(void)
00196 {
00197     if (ptr_mappedfile)
00198     {
00199         vicepause();
00200         vicewriteregister(reg_pc, 0xe39d); // better than 0xa474, as it restores the SP
00201         viceresume();
00202 
00203         vicewaittrap();
00204 
00205         if (InterlockedExchangeAdd(&ptr_mappedfile->version, 0) == 1)
00206             InterlockedDecrement(&ptr_mappedfile->controllerAvailable);
00207 
00208         UnmapViewOfFile(ptr_mappedfile);
00209         ptr_mappedfile = 0;
00210     }
00211 
00212     if (handle_mappedfile)
00213     {
00214         CloseHandle(handle_mappedfile);
00215         handle_mappedfile = 0;
00216     }
00217 }
00218 
00219 BOOLEAN viceinit(void)
00220 {
00221     static BOOLEAN success = FALSE;
00222 
00223     do {
00224 #if 0
00225         handle_mappedfile =
00226             CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE,
00227             0, sizeof(*ptr_mappedfile), "VICE_REMOTE_CONTROL");
00228 #else
00229         handle_mappedfile =
00230             OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, "VICE_REMOTE_CONTROL");
00231 #endif
00232 
00233         if (!handle_mappedfile || handle_mappedfile == INVALID_HANDLE_VALUE)
00234         {
00235             handle_mappedfile = 0;
00236             break;
00237         }
00238 
00239         ptr_mappedfile =
00240             MapViewOfFile(handle_mappedfile, FILE_MAP_ALL_ACCESS,
00241             0, 0, sizeof(*ptr_mappedfile));
00242 
00243         if (!ptr_mappedfile)
00244         {
00245             break;
00246         }
00247     } while (0);
00248 
00249     do {
00250         if (!ptr_mappedfile)
00251             break;
00252 
00253 #ifdef MSVC_COMPILE
00254 /*
00255  * Why this #ifdef and the #define?
00256  * - With older headers (for example, as given with MSVC6), there
00257  *   was only an 
00258  *   PVOID InterlockedCompareExchange(PVOID *Dest, PVOID Exch, PVOID Comperand);
00259  * - With ne^wer SDKs (and the DDK), the above function has been renamed to
00260  *   InterlockedCompareExchangePointer(), and a new function
00261  *   LONG InterlockedCompareExchange(PLONG Dest, LONG Exch, LONG Comperand);
00262  *   has been added.
00263  *   (This is due to the fact that a pointer and an ULONG are not necessarily
00264  *   the same length anymore with the introduction of WIN64, cf. ULONG_PTR,
00265  *   InterlockedCompareExchange64(), etc.)
00266  *   Thus, depending upon the headers we are including, the one or the other
00267  *   use gets some warning. This #ifdef (both paths only differ in the casts)
00268  *   avoids any warnings.
00269  * -@srt.20060221
00270  */
00271 
00272 # define InterlockedCompareExchange(_a, _b, _c) \
00273     (LONG) InterlockedCompareExchange(_a, (PVOID)_b, (PVOID)_c)
00274 
00275 #endif
00276 
00277         if (InterlockedCompareExchange(
00278                   (PVOID)&ptr_mappedfile->version, 1, 0)
00279                   > 1)
00280             break;
00281 
00282 #undef InterlockedCompareExchange
00283 
00284         if (InterlockedIncrement(&ptr_mappedfile->controllerAvailable) > 1)
00285             break;
00286 
00287         success = TRUE;        
00288     } while (0);
00289 
00290     if (!success)
00291     {
00292         vicerelease();
00293     }
00294 
00295     return success;
00296 }

Generated on Sun Apr 30 18:46:00 2006 for opencbm by  doxygen 1.4.2