~cosmos-door/ubuntu/quantal/avarice/fix-ftbfs-1058667

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
/*
 *	avarice - The "avarice" program.
 *	Copyright (C) 2001 Scott Finneran
 *      Copyright (C) 2002 Intel Corporation
 *	Copyright (C) 2005, 2007 Joerg Wunsch
 *
 *	This program is free software; you can redistribute it and/or modify
 *	it under the terms of the GNU General Public License Version 2
 *      as published by the Free Software Foundation.
 *
 *	This program is distributed in the hope that it will be useful,
 *	but WITHOUT ANY WARRANTY; without even the implied warranty of
 *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *	GNU General Public License for more details.
 *
 *	You should have received a copy of the GNU General Public License
 *	along with this program; if not, write to the Free Software
 *	Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
 *
 * This file contains functions for interfacing with the JTAG box.
 *
 * $Id: jtagrun.cc,v 1.6 2007/08/29 11:04:43 joerg_wunsch Exp $
 */


#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <termios.h>
#include <fcntl.h>
#include <string.h>

#include "avarice.h"
#include "jtag.h"
#include "jtag1.h"
#include "remote.h"

unsigned long jtag1::getProgramCounter(void)
{
    uchar *response = NULL;
    uchar command[] = {'2', JTAG_EOM };
    unsigned long result = 0;

    response = doJtagCommand(command, sizeof(command), 4);

    if (response[3] != JTAG_R_OK)
	result = PC_INVALID;
    else
    {
	result = decodeAddress(response);

	result--; // returned value is PC + 1 as far as GDB is concerned

	// The JTAG box sees program memory as 16-bit wide locations. GDB
	// sees bytes. As such, double the PC value.
	result *= 2;
    }

    delete [] response;
    return result;
}

bool jtag1::setProgramCounter(unsigned long pc)
{
    uchar *response = NULL;
    uchar command[] = {'3', 0, 0, 0, JTAG_EOM };
    bool result;

    // See decoding in getProgramCounter
    encodeAddress(&command[1], pc / 2 + 1);

    response = doJtagCommand(command, sizeof(command), 1);

    result = response[0] == JTAG_R_OK;

    delete [] response;

    return result;
}

bool jtag1::resetProgram(void)
{
    return doSimpleJtagCommand('x', 1);
}

bool jtag1::interruptProgram(void)
{
    // Just ignore the returned PC. It appears to be wrong if the most
    // recent instruction was a branch.
    return doSimpleJtagCommand('F', 4);
}

bool jtag1::resumeProgram(void)
{
    return doSimpleJtagCommand('G', 0);
}

bool jtag1::jtagSingleStep(bool useHLL)
{
    return doSimpleJtagCommand('1', 1);
}

void jtag1::parseEvents(const char *)
{
    // current no event name parsing in mkI
}

bool jtag1::jtagContinue(void)
{
    updateBreakpoints();        // download new bp configuration

    if (!doSimpleJtagCommand('G', 0))
    {
	gdbOut("Failed to continue\n");
	return true;
    }

    for (;;)
    {
	int maxfd;
	fd_set readfds;
	bool breakpoint = false, gdbInterrupt = false;

	// Now that we are "going", wait for either a response from the JTAG
	// box or a nudge from GDB.
	debugOut("Waiting for input.\n");

	// Check for input from JTAG ICE (breakpoint, sleep, info, power)
	// or gdb (user break)
	FD_ZERO (&readfds);
	FD_SET (gdbFileDescriptor, &readfds);
	FD_SET (jtagBox, &readfds);
	maxfd = jtagBox > gdbFileDescriptor ? jtagBox : gdbFileDescriptor;

	int numfds = select(maxfd + 1, &readfds, 0, 0, 0);
	unixCheck(numfds, "GDB/JTAG ICE communications failure");

	if (FD_ISSET(gdbFileDescriptor, &readfds))
	{
	    int c = getDebugChar();
	    if (c == 3) // interrupt
	    {
		debugOut("interrupted by GDB\n");
		gdbInterrupt = true;
	    }
	    else
		debugOut("Unexpected GDB input `%02x'\n", c);
	}

	// Read all extant responses (there's a small chance there could
	// be more than one)

	// Note: In case of a gdb interrupt, it's possible that we will
	// receive one of these responses before interruptProgram is 
	// called. This should not cause a problem as the normal retry
	// mechanism should eat up this response.
	// It might be cleaner to handle JTAG_R_xxx in sendJtagCommand

	// Check the JTAG ICE's message. It can indicate a breakpoint
	// which causes us to return, a sleep status change (ignored),
	// power "event" -- whatever that is (ignored), or a byte of
	// info sent by the program (currently ignored, could be used
	// for something...)
	uchar response;

        // This read shouldn't need to be a timeout_read(), but some cygwin
        // systems don't seem to honor the O_NONBLOCK flag on file
        // descriptors.
	while (timeout_read(&response, 1, 1) == 1)
	{
	    uchar buf[2];
	    int count;

	    debugOut("JTAG box sent %c", response);
	    switch (response)
	    {
	    case JTAG_R_BREAK:
		count = timeout_read(buf, 2, JTAG_RESPONSE_TIMEOUT);
		jtagCheck(count);
		check(count == 2, JTAG_CAUSE);
		breakpoint = true;
                debugOut(": Break Status Register = 0x%02x%02x\n",
                         buf[0], buf[1]);
		break;
	    case JTAG_R_INFO: case JTAG_R_SLEEP:
		// we could do something here, esp. for info
		count = timeout_read(buf, 2, JTAG_RESPONSE_TIMEOUT);
		jtagCheck(count);
		check(count == 2, JTAG_CAUSE);
                debugOut(": 0x%02, 0x%02\n", buf[0], buf[1]);
		break;
	    case JTAG_R_POWER:
		// apparently no args?
                debugOut("\n");
		break;
	    default:
		debugOut(": Unknown response\n");
		break; 
	    }
	}

	// We give priority to user interrupts
	if (gdbInterrupt)
	    return false;
	if (breakpoint)
	    return true;
    }
}