コード例 #1
0
// Read some bytes from the specified channel, synchronously.
// TODO: Deal with early-termination properly - it should not be treated like an error.
//       This will require changes in usbBulkRead(). Async API is already correct.
//
DLLEXPORT(FLStatus) flReadChannel(
	struct FLContext *handle, uint8 chan, size_t count, uint8 *buffer,
	const char **error)
{
	FLStatus retVal = FL_SUCCESS, fStatus;
	const uint8 *data;
	uint32 requestLength, actualLength;
	CHECK_STATUS(
		count == 0, FL_PROTOCOL_ERR, cleanup,
		"flReadChannel(): Zero-length reads are illegal!");
	CHECK_STATUS(
		!handle->isCommCapable, FL_PROTOCOL_ERR, cleanup,
		"flReadChannel(): This device does not support CommFPGA");
	if ( count >= 0x10000 ) {
		fStatus = flReadChannelAsyncSubmit(handle, chan, 0x10000, buffer, error);
		CHECK_STATUS(fStatus, fStatus, cleanup, "flReadChannel()");
		count -= 0x10000;
		buffer += 0x10000;
		while ( count >= 0x10000 ) {
			fStatus = flReadChannelAsyncSubmit(handle, chan, 0x10000, buffer, error);
			CHECK_STATUS(fStatus, fStatus, cleanup, "flReadChannel()");
			count -= 0x10000;
			buffer += 0x10000;
			fStatus = flReadChannelAsyncAwait(handle, &data, &requestLength, &actualLength, error);
			CHECK_STATUS(fStatus, fStatus, cleanup, "flReadChannel()");
			CHECK_STATUS(
				actualLength != requestLength,
				FL_EARLY_TERM, cleanup, "flReadChannel()");
		}
		if ( count ) {
			fStatus = flReadChannelAsyncSubmit(handle, chan, (uint32)count, buffer, error);
			CHECK_STATUS(fStatus, fStatus, cleanup, "flReadChannel()");
			fStatus = flReadChannelAsyncAwait(handle, &data, &requestLength, &actualLength, error);
			CHECK_STATUS(fStatus, fStatus, cleanup, "flReadChannel()");
			CHECK_STATUS(
				actualLength != requestLength,
				FL_EARLY_TERM, cleanup, "flReadChannel()");
		}
	} else {
		fStatus = flReadChannelAsyncSubmit(handle, chan, (uint32)count, buffer, error);
		CHECK_STATUS(fStatus, fStatus, cleanup, "flReadChannel()");
	}
	fStatus = flReadChannelAsyncAwait(handle, &data, &requestLength, &actualLength, error);
	CHECK_STATUS(fStatus, fStatus, cleanup, "flReadChannel()");
	CHECK_STATUS(
		actualLength != requestLength,
		FL_EARLY_TERM, cleanup, "flReadChannel()");
cleanup:
	return retVal;
}
コード例 #2
0
ファイル: mem.c プロジェクト: Frankz/umdkv2
// Tell the monitor to continue execution with the (possibly new) register/memory context, until
// a breakpoint is hit. If there is no breakpoint in the execution-path, this function will wait
// forever.
//
int umdkContWait(
	struct FLContext *handle, bool debug, struct Registers *regs, const char **error)
{
	int retVal = 0, status, i;
	uint8 tmpData[65536];
	size_t scrapSize;
	uint32 vbAddr, actualLength;
	uint16 oldOp;
	union RegUnion {
		struct Registers reg;
		uint32 longs[18];
		uint8 bytes[18*4];
	} *const u = (union RegUnion *)regs;
	const uint8 *recvData;
	FILE *file = NULL;

	if ( debug ) {
		// Read RAM
		status = umdkReadBytes(handle, 0xFF0000, 65536, tmpData, error);
		CHECK_STATUS(status, status, cleanup);
		
		// Save it
		file = fopen("ramBefore.bin", "wb");
		CHECK_STATUS(!file, 13, cleanup, "umdkContWait(): Unable to open ramBefore.bin for writing!");
		fwrite(tmpData, 1, 65536, file);
		fclose(file);
		file = NULL;
		
		// Open trace log
		file = fopen("trace.log", "wb");
		CHECK_STATUS(!file, 13, cleanup, "umdkContWait(): Unable to open trace.log for writing!");
	}

	// Get address of VDP vertical interrupt routine and its first opcode
	status = umdkDirectReadLong(handle, VB_VEC, &vbAddr, error);
	CHECK_STATUS(status, status, cleanup);
	status = umdkDirectReadWord(handle, vbAddr, &oldOp, error);
	CHECK_STATUS(status, status, cleanup);

	// Write monitor address to illegal instruction vector
	status = umdkDirectWriteLong(handle, IL_VEC, MONITOR, error);
	CHECK_STATUS(status, status, cleanup);

	if ( debug ) {
		// Disable tracing (if any) & clear junk from trace FIFO
		tmpData[0] = 0x00;
		status = flWriteChannel(handle, 0x01, 1, tmpData, error);
		CHECK_STATUS(status, 25, cleanup);
		status = flReadChannel(handle, 0x03, 1, tmpData, error);
		CHECK_STATUS(status, 20, cleanup);
		scrapSize = tmpData[0] << 8;
		status = flReadChannel(handle, 0x04, 1, tmpData, error);
		CHECK_STATUS(status, 20, cleanup);
		scrapSize |= tmpData[0];
		while ( scrapSize ) {
			// Clear junk from FIFO
			status = flReadChannel(handle, 0x02, scrapSize, tmpData, error);
			CHECK_STATUS(status, 20, cleanup);
			
			// Verify no junk remaining
			status = flReadChannel(handle, 0x03, 1, tmpData, error);
			CHECK_STATUS(status, 20, cleanup);
			scrapSize = tmpData[0] << 8;
			status = flReadChannel(handle, 0x04, 1, tmpData, error);
			CHECK_STATUS(status, 20, cleanup);
			scrapSize |= tmpData[0];
		}
		
		// Enable tracing
		tmpData[0] = 0x02;
		status = flWriteChannelAsync(handle, 0x01, 1, tmpData, error);
		CHECK_STATUS(status, 25, cleanup);
	}

	// Set up the continue command and execute it
	status = umdkDirectWriteWord(handle, CB_INDEX, CMD_CONT, error);
	CHECK_STATUS(status, status, cleanup);
	status = umdkDirectWriteWord(handle, CB_FLAG, CF_CMD, error);
	CHECK_STATUS(status, status, cleanup);

	if ( debug ) {
		// Submit 1st read for some trace data
		status = flReadChannelAsyncSubmit(handle, 2, 22528, NULL, error);
		CHECK_STATUS(status, 28, cleanup);
	}

	// Submit 1st read for the command status flag
	status = umdkDirectReadBytesAsync(handle, CB_FLAG, 2, error);
	CHECK_STATUS(status, status, cleanup);
	do {
		// If interrupted (escape or ctrl-c in gdb), induce a suspend at the next vblank
		if ( isInterrupted() ) {
			status = umdkDirectWriteWord(handle, vbAddr, ILLEGAL, error);
			CHECK_STATUS(status, status, cleanup);
		}

		if ( debug ) {
			// Submit a read for some trace data
			status = flReadChannelAsyncSubmit(handle, 2, 22528, NULL, error);
			CHECK_STATUS(status, 28, cleanup);
		}

		// Submit a read for the command status flag
		status = umdkDirectReadBytesAsync(handle, CB_FLAG, 2, error);
		CHECK_STATUS(status, status, cleanup);

		if ( debug ) {
			// Await the requested trace data
			status = flReadChannelAsyncAwait(handle, &recvData, &actualLength, &actualLength, error);
			CHECK_STATUS(status, status, cleanup);

			// Write it to the trace-log
			fwrite(recvData, 1, actualLength, file);
		}

		// Await the requested command status flag
		status = flReadChannelAsyncAwait(handle, &recvData, &actualLength, &actualLength, error);
		CHECK_STATUS(status, status, cleanup);
	} while ( recvData[0] != 0x00 || recvData[1] != CF_READY );

	if ( debug ) {
		// Await the final block of trace-data
		status = flReadChannelAsyncAwait(handle, &recvData, &actualLength, &actualLength, error);
		CHECK_STATUS(status, status, cleanup);
		
		// Write it to the trace-log
		fwrite(recvData, 1, actualLength, file);
		fclose(file);
		file = NULL;
	}
	
	// Await the final command-flag
	status = flReadChannelAsyncAwait(handle, &recvData, &actualLength, &actualLength, error);
	CHECK_STATUS(status, status, cleanup);

	// Restore old opcode to vbAddr
	status = umdkDirectWriteWord(handle, vbAddr, oldOp, error);
	CHECK_STATUS(status, status, cleanup);

	// Read saved registers, if necessary
	if ( regs ) {
		status = umdkDirectReadBytes(handle, CB_REGS, 18*4, u->bytes, error);
		CHECK_STATUS(status, status, cleanup);
		for ( i = 0; i < 18; i++ ) {
			u->longs[i] = bigEndian32(u->longs[i]);
		}
	}

	if ( debug ) {
		// Read RAM
		status = umdkReadBytes(handle, 0xFF0000, 65536, tmpData, error);
		CHECK_STATUS(status, status, cleanup);
		
		// Save it
		file = fopen("ramAfter.bin", "wb");
		CHECK_STATUS(!file, 13, cleanup, "umdkContWait(): Unable to open ramAfter.bin for writing!");
		fwrite(tmpData, 1, 65536, file);
		fclose(file);
		file = NULL;
	}
cleanup:
	if ( file ) {
		fclose(file);
	}
	return retVal;
}