diff --git a/CMakeLists.txt b/CMakeLists.txt index 7fe3f5fc..0f87d994 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -31,6 +31,7 @@ OPTION( BUILD_BOCHS "Build Bochs Variant?" ON) OPTION( BUILD_GEM5 "Build gem5 Variant?" OFF) OPTION( BUILD_OVP "Build OVP Variant?" OFF) OPTION( BUILD_QEMU "Build QEMU Variant?" OFF) +OPTION( BUILD_T32 "Build Lauterbach Trace32 Variant?" OFF) # FIXME: only add simulators/ to include_directories, and include, e.g., # bochs/bochs.h in Fail*. -> avoids naming conflicts (e.g., /usr/include/elf.h @@ -46,6 +47,8 @@ elseif(BUILD_OVP) add_subdirectory(simulators/ovp) elseif(BUILD_QEMU) include_directories(simulators) +elseif(BUILD_T32) + add_subdirectory(hwdebuggers/t32) endif(BUILD_BOCHS) ## Additional compiler and linker flags ## @@ -68,7 +71,7 @@ include(bochs) include(gem5) include(ovp) include(qemu) - +include(t32) ## Just for testing: ## Invoking bochs build via external project # Setup configure call for bochs (-> make ebochs) diff --git a/cmake/gem5.cmake b/cmake/gem5.cmake index 7dce4bec..9acfdc40 100644 --- a/cmake/gem5.cmake +++ b/cmake/gem5.cmake @@ -2,6 +2,6 @@ if(BUILD_GEM5) message(STATUS "[${PROJECT_NAME}] Building gem5 variant ...") SET(VARIANT gem5) - + #set(gem5_src_dir ${PROJECT_SOURCE_DIR}/simulators/gem5) endif(BUILD_GEM5) diff --git a/cmake/t32.cmake b/cmake/t32.cmake new file mode 100644 index 00000000..e73579eb --- /dev/null +++ b/cmake/t32.cmake @@ -0,0 +1,10 @@ +#### Add some custom targets for T32 +if(BUILD_T32) + + message(STATUS "[${PROJECT_NAME}] Building T32 variant ...") + SET(VARIANT t32) + + # make sure aspects don't fail to match in entry.cc + include_directories(${PROJECT_SOURCE_DIR}/src/core ${CMAKE_BINARY_DIR}/src/core) + +endif(BUILD_T32) diff --git a/hwdebuggers/t32/CMakeLists.txt b/hwdebuggers/t32/CMakeLists.txt new file mode 100644 index 00000000..46951147 --- /dev/null +++ b/hwdebuggers/t32/CMakeLists.txt @@ -0,0 +1,8 @@ + +include_directories(include) + +include_directories(${CMAKE_BINARY_DIR}/src/core) + +add_subdirectory(api) +add_subdirectory(src) + diff --git a/hwdebuggers/t32/api/CMakeLists.txt b/hwdebuggers/t32/api/CMakeLists.txt new file mode 100644 index 00000000..d455b686 --- /dev/null +++ b/hwdebuggers/t32/api/CMakeLists.txt @@ -0,0 +1,6 @@ +set(SRCS + hlinknet.cc + hremote.cc +) + +add_library(t32api ${SRCS}) diff --git a/hwdebuggers/t32/api/hlinknet.cc b/hwdebuggers/t32/api/hlinknet.cc new file mode 100644 index 00000000..067f729c --- /dev/null +++ b/hwdebuggers/t32/api/hlinknet.cc @@ -0,0 +1,882 @@ +/**************************************************************** +* * +* Copyright notice: * +* * +* Lauterbach Datentechnik GmbH * +* Alle Rechte vorbehalten - All rights reserved * +* * +***************************************************************** + + Module: hlinknet.c + Function: Low level communication protocol for talking to TRACE32. + Is used by CAPI routined implemented in hremote.c. + Link both files with your application. + +***************************************************************/ + +#include "t32.h" + +#include +#include +#include + +#ifdef MS_WINDOWS +# include +# include +# include +typedef int socklen_t; +#endif + +#ifdef DEC_VMS +# include +# include +# include +# include +# include +# include +# include +# define DONT_USE_ASYNC +#endif + +#ifdef __linux__ +# include +# include +# include +# include +# include +# include +# include +# include +#endif + + +#ifdef UNIX_V +# include +# include +# include +# include +# include +# include +# include +# ifdef HP_UX +typedef int socklen_t; +# else +# include +# endif +#endif + +#ifdef OS_9 +# include +# include +# include +# include +# include +# include +#endif + + +#define PCKLEN_MAX 1472 /* maximum size of UDP-packet */ +#define BUFLEN_MIN 6000 + +#ifndef MS_WINDOWS +# ifndef UNIX_V +extern struct hostent * gethostbyaddr(); +# endif +#endif + +#ifdef DEC_VMS +# define fd_set int +# define FD_ZERO(fdset) (*fdset = 0) +# define FD_SET(fd,fdset) (*fdset |= (1<<(fd))) +# define FD_ISSET(fd,fdset) (*fdset & (1<<(fd))) +#endif + +#if defined(DEC_VMS) || defined(MS_WINDOWS) || defined(OS_9) || defined(LINUX) +# define RECEIVEADDR (&ReceiveSocketAddress) +static struct sockaddr ReceiveSocketAddress; +#else +# define RECEIVEADDR 0 +#endif + + +struct LineStruct { + char NodeName[80]; /* node name of host running T32 SW */ + int CommSocket; /* socket for communication */ + unsigned short HostPort; /* Host side port */ + unsigned short ReceivePort; /* Receiver Port */ + unsigned short TransmitPort; /* Transmitter Port in T32 */ + int PacketSize; /* Max. size of UDP-packet data */ + int PollTimeSec; + int ReceiveToggleBit; + unsigned char MessageId; + int LineUp; + unsigned short ReceiveSeq, TransmitSeq; /* block-ids */ + unsigned short LastReceiveSeq, LastTransmitSeq; + unsigned char* LastTransmitBuffer; + int LastTransmitSize; + struct sockaddr_in SocketAddress; +}; + +#ifdef MS_WINDOWS +extern void T32_InstallAsyncSelect(HWND hwnd, int msg); +extern void T32_UnInstallAsyncSelect(HWND hwnd); +#endif + +extern void LINE_SetReceiveToggleBit(int value); +extern int LINE_GetReceiveToggleBit(void); +extern int LINE_GetNextMessageId(void); +extern int LINE_GetMessageId(void); +extern int LINE_GetLineParamsSize (void); +extern void LINE_SetDefaultLineParams (LineStruct* params); +extern LineStruct* LINE_GetLine0Params (void); +extern void LINE_SetLine (LineStruct* params); +extern int LINE_LineConfig(char * in); +extern void LINE_LineExit(void); +extern int LINE_LineInit(char * message); +extern int LINE_LineTransmit(unsigned char * in, int size); +extern int LINE_LineDriverGetSocket(void); +extern int LINE_LineReceive(unsigned char * out); +extern int LINE_ReceiveNotifyMessage(unsigned char* package); +extern int LINE_LineSync(void); + +static int Connection(unsigned char *ipaddrused); + +static struct timeval LongTime = { 0, 500000 }; + + + +static const LineStruct LineDefaultParams = { + "localhost", -1, 0, 0, 20000, 1024, 5, -1, 0, 0}; +static LineStruct Line0Params = { + "localhost", -1, 0, 0, 20000, 1024, 5, -1, 0, 0}; + +static LineStruct* pLineParams = &Line0Params; + + + +static int str2dec (char* in) +{ + int x = 0; + while (*in) { + x *= 10; + if (*in < '0' || *in > '9') + return -1; + x += *in - '0'; + in++; + } + return x; +} + + +void LINE_SetReceiveToggleBit(int value) +{ + pLineParams->ReceiveToggleBit = value; +} + + +int LINE_GetReceiveToggleBit(void) +{ + return pLineParams->ReceiveToggleBit; +} + + +int LINE_GetNextMessageId(void) +{ + return ++pLineParams->MessageId; +} + + +int LINE_GetMessageId(void) +{ + return pLineParams->MessageId; +} + + +int LINE_GetLineParamsSize (void) +{ + return sizeof (LineStruct); +} + +void LINE_SetDefaultLineParams (LineStruct* params) +{ + *params = LineDefaultParams; + return; +} + + +LineStruct* LINE_GetLine0Params (void) +{ + return &Line0Params; +} + + +void LINE_SetLine (LineStruct* params) +{ + pLineParams = params; +} + + +int LINE_LineConfig(char * in) +{ + int x; + LineStruct* line = pLineParams; + + if (!strncmp((char *) in, "NODE=", 5)) { + strcpy(line->NodeName, in+5); + return 1; + } + if (!strncmp((char *) in, "PORT=", 5)) { + x = str2dec (in+5); + if (x == -1) + return -1; + line->TransmitPort = x; + return 1; + } + if (!strncmp((char *) in, "HOSTPORT=", 9)) { + x = str2dec (in+9); + if (x == -1) + return -1; + line->HostPort = x; + return 1; + } + if (!strncmp((char *) in, "PACKLEN=", 8)) { + x = str2dec (in+8); + if (x == -1) + return -1; + line->PacketSize = x; + return 1; + } + if (!strncmp((char *) in, "TIMEOUT=", 8)) { + x = str2dec (in+8); + if (x == -1) + return -1; + line->PollTimeSec = x; + return 1; + } + return -1; +} + + +static void WinsockErrorMessage(char * out) +{ +#ifdef MS_WINDOWS + int err; + err = WSAGetLastError(); + + switch (err) { + case WSAHOST_NOT_FOUND: + strcat(out, " (HOST_NOT_FOUND)"); + break; + case WSATRY_AGAIN: + strcat(out, " (TRY_AGAIN)"); + break; + case WSANO_RECOVERY: + strcat(out, " (NO_RECOVERY)"); + break; + case WSANO_DATA: + strcat(out, " (NO_DATA)"); + break; + case WSAEINTR: + strcat(out, " (INTR)"); + break; + case WSANOTINITIALISED: + strcat(out, " (NOTINITIALISED)"); + break; + case WSAENETDOWN: + strcat(out, " (NETDOWN)"); + break; + case WSAEAFNOSUPPORT: + strcat(out, " (WSAEAFNOSUPPORT)"); + break; + case WSAEINPROGRESS: + strcat(out, " (INPROGRESS)"); + break; + case WSAEMFILE: + strcat(out, " (WSAEMFILE)"); + break; + case WSAENOBUFS: + strcat(out, " (WSAENOBUFS)"); + break; + case WSAEPROTONOSUPPORT: + strcat(out, " (WSAEPROTONOSUPPORT)"); + break; + case WSAEPROTOTYPE: + strcat(out, " (WSAEPROTOTYPE)"); + break; + case WSAESOCKTNOSUPPORT: + strcat(out, " (WSAESOCKTNOSUPPORT)"); + break; + } +#endif +} + + +static long GetInetAddress(char * name, char * message) +{ + struct hostent *hp; + int i1, i2, i3, i4; + + char ownname[256]; + + if (name == NULL) { + gethostname(ownname, sizeof(ownname)); + name = ownname; + } + i1 = i2 = i3 = i4 = 0; + + if (sscanf(name, "%d.%d.%d.%d", &i1, &i2, &i3, &i4) == 4) { + if (i1 || i2 || i3 || i4) { + return (i1 << 24) | (i2 << 16) | (i3 << 8) | (i4); + } + } + hp = gethostbyname(name); + + if (!hp) { + strcpy(message, "node name ("); + strcat(message, name); + strcat(message, ") unknown"); + WinsockErrorMessage(message); + return -1l; + } + return ntohl(*(long *) (hp->h_addr)); +} + + +void LINE_LineExit(void) +{ + int i; + LineStruct* line = pLineParams; + static const unsigned char discon[] = {4, 0, 0, 0, 0, 0, 0, 0, 'T', 'R', 'A', 'C', 'E', '3', '2', 0}; + + if (!line->LineUp) + return; + + if (line->CommSocket != -1) { + for (i = 0; i < 5; i++) + sendto(line->CommSocket, (char *) discon, 16, 0, + (struct sockaddr *) &(line->SocketAddress), sizeof(line->SocketAddress)); + +#ifdef MS_WINDOWS + closesocket(line->CommSocket); +#endif +#if defined(DEC_VMS) || defined(UNIX_V) || defined(OS_9) + close(line->CommSocket); +#endif + } +#ifdef MS_WINDOWS + WSACleanup(); +#endif + + line->CommSocket = -1; + line->LineUp = 0; +} + + +int LINE_LineInit(char * message) +{ + int i, j; + socklen_t length; + int val; + unsigned char ipaddrused[4]; + long remote_ip; + int buflen; + LineStruct* line = pLineParams; + + if (line->LineUp) + return 0; + + if (line->CommSocket == -1) { +#ifdef MS_WINDOWS + WSADATA wsaData; + if (WSAStartup(0x0101, &wsaData)) { + strcpy(message, "TCP/IP not ready, check configuration"); + return -1; + } +#endif + } + if ((remote_ip = GetInetAddress(line->NodeName, message)) == -1l) + return -1; + + if (line->CommSocket == -1) { + line->SocketAddress.sin_family = AF_INET; + line->SocketAddress.sin_addr.s_addr = INADDR_ANY; + line->SocketAddress.sin_port = line->HostPort; /* Port can be determined by + * host */ + + if ((line->CommSocket = socket(AF_INET, SOCK_DGRAM, 0)) == -1) { + strcpy(message, "cannot create socket"); + WinsockErrorMessage(message); + goto done; + } + if ((i = bind(line->CommSocket, (struct sockaddr *) & line->SocketAddress, sizeof(line->SocketAddress))) == -1) { + strcpy(message, "cannot bind socket"); + WinsockErrorMessage(message); + goto done; + } + length = sizeof(line->SocketAddress); + if (getsockname(line->CommSocket, (struct sockaddr *) & line->SocketAddress, &length) == -1) { + strcpy(message, "cannot identify port"); + WinsockErrorMessage(message); + goto done; + } + line->ReceivePort = ntohs(line->SocketAddress.sin_port); + + line->SocketAddress.sin_family = AF_INET; + line->SocketAddress.sin_addr.s_addr = INADDR_ANY; + line->SocketAddress.sin_port = htons(line->TransmitPort); + } + line->SocketAddress.sin_addr.s_addr = htonl(remote_ip); + + buflen = 18000; + +#if !defined(OS_9) + val = 0; + length = sizeof(val); + getsockopt(line->CommSocket, SOL_SOCKET, SO_RCVBUF, (char *) &val, &length); + + if (val > 0 && val < line->PacketSize) + line->PacketSize = val; + + if (val < buflen) { + val = buflen; + length = sizeof(val); + if (setsockopt(line->CommSocket, SOL_SOCKET, SO_RCVBUF, (char *) &val, length) == -1) { + strcpy(message, "cannot alloc buffer for rcvsocket"); + goto done; + } + val = 0; + length = sizeof(val); + getsockopt(line->CommSocket, SOL_SOCKET, SO_RCVBUF, (char *) &val, &length); + if (val < buflen) { + strcpy(message, "cannot alloc buffer for rcvsocket"); + goto done; + } + } + val = 0; + length = sizeof(val); + getsockopt(line->CommSocket, SOL_SOCKET, SO_SNDBUF, (char *) &val, &length); + if (val < buflen) { + val = buflen; + length = sizeof(val); + if (setsockopt(line->CommSocket, SOL_SOCKET, SO_SNDBUF, (char *) &val, length) == -1) { + strcpy(message, "cannot alloc buffer for sndsocket"); + goto done; + } + val = 0; + length = sizeof(val); + getsockopt(line->CommSocket, SOL_SOCKET, SO_SNDBUF, (char *) &val, &length); + if (val < buflen) { + strcpy(message, "cannot alloc buffer for sndsocket"); + goto done; + } + } +#endif + + for (i = 0; i < 10; i++) { + j = Connection(ipaddrused); + + if (j == 0) + continue; + + if (j == 1) { + line->LineUp = 1; + return 1; + } + + strcpy(message, "TRACE32 access refused"); + goto done; + } + + strcpy(message, "TRACE32 not responding"); + +done: + LINE_LineExit(); /* Close connection if no success */ + return -1; +} + + +#ifdef MS_WINDOWS + +void T32_InstallAsyncSelect(HWND hwnd, int msg) +{ +#ifndef DONT_USE_ASYNC + WSAAsyncSelect(pLineParams->CommSocket, hwnd, msg, FD_READ); +#endif +} + +void T32_UnInstallAsyncSelect(HWND hwnd) +{ +#ifndef DONT_USE_ASYNC + WSAAsyncSelect(pLineParams->CommSocket, hwnd, 0, 0); +#endif +} + +#endif + +/** + Sends a message to T32. Handles segmentation of _message_ into (one + or multiple) _packages_. + + @param in pointer to outgoing message (already includes 5 byte message header) + @param size size of message + @note the message must be allocated such that there is space in + front of the message for adding the packet header + */ + +int LINE_LineTransmit(unsigned char * in, int size) +{ + int packetSize; + unsigned int tmpl; + LineStruct* line = pLineParams; + + line->LastTransmitBuffer = in; + line->LastTransmitSize = size; + line->LastTransmitSeq = line->TransmitSeq; + in -= 4; /* space for packet header */ + + do { + packetSize = (size > line->PacketSize - 4) ? line->PacketSize - 4 : size; + + /* When sending multiple packets, the packet header is written inside the + message's payload. Original contents needs to be saved/restored */ + + SETLONGVAR(tmpl, in[0]); /* save */ + + in[0] = 0x11; /* transmit data package */ + in[1] = (size > packetSize) ? 1 : 0; /* more packets follow */ + SETWORDVAR(in[2], line->TransmitSeq); /* packet sequence ID */ + + if (sendto(line->CommSocket, + (char *) in, + packetSize + 4, 0, + (struct sockaddr *) & line->SocketAddress, sizeof(line->SocketAddress) + ) != packetSize + 4) { + + SETLONGVAR(in[0], tmpl); /* restore buffer */ + return 0; + } + SETLONGVAR(in[0], tmpl); /* restore buffer */ + + line->TransmitSeq++; + in += packetSize; + size -= packetSize; + } + while (size > 0); /* more packets required? */ + + return line->LastTransmitSize; +} + +/** Receives a package from the socket, with timeout handling. + @return number of received bytes or error number (<0) +*/ +static int ReceiveWithTimeout(struct timeval *tim, unsigned char *dest, int size) +{ + int i; + fd_set readfds; + socklen_t length; + struct timeval timeout; + LineStruct* line = pLineParams; + + timeout = *tim; + +#ifdef POLL_NET + DWORD endpoll; + static struct timeval tival = {0}; + + if (tim->tv_usec || tim->tv_sec) + endpoll = GetCurrentTime() + tim->tv_usec / 1000 + tim->tv_sec * 1000; + else + endpoll = 0; +retry: +#endif + + FD_ZERO(&readfds); + FD_SET( (unsigned int)line->CommSocket, &readfds); + +#ifdef POLL_NET + i = select(FD_SETSIZE, &readfds, (fd_set *) NULL, (fd_set *) NULL, &tival); + + if (i < 0) + return i; + + if (i == 0) { + if (endpoll) { + if (GetCurrentTime() < endpoll) { + ScreenDispatcher(line->CommSocket); + goto retry; + } + } + return i; + } +#else + i = select(FD_SETSIZE, &readfds, (fd_set *) NULL, (fd_set *) NULL, &timeout); +#endif + + if (i <= 0) { + return i; + } + length = sizeof(struct sockaddr); + return recvfrom(line->CommSocket, dest, size, 0, (struct sockaddr *) RECEIVEADDR, &length); +} + + +int LINE_LineDriverGetSocket(void) +{ + return pLineParams->CommSocket; +} + +/* Queue pending notifications */ +T32_NotificationPackage *T32_NotificationHead = NULL, *T32_NotificationTail = NULL; + +/** Receives messages from the socket. Assembles multiple packets into + a single message. + + @param out output buffer for storing payload. Attention: there must + be some space _before_ the output buffer (4 bytes or more) + for temporary usage. + @return number of bytes of the message or error number (<0) + */ + +int LINE_LineReceive(unsigned char * out) +{ + int i, flag; + int count; + unsigned short tmpw; + unsigned int tmpl; + unsigned short s; + LineStruct* line = pLineParams; + register unsigned char *dest; + static unsigned char handshake[] = {7, 0, 0, 0, 0, 0, 0, 0, 'T', 'R', 'A', 'C', 'E', '3', '2', 0}; + +retry: + dest = out-4; /* adjust pointer so we place header BEFORE "out" and thus payload AT "out" */ + count = 0; + s = line->ReceiveSeq; + + do { + + /* multiple packets are merged in-place: backup data that is + overwritten package aby header */ + SETLONGVAR(tmpl, dest[0]); + + do { + struct timeval PollTime = {0, 0}; + PollTime.tv_sec = line->PollTimeSec; + if ((i = ReceiveWithTimeout(&PollTime, dest, line->PacketSize)) <= 0) { + if (i == -2) + goto retry; + return -1; + } + if (i <= 4) { + return -1; + } + + + /* Detect and enqeue async notification that slipped into a request/reply pair */ + if (dest[0] == T32_API_NOTIFICATION) + { + T32_NotificationPackage *newPackage, *oldHead; + + newPackage = reinterpret_cast( malloc(sizeof(T32_NotificationPackage)) ); + if (newPackage==NULL) + return -1; + + memcpy(newPackage, dest, i); /* in theory i should always be the package size, at least for ethernet */ + oldHead = T32_NotificationHead; + newPackage->prev = NULL; + newPackage->next = oldHead; + if (oldHead) + oldHead->prev = newPackage; + T32_NotificationHead = newPackage; + if (T32_NotificationTail==NULL) { + T32_NotificationTail=newPackage; + } + goto retry; + } + + if (dest[0] != T32_API_RECEIVE) { + return -1; + } + SETWORDVAR(tmpw, dest[2]); + + if (tmpw == line->LastReceiveSeq && line->LastTransmitSize) { + line->TransmitSeq = line->LastTransmitSeq; + LINE_LineTransmit(line->LastTransmitBuffer, line->LastTransmitSize); + } + } + while (tmpw != line->ReceiveSeq); + + line->ReceiveSeq++; + flag = dest[1]; + SETLONGVAR(dest[0], tmpl); /* restore payload overwritten by package header */ + dest += i - 4; + count += i - 4; + + if (count > LINE_MSIZE) { + return -1; + } + if (flag == 2) { + if (sendto(line->CommSocket, (char *) handshake, 16, 0, + (struct sockaddr *) &line->SocketAddress, sizeof(line->SocketAddress)) != 16) { + return -1; + } + } + } + while (flag); + + line->LastReceiveSeq = s; + + return count; +} + + +/** Receives notification messages. First checks for a queued + notification and if none is available polls the socket for new + notifications. For getting all pending notifications call the + function until it returns -1. + + @param package output buffer of size T32_PCKLEN_MAX for the package + @return -1 no notification pending, + >=0 notificataion type T32_E_BREAK, T32_E_EDIT, T32_E_BREAKPOINTCONFIG + + */ + + +int LINE_ReceiveNotifyMessage(unsigned char* package) +{ + int len; + static struct timeval LongTime = {0, 0}; + + /* Check for asynchronous notifications */ + if (T32_NotificationTail) { + T32_NotificationPackage *prev = T32_NotificationTail->prev; + if (prev) + prev->next = NULL; + memcpy(package, T32_NotificationTail->payload, T32_PCKLEN_MAX); + free(T32_NotificationTail); + T32_NotificationTail = prev; + if (prev==NULL) /* deleted last message */ + T32_NotificationHead = NULL; + } else { + len = ReceiveWithTimeout(&LongTime, package, T32_PCKLEN_MAX); + if (len < 2) + return -1; + } + + if (package[0] != T32_API_NOTIFICATION) + return -1; + + return package[1]; /* type of notification: T32_E_BREAK, T32_E_EDIT, T32_E_BREAKPOINTCONFIG */ + } + +/** Sends sync packets */ +int LINE_LineSync(void) +{ + int i, j; + unsigned char packet[T32_PCKLEN_MAX]; + static char magicPattern[] = "TRACE32"; + LineStruct* line = pLineParams; + + j = 0; + memset(packet, 0, sizeof(packet)); + +retry: + packet[0] = T32_API_SYNCREQUEST; + packet[1] = 0; + SETWORDVAR(packet[2], line->TransmitSeq); + SETWORDCONST(packet[4], 0); + SETWORDCONST(packet[6], 0); + strcpy((char *) (packet + 8), magicPattern); + + if (sendto(line->CommSocket, (char *) packet, 16 /*size*/, 0, + (struct sockaddr *) & line->SocketAddress, sizeof(line->SocketAddress)) == -1) { + return -1; + } + while (1) { /* empty queue */ + if (++j > 20) { + return -1; + } + if ((i = ReceiveWithTimeout(&LongTime, packet, T32_PCKLEN_MAX)) <= 0) { + return -1; + } + if (i != 16 || packet[0] != T32_API_SYNCACKN || strcmp((char *) packet + 8, magicPattern)) { + if (i == 16 && packet[0] == 5) + goto retry; + continue; + } + break; + } + + SETWORDVAR(line->ReceiveSeq, packet[2]); + line->LastReceiveSeq = line->ReceiveSeq - 100; + + + packet[0] = T32_API_SYNCBACK; + packet[1] = 0; + SETWORDVAR(packet[2], line->TransmitSeq); + SETWORDCONST(packet[4], 0); + SETWORDCONST(packet[6], 0); + strcpy((char *) (packet + 8), magicPattern); + + if (sendto(line->CommSocket, (char *) packet, 16, 0, (struct sockaddr *) & line->SocketAddress, sizeof(line->SocketAddress)) == -1) { + return -1; + } + return 1; +} + + +static int Connection(unsigned char *ipaddrused) +{ + int i; + unsigned char buffer[T32_PCKLEN_MAX]; + LineStruct* line = pLineParams; + static const char magicPattern[] = "TRACE32"; + + memset(buffer, 0, sizeof(buffer)); + + buffer[0] = 3; /* CONNECTREQUEST */ + buffer[1] = 0; + + line->TransmitSeq = 1; + SETWORDVAR(buffer[2], line->TransmitSeq); + SETWORDVAR(buffer[4], line->TransmitPort); + SETWORDVAR(buffer[6], line->ReceivePort); + + strcpy((char *) (buffer + 8), magicPattern); + + if (sendto(line->CommSocket, (char *) buffer, line->PacketSize, 0, (struct sockaddr *) & line->SocketAddress, sizeof(line->SocketAddress)) == -1) { + return 0; + } + if ((i = ReceiveWithTimeout(&LongTime, buffer, line->PacketSize)) <= 0) { + return 0; + } + if (strcmp((char *) (buffer + 8), magicPattern)) { + return 0; + } + SETWORDVAR(line->ReceiveSeq, buffer[2]); + + if (buffer[0] == 0x53) { /* POSITIVE CONNECTACKN from Debug Unit ? */ + ipaddrused[0] = 1; + ipaddrused[1] = 1; + ipaddrused[2] = 1; + ipaddrused[3] = 11; + return 2; + } + + if (buffer[0] != 0x13) { /* POSITIVE CONNECTACKN ? */ + if (buffer[0] == 0x23) {/* NEGATIVE ? */ + ipaddrused[0] = buffer[4]; + ipaddrused[1] = buffer[5]; + ipaddrused[2] = buffer[6]; + ipaddrused[3] = buffer[7]; + return 2; + } + return 0; + } + line->PacketSize = i; + + return 1; +} + + + diff --git a/hwdebuggers/t32/api/hremote.cc b/hwdebuggers/t32/api/hremote.cc new file mode 100644 index 00000000..8d20a648 --- /dev/null +++ b/hwdebuggers/t32/api/hremote.cc @@ -0,0 +1,2427 @@ +/**************************************************************** +* * +* Copyright notice: * +* * +* Lauterbach Datentechnik GmbH * +* Alle Rechte vorbehalten - All rights reserved * +* * +***************************************************************** + + Module: hremote.c + Function: CAPI routines for communication with TRACE32. + Uses low level protocol implemented in hlinknet.c. + Link both files with your application. + + Author: A. Nieser + Date: 15.10.98 + +***************************************************************/ + +#include "t32.h" +#include +#include +#ifdef MS_WINDOWS +#include "windows.h" +#else +#include +#include +#endif + + +int T32_Errno; + + +#define MAXRETRY 5 + +#define LINE_SBLOCK 4096 /* small block mode */ + +#define T32_MSG_LHANDLE 0x10 +#define T32_MSG_LRETRY 0x08 + + +unsigned char LINE_OutBuffer[LINE_MSIZE+256]; +unsigned char LINE_InBuffer[LINE_MSIZE+256]; + +#define T32_OUTBUFFER (LINE_OutBuffer+13+4) +#define T32_INBUFFER (LINE_InBuffer+13) + +struct LineStruct; + +extern int LINE_LineConfig(char * in); +extern int LINE_LineInit(char * message); +extern void LINE_LineExit(void); +extern int LINE_LineDriverGetSocket(void); +extern int LINE_LineTransmit(byte * in, int size); +extern int LINE_LineReceive(byte * out); +extern int LINE_ReceiveNotifyMessage(unsigned char* package); +extern int LINE_LineSync(void); +extern int LINE_GetLineParamsSize(void); +extern void LINE_SetDefaultLineParams(LineStruct * params); +extern void * LINE_GetLine0Params(void); +extern void LINE_SetLine(LineStruct* params); +extern void LINE_SetReceiveToggleBit(int value); +extern int LINE_GetReceiveToggleBit(void); +extern int LINE_GetNextMessageId(void); +extern int LINE_GetMessageId(void); + +extern int LINE_Transmit(int len); +extern int LINE_Receive(void); +static int LINE_Sync(void); + +static const int MaxPacketSize = 2048; + +static T32_NotificationCallback_t notificationCallback[T32_MAX_EVENTS]; + +/************************************************************************** + + T32_GetLineSize - Get sizeof line structure for Multi-Line usage + + Parameter: - + + Return: sizeof line structure + + Usage: void* line = malloc (T32_GetLineSize()); + +***************************************************************************/ + +int T32_GetChannelSize(void) +{ + return LINE_GetLineParamsSize(); +} + +/************************************************************************** + + T32_GetLineDefaults - Get default parameters for Multi-Line usage + + Parameter: out pointer to line receiving the defaults + + Return: - + + Usage: T32_GetLineDefaults (line); + +***************************************************************************/ + +void T32_GetChannelDefaults (void* line) +{ + LINE_SetDefaultLineParams ( reinterpret_cast( line ) ); + return; +} + +/************************************************************************** + + T32_SetLine - Set active line for Multi-Line usage + + Parameter: in pointer to now active line + + Return: - + + Usage: T32_SetChannel (line); + +***************************************************************************/ + +void T32_SetChannel (void* line) +{ + LINE_SetLine ( (LineStruct*) line); + return; +} + +/************************************************************************** + + T32_GetLine0 - Get default line used by Single-Line usage + + Parameter: - + + Return: pointer to default line + + Usage: void* line = T32_GetChannel0; + +***************************************************************************/ + +void* T32_GetChannel0 (void) +{ + return (void*) LINE_GetLine0Params (); +} + +/************************************************************************** + + T32_Nop - Sends one NIL message to the system + + Parameter: - + + Return: int 0 or Number of Error + +***************************************************************************/ +int T32_Nop(void) +{ + T32_OUTBUFFER[0] = 0x02; + T32_OUTBUFFER[1] = 0x70; + T32_OUTBUFFER[2] = 0x00; + T32_OUTBUFFER[3] = LINE_GetNextMessageId(); + + if (LINE_Transmit(4) == -1) + return T32_Errno = T32_COM_TRANSMIT_FAIL; + + if (LINE_Receive() == -1) + return T32_Errno = T32_COM_RECEIVE_FAIL; + + return T32_Errno = T32_INBUFFER[2]; +} + + +/************************************************************************** + + T32_NopFail - Sends one NIL message to the system + + Parameter: - + + Return: int -1 or Number of Error + +***************************************************************************/ +int T32_NopFail(void) +{ + T32_OUTBUFFER[0] = 0x02; + T32_OUTBUFFER[1] = 0x70; + T32_OUTBUFFER[2] = 0x00; + T32_OUTBUFFER[3] = LINE_GetNextMessageId(); + + if (LINE_Transmit(4) == -1) + return T32_Errno = T32_COM_TRANSMIT_FAIL; + + return -1; +} + + +/************************************************************************** + + T32_Ping - Sends one PING message to the system + + Parameter: - + + Return: int 0 or Number of Error + +***************************************************************************/ +int T32_Ping(void) +{ + T32_OUTBUFFER[0] = 0x02; + T32_OUTBUFFER[1] = 0x73; + T32_OUTBUFFER[2] = 0x00; + T32_OUTBUFFER[3] = LINE_GetNextMessageId(); + + if (LINE_Transmit(4) == -1) + return T32_Errno = T32_COM_TRANSMIT_FAIL; + + if (LINE_Receive() == -1) + return T32_Errno = T32_COM_RECEIVE_FAIL; + + return T32_Errno = T32_INBUFFER[2]; +} + + +/************************************************************************** + + T32_Stop - Stop the actual running PRACTICE program + + Parameter: - + + Return: int 0 or Number of Error + +***************************************************************************/ +int T32_Stop(void) +{ + T32_OUTBUFFER[0] = 0x00; + T32_OUTBUFFER[1] = 0x50; + T32_OUTBUFFER[2] = 0x02; + T32_OUTBUFFER[3] = 0x72; + T32_OUTBUFFER[4] = 0x00; + T32_OUTBUFFER[5] = LINE_GetNextMessageId(); + + if (LINE_Transmit(6) == -1) + return T32_Errno = T32_COM_TRANSMIT_FAIL; + + if (LINE_Receive() == -1) + return T32_Errno = T32_COM_RECEIVE_FAIL; + + return T32_Errno = T32_INBUFFER[2]; +} + + +/************************************************************************** + + T32_Terminate - Terminate executable + + Parameter: - + + Return: int 0 or Number of Error + +***************************************************************************/ +int T32_Terminate(int retval) +{ + + T32_OUTBUFFER[0] = 2; + T32_OUTBUFFER[1] = 0x79; + T32_OUTBUFFER[2] = retval; + T32_OUTBUFFER[3] = LINE_GetNextMessageId(); + + if (LINE_Transmit(4) == -1) + return T32_Errno = T32_COM_TRANSMIT_FAIL; + + if (LINE_Receive() == -1) + return T32_Errno = T32_COM_RECEIVE_FAIL; + + return T32_Errno = T32_INBUFFER[2]; +} + + + +/************************************************************************** + + T32_Attach - Attaches control to a device + + Parameter: in int dev Number of device (T32_DEV_OS, T32_DEV_ICE, T32_DEV_ICD) + + Return: int 0 or Number of Error + +***************************************************************************/ +int T32_Attach(int dev) +{ + T32_OUTBUFFER[0] = 2; + T32_OUTBUFFER[1] = 0x71; + T32_OUTBUFFER[2] = dev; + T32_OUTBUFFER[3] = LINE_GetNextMessageId(); + + if (LINE_Transmit(4) == -1) + return T32_Errno = T32_COM_TRANSMIT_FAIL; + + if (LINE_Receive() == -1) + return T32_Errno = T32_COM_RECEIVE_FAIL; + + return T32_Errno = T32_INBUFFER[2]; +} + + +/************************************************************************** + + T32_GetState - Return information about the state of TRACE32 + + Parameter: out int * pstate Pointer to variable to return the state + 0 System down + 1 System halted + 2 Emulation stopped + 3 Emulation running + + Return: int 0 or Number of Error + + +***************************************************************************/ +int T32_GetState(int * pstate) +{ + T32_OUTBUFFER[0] = 2; + T32_OUTBUFFER[1] = 0x74; + T32_OUTBUFFER[2] = 0x10; + T32_OUTBUFFER[3] = LINE_GetNextMessageId(); + + if (LINE_Transmit(4) == -1) + return T32_Errno = T32_COM_TRANSMIT_FAIL; + + if (LINE_Receive() == -1) + return T32_Errno = T32_COM_RECEIVE_FAIL; + + + *pstate = T32_INBUFFER[4]; + + return T32_Errno = T32_INBUFFER[2]; +} + + +/************************************************************************** + + T32_GetCpuInfo - Get information about the used CPU + + Parameter: out char ** string Pointer to a string decribing the CPU + out word * fpu Pointer to catch the FPU type ( not used, always 0 ) + out word * endian Pointer to catch the Endian mode + 1 BigEndian + 0 LittleEndian + out word * type Pointer to get internal information + (for internal use only) + + Return: int 0 or Number of Error + +***************************************************************************/ +int T32_GetCpuInfo( char **string, word * fpu, word * endian, word * type ) /* Get CPU information report */ +{ + int i; + static char cpu_string[16]; + + T32_OUTBUFFER[0] = 2; + T32_OUTBUFFER[1] = 0x74; + T32_OUTBUFFER[2] = 0x13; + T32_OUTBUFFER[3] = LINE_GetNextMessageId(); + + if (LINE_Transmit(4) == -1) + return T32_Errno = T32_COM_TRANSMIT_FAIL; + + if (LINE_Receive() == -1) + return T32_Errno = T32_COM_RECEIVE_FAIL; + + + for (i = 0; i < 15; i++) + cpu_string[i] = (T32_INBUFFER + 4)[i]; + + cpu_string[15] = 0; + *string = cpu_string; + *fpu = *endian = *type = 0; + SETWORDVAR(*fpu, T32_INBUFFER[22]); + SETWORDVAR(*endian, T32_INBUFFER[24]); + SETWORDVAR(*type, T32_INBUFFER[20]); + + return T32_Errno = T32_INBUFFER[2]; +} + + +int T32_GetRam (dword *startaddr, dword *endaddr, word *access) /* Get Data or Program RAM addresses */ +{ + dword t32access; + + T32_OUTBUFFER[0] = 8; + T32_OUTBUFFER[1] = 0x74; + T32_OUTBUFFER[2] = 0x16; + T32_OUTBUFFER[3] = LINE_GetNextMessageId(); + SETLONGVAR(T32_OUTBUFFER[4], *startaddr); + SETWORDVAR(T32_OUTBUFFER[8], *access); + + if (LINE_Transmit(10) == -1) + return T32_Errno = T32_COM_TRANSMIT_FAIL; + + if (LINE_Receive() == -1) + return T32_Errno = T32_COM_RECEIVE_FAIL; + + SETLONGVAR(*startaddr, T32_INBUFFER[4]); + SETLONGVAR(*endaddr, T32_INBUFFER[8]); + SETLONGVAR(t32access, T32_INBUFFER[12]); + + if (!t32access) + *access = 0; + + return T32_Errno = T32_INBUFFER[2]; +} + + +int T32_ResetCPU(void) /* Reset CPU Registers */ +{ + + T32_OUTBUFFER[0] = 2; + T32_OUTBUFFER[1] = 0x74; + T32_OUTBUFFER[2] = 0x11; + T32_OUTBUFFER[3] = LINE_GetNextMessageId(); + + if (LINE_Transmit(4) == -1) + return T32_Errno = T32_COM_TRANSMIT_FAIL; + + if (LINE_Receive() == -1) + return T32_Errno = T32_COM_RECEIVE_FAIL; + + + return T32_Errno = T32_INBUFFER[2]; +} + + +/* + * ADDRESS memory address + * FLAGS memory access flags + * BUFFER data to be written + * SIZE size of data + */ + +int T32_WriteMemory(dword address, int flags, byte * buffer, int size) /* Write Memory */ +{ + int result; + + if (size > MaxPacketSize) { + result = T32_WriteMemoryPipe(address, flags, buffer, size); + if (result) + return result; + return T32_WriteMemoryPipe(address, flags, buffer, 0); + } + T32_OUTBUFFER[0] = 10; + T32_OUTBUFFER[1] = 0x74; + T32_OUTBUFFER[2] = 0x31; + T32_OUTBUFFER[3] = LINE_GetNextMessageId(); + + SETLONGVAR(T32_OUTBUFFER[4], address); + T32_OUTBUFFER[8] = flags; + T32_OUTBUFFER[9] = 0; + T32_OUTBUFFER[10] = size; + T32_OUTBUFFER[11] = size >> 8; + + memcpy(T32_OUTBUFFER + 12, buffer, size); + + if (LINE_Transmit(12 + ((size + 1) & (~1))) == -1) + return T32_Errno = T32_COM_TRANSMIT_FAIL; + + if (LINE_Receive() == -1) + return T32_Errno = T32_COM_RECEIVE_FAIL; + + + return T32_Errno = T32_INBUFFER[2]; +} + + +/* + * ADDRESS memory address + * FLAGS memory access flags + * BUFFER data to be written + * SIZE size of data + */ + +int T32_WriteMemoryPipe(dword address, int flags, byte * buffer, int size) /* Write Memory, Pipelined */ +{ + int len; + + if (size == 0) { + T32_OUTBUFFER[0] = 2; + T32_OUTBUFFER[1] = 0x74; + T32_OUTBUFFER[2] = 0x32; + T32_OUTBUFFER[3] = LINE_GetNextMessageId(); + + if (LINE_Transmit(4) == -1) + return T32_Errno = T32_COM_TRANSMIT_FAIL; + + if (LINE_Receive() == -1) + return T32_Errno = T32_COM_RECEIVE_FAIL; + + return T32_Errno = T32_INBUFFER[2]; + } + while (size > 0) { + len = size; + if (len > MaxPacketSize) + len = MaxPacketSize; + + T32_OUTBUFFER[0] = 10; + T32_OUTBUFFER[1] = 0x74; + T32_OUTBUFFER[2] = 0x32; + T32_OUTBUFFER[3] = LINE_GetNextMessageId(); + + SETLONGVAR(T32_OUTBUFFER[4], address); + T32_OUTBUFFER[8] = flags; + T32_OUTBUFFER[9] = 0; + T32_OUTBUFFER[10] = len; + T32_OUTBUFFER[11] = len >> 8; + + memcpy(T32_OUTBUFFER + 12, buffer, len); + + if (LINE_Transmit(12 + ((len + 1) & (~1))) == -1) + return T32_Errno = T32_COM_TRANSMIT_FAIL; + + if (LINE_Receive() == -1) + return T32_Errno = T32_COM_RECEIVE_FAIL; + + if ((T32_Errno = T32_INBUFFER[2]) != 0) + return T32_Errno; + + size -= len; + address += len; + buffer += len; + } + return 0; +} + + +int T32_WriteMemoryEx(dword address, int segment, int access, int attr, byte * buffer, int size) /* Write Memory, extended version */ +{ + int len, hlen; + + while (size > 0) { + len = size; + if (len > MaxPacketSize) + len = MaxPacketSize; + + hlen = 0; + T32_OUTBUFFER[hlen] = 0; + T32_OUTBUFFER[hlen + 1] = 0x74; + T32_OUTBUFFER[hlen + 2] = 0x33; + T32_OUTBUFFER[hlen + 3] = LINE_GetNextMessageId(); + + T32_OUTBUFFER[hlen + 4] = 0x02; + T32_OUTBUFFER[hlen + 5] = (segment == -1) ? 0x00 : 0x40; + hlen += 6; + SETLONGVAR(T32_OUTBUFFER[hlen], address); + hlen += 4; + if (segment != -1) { + SETLONGVAR(T32_OUTBUFFER[hlen], segment); + hlen += 4; + } + SETLONGVAR(T32_OUTBUFFER[hlen], access); + hlen += 2; + SETLONGVAR(T32_OUTBUFFER[hlen], attr); + hlen += 4; + SETLONGVAR(T32_OUTBUFFER[hlen], len); + hlen += 2; + + memcpy(T32_OUTBUFFER + hlen, buffer, len); + hlen += ((len + 1) & (~1)); + + T32_OUTBUFFER[hlen] = 0; + T32_OUTBUFFER[hlen + 1] = 0; + hlen += 2; + + if (LINE_Transmit(hlen) == -1) + return T32_Errno = T32_COM_TRANSMIT_FAIL; + + if (LINE_Receive() == -1) + return T32_Errno = T32_COM_RECEIVE_FAIL; + + if ((T32_Errno = T32_INBUFFER[2]) != 0) + return T32_Errno; + + if ((T32_Errno = T32_INBUFFER[4]) != 0) + return T32_Errno; + + size -= len; + if (!(attr & T32_MEMORY_ATTR_NOINCREMENT)) + address += len; + buffer += len; + } + return 0; +} + + + +/* + * ADDRESS memory address in target memory + * ACCESS memory access specifier + * BUFFER output buffer + * SIZE size of data in bytes + */ + +int T32_ReadMemory(dword address, int access, byte * buffer, int size) /* Read Memory */ +{ + int len; + + while (size > 0) { + len = size; + if (len > MaxPacketSize) + len = MaxPacketSize; + + T32_OUTBUFFER[0] = 10; + T32_OUTBUFFER[1] = 0x74; + T32_OUTBUFFER[2] = 0x30; + T32_OUTBUFFER[3] = LINE_GetNextMessageId(); + + SETLONGVAR(T32_OUTBUFFER[4], address); + T32_OUTBUFFER[8] = access; + T32_OUTBUFFER[9] = 0; + T32_OUTBUFFER[10] = len; + T32_OUTBUFFER[11] = len >> 8; + + if (LINE_Transmit(12) == -1) + return T32_Errno = T32_COM_TRANSMIT_FAIL; + + if (LINE_Receive() == -1) + return T32_Errno = T32_COM_RECEIVE_FAIL; + + memcpy(buffer, T32_INBUFFER + 4, len); + + if ((T32_Errno = T32_INBUFFER[2]) != 0) + return T32_Errno; + + size -= len; + address += len; + buffer += len; + } + return 0; +} + + +int T32_ReadMemoryEx(dword address, int segment, int access, int attr, byte * buffer, int size) /* Read Memory, extended version */ +{ + int len, hlen; + + while (size > 0) { + len = size; + if (len > MaxPacketSize) + len = MaxPacketSize; + + hlen = 0; + T32_OUTBUFFER[hlen] = 0; + T32_OUTBUFFER[hlen + 1] = 0x74; + T32_OUTBUFFER[hlen + 2] = 0x33; + T32_OUTBUFFER[hlen + 3] = LINE_GetNextMessageId(); + + T32_OUTBUFFER[hlen + 4] = 0x01; + T32_OUTBUFFER[hlen + 5] = (segment == -1) ? 0x00 : 0x40; + hlen += 6; + SETLONGVAR(T32_OUTBUFFER[hlen], address); + hlen += 4; + if (segment != -1) { + SETLONGVAR(T32_OUTBUFFER[hlen], segment); + hlen += 4; + } + SETLONGVAR(T32_OUTBUFFER[hlen], access); + hlen += 2; + SETLONGVAR(T32_OUTBUFFER[hlen], attr); + hlen += 4; + SETLONGVAR(T32_OUTBUFFER[hlen], len); + hlen += 2; + T32_OUTBUFFER[hlen] = 0; + T32_OUTBUFFER[hlen + 1] = 0; + hlen += 2; + + if (LINE_Transmit(hlen) == -1) + return T32_Errno = T32_COM_TRANSMIT_FAIL; + + if (LINE_Receive() == -1) + return T32_Errno = T32_COM_RECEIVE_FAIL; + + if ((T32_Errno = T32_INBUFFER[2]) != 0) + return T32_Errno; + + if ((T32_Errno = T32_INBUFFER[4]) != 0) + return T32_Errno; + + memcpy(buffer, T32_INBUFFER + 8, len); + + size -= len; + if (!(attr & T32_MEMORY_ATTR_NOINCREMENT)) + address += len; + buffer += len; + } + return 0; +} + + +/* + * MASK1 defines the registers to be set + * MASK2 + * BUFFER array of all registers + */ + +int T32_WriteRegister(dword mask1, dword mask2, dword *buffer) /* Write Registers */ +{ + int index, i; + dword tmp; + + index = 12; + tmp = mask1; + SETLONGVAR(T32_OUTBUFFER[4], tmp); + tmp = mask2; + SETLONGVAR(T32_OUTBUFFER[8], tmp); + + for (i = 0; i < 32; i++) { + if (mask1 & 1l) { + tmp = *buffer; + SETLONGVAR(T32_OUTBUFFER[index], tmp); + index += 4; + } + buffer++; + mask1 >>= 1; + } + + for (; i < 64; i++) { + if (mask2 & 1l) { + tmp = *buffer; + SETLONGVAR(T32_OUTBUFFER[index], tmp); + index += 4; + } + buffer++; + mask2 >>= 1; + } + + T32_OUTBUFFER[0] = index; + T32_OUTBUFFER[1] = 0x74; + T32_OUTBUFFER[2] = 0x21; + T32_OUTBUFFER[3] = LINE_GetNextMessageId(); + + if (LINE_Transmit(index) == -1) + return T32_Errno = T32_COM_TRANSMIT_FAIL; + + if (LINE_Receive() == -1) + return T32_Errno = T32_COM_RECEIVE_FAIL; + + + return T32_Errno = T32_INBUFFER[2]; +} + + +/* + * MASK1 defines the registers to be read + * MASK2 + * BUFFER array of all registers + */ + +int T32_ReadRegister(dword mask1, dword mask2, dword *buffer) /* Read Registers */ +{ + int index, i; + dword tmp; + + tmp = mask1; + SETLONGVAR(T32_OUTBUFFER[4], tmp); + tmp = mask2; + SETLONGVAR(T32_OUTBUFFER[8], tmp); + + T32_OUTBUFFER[0] = 12; + T32_OUTBUFFER[1] = 0x74; + T32_OUTBUFFER[2] = 0x20; + T32_OUTBUFFER[3] = LINE_GetNextMessageId(); + + if (LINE_Transmit(12) == -1) + return T32_Errno = T32_COM_TRANSMIT_FAIL; + + if (LINE_Receive() == -1) + return T32_Errno = T32_COM_RECEIVE_FAIL; + + + index = 4; + for (i = 0; i < 32; i++) { + if (mask1 & 1l) { + SETLONGVAR(tmp, T32_INBUFFER[index]); + index += 4; + *buffer = tmp; + } else + *buffer = 0x0; + buffer++; + mask1 >>= 1; + } + + for (; i < 64; i++) { + if (mask2 & 1l) { + SETLONGVAR(tmp, T32_INBUFFER[index]); + index += 4; + *buffer = tmp; + } else + *buffer = 0x0; + buffer++; + mask2 >>= 1; + } + + return T32_Errno = T32_INBUFFER[2]; +} + + +int T32_ReadPP ( dword *pp ) /* Returns Program Pointer */ +{ + + T32_OUTBUFFER[0] = 2; + T32_OUTBUFFER[1] = 0x74; + T32_OUTBUFFER[2] = 0x22; + T32_OUTBUFFER[3] = LINE_GetNextMessageId(); + + if (LINE_Transmit(4) == -1) + return T32_Errno = T32_COM_TRANSMIT_FAIL; + + if (LINE_Receive() == -1) + return T32_Errno = T32_COM_RECEIVE_FAIL; + + + SETLONGVAR(*pp, T32_INBUFFER[4]); + + return T32_Errno = T32_INBUFFER[2]; +} + + +/* + * ADDRESS memory address + * FLAGS memory access flags + * BREAKP breakpoint type, bit 8 set to clear breakpoints + * SIZE size of range + */ + +int T32_WriteBreakpoint(dword address, int flags, int breakp, int size) /* Set/Clear Breakpoints */ +{ + int len; + + while (size > 0) { + len = size; + if (len > MaxPacketSize) + len = MaxPacketSize; + + T32_OUTBUFFER[0] = 10; + T32_OUTBUFFER[1] = 0x74; + T32_OUTBUFFER[2] = (breakp & 0x100) ? 0x42 : 0x41; + T32_OUTBUFFER[3] = LINE_GetNextMessageId(); + + SETLONGVAR(T32_OUTBUFFER[4], address); + T32_OUTBUFFER[8] = flags; + T32_OUTBUFFER[9] = breakp; + T32_OUTBUFFER[10] = len; + T32_OUTBUFFER[11] = len >> 8; + + if (LINE_Transmit(12) == -1) + return T32_Errno = T32_COM_TRANSMIT_FAIL; + + if (LINE_Receive() == -1) + return T32_Errno = T32_COM_RECEIVE_FAIL; + + if ((T32_Errno = T32_INBUFFER[2]) != 0) + return T32_Errno; + + size -= len; + address += len; + } + return 0; +} + + +/* + * ADDRESS memory address + * FLAGS memory access flags + * BUFFER buffer to receive breakpoint information + * SIZE size of range + */ + +int T32_ReadBreakpoint(dword address, int flags, word *buffer, int size) /* Get Breakpoint/Flag Information */ +{ + int i, len; + int outindex = 0; + + while (size > 0) { + len = size; + if (len > MaxPacketSize / 2) + len = MaxPacketSize / 2; + + T32_OUTBUFFER[0] = 10; + T32_OUTBUFFER[1] = 0x74; + T32_OUTBUFFER[2] = 0x40; + T32_OUTBUFFER[3] = LINE_GetNextMessageId(); + + SETLONGVAR(T32_OUTBUFFER[4], address); + T32_OUTBUFFER[8] = flags; + T32_OUTBUFFER[9] = 0; + T32_OUTBUFFER[10] = len; + T32_OUTBUFFER[11] = len >> 8; + + if (LINE_Transmit(12) == -1) + return T32_Errno = T32_COM_TRANSMIT_FAIL; + + if (LINE_Receive() == -1) + return T32_Errno = T32_COM_RECEIVE_FAIL; + + for (i = 0; i < len; i++) { + buffer[outindex++] = T32_INBUFFER[4 + 2 * i] | (T32_INBUFFER[4 + 2 * i + 1] << 8); + } + + if ((T32_Errno = T32_INBUFFER[2]) != 0) + return T32_Errno; + + size -= len; + address += len; + } + return 0; +} + + +int T32_Step(void) /* Single Step */ +{ + + T32_OUTBUFFER[0] = 2; + T32_OUTBUFFER[1] = 0x74; + T32_OUTBUFFER[2] = 0x50; + T32_OUTBUFFER[3] = LINE_GetNextMessageId(); + + if (LINE_Transmit(4) == -1) + return T32_Errno = T32_COM_TRANSMIT_FAIL; + + if (LINE_Receive() == -1) + return T32_Errno = T32_COM_RECEIVE_FAIL; + + + return T32_Errno = T32_INBUFFER[2]; +} + +/* + * MODE 0=ASM, 1=HLL, 2=MIX + */ + +int T32_StepMode(int mode) /* Single Step in Mode */ +{ + + T32_OUTBUFFER[0] = 2; + T32_OUTBUFFER[1] = 0x74; + T32_OUTBUFFER[2] = 0x54; + T32_OUTBUFFER[3] = LINE_GetNextMessageId(); + T32_OUTBUFFER[4] = mode; + T32_OUTBUFFER[5] = 0; + + if (LINE_Transmit(6) == -1) + return T32_Errno = T32_COM_TRANSMIT_FAIL; + + if (LINE_Receive() == -1) + return T32_Errno = T32_COM_RECEIVE_FAIL; + + return T32_Errno = T32_INBUFFER[2]; +} + +/* + * MODE 0=ASM, 1=HLL, 2=MIX + */ + +int T32_SetMode(int mode) /* Set Mode */ +{ + + T32_OUTBUFFER[0] = 2; + T32_OUTBUFFER[1] = 0x74; + T32_OUTBUFFER[2] = 0x53; + T32_OUTBUFFER[3] = LINE_GetNextMessageId(); + T32_OUTBUFFER[4] = mode; + T32_OUTBUFFER[5] = 0; + + if (LINE_Transmit(6) == -1) + return T32_Errno = T32_COM_TRANSMIT_FAIL; + + if (LINE_Receive() == -1) + return T32_Errno = T32_COM_RECEIVE_FAIL; + + return T32_Errno = T32_INBUFFER[2]; +} + + +int T32_Go(void) /* Start Realtime */ +{ + + T32_OUTBUFFER[0] = 2; + T32_OUTBUFFER[1] = 0x74; + T32_OUTBUFFER[2] = 0x51; + T32_OUTBUFFER[3] = LINE_GetNextMessageId(); + + if (LINE_Transmit(4) == -1) + return T32_Errno = T32_COM_TRANSMIT_FAIL; + + if (LINE_Receive() == -1) + return T32_Errno = T32_COM_RECEIVE_FAIL; + + return T32_Errno = T32_INBUFFER[2]; +} + + +int T32_Break(void) /* Stop Realtime */ +{ + + T32_OUTBUFFER[0] = 2; + T32_OUTBUFFER[1] = 0x74; + T32_OUTBUFFER[2] = 0x52; + T32_OUTBUFFER[3] = LINE_GetNextMessageId(); + + if (LINE_Transmit(4) == -1) + return T32_Errno = T32_COM_TRANSMIT_FAIL; + + if (LINE_Receive() == -1) + return T32_Errno = T32_COM_RECEIVE_FAIL; + + return T32_Errno = T32_INBUFFER[2]; +} + + +/* + * NAME commandline + */ + +int T32_Cmd(char *name) /* Executes a command line */ +{ + int len; + + len = strlen(name); + + if (len >= 256) + return T32_Errno = T32_COM_PARA_FAIL; + + T32_OUTBUFFER[0] = len + 3; + T32_OUTBUFFER[1] = 0x72; + T32_OUTBUFFER[2] = 0x02; + T32_OUTBUFFER[3] = LINE_GetNextMessageId(); + strcpy((char *) (T32_OUTBUFFER + 4), name); + + if (LINE_Transmit((len + 5 + 1) & (~1)) == -1) + return T32_Errno = T32_COM_TRANSMIT_FAIL; + + if (LINE_Receive() == -1) + return T32_Errno = T32_COM_RECEIVE_FAIL; + + return T32_Errno = T32_INBUFFER[2]; +} + + +/************************************************************************** + + T32_GetPracticeState - Return information about the state of PRACTICE + + Parameter: out int * pstate Pointer to variable to return the state + 0 not running + 1 running + + Return: int 0 or Number of Error + + +***************************************************************************/ + +int T32_GetPracticeState(int * pstate) /* Returns the run-state of PRACTICE */ +{ + + T32_OUTBUFFER[0] = 2; + T32_OUTBUFFER[1] = 0x72; + T32_OUTBUFFER[2] = 0x03; + T32_OUTBUFFER[3] = LINE_GetNextMessageId(); + + if (LINE_Transmit(4) == -1) + return T32_Errno = T32_COM_TRANSMIT_FAIL; + + if (LINE_Receive() == -1) + return T32_Errno = T32_COM_RECEIVE_FAIL; + + *pstate = T32_INBUFFER[4]; + + return T32_Errno = T32_INBUFFER[2]; +} + + +/****** Executing a PRACTICE command with given windows handler *****/ + +int T32_CmdWin (dword handle, char* command) +{ + int len; + + len = strlen(command); + + if (len >= 256) + return T32_Errno = T32_COM_PARA_FAIL; + + T32_OUTBUFFER[0] = len + 7; + T32_OUTBUFFER[1] = 0x75; + T32_OUTBUFFER[2] = 0x02; + T32_OUTBUFFER[3] = LINE_GetNextMessageId(); + + SETLONGVAR(T32_OUTBUFFER[4], handle); + strcpy((char *) (T32_OUTBUFFER + 8), command); + + if (LINE_Transmit((len + 9 + 1) & (~1)) == -1) + return T32_Errno = T32_COM_TRANSMIT_FAIL; + + if (LINE_Receive() == -1) + return T32_Errno = T32_COM_RECEIVE_FAIL; + + return T32_Errno = T32_INBUFFER[2]; +} + + +int T32_EvalGet (dword *peval) /* Returns Evaluation Result */ +{ + + T32_OUTBUFFER[0] = 2; + T32_OUTBUFFER[1] = 0x74; + T32_OUTBUFFER[2] = 0x14; + T32_OUTBUFFER[3] = LINE_GetNextMessageId(); + + if (LINE_Transmit(4) == -1) + return T32_Errno = T32_COM_TRANSMIT_FAIL; + + if (LINE_Receive() == -1) + return T32_Errno = T32_COM_RECEIVE_FAIL; + + SETLONGVAR(*peval, T32_INBUFFER[4]); + + return T32_Errno = T32_INBUFFER[2]; +} + + +int T32_GetMessage (char *message, word *mode) +{ + dword dmode; + + T32_OUTBUFFER[0] = 0x02; + T32_OUTBUFFER[1] = 0x76; + T32_OUTBUFFER[2] = 0x00; + T32_OUTBUFFER[3] = LINE_GetNextMessageId(); + + if (LINE_Transmit(4)) + return T32_Errno = T32_COM_TRANSMIT_FAIL; + + if (LINE_Receive() == -1) + return T32_Errno = T32_COM_RECEIVE_FAIL; + + strcpy(message, (char *) T32_INBUFFER + 8); + + SETLONGVAR(dmode, T32_INBUFFER[4]); + *mode = (word) dmode; + + return T32_Errno = T32_INBUFFER[2]; +} + + +int T32_GetTriggerMessage (char *message) +{ + T32_OUTBUFFER[0] = 0x02; + T32_OUTBUFFER[1] = 0x74; + T32_OUTBUFFER[2] = 0x63; + T32_OUTBUFFER[3] = LINE_GetNextMessageId(); + if (LINE_Transmit(4)) + return T32_Errno = T32_COM_TRANSMIT_FAIL; + if (LINE_Receive() == -1) + return T32_Errno = T32_COM_RECEIVE_FAIL; + strcpy(message, (char *) T32_INBUFFER + 4); + return T32_Errno = T32_INBUFFER[2]; +} + + +int T32_GetSymbol (char *symbol, dword *address, dword *size, dword *access) +{ + int len; + + len = strlen(symbol); + + if (len >= 256) + return T32_Errno = T32_COM_PARA_FAIL; + + T32_OUTBUFFER[0] = len + 3; + T32_OUTBUFFER[1] = 0x74; + T32_OUTBUFFER[2] = 0x62; + T32_OUTBUFFER[3] = LINE_GetNextMessageId(); + strcpy((char *) (T32_OUTBUFFER + 4), symbol); + + if (LINE_Transmit((len + 5 + 1) & (~1)) == -1) + return T32_Errno = T32_COM_TRANSMIT_FAIL; + + if (LINE_Receive() == -1) + return T32_Errno = T32_COM_RECEIVE_FAIL; + + SETLONGVAR(*address, T32_INBUFFER[4]); + SETLONGVAR(*size, T32_INBUFFER[8]); + SETLONGVAR(*access, T32_INBUFFER[12]); + + return T32_Errno = T32_INBUFFER[2]; +} + + +int T32_GetSource (dword address, char *filename, dword *line) +{ + + T32_OUTBUFFER[0] = 6; + T32_OUTBUFFER[1] = 0x74; + T32_OUTBUFFER[2] = 0x60; + T32_OUTBUFFER[3] = LINE_GetNextMessageId(); + SETLONGVAR(T32_OUTBUFFER[4], address); + + if (LINE_Transmit(8) == -1) + return T32_Errno = T32_COM_TRANSMIT_FAIL; + + if (LINE_Receive() == -1) + return T32_Errno = T32_COM_RECEIVE_FAIL; + + strcpy(filename, (char *) T32_INBUFFER + 8); + + *line = 0; + SETLONGVAR(*line, T32_INBUFFER[4]); + + return T32_Errno = T32_INBUFFER[2]; +} + + +int T32_GetSelectedSource (char *filename, dword *line) +{ + + T32_OUTBUFFER[0] = 2; + T32_OUTBUFFER[1] = 0x74; + T32_OUTBUFFER[2] = 0x61; + T32_OUTBUFFER[3] = LINE_GetNextMessageId(); + + if (LINE_Transmit(4) == -1) + return T32_Errno = T32_COM_TRANSMIT_FAIL; + + if (LINE_Receive() == -1) + return T32_Errno = T32_COM_RECEIVE_FAIL; + + strcpy(filename, (char *) T32_INBUFFER + 8); + + *line = 0; + SETLONGVAR(*line, T32_INBUFFER[4]); + + return T32_Errno = T32_INBUFFER[2]; +} + + +/************************************************************************** + + Trace interface + +***************************************************************************/ + +/* + * STATE Analyzer state + * SIZE Size of Tracebuffer + * MIN Min. Record Number + * MAX Max. Record Number + */ + +int T32_AnaStatusGet (byte *state, long *size, long *min, long *max ) /* Get Analyzer Status */ +{ + + T32_OUTBUFFER[0] = 2; + T32_OUTBUFFER[1] = 0x74; + T32_OUTBUFFER[2] = 0x80; + T32_OUTBUFFER[3] = LINE_GetNextMessageId(); + + if (LINE_Transmit(4) == -1) + return T32_Errno = T32_COM_TRANSMIT_FAIL; + + if (LINE_Receive() == -1) + return T32_Errno = T32_COM_RECEIVE_FAIL; + + *state = T32_INBUFFER[4]; + SETLONGVAR(*size, T32_INBUFFER[8]); + SETLONGVAR(*min, T32_INBUFFER[12]); + SETLONGVAR(*max, T32_INBUFFER[16]); + + if ((T32_Errno = T32_INBUFFER[2]) != 0) + return T32_Errno; + + return 0; +} + + +int T32_AnaRecordGet(long record, byte * buffer, int len) +{ + word wlen; + dword drecord; + + T32_OUTBUFFER[0] = 8; + T32_OUTBUFFER[1] = 0x74; + T32_OUTBUFFER[2] = 0x81; + T32_OUTBUFFER[3] = LINE_GetNextMessageId(); + + drecord = (dword) record; + wlen = (word) len; + SETLONGVAR(T32_OUTBUFFER[4], drecord); + SETWORDVAR(T32_OUTBUFFER[8], wlen); + + if (LINE_Transmit(10) == -1) + return T32_Errno = T32_COM_TRANSMIT_FAIL; + + if (LINE_Receive() == -1) + return T32_Errno = T32_COM_RECEIVE_FAIL; + + if (!len) + len = 128; + + memcpy(buffer, T32_INBUFFER + 4, len); + + if ((T32_Errno = T32_INBUFFER[2]) != 0) + return T32_Errno; + + return 0; +} + + +int T32_GetTraceState(int tracetype, int * state, long * size, long * min, long * max) +{ + + T32_OUTBUFFER[0] = 2; + T32_OUTBUFFER[1] = 0x74; + T32_OUTBUFFER[2] = 0x82; + T32_OUTBUFFER[3] = LINE_GetNextMessageId(); + T32_OUTBUFFER[4] = tracetype; + T32_OUTBUFFER[5] = 0; + + if (LINE_Transmit(6) == -1) + return T32_Errno = T32_COM_TRANSMIT_FAIL; + + if (LINE_Receive() == -1) + return T32_Errno = T32_COM_RECEIVE_FAIL; + + *state = T32_INBUFFER[4]; + SETLONGVAR(*size, T32_INBUFFER[8]); + SETLONGVAR(*min, T32_INBUFFER[12]); + SETLONGVAR(*max, T32_INBUFFER[16]); + + if ((T32_Errno = T32_INBUFFER[2]) != 0) + return T32_Errno; + + return 0; +} + + +int T32_ReadTrace(int tracetype, long record, int nrecords, unsigned long mask, byte * buffer) +{ + int nbytes; + word nrecs; + dword drecord, dmask; + unsigned long mask2; + + if (nrecords < 0) { + T32_Errno = T32_COM_PARA_FAIL; + return -1; + } + dmask = (dword) mask; + nbytes = 0; + for (mask2 = mask; mask2; mask2 >>= 1) { + if (mask2 & 1) + nbytes += 4; + } + + while (nrecords > 0) { + if (nrecords * nbytes > LINE_SBLOCK) + nrecs = LINE_SBLOCK / nbytes; + else + nrecs = (word) nrecords; + drecord = (dword) record; + + T32_OUTBUFFER[0] = 8; + T32_OUTBUFFER[1] = 0x74; + T32_OUTBUFFER[2] = 0x83; + T32_OUTBUFFER[3] = LINE_GetNextMessageId(); + T32_OUTBUFFER[4] = tracetype; + T32_OUTBUFFER[5] = 0; + + SETLONGVAR(T32_OUTBUFFER[6], drecord); + SETLONGVAR(T32_OUTBUFFER[10], dmask); + SETWORDVAR(T32_OUTBUFFER[14], nrecs); + + if (LINE_Transmit(16) == -1) + return T32_Errno = T32_COM_TRANSMIT_FAIL; + + if (LINE_Receive() == -1) + return T32_Errno = T32_COM_RECEIVE_FAIL; + + memcpy(buffer, T32_INBUFFER + 4, nrecs * nbytes); + + if ((T32_Errno = T32_INBUFFER[2]) != 0) + return T32_Errno; + + record += nrecs; + nrecords -= nrecs; + buffer += nrecs * nbytes; + } + + return 0; +} + + +/************************************************************************** + + T32_Fdx* - Fast Data Exchange + +***************************************************************************/ + +int T32_Fdx_Open(char * name, char * mode) +{ + int len, lenm; + dword id; + + len = strlen(name); + lenm = strlen(mode); + T32_OUTBUFFER[0] = 3 + len+lenm+1; + T32_OUTBUFFER[1] = 0x74; + T32_OUTBUFFER[2] = 0xa1; + T32_OUTBUFFER[3] = LINE_GetNextMessageId(); + + strcpy((char *) (T32_OUTBUFFER + 4), name); + strcpy((char *) (T32_OUTBUFFER + 4+len+1), mode); + + if (LINE_Transmit((len + lenm + 6 + 1) & (~1)) == -1) { + T32_Errno = T32_COM_TRANSMIT_FAIL; + return -1; + } + + if (LINE_Receive() == -1) { + T32_Errno = T32_COM_RECEIVE_FAIL; + return -1; + } + + if ((T32_Errno = T32_INBUFFER[2]) != 0) { + return -1; + } + + SETLONGVAR(id, T32_INBUFFER[4]); + + return (int) id; +} + + +int T32_Fdx_Close(int channel) +{ + dword id; + + id = (dword) channel; + T32_OUTBUFFER[0] = 6; + T32_OUTBUFFER[1] = 0x74; + T32_OUTBUFFER[2] = 0xa6; + T32_OUTBUFFER[3] = LINE_GetNextMessageId(); + + SETLONGVAR(T32_OUTBUFFER[4], id); + + if (LINE_Transmit(8) == -1) { + T32_Errno = T32_COM_TRANSMIT_FAIL; + return -1; + } + if (LINE_Receive() == -1) { + T32_Errno = T32_COM_RECEIVE_FAIL; + return -1; + } + if ((T32_Errno = T32_INBUFFER[2]) != 0) { + return -1; + } + return 0; +} + + +int T32_Fdx_Resolve(char * name) +{ + int len; + dword id; + + len = strlen(name); + T32_OUTBUFFER[0] = 3 + len; + T32_OUTBUFFER[1] = 0x74; + T32_OUTBUFFER[2] = 0xa0; + T32_OUTBUFFER[3] = LINE_GetNextMessageId(); + + strcpy((char *) (T32_OUTBUFFER + 4), name); + + if (LINE_Transmit((len + 5 + 1) & (~1)) == -1) { + T32_Errno = T32_COM_TRANSMIT_FAIL; + return -1; + } + + if (LINE_Receive() == -1) { + T32_Errno = T32_COM_RECEIVE_FAIL; + return -1; + } + + if ((T32_Errno = T32_INBUFFER[2]) != 0) { + return -1; + } + + SETLONGVAR(id, T32_INBUFFER[4]); + + return (int) id; +} + + +int T32_Fdx_ReceivePoll(int channel, void * data, int width, int maxsize) +{ + int size, len; + dword id; + + id = (dword) channel; + if (width <= 0 || width > 16) { + T32_Errno = T32_COM_PARA_FAIL; + return -1; + } + if (maxsize <= 0) { + T32_Errno = T32_COM_PARA_FAIL; + return -1; + } + maxsize *= width; + if (maxsize > LINE_SBLOCK) + maxsize = LINE_SBLOCK; + + T32_OUTBUFFER[0] = 6; + T32_OUTBUFFER[1] = 0x74; + T32_OUTBUFFER[2] = 0xa2; + T32_OUTBUFFER[3] = LINE_GetNextMessageId(); + + SETLONGVAR(T32_OUTBUFFER[4], id); + + T32_OUTBUFFER[8] = width; + +#if defined(HIGH_LOW) || defined(HIGH_LOW_BYTE) + T32_OUTBUFFER[8] |= 0x80; +#endif + + T32_OUTBUFFER[9] = 0; + + if (LINE_Transmit(10) == -1) { + T32_Errno = T32_COM_TRANSMIT_FAIL; + return -1; + } + if ((len = LINE_Receive()) == -1) { + T32_Errno = T32_COM_RECEIVE_FAIL; + return -1; + } + if ((T32_Errno = T32_INBUFFER[2]) != 0) { + return -1; + } + len -= 4; + if (len < 0) { + T32_Errno = T32_COM_SEQ_FAIL; + return -1; + } + size = (len > maxsize) ? maxsize : len; + + if (size > 0) + memcpy(data, T32_INBUFFER + 4, size); + + if (width <= 1) + return size; + return size / width; +} + + +int T32_Fdx_Receive(int channel, void * data, int width, int maxsize) +{ + int size, len, paramWidth; + dword id; + + paramWidth=width; + width&=0x3F; + if (width <= 0 || width > 16) { + T32_Errno = T32_COM_PARA_FAIL; + return -1; + } + if (maxsize <= 0) { + T32_Errno = T32_COM_PARA_FAIL; + return -1; + } + maxsize *= width; + if (maxsize > LINE_SBLOCK) + maxsize = LINE_SBLOCK; + + do { + id = (dword) channel; + T32_OUTBUFFER[0] = 6; + T32_OUTBUFFER[1] = 0x74; + T32_OUTBUFFER[2] = 0xa3; + T32_OUTBUFFER[3] = LINE_GetNextMessageId(); + + SETLONGVAR(T32_OUTBUFFER[4], id); + + T32_OUTBUFFER[8] = paramWidth; +#if defined(HIGH_LOW) || defined(HIGH_LOW_BYTE) + T32_OUTBUFFER[8] |= 0x80; +#endif + + T32_OUTBUFFER[9] = 0; + + if (LINE_Transmit(10) == -1) { + T32_Errno = T32_COM_TRANSMIT_FAIL; + return -1; + } + if ((len = LINE_Receive()) == -1) { + T32_Errno = T32_COM_RECEIVE_FAIL; + return -1; + } + if ((T32_Errno = T32_INBUFFER[2]) != 0) { + return -1; + } + len -= 4; + if (len < 0) { + T32_Errno = T32_COM_SEQ_FAIL; + return -1; + } + size = (len > maxsize) ? maxsize : len; + + } while (size <= 0); + + memcpy(data, T32_INBUFFER + 4, size); + + if (width <= 1) + return size; + return size / width; +} + + +int T32_Fdx_SendPoll(int channel, void * data, int width, int size) +{ + int bsize; + dword id; + + if (width <= 0 || width > 16) { + T32_Errno = T32_COM_PARA_FAIL; + return -1; + } + bsize = size * width; + if (bsize > LINE_SBLOCK || bsize <= 0) { + T32_Errno = T32_COM_PARA_FAIL; + return -1; + } + id = (dword) channel; + T32_OUTBUFFER[0] = 0; + T32_OUTBUFFER[1] = 0x74; + T32_OUTBUFFER[2] = 0xa4; + T32_OUTBUFFER[3] = LINE_GetNextMessageId(); + + SETLONGVAR(T32_OUTBUFFER[4], id); + +#if defined(HIGH_LOW) || defined(HIGH_LOW_BYTE) + width |= 0x80; +#endif + + T32_OUTBUFFER[8] = width; + T32_OUTBUFFER[9] = 0; + T32_OUTBUFFER[10] = (10 + bsize) & 0xff; + T32_OUTBUFFER[11] = ((10 + bsize) >> 8) & 0xff; + memcpy(T32_OUTBUFFER + 12, data, bsize); + + if (LINE_Transmit((bsize + 12 + 1) & (~1)) == -1) { + T32_Errno = T32_COM_TRANSMIT_FAIL; + return -1; + } + if (LINE_Receive() == -1) { + T32_Errno = T32_COM_RECEIVE_FAIL; + return -1; + } + if (T32_INBUFFER[2] == 1) + return 0; + if ((T32_Errno = T32_INBUFFER[2]) != 0) { + return -1; + } + return size; +} + + +int T32_Fdx_Send(int channel, void * data, int width, int size) +{ + int bsize; + dword id; + + if (width <= 0 || width > 16) { + T32_Errno = T32_COM_PARA_FAIL; + return -1; + } + bsize = size * width; + if (bsize > LINE_SBLOCK || bsize <= 0) { + T32_Errno = T32_COM_PARA_FAIL; + return -1; + } + id = (dword) channel; + + do { + T32_OUTBUFFER[0] = 0; + T32_OUTBUFFER[1] = 0x74; + T32_OUTBUFFER[2] = 0xa5; + T32_OUTBUFFER[3] = LINE_GetNextMessageId(); + SETLONGVAR(T32_OUTBUFFER[4], id); + +#if defined(HIGH_LOW) || defined(HIGH_LOW_BYTE) + width |= 0x80; +#endif + + T32_OUTBUFFER[8] = width; + T32_OUTBUFFER[9] = 0; + T32_OUTBUFFER[10] = (10 + bsize) & 0xff; + T32_OUTBUFFER[11] = ((10 + bsize) >> 8) & 0xff; + memcpy(T32_OUTBUFFER + 12, data, bsize); + + if (LINE_Transmit((bsize + 12 + 1) & (~1)) == -1) { + T32_Errno = T32_COM_TRANSMIT_FAIL; + return -1; + } + if (LINE_Receive() == -1) { + T32_Errno = T32_COM_RECEIVE_FAIL; + return -1; + } + } while (T32_INBUFFER[2] == 1); + + if ((T32_Errno = T32_INBUFFER[2]) != 0) { + return -1; + } + return size; +} + + +T32_Fdx_Stream *T32_Fdx_OpenStream(char *name, char *mode) +{ + int channel; + T32_Fdx_Stream *pstream; + + pstream = (T32_Fdx_Stream *) malloc(sizeof(T32_Fdx_Stream)); + if (!pstream) + return (T32_Fdx_Stream *) 0; + + channel = T32_Fdx_Open(name, mode); + if (channel == -1) + return (T32_Fdx_Stream *) 0; + + memset(pstream, 0, sizeof(T32_Fdx_Stream)); + + pstream->channel = channel; + return pstream; +} + +int T32_Fdx_CloseStream(T32_Fdx_Stream * pstream) +{ + T32_Fdx_Close(pstream->channel); + free(pstream); + return 0; +} + +int T32_Fdx_ReceiveStreamNext(T32_Fdx_Stream * pstream, unsigned char *target, int width, int size) +{ + int len; + + len = T32_Fdx_Receive(pstream->channel, pstream->buffer, width | 0x40, sizeof(pstream->buffer)); + if (len <= 0) + return len; + pstream->ptr = pstream->buffer; + pstream->ptrend = pstream->buffer + len; + return T32_Fdx_ReceiveStream(pstream, target, width, size); +} + +/************************************************************************** + + T32_TapAccess* - Low level JTAG access functions + +***************************************************************************/ + +typedef struct tapAccessHeader +{ + struct tapAccessHeader * next; + int cmd; + int numberofbits; + int numberofinbits; + byte * pinbits; + unsigned char outbits[1]; +} +tapAccessHeader; + + +typedef struct tapAccessHandle +{ + struct tapAccessHeader * first; + struct tapAccessHeader * current; +} +tapAccessHandle; + + +static int TAPAccess(int cmd, T32_TAPACCESS_HANDLE connection, int numberofbits, byte * poutbits, byte * pinbits, int numberofinbits) +{ + int size, len; + unsigned char *ptr; + int indatasize; + + ptr = T32_OUTBUFFER + 6; + indatasize = (numberofinbits + 7)/8; + + if (numberofbits >= 0) { + if (poutbits) { + cmd |= 2; + } + if (pinbits) { + cmd |= 1; + } + if (numberofbits < 0x0f) { + *ptr++ = (cmd << 4) | numberofbits; + } else if (numberofbits < 0xff) { + *ptr++ = (cmd << 4) | 0x0f; + *ptr++ = numberofbits; + } else { + *ptr++ = (cmd << 4) | 0x0f; + *ptr++ = 0xff; + ptr[0] = (numberofbits & 0xff); + ptr[1] = ((numberofbits >> 8) & 0xff); + ptr[2] = ((numberofbits >> 16) & 0xff); + ptr[3] = ((numberofbits >> 24) & 0xff); + ptr += 4; + } + + size = (numberofbits + 7) / 8; + if (size && (cmd & 2)) { + memcpy(ptr, poutbits, size); + ptr += size; + } + } + + if (connection != T32_TAPACCESS_HOLD) + *ptr++ = 0; + + size = (int) (ptr - (T32_OUTBUFFER + 6)); + + T32_OUTBUFFER[0] = 0; + T32_OUTBUFFER[1] = 0x74; + T32_OUTBUFFER[2] = (connection == T32_TAPACCESS_HOLD) ? 0x93 : 0x92; + T32_OUTBUFFER[3] = LINE_GetNextMessageId(); + T32_OUTBUFFER[4] = (4 + size) & 0xff; + T32_OUTBUFFER[5] = ((4 + size) >> 8) & 0xff; + + if (LINE_Transmit(6 + ((size + 1) & (~1))) == -1) + return T32_Errno = T32_COM_TRANSMIT_FAIL; + + if ((len = LINE_Receive()) == -1) + return T32_Errno = T32_COM_RECEIVE_FAIL; + + T32_Errno = T32_INBUFFER[2]; + + if (pinbits && len >= indatasize + 4) + memcpy(pinbits, T32_INBUFFER + 4, indatasize); + + return T32_Errno; +} + + +static int TAPAccessStore(int cmd, T32_TAPACCESS_HANDLE connection, int numberofbits, byte * poutbits, byte * pinbits, int numberofinbits) +{ + tapAccessHandle *taphandle; + tapAccessHeader *tapptr; + int size; + + taphandle = (tapAccessHandle *) connection; + + size = (numberofbits + 7) / 8; + tapptr = (tapAccessHeader *) malloc(sizeof(tapAccessHeader) + size); + if (!tapptr) { + T32_Errno = T32_MALLOC_FAIL; + return T32_Errno; + } + + if (poutbits) { + memcpy(tapptr->outbits, poutbits, size); + cmd |= 2; + } + if (pinbits) { + cmd |= 1; + } + + tapptr->next = NULL; + tapptr->cmd = cmd; + tapptr->numberofbits = numberofbits; + tapptr->pinbits = pinbits; + tapptr->numberofinbits = numberofinbits; + + if (taphandle->current) + taphandle->current->next = tapptr; + else + taphandle->first = tapptr; + taphandle->current = tapptr; + + T32_Errno = 0; + return T32_Errno; +} + + +T32_TAPACCESS_HANDLE T32_TAPAccessAlloc(void) +{ + tapAccessHandle *taphandle; + + taphandle = (tapAccessHandle *) malloc(sizeof(tapAccessHandle)); + if (!taphandle) { + T32_Errno = T32_MALLOC_FAIL; + return NULL; + } + + taphandle->first = NULL; + taphandle->current = NULL; + + T32_Errno = 0; + return taphandle; +} + + +static int TAPAccessSend(T32_TAPACCESS_HANDLE connection, int size, byte ** bitptr, int * bitsizesenddata, int *bitsizereceivedata, int npairs) +{ + int i, len; + unsigned char *ptr; + + T32_OUTBUFFER[0] = 0; + T32_OUTBUFFER[1] = 0x74; + T32_OUTBUFFER[2] = (connection == T32_TAPACCESS_HOLD) ? 0x93 : 0x92; + T32_OUTBUFFER[3] = LINE_GetNextMessageId(); + T32_OUTBUFFER[4] = (4 + size) & 0xff; + T32_OUTBUFFER[5] = ((4 + size) >> 8) & 0xff; + + if (LINE_Transmit(6 + ((size + 1) & (~1))) == -1) + return T32_Errno = T32_COM_TRANSMIT_FAIL; + + if ((len = LINE_Receive()) == -1) + return T32_Errno = T32_COM_RECEIVE_FAIL; + + T32_Errno = T32_INBUFFER[2]; + + ptr = T32_INBUFFER + 4; + for (i = 0; i < npairs; i++) { + if (bitptr[i]) { + memcpy(bitptr[i], ptr, (bitsizereceivedata[i] + 7) / 8); + ptr += ((bitsizesenddata[i] + 7) / 8); + } + } + + return T32_Errno; +} + + +int T32_TAPAccessExecute(T32_TAPACCESS_HANDLE connection, T32_TAPACCESS_HANDLE connectionhold) +{ + unsigned char *ptr; + int datasize, size, maxsize, n, cmd, numberofbits; + tapAccessHandle *taphandle; + tapAccessHeader *tapptr; + unsigned char *bitptr[2048]; + int bitsizessend[2048]; + int bitsizesreceive[2048]; + + if (!(connection > T32_TAPACCESS_HOLD)) { + T32_Errno = T32_COM_PARA_FAIL; + return T32_Errno; + } + + taphandle = (tapAccessHandle *) connection; + + ptr = T32_OUTBUFFER + 6; + tapptr = taphandle->first; + datasize = 0; + n = 0; + maxsize = 0x3b00; + + while (tapptr) { + + cmd = tapptr->cmd; + numberofbits = tapptr->numberofbits; + size = (numberofbits + 7) / 8; + + if (datasize >= maxsize) { + if (TAPAccessSend(T32_TAPACCESS_HOLD, (int) (ptr - (T32_OUTBUFFER + 6)), bitptr, bitsizessend, bitsizesreceive, n)) + return T32_Errno; + ptr = T32_OUTBUFFER + 6; + datasize = 0; + n = 0; + } + if (numberofbits < 0x0f) { + *ptr++ = (cmd << 4) | numberofbits; + datasize++; + } else if (numberofbits < 0xff) { + *ptr++ = (cmd << 4) | 0x0f; + *ptr++ = numberofbits; + datasize += 2; + } else { + *ptr++ = (cmd << 4) | 0x0f; + *ptr++ = 0xff; + ptr[0] = (numberofbits & 0xff); + ptr[1] = ((numberofbits >> 8) & 0xff); + ptr[2] = ((numberofbits >> 16) & 0xff); + ptr[3] = ((numberofbits >> 24) & 0xff); + ptr += 4; + datasize += 6; + } + + if (size && (cmd & 2)) { + memcpy(ptr, tapptr->outbits, size); + ptr += size; + } + bitptr[n] = tapptr->pinbits; + bitsizessend[n] = tapptr->numberofbits; + bitsizesreceive[n] = tapptr->numberofinbits; + n++; + + datasize += size; + tapptr = tapptr->next; + } + + if (connectionhold != T32_TAPACCESS_HOLD) + *ptr++ = 0; + + return TAPAccessSend(connectionhold, (int) (ptr - (T32_OUTBUFFER + 6)), bitptr, bitsizessend, bitsizesreceive, n); +} + + +int T32_TAPAccessFree(T32_TAPACCESS_HANDLE connection) +{ + tapAccessHandle *taphandle; + tapAccessHeader *tapptr; + tapAccessHeader *tapptrnext; + + taphandle = (tapAccessHandle *) connection; + + tapptr = taphandle->first; + while (tapptr) { + tapptrnext = tapptr->next; + free(tapptr); + tapptr = tapptrnext; + } + + free(taphandle); + + T32_Errno = 0; + return 0; +} + + +int T32_TAPAccessSetInfo(int irpre, int irpost, int drpre, int drpost, int tristate, int tapstate, int tcklevel, int slave) +{ + unsigned char outbits[20]; + + outbits[0] = irpre & 0xff; + outbits[1] = (irpre >> 8) & 0xff; + outbits[2] = (irpre >> 16) & 0xff; + outbits[3] = (irpre >> 24) & 0xff; + outbits[4] = irpost & 0xff; + outbits[5] = (irpost >> 8) & 0xff; + outbits[6] = (irpost >> 16) & 0xff; + outbits[7] = (irpost >> 24) & 0xff; + outbits[8] = drpre & 0xff; + outbits[9] = (drpre >> 8) & 0xff; + outbits[10] = (drpre >> 16) & 0xff; + outbits[11] = (drpre >> 24) & 0xff; + outbits[12] = drpost & 0xff; + outbits[13] = (drpost >> 8) & 0xff; + outbits[14] = (drpost >> 16) & 0xff; + outbits[15] = (drpost >> 24) & 0xff; + outbits[16] = tristate; + outbits[17] = tapstate; + outbits[18] = tcklevel; + outbits[19] = slave; + + return TAPAccess(0, T32_TAPACCESS_RELEASE, 160, outbits, NULL, 0); +} + + +int T32_TAPAccessShiftRaw(T32_TAPACCESS_HANDLE connection, int numberofbits, byte * pTMSBits, byte * pTDIBits, byte * pTDOBits, int options) +{ + int usedbytes = 0; + unsigned char poutbuffer[T32_TAPACCESS_MAXBITS]; + unsigned char *poutptr = poutbuffer; + int nDataByteSize = 0; + if (!numberofbits) + return T32_Errno = 0; + nDataByteSize = (numberofbits + 7) / 8 ; + poutbuffer[0] = 0x90; + /* sub function 0x0*/ + poutbuffer[1] = 0x0; + /* setup options */ + options &= ~SHIFTRAW_OPTION_INTERNAL_ALL; + if (pTMSBits) + options |= SHIFTRAW_OPTION_INTERNAL_TMS; + if (pTDIBits) + options |= SHIFTRAW_OPTION_INTERNAL_TDI; + if (pTDOBits) + options |= SHIFTRAW_OPTION_INTERNAL_TDO; + poutbuffer[2] = options & 0xFF; + poutbuffer[3] = (options >> 8) & 0xFF; + /* store bitlength */ + poutbuffer[4] = numberofbits & 0xff; + poutbuffer[5] = (numberofbits >> 8) & 0xff; + poutbuffer[6] = (numberofbits >> 16) & 0xff; + poutbuffer[7] = (numberofbits >> 24) & 0xff; + usedbytes += 8; + poutptr = poutbuffer + 8; + if (usedbytes + ((pTDOBits)?nDataByteSize:0) + ((pTDIBits && pTMSBits)?nDataByteSize:0) > T32_TAPACCESS_MAXBITS) + return T32_Errno = T32_COM_PARA_FAIL; + if (pTMSBits) + { + memcpy(poutptr, pTMSBits, nDataByteSize); + poutptr += nDataByteSize; + usedbytes += nDataByteSize; + } + if (pTDIBits) + { + memcpy(poutptr, pTDIBits, nDataByteSize); + poutptr += nDataByteSize; + usedbytes += nDataByteSize; + } + if (pTDOBits && !pTMSBits && !pTDIBits) + usedbytes += nDataByteSize; + if (connection > T32_TAPACCESS_HOLD) + T32_Errno = TAPAccessStore(12, connection, usedbytes*8 , poutbuffer, pTDOBits, ((pTDOBits)?numberofbits:0) ); + else + T32_Errno = TAPAccess(12, connection, usedbytes*8, poutbuffer, pTDOBits, ((pTDOBits)?numberofbits:0) ); + return T32_Errno; +} + + +int T32_TAPAccessShiftIR(T32_TAPACCESS_HANDLE connection, int numberofbits, byte * poutbits, byte * pinbits) +{ + if (numberofbits > T32_TAPACCESS_MAXBITS) { + T32_Errno = T32_COM_PARA_FAIL; + return T32_Errno; + } + if (connection > T32_TAPACCESS_HOLD) + return TAPAccessStore(4, connection, numberofbits, poutbits, pinbits, numberofbits); + else + return TAPAccess(4, connection, numberofbits, poutbits, pinbits, numberofbits); +} + + +int T32_TAPAccessShiftDR(T32_TAPACCESS_HANDLE connection, int numberofbits, byte * poutbits, byte * pinbits) +{ + if (numberofbits > T32_TAPACCESS_MAXBITS) { + T32_Errno = T32_COM_PARA_FAIL; + return T32_Errno; + } + if (connection > T32_TAPACCESS_HOLD) + return TAPAccessStore(8, connection, numberofbits, poutbits, pinbits, numberofbits); + else + return TAPAccess(8, connection, numberofbits, poutbits, pinbits, numberofbits); +} + + +int T32_TAPAccessDirect(T32_TAPACCESS_HANDLE connection, int nbytes, byte * poutbytes, byte * pinbytes) +{ + if (poutbytes == NULL && pinbytes == NULL) { + T32_Errno = T32_COM_PARA_FAIL; + return T32_Errno; + } + if (nbytes * 8 > T32_TAPACCESS_MAXBITS) { + T32_Errno = T32_COM_PARA_FAIL; + return T32_Errno; + } + if (connection > T32_TAPACCESS_HOLD) + return TAPAccessStore(12, connection, nbytes * 8, poutbytes, pinbytes, nbytes * 8); + else + return TAPAccess(12, connection, nbytes * 8, poutbytes, pinbytes, nbytes * 8); +} + + +int T32_TAPAccessRelease(void) +{ + return TAPAccess(0, T32_TAPACCESS_RELEASE, -1, NULL, NULL, 0); +} + + +/************************************************************************** + + network layer + transport layer + +***************************************************************************/ + +/** Sends message with payload contained in T32_OUTBUFFER[0...len-1]. + Adds the (empty) message header and calls LINE_LineTransmit. + */ +int LINE_Transmit(int len) +{ + int LastTransmitLen = 0; + + if (len) + LastTransmitLen = len + 4 + 1; + + T32_OUTBUFFER[-5] = 0; /* message header */ + + T32_OUTBUFFER[-4] = 0; + T32_OUTBUFFER[-3] = 0; + T32_OUTBUFFER[-2] = 0; + T32_OUTBUFFER[-1] = 0; + + if (LINE_LineTransmit(T32_OUTBUFFER - 5, LastTransmitLen) == -1) { + T32_Errno = T32_COM_TRANSMIT_FAIL; + return -1; + } + return 0; +} + + +int LINE_Receive(void) +{ + int len; + int retry; + + for (retry = 0; retry < MAXRETRY; retry++) { + len = LINE_LineReceive(T32_INBUFFER - 1); + if (len == -1) { + T32_Errno = T32_COM_RECEIVE_FAIL; + return -1; + } + if (T32_INBUFFER[2] == 0xfe) { + retry = 0; + LINE_SetReceiveToggleBit(-1); + continue; + } + if (T32_INBUFFER[3] != LINE_GetMessageId()) + continue; + + if (T32_INBUFFER[-1] & T32_MSG_LRETRY) { + if (LINE_GetReceiveToggleBit() == (!!(T32_INBUFFER[-1] & T32_MSG_LHANDLE))) { + if (LINE_Transmit(0) == -1) + LINE_Sync(); + continue; + } + } + LINE_SetReceiveToggleBit(!!(T32_INBUFFER[-1] & T32_MSG_LHANDLE)); + + return len - 1; + } + + T32_Errno = T32_COM_RECEIVE_FAIL; + return -1; +} + + +static int LINE_Sync(void) +{ + int retry; + + for (retry = MAXRETRY; --retry > 0;) { + if (LINE_LineSync() != -1) + return 0; + } + + return -1; +} + + +int T32_Config(const char *str1, const char *str2) +{ + char configline[256]; + strcpy(configline, str1); + strcat(configline, str2); + if (LINE_LineConfig(configline) == -1) + return -1; + return 0; +} + + +int T32_Init(void) +{ + char errorline[256]; + int i; + + if (LINE_LineInit(errorline) == -1) + return -1; + + LINE_SetReceiveToggleBit(-1); + + if (LINE_Sync() == -1) + return -1; + + for(i=0; i= T32_MAX_EVENTS) + return T32_Errno = T32_MAX_EVENT_FAIL; + + T32_EventMask |= 1 << eventNr; + + if (eventNr==T32_E_EDIT) /* device independent -> win/main.c */ + { + T32_OUTBUFFER[0] = 2; + T32_OUTBUFFER[1] = 0x78; + T32_OUTBUFFER[2] = 0x0; + T32_OUTBUFFER[3] = LINE_GetNextMessageId(); + T32_OUTBUFFER[4] = 0x1; /* No mask, just an enable bit */ + } + else /* device dependent -> debug/comemu12.c */ + { + T32_OUTBUFFER[0] = 2; + T32_OUTBUFFER[1] = 0x74; + T32_OUTBUFFER[2] = 0x12; /* -> T32_NotifyStateEnable */ + T32_OUTBUFFER[3] = LINE_GetNextMessageId(); + T32_OUTBUFFER[4] = T32_EventMask; + } + + if (LINE_Transmit(6) == -1) + return (T32_Errno = T32_COM_TRANSMIT_FAIL); + + if (LINE_Receive() == -1) + return (T32_Errno = T32_COM_RECEIVE_FAIL); + + notificationCallback[eventNr] = func; /* update pointer in case of success only */ + + return 0; +} + + + + +/************************************************************************** + + T32_CheckStateNotify - Checks socket for all pending notification + messages and invokes callback functions if required for each of them. + + Parameter: in unsigned param1 Parameter to give to the Event Callback + + Return: int OK=0 or Number of Error (<0) + +***************************************************************************/ + +int T32_CheckStateNotify(unsigned param1) +{ + + unsigned char package[T32_PCKLEN_MAX]; + int notifyid = LINE_ReceiveNotifyMessage(package); /* Check if there is a pending notification message */ + + while (notifyid!=-1) { + + switch (notifyid) { + + case T32_E_BREAK: + { + int state, err; + err = T32_GetState(&state); + switch (state) { + case 0: break; /* system down */ + case 1: break; /* system halted */ + case 2: /* break (stopped) */ + if (notificationCallback[T32_E_BREAK]) { + ((T32_NotificationCallback_i_t) notificationCallback[T32_E_BREAK]) (param1); + } + break; + case 3: break; /* running */ + } + } + break; + + case T32_E_EDIT: + if (notificationCallback[T32_E_EDIT]) { + int off=16; + int lineNr = package[off] + (package[off+1]<<8) + (package[off+2]<<16)+ (package[off+3]<<24); /* LE */ + unsigned char *fileName = package+20; + ((T32_NotificationCallback_iicp_t) notificationCallback[T32_E_EDIT]) (param1, lineNr, fileName); + } + break; + + + case T32_E_BREAKPOINTCONFIG: + if (notificationCallback[T32_E_BREAKPOINTCONFIG]) { + ((T32_NotificationCallback_i_t) notificationCallback[T32_E_BREAKPOINTCONFIG]) (param1); + } + break; + } + + notifyid = LINE_ReceiveNotifyMessage(package); + } + return 0; +} + + +/************************************************************************** + + T32_GetSocketHandle - Get socket handle of TRACE32 remote connection + + Parameter: in SOCKET *t32soc + + Return: - + +***************************************************************************/ + +void T32_GetSocketHandle(int *t32soc) +{ + *t32soc = LINE_LineDriverGetSocket(); +} + diff --git a/hwdebuggers/t32/include/t32.h b/hwdebuggers/t32/include/t32.h new file mode 100644 index 00000000..0c9ea823 --- /dev/null +++ b/hwdebuggers/t32/include/t32.h @@ -0,0 +1,362 @@ + +#include + +#if defined WIN32 || defined WIN64 +#ifndef MS_WINDOWS +#define MS_WINDOWS +#endif +#define LOW_HIGH +#endif + +#ifdef DEC_VMS +#define LOW_HIGH_BYTE +#endif + +#ifdef DEC_OSF1 +#define UNIX_V +#define LOW_HIGH_BYTE +#endif + +#ifdef HP_UX +#define UNIX_V +#define HIGH_LOW_BYTE +#endif + +#ifdef IBM_AIX +#define UNIX_V +#define HIGH_LOW_BYTE +#endif + +#ifdef __linux__ +# ifndef LINUX +# define LINUX +# endif +# define UNIX_V +# define LOW_HIGH_BYTE +#endif + +#ifdef T32HOST_LINUX_X64 +# define UNIX_V +# define LOW_HIGH_BYTE +#endif + +#ifdef LINUX_PPC +# ifndef LINUX +# define LINUX +# endif +# define UNIX_V +# define HIGH_LOW_BYTE +#endif + +#ifdef T32HOST_MACOSX_X86 +# define UNIX_V +# define LOW_HIGH_BYTE +#endif + +#ifdef SUN_SOL +#define UNIX_V +#define HIGH_LOW_BYTE +#endif + + +typedef unsigned char byte; +typedef unsigned short word; +typedef unsigned int dword; + + +#ifdef HIGH_LOW_BYTE + +#define SETWORDCONST(A,B) ( ((unsigned char *)&(A))[0] = (B),((unsigned char *)&(A))[1] = (B)>>8 ) +#define SETLONGCONST(A,B) ( ((unsigned char *)&(A))[0] = (B),((unsigned char *)&(A))[1] = (B)>>8,((unsigned char *)&(A))[2] = (B)>>16,((unsigned char *)&(A))[3] = (B)>>24 ) + +#define SETWORDVAR(A,B) ( ((unsigned char *)&(A))[0] = ((unsigned char *)&(B))[1],((unsigned char *)&(A))[1] = ((unsigned char *)&(B))[0] ) +#define SETLONGVAR(A,B) ( ((unsigned char *)&(A))[0] = ((unsigned char *)&(B))[3],((unsigned char *)&(A))[1] = ((unsigned char *)&(B))[2],((unsigned char *)&(A))[2] = ((unsigned char *)&(B))[1],((unsigned char *)&(A))[3] = ((unsigned char *)&(B))[0] ) + +#endif + +#ifdef HIGH_LOW + +#define SETWORDCONST(A,B) ((*((unsigned short *)&(A))) = (unsigned short)((((B)>>8)&0xff)|(((B)<<8)&0xff00))) +#define SETLONGCONST(A,B) ((*((int *)&(A))) = (int)((((B)>>24)&0xffl)|(((B)>>8)&0xff00l)|(((B)<<8)&0xff0000l)|(((B)<<24)&0xff000000l))) + +#define SETWORDVAR(A,B) ( ((unsigned char *)&(A))[0] = ((unsigned char *)&(B))[1],((unsigned char *)&(A))[1] = ((unsigned char *)&(B))[0] ) +#define SETLONGVAR(A,B) ( ((unsigned char *)&(A))[0] = ((unsigned char *)&(B))[3],((unsigned char *)&(A))[1] = ((unsigned char *)&(B))[2],((unsigned char *)&(A))[2] = ((unsigned char *)&(B))[1],((unsigned char *)&(A))[3] = ((unsigned char *)&(B))[0] ) + +#endif + +#ifdef LOW_HIGH + +#define SETWORDCONST(A,B) ((*((unsigned short *)&(A))) = (unsigned short)(B)) +#define SETLONGCONST(A,B) ((*((int *)&(A))) = (int)(B)) + +#define SETWORDVAR(A,B) ((*((unsigned short *)&(A))) = (*((unsigned short *)&(B)))) +#define SETLONGVAR(A,B) ((*((int *)&(A))) = (*((int *)&(B)))) + +#endif + +#ifdef LOW_HIGH_BYTE + +#define SETWORDCONST(A,B) ( ((unsigned char *)&(A))[0] = (B),((unsigned char *)&(A))[1] = (B)>>8 ) +#define SETLONGCONST(A,B) ( ((unsigned char *)&(A))[0] = (B),((unsigned char *)&(A))[1] = (B)>>8,((unsigned char *)&(A))[2] = (B)>>16,((unsigned char *)&(A))[3] = (B)>>24 ) + +#define SETWORDVAR(A,B) ( ((unsigned char *)&(A))[0] = ((unsigned char *)&(B))[0],((unsigned char *)&(A))[1] = ((unsigned char *)&(B))[1] ) +#define SETLONGVAR(A,B) ( ((unsigned char *)&(A))[0] = ((unsigned char *)&(B))[0],((unsigned char *)&(A))[1] = ((unsigned char *)&(B))[1],((unsigned char *)&(A))[2] = ((unsigned char *)&(B))[2],((unsigned char *)&(A))[3] = ((unsigned char *)&(B))[3] ) + +#endif + + +#define LINE_MBLOCK 16384 /* large block mode */ +#define LINE_MSIZE (LINE_MBLOCK+256) + +#define T32_DEV_OS 0 +#define T32_DEV_ICE 1 +#define T32_DEV_ICD 1 /* similar to ICE but clearer for user */ + +/* Events that can be generated by T32 */ +#define T32_MAX_EVENTS 3 +#define T32_E_BREAK 0x0 /* change in runstate, probably only "break" */ +#define T32_E_EDIT 0x1 /* user requested "edit source" in external editor */ +#define T32_E_BREAKPOINTCONFIG 0x2 /* breakpoint configuration changed (breakpoint set/removed) */ + +/* Callbacks should have the following protoypes */ +/************************* WARNING *****************************/ +/* + * If you add more callback functions here, make sure you ONLY + * use 'int', 'unsigned int', 'integral-type *' or 'float-type *' as parameters. + * + * No 'long', no 'long long', no 'short', no 'char', no floats, no typedefs + * and no function pointers! + * This is because we absolutely need to avoid portability problems here. + * + * Explanation: + * The T32_NotificationCallback_t typedef'd below has an empty parameter list, + * which we can't change anymore to a va_list because of backwards compatibility. + * This means only the native types like 'int' and 'integral type *' can be used + * safely, otherwise we run into hard-to-debug problems with type-promotion and + * parameter-passing conventions on the varying platforms we support. + */ +extern void T32_callbackBreak(int generic); +extern void T32_callbackEditExtern(int generic, int lineNr, unsigned char *fileName); +extern void T32_callbackBreakpointConfig(int generic); + + +#define T32_API_RECEIVE 0x1 +/* Missing: 0x5, */ +#define T32_API_NOTIFICATION 0x6 + +#define T32_API_SYNCREQUEST 0x02 +#define T32_API_SYNCACKN 0x12 +#define T32_API_SYNCBACK 0x22 + +#define T32_PCKLEN_MAX 1472 + + + +typedef struct t32_notification { + + char payload[T32_PCKLEN_MAX]; /* maximum packet size*/ + + struct t32_notification *next, *prev; + /* T32_NotificationPackage *next; + T32_NotificationPackage *prev; */ + +} T32_NotificationPackage; + +extern T32_NotificationPackage *T32_NotificationHead, *T32_NotificationTail; /* Queue pending notifications */ + + + + +#define T32_COM_RECEIVE_FAIL -1 +#define T32_COM_TRANSMIT_FAIL -2 +#define T32_COM_PARA_FAIL -3 +#define T32_COM_SEQ_FAIL -4 +#define T32_MAX_EVENT_FAIL -5 +#define T32_MALLOC_FAIL -6 + + +typedef void * T32_TAPACCESS_HANDLE; + +#define T32_TAPACCESS_MAXBITS 0x3b00 + +#define T32_TAPACCESS_RELEASE ((T32_TAPACCESS_HANDLE)0) +#define T32_TAPACCESS_HOLD ((T32_TAPACCESS_HANDLE)1) + +#define T32_TAPACCESS_TDO 0x00 +#define T32_TAPACCESS_TDI 0x04 +#define T32_TAPACCESS_TMS 0x08 +#define T32_TAPACCESS_TCK 0x0c +#define T32_TAPACCESS_nTRST 0x10 +#define T32_TAPACCESS_nRESET 0x14 +#define T32_TAPACCESS_nRESET_LATCH 0x18 +#define T32_TAPACCESS_VTREF 0x1c +#define T32_TAPACCESS_VTREF_LATCH 0x20 +#define T32_TAPACCESS_nENOUT 0x24 + +#define T32_TAPACCESS_SET(x) (2|((x)&1)) +#define T32_TAPACCESS_SET_LOW 2 +#define T32_TAPACCESS_SET_HIGH 3 +#define T32_TAPACCESS_SET_0 T32_TAPACCESS_SET_LOW +#define T32_TAPACCESS_SET_1 T32_TAPACCESS_SET_HIGH + +#define T32_TAPACCESS_SHIFT 0x30 +#define T32_TAPACCESS_SHIFTTMS 0x40 +#define T32_TAPACCESS_SHIFTIR 0x50 +#define T32_TAPACCESS_SHIFTDR 0x60 + +#define T32_TAPACCESS_SLEEP_MS 0x7c +#define T32_TAPACCESS_SLEEP_US 0x7d +#define T32_TAPACCESS_SLEEP_HALF_CLOCK 0x7e +#define T32_TAPACCESS_SLEEP T32_TAPACCESS_SLEEP_MS /*just for backwards compatibility*/ + + +#define SHIFTRAW_OPTION_INTERNAL_TMS 0x0001 /*do not use the internal options*/ +#define SHIFTRAW_OPTION_INTERNAL_TDI 0x0002 +#define SHIFTRAW_OPTION_INTERNAL_TDO 0x0004 +#define SHIFTRAW_OPTION_INTERNAL_ALL 0x0007 + +#define SHIFTRAW_OPTION_NONE 0x0000 +#define SHIFTRAW_OPTION_LASTTMS_ONE 0x0008 +#define SHIFTRAW_OPTION_TMS_ONE 0x0010 +#define SHIFTRAW_OPTION_TMS_ZERO 0x0000 +#define SHIFTRAW_OPTION_TDI_ONE 0x0040 +#define SHIFTRAW_OPTION_TDI_ZERO 0x0000 +#define SHIFTRAW_OPTION_TDI_LASTTDO 0x0020 + +#define T32_TAPACCESS_SPECIAL 0x80 + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef _NO_PROTO + +extern int T32_Config( const char *, const char * ); +extern int T32_Init(void); +extern int T32_Exit(void); +extern int T32_Nop(void); +extern int T32_NopFail(void); +extern int T32_Ping(void); +extern int T32_Stop(void); +extern int T32_GetPracticeState(int * ); +extern int T32_Attach( int ); +extern int T32_GetState( int * ); +extern int T32_GetCpuInfo( char **, word *, word *, word * ); +extern int T32_GetRam(dword *, dword *, word *); +extern int T32_ResetCPU(void); + +extern int T32_WriteMemory( dword, int, byte * , int ); +extern int T32_WriteMemoryPipe( dword, int, byte * , int ); +extern int T32_WriteMemoryEx( dword, int, int, int, byte * , int ); +extern int T32_ReadMemory( dword, int, byte *, int ); +extern int T32_ReadMemoryEx( dword, int, int, int, byte * , int ); + + +#define T32_MEMORY_ACCESS_DATA 0x0000 +#define T32_MEMORY_ACCESS_PROGRAM 0x0001 +#define T32_MEMORY_ACCESS_ARM_CP0 0x0002 +#define T32_MEMORY_ACCESS_ARM_ICE 0x0003 +#define T32_MEMORY_ACCESS_ARM_ETM 0x0004 +#define T32_MEMORY_ACCESS_ARM_CP14 0x0005 +#define T32_MEMORY_ACCESS_ARM_CP15 0x0006 +#define T32_MEMORY_ACCESS_ARM_ARM 0x0007 +#define T32_MEMORY_ACCESS_ARM_THUMB 0x0008 +#define T32_MEMORY_ACCESS_ARM_PHYSICAL_ARM 0x0009 +#define T32_MEMORY_ACCESS_ARM_PHYSICAL_THUMB 0x000a +#define T32_MEMORY_ACCESS_ARM_ETB 0x000b +#define T32_MEMORY_ACCESS_ARM_PHYSICAL_DATA 0x000c +#define T32_MEMORY_ACCESS_ARM_PHYSICAL_PROGRAM 0x000d +#define T32_MEMORY_ACCESS_ARM_DAP 0x000e +#define T32_MEMORY_ACCESS_ARM_USR 0x000f + +#define T32_MEMORY_ATTR_WIDTHMASK 0x000f +#define T32_MEMORY_ATTR_DUALPORT 0x0400 +#define T32_MEMORY_ATTR_NOINCREMENT 0x4000 + + +extern int T32_WriteRegister( dword, dword, dword * ); +extern int T32_ReadRegister( dword, dword, dword * ); +extern int T32_ReadPP( dword * ); +extern int T32_WriteBreakpoint( dword, int, int, int ); +extern int T32_ReadBreakpoint( dword, int, word * , int ); +extern int T32_Step(void); +extern int T32_StepMode(int); +extern int T32_SetMode(int); +extern int T32_Go(void); +extern int T32_Break(void); +extern int T32_Terminate(int retval); +extern int T32_Cmd( char * ); +extern int T32_CmdWin( dword, char * ); +extern int T32_EvalGet ( dword * ); +extern int T32_GetMessage ( char *, word * ); +extern int T32_GetTriggerMessage ( char* ); +extern int T32_GetSymbol ( char *, dword *, dword * , dword * ); +extern int T32_GetSource ( dword, char *, dword * ); +extern int T32_GetSelectedSource( char *, dword * ); + +extern int T32_AnaStatusGet( byte *, long *, long *, long * ); +extern int T32_AnaRecordGet( long , byte *, int ); +extern int T32_GetTraceState(int tracetype, int * state, long * size, long * min, long * max); +extern int T32_ReadTrace(int tracetype, long record, int nrecords, unsigned long mask, byte * buffer); + +typedef void (*T32_NotificationCallback_i_t)(int); +typedef void (*T32_NotificationCallback_iicp_t)(int, int, unsigned char *); + +#ifndef SUPPRESS_FUNCTION_TYPE_WARNING +typedef void (*T32_NotificationCallback_t)(); +extern int T32_NotifyStateEnable( int event, T32_NotificationCallback_t func); +#endif + +extern int T32_CheckStateNotify( unsigned param1); +extern void T32_GetSocketHandle( int *t32soc ); + +extern T32_TAPACCESS_HANDLE T32_TAPAccessAlloc(void); +extern int T32_TAPAccessExecute(T32_TAPACCESS_HANDLE connection, T32_TAPACCESS_HANDLE connectionhold); +extern int T32_TAPAccessFree(T32_TAPACCESS_HANDLE connection); +extern int T32_TAPAccessSetInfo(int irpre, int irpost, int drpre, int drpost, int tristate, int tapstate, int tcklevel, int slave); +extern int T32_TAPAccessShiftIR(T32_TAPACCESS_HANDLE connection, int numberofbits, byte * poutbits, byte * pinbits); +extern int T32_TAPAccessShiftDR(T32_TAPACCESS_HANDLE connection, int numberofbits, byte * poutbits, byte * pinbits); +extern int T32_TAPAccessShiftRaw(T32_TAPACCESS_HANDLE connection, int numberofbits, byte * pTMSBits, byte * pTDIBits, byte * pTDOBits, int options); +extern int T32_TAPAccessDirect(T32_TAPACCESS_HANDLE connection, int nbytes, byte * poutbytes, byte * pinbytes); +extern int T32_TAPAccessRelease(void); + +extern int T32_Fdx_Resolve(char * name); +extern int T32_Fdx_Open(char * name, char * mode); +extern int T32_Fdx_Close(int channel); +extern int T32_Fdx_ReceivePoll(int channel, void * data, int width, int maxsize); +extern int T32_Fdx_Receive(int channel, void * data, int width, int maxsize); +extern int T32_Fdx_SendPoll(int channel, void * data, int width, int size); +extern int T32_Fdx_Send(int channel, void * data, int width, int size); + +/* + * New stream structure, to improve performance for PIPE mode. + */ +typedef struct +{ + int blen; + unsigned char *ptr; + unsigned char *ptrend; + int channel; + unsigned char buffer[4096]; +} T32_Fdx_Stream; + +extern T32_Fdx_Stream *T32_Fdx_OpenStream(char *name, char *mode); +extern int T32_Fdx_CloseStream(T32_Fdx_Stream * pstream); +extern int T32_Fdx_ReceiveStreamNext(T32_Fdx_Stream * pstream, unsigned char *target, int width, int size); + +#define T32_Fdx_ReceiveStream(__pstream,__target,__width,__len) ( \ + (((__pstream)->ptr >= (__pstream)->ptrend) ? \ + T32_Fdx_ReceiveStreamNext(__pstream,__target,__width,__len) : \ + ((__pstream)->blen = ((__pstream)->ptr[0]|((__pstream)->ptr[1]<<8)), memcpy((__target),(__pstream)->ptr+2,(__pstream)->blen), (__pstream)->ptr += 2+(__pstream)->blen, (__pstream)->blen))) + + +extern int T32_GetChannelSize(void); +extern void T32_GetChannelDefaults(void* line); +extern void T32_SetChannel(void* line); +extern void* T32_GetChannel0(void); + +#endif + +#ifdef __cplusplus +} +#endif diff --git a/hwdebuggers/t32/src/CMakeLists.txt b/hwdebuggers/t32/src/CMakeLists.txt new file mode 100644 index 00000000..757040d9 --- /dev/null +++ b/hwdebuggers/t32/src/CMakeLists.txt @@ -0,0 +1,9 @@ +set(SRCS + t32connector.cc +) + +add_executable(fail-client ${SRCS}) +target_link_libraries(fail-client -Wl,-whole-archive t32api -Wl,-no-whole-archive fail ) + +install(TARGETS fail-client RUNTIME DESTINATION bin) + diff --git a/hwdebuggers/t32/src/t32connector.cc b/hwdebuggers/t32/src/t32connector.cc new file mode 100644 index 00000000..2f4f6d1d --- /dev/null +++ b/hwdebuggers/t32/src/t32connector.cc @@ -0,0 +1,63 @@ +#include +#include +#include +#include + +using namespace std; + +void err(int ernum){ + if(err != 0){ + cerr << "Error: " << err << endl; + //exit(-1); + } +} + + +int eval_command(){ + string cmd; + char errmsg[128]; + cout << "%> "; + getline(cin, cmd); + if(cmd.compare("bye") == 0) return -1; + + int err = T32_Cmd((char*)cmd.c_str()); + if(err != 0){ + cerr << "Could not execute command: " << err << endl; + word errnum; + T32_GetMessage(errmsg, &errnum); + cerr << errmsg << "Type: " << errnum << endl; + } + + return 0; + +} + + +int main(void){ + cout << "Lauterbach remote connection" << endl; + cout << "Enter bye to exit." << endl; + int error; + char hostname[] = "localhost"; + char packlen[] = "1024"; + char port[] = "20010"; + + cout << "[T32] Connecting to " << hostname << ":" << port << " Packlen: " << packlen << endl; + T32_Config("NODE=", hostname); + T32_Config("PACKLEN=", packlen); + T32_Config("PORT=", port); + + cout << "[T32] Init." << endl; + err(T32_Init()); + + cout << "[T32] Attach." << endl; + err(T32_Attach(T32_DEV_ICD)); + + while(eval_command() != -1); + + cout << "[T32] Exit." << endl; + err(T32_Exit()); + cout << "Bye." << endl; + + return 0; +} + diff --git a/src/core/config/VariantConfig.hpp.in b/src/core/config/VariantConfig.hpp.in index 02fa8727..7675055c 100644 --- a/src/core/config/VariantConfig.hpp.in +++ b/src/core/config/VariantConfig.hpp.in @@ -5,5 +5,6 @@ #cmakedefine BUILD_GEM5 #cmakedefine BUILD_OVP #cmakedefine BUILD_QEMU +#cmakedefine BUILD_T32 #endif // __VARIANT_CONFIG_HPP__ diff --git a/src/core/sal/CMakeLists.txt b/src/core/sal/CMakeLists.txt index 35360744..9c1deb33 100644 --- a/src/core/sal/CMakeLists.txt +++ b/src/core/sal/CMakeLists.txt @@ -41,6 +41,17 @@ elseif(BUILD_QEMU) qemu/QEMUController.cc qemu/wrappers.cc ) +elseif(BUILD_T32) + set(SRCS + Listener.cc + ListenerManager.cc + SALConfig.cc + Register.cc + perf/BreakpointBuffer.cc + SimulatorController.cc + t32/T32Controller.cc + t32/wrappers.cc + ) endif(BUILD_BOCHS) add_library(fail-sal ${SRCS}) diff --git a/src/core/sal/SALConfig.cc b/src/core/sal/SALConfig.cc index db5acdd5..cdb65c59 100644 --- a/src/core/sal/SALConfig.cc +++ b/src/core/sal/SALConfig.cc @@ -5,7 +5,8 @@ namespace fail { // Flag initialization depends on the current selected simulator // (For now, the initialization values are all the same): #if defined BUILD_BOCHS || defined BUILD_GEM5 || \ - defined BUILD_OVP || defined BUILD_QEMU + defined BUILD_OVP || defined BUILD_QEMU || \ + defined BUILD_T32 const address_t ADDR_INV = static_cast (0); const address_t ANY_ADDR = static_cast (-1); const unsigned ANY_INSTR = static_cast (-1); diff --git a/src/core/sal/SALConfig.hpp b/src/core/sal/SALConfig.hpp index 048e3e79..371e7266 100644 --- a/src/core/sal/SALConfig.hpp +++ b/src/core/sal/SALConfig.hpp @@ -14,6 +14,8 @@ #include "ovp/OVPConfig.hpp" #elif defined BUILD_QEMU #include "qemu/QEMUConfig.hpp" +#elif defined BUILD_T32 + #include "t32/T32Config.hpp" #else #error SAL Config Target not defined #endif diff --git a/src/core/sal/SALInst.hpp b/src/core/sal/SALInst.hpp index 3dfb573c..974c5835 100644 --- a/src/core/sal/SALInst.hpp +++ b/src/core/sal/SALInst.hpp @@ -36,6 +36,15 @@ namespace fail { typedef QEMUController ConcreteSimulatorController; //!< concrete simulator (type) } +#elif defined BUILD_T32 + +#include "t32/T32Controller.hpp" + +namespace fail { +typedef T32Controller ConcreteSimulatorController; //!< concrete simulator (type) +} + + #else #error SAL Instance not defined #endif diff --git a/src/core/sal/t32/T32Config.hpp b/src/core/sal/t32/T32Config.hpp new file mode 100644 index 00000000..fe80cdbf --- /dev/null +++ b/src/core/sal/t32/T32Config.hpp @@ -0,0 +1,20 @@ +/** + * \brief Type definitions and configuration settings for the + * T32 target backend. + */ + +#ifndef __T32_CONFIG_HPP__ +#define __T32_CONFIG_HPP__ + +struct T32Timer; + +namespace fail { + +typedef uint32_t guest_address_t; //!< the guest memory address type +typedef unsigned char* host_address_t; //!< the host memory address type +typedef uint32_t register_data_t; //!< register data type (64 bit) +typedef T32Timer* timer_t; //!< type of timer IDs + +} // end-of-namespace: fail + +#endif // __T32_CONFIG_HPP__ diff --git a/src/core/sal/t32/T32Controller.cc b/src/core/sal/t32/T32Controller.cc new file mode 100644 index 00000000..425efceb --- /dev/null +++ b/src/core/sal/t32/T32Controller.cc @@ -0,0 +1,24 @@ +#include + +#include "T32Controller.hpp" +#include "T32Memory.hpp" +#include "T32Register.hpp" +#include "../Register.hpp" +#include "../SALInst.hpp" + +namespace fail { + +T32Controller::T32Controller() + : SimulatorController(new T32RegisterManager(), new T32MemoryManager()) +{ + // TODO: probably do additional RegisterManager initializations +} + +T32Controller::~T32Controller() +{ + delete m_Regs; + delete m_Mem; +} + + +} // end-of-namespace: fail diff --git a/src/core/sal/t32/T32Controller.hpp b/src/core/sal/t32/T32Controller.hpp new file mode 100644 index 00000000..b6712323 --- /dev/null +++ b/src/core/sal/t32/T32Controller.hpp @@ -0,0 +1,51 @@ +#ifndef __T32_CONTROLLER_HPP__ + #define __T32_CONTROLLER_HPP__ + +#include +#include +#include +#include +#include + +#include "../SimulatorController.hpp" + +namespace fail { + +class ExperimentFlow; +class TimerListener; + +/** + * \class T32Controller + * Very rudimentary, T32-specific implementation of a SimulatorController. + */ +class T32Controller : public SimulatorController { +public: + // Initialize the controller. + T32Controller(); + ~T32Controller(); + + + /* ******************************************************************** + * Simulator Controller & Access API: + * ********************************************************************/ + /** + * Save simulator state. Quite hard on real hardware! Also safe all + * HW registers! + * @param path Location to store state information + * @return \c true if the state has been successfully saved, \c false otherwise + */ + bool save(const std::string& path) { return false; } + /** + * Restore simulator state. Clears all Listeners. TODO. + * @param path Location to previously saved state information + */ + void restore(const std::string& path) {} + /** + * Reboot simulator. Clears all Listeners. TODO. + */ + void reboot() {} +}; + +} // end-of-namespace: fail + +#endif // __T32_CONTROLLER_HPP__ diff --git a/src/core/sal/t32/T32Listener.ah b/src/core/sal/t32/T32Listener.ah new file mode 100644 index 00000000..d7e9e01e --- /dev/null +++ b/src/core/sal/t32/T32Listener.ah @@ -0,0 +1,35 @@ +#ifndef __T32LISTENER_AH__ + #define __T32LISTENER_AH__ + +#include "config/VariantConfig.hpp" +#include "config/FailConfig.hpp" + +#if defined(BUILD_T32) && defined(CONFIG_EVENT_BREAKPOINTS) + +#include "../SALInst.hpp" + +aspect T32Listener + + advice "fail::MemWriteListener" : slice class + { + public: + bool onAddition() + { + //std::cout << "T32MemWriteListener::onAddition" << std::endl; + //if (failqemu_add_watchpoint(simulator.m_cpuenv, m_WatchAddr, m_WatchWidth, 1) != 0) { + // std::cout << "adding watchpoint failed!" << std::endl; + return false; + //} + //return true; + } + + void onDeletion() + { + //std::cout << "T32MemWriteListener::onDeletion" << std::endl; + //failqemu_remove_watchpoint(simulator.m_cpuenv, m_WatchAddr, m_WatchWidth, 1); + } + }; +}; + +#endif // BUILD_T32 && CONFIG_EVENT_BREAKPOINTS +#endif // __T32LISTENER_AH__ diff --git a/src/core/sal/t32/T32Memory.hpp b/src/core/sal/t32/T32Memory.hpp new file mode 100644 index 00000000..17cf326e --- /dev/null +++ b/src/core/sal/t32/T32Memory.hpp @@ -0,0 +1,41 @@ +#ifndef __T32_MEMORY_HPP__ + #define __T32_MEMORY_HPP__ + +#include "../Memory.hpp" + +namespace fail { + +/** + * \class T32MemoryManager + * Represents a concrete implemenation of the abstract + * MemoryManager to provide access to T32's memory pool. + */ +class T32MemoryManager : public MemoryManager { +public: + size_t getPoolSize() const { return 0; /* TODO */ } + host_address_t getStartAddr() const { return 0; } + byte_t getByte(guest_address_t addr) + { + return 0; //failqemu_mem_read_byte(addr); + } + void getBytes(guest_address_t addr, size_t cnt, void *dest) + { + char *d = static_cast(dest); + for (size_t i = 0; i < cnt; ++i) + d[i] = 0; //getByte(addr + i); + } + void setByte(guest_address_t addr, byte_t data) + { + //failqemu_mem_write_byte(addr, data); + } + void setBytes(guest_address_t addr, size_t cnt, void const *src) + { + //char const *s = static_cast(src); + for (size_t i = 0; i < cnt; ++i) + ; //setByte(addr + i, s[i]); + } +}; + +} // end-of-namespace: fail + +#endif // __T32_MEMORY_HPP__ diff --git a/src/core/sal/t32/T32Register.hpp b/src/core/sal/t32/T32Register.hpp new file mode 100644 index 00000000..06b1df18 --- /dev/null +++ b/src/core/sal/t32/T32Register.hpp @@ -0,0 +1,45 @@ +#ifndef __T32_REGISTER_HPP__ + #define __T32_REGISTER_HPP__ + +#include "../Register.hpp" + +#include +#include + +namespace fail { + +/** + * \class T32Register + * T32-specific implementation of ?? registers. TODO. + */ +class T32Register : public Register { +public: + T32Register(unsigned int id, regwidth_t width, regdata_t* link, RegisterType t) + : Register(id, t, width) { } + regdata_t getData() { return 0; /* TODO */ } + void setData(regdata_t data) { /* TODO */ } +}; + +/** + * \class T32RegisterManager + * T32-specific implementation of the RegisterManager. TODO. + */ +class T32RegisterManager : public RegisterManager { +public: + address_t getInstructionPointer() + { + return static_cast(0); /* TODO */ + } + address_t getStackPointer() + { + return static_cast(0); /* TODO */ + } + address_t getBasePointer() + { + return static_cast(0); /* TODO */ + } +}; + +} // end-of-namespace: fail + +#endif // __T32_REGISTER_HPP__ diff --git a/src/core/sal/t32/wrappers.cc b/src/core/sal/t32/wrappers.cc new file mode 100644 index 00000000..10c0f85e --- /dev/null +++ b/src/core/sal/t32/wrappers.cc @@ -0,0 +1,21 @@ +#include + +#include "../SALInst.hpp" +#include "../SALConfig.hpp" +#include "config/FailConfig.hpp" + +extern "C" { + +void fail_init(struct CPUX86State *env) +{ + std::cout << "FailT32" FAIL_VERSION << std::endl; + fail::simulator.startup(); +} + +void fail_watchpoint_hit(struct CPUX86State *env, uint64_t addr, int width, int is_write) +{ + // FIXME: instruction pointer + fail::simulator.onMemoryAccess(addr, width, is_write == 1, 0); +} + +}