Example #1
0
static FLStatus sendXSize(struct Buffer *outBuf, uint32 xSize, const char **error) {
	FLStatus retVal = FL_SUCCESS;
	BufferStatus bStatus;
	bStatus = bufAppendByte(outBuf, XSDRSIZE, error);
	CHECK_STATUS(bStatus, FL_ALLOC_ERR, cleanup, "sendXSize()");
	bStatus = bufAppendLongBE(outBuf, xSize, error);
	CHECK_STATUS(bStatus, FL_ALLOC_ERR, cleanup, "sendXSize()");
cleanup:
	return retVal;
}
Example #2
0
static FLStatus shiftLeft(
	struct Buffer *buffer, uint32 numBits, uint32 shiftCount, const char **error)
{
	FLStatus retVal = FL_SUCCESS;
	uint32 shiftBytes = shiftCount>>3;
	uint32 shiftBits = shiftCount&7;
	uint16 accum;
	const uint8 *p = buffer->data;
	const uint8 *const end = buffer->data + buffer->length;
	struct Buffer newBuffer = {0,};
	BufferStatus bStatus;
	if ( shiftBits ) {
		bStatus = bufInitialise(&newBuffer, 1024, 0x00, error);
		CHECK_STATUS(bStatus, FL_BUF_INIT_ERR, cleanup, "shiftLeft()");
		numBits &= 7;  // Now the number of significant bits in first byte.
		if ( numBits ) {
			numBits = 8 - numBits; // Now the number of insignificant bits in first byte.
		}
		accum = p[0];
		if ( p < end ) {
			accum = (uint16)(accum >> (8-shiftBits));
			if ( shiftBits > numBits ) {
				// We're shifting by more than the number of insignificant bits
				bStatus = bufAppendByte(&newBuffer, (uint8)(accum&0xFF), error);
				CHECK_STATUS(bStatus, FL_BUF_APPEND_ERR, cleanup, "shiftLeft()");
			}
			accum = (uint16)((p[0]<<8) + p[1]);
			p++;
			while ( p < end ) {
				accum = (uint16)(accum >> (8-shiftBits));
				bStatus = bufAppendByte(&newBuffer, (uint8)(accum&0xFF), error);
				CHECK_STATUS(bStatus, FL_BUF_APPEND_ERR, cleanup, "shiftLeft()");
				accum = (uint16)((p[0]<<8) + p[1]);
				p++;
			}
		}
		accum &= 0xFF00;
		accum = (uint16)(accum >> (8-shiftBits));
		bStatus = bufAppendByte(&newBuffer, (uint8)(accum&0xFF), error);
		CHECK_STATUS(bStatus, FL_BUF_APPEND_ERR, cleanup, "shiftLeft()");
		bufSwap(&newBuffer, buffer);
	}
Example #3
0
// Parse the XSVF, reversing the byte-ordering of all the bytestreams.
//
static FLStatus xsvfSwapBytes(XC *xc, struct Buffer *outBuf, uint32 *maxBufSize, const char **error) {
	FLStatus fStatus, retVal = FL_SUCCESS;
	uint32 newXSize = 0, curXSize = 0, totOffset = 0;
	uint32 numBytes;
	BufferStatus bStatus;
	uint8 thisByte;
	uint32 dummy;
	bool zeroMask = false;

	if ( !maxBufSize ) {
		maxBufSize = &dummy;
	}
	*maxBufSize = 0;
	thisByte = getNextByte(xc);
	while ( thisByte != XCOMPLETE ) {
		switch ( thisByte ) {
		case XTDOMASK:{
			// Swap the XTDOMASK bytes.
			uint32 initLength;
			const uint8 *p;
			const uint8 *end;
			if ( newXSize != curXSize ) {
				curXSize = newXSize;
				sendXSize(outBuf, curXSize, error);
			}
			initLength = (uint32)outBuf->length;
			numBytes = bitsToBytes(curXSize);
			bStatus = bufAppendByte(outBuf, XTDOMASK, error);
			CHECK_STATUS(bStatus, FL_ALLOC_ERR, cleanup, "xsvfSwapBytes()");
			fStatus = swapBytes(xc, numBytes, outBuf, error);
			CHECK_STATUS(fStatus, fStatus, cleanup, "xsvfSwapBytes()");
			p = outBuf->data + initLength + 1;
			end = outBuf->data + outBuf->length;
			while ( *p == 0 && p < end ) p++;
			if ( p == end ) {
				// All zeros so delete the command
				outBuf->length = initLength;
				zeroMask = true;
			} else {
				// Keep the command
				if ( numBytes > *maxBufSize ) {
					*maxBufSize = numBytes;
				}
				zeroMask = false;
			}
			break;
		}

		case XSDRTDO:
			// Swap the tdiValue and tdoExpected bytes.
			if ( newXSize != curXSize ) {
				curXSize = newXSize;
				sendXSize(outBuf, curXSize, error);
			}
			numBytes = bitsToBytes(curXSize);
			if ( zeroMask ) {
				// The last mask was all zeros, so replace this XSDRTDO with an XSDR and throw away
				// the tdoExpected bytes.
				bStatus = bufAppendByte(outBuf, XSDR, error);
				CHECK_STATUS(bStatus, FL_ALLOC_ERR, cleanup, "xsvfSwapBytes()");
				fStatus = swapBytes(xc, numBytes, outBuf, error);
				CHECK_STATUS(fStatus, fStatus, cleanup, "xsvfSwapBytes()");
				while ( numBytes-- ) {
					getNextByte(xc);
				}
			} else {
				// The last mask was not all zeros, so we must honour the XSDRTDO's tdoExpected bytes.
				CHECK_STATUS(
					numBytes > BUF_SIZE, FL_UNSUPPORTED_SIZE_ERR, cleanup,
					"xsvfSwapBytes(): Previous mask was nonzero, but no room to compare %d bytes", numBytes);
				if ( numBytes > *maxBufSize ) {
					*maxBufSize = numBytes;
				}
				bStatus = bufAppendByte(outBuf, XSDRTDO, error);
				CHECK_STATUS(bStatus, FL_ALLOC_ERR, cleanup, "xsvfSwapBytes()");
				fStatus = swapAndInterleaveBytes(xc, numBytes, outBuf, error);
				CHECK_STATUS(fStatus, fStatus, cleanup, "xsvfSwapBytes()");
			}
			break;

		case XREPEAT:
			// Drop XREPEAT for now. Will probably be needed for CPLDs.
			getNextByte(xc);
			break;
			
		case XRUNTEST:
			// Copy the XRUNTEST bytes as-is.
			bStatus = bufAppendByte(outBuf, XRUNTEST, error);
			CHECK_STATUS(bStatus, FL_ALLOC_ERR, cleanup, "xsvfSwapBytes()");
			bStatus = bufAppendByte(outBuf, getNextByte(xc), error);
			CHECK_STATUS(bStatus, FL_ALLOC_ERR, cleanup, "xsvfSwapBytes()");
			bStatus = bufAppendByte(outBuf, getNextByte(xc), error);
			CHECK_STATUS(bStatus, FL_ALLOC_ERR, cleanup, "xsvfSwapBytes()");
			bStatus = bufAppendByte(outBuf, getNextByte(xc), error);
			CHECK_STATUS(bStatus, FL_ALLOC_ERR, cleanup, "xsvfSwapBytes()");
			bStatus = bufAppendByte(outBuf, getNextByte(xc), error);
			CHECK_STATUS(bStatus, FL_ALLOC_ERR, cleanup, "xsvfSwapBytes()");
			break;

		case XSIR:
			// Swap the XSIR bytes.
			bStatus = bufAppendByte(outBuf, XSIR, error);
			CHECK_STATUS(bStatus, FL_ALLOC_ERR, cleanup, "xsvfSwapBytes()");
			thisByte = getNextByte(xc);
			bStatus = bufAppendByte(outBuf, thisByte, error);
			CHECK_STATUS(bStatus, FL_ALLOC_ERR, cleanup, "xsvfSwapBytes()");
			fStatus = swapBytes(xc, (uint32)bitsToBytes(thisByte), outBuf, error);
			CHECK_STATUS(fStatus, fStatus, cleanup, "xsvfSwapBytes()");
			break;

		case XSDRSIZE:
			// Just store it; if it differs from the old one it will be sent when required
			newXSize = getNextByte(xc);  // Get MSB
			newXSize <<= 8;
			newXSize |= getNextByte(xc);
			newXSize <<= 8;
			newXSize |= getNextByte(xc);
			newXSize <<= 8;
			newXSize |= getNextByte(xc); // Get LSB
			break;

		case XSDR:
			// Copy over
			if ( newXSize != curXSize ) {
				curXSize = newXSize;
				sendXSize(outBuf, curXSize, error);
			}
			bStatus = bufAppendByte(outBuf, XSDR, error);
			CHECK_STATUS(bStatus, FL_ALLOC_ERR, cleanup, "xsvfSwapBytes()");
			fStatus = swapBytes(xc, bitsToBytes(curXSize), outBuf, error);
			CHECK_STATUS(fStatus, fStatus, cleanup, "xsvfSwapBytes()");
			break;

		case XSDRB:
			// Roll XSDRB, XSDRC*, XSDRE into one XSDR
			curXSize = newXSize;
			sendXSize(outBuf, curXSize, error);
			totOffset = (uint32)outBuf->length - 4; // each subsequent XSDRC & XSDRE updates this XSDRSIZE
			bStatus = bufAppendByte(outBuf, XSDR, error);
			CHECK_STATUS(bStatus, FL_ALLOC_ERR, cleanup, "xsvfSwapBytes()");
			fStatus = swapBytes(xc, bitsToBytes(newXSize), outBuf, error);
			CHECK_STATUS(fStatus, fStatus, cleanup, "xsvfSwapBytes()");
			break;

		case XSDRC:
			// Just add the XSDRC data to the end of the previous XSDR
			curXSize += newXSize;
			bStatus = bufWriteLongBE(outBuf, totOffset, curXSize, error);
			CHECK_STATUS(bStatus, FL_ALLOC_ERR, cleanup, "xsvfSwapBytes()");
			fStatus = swapBytes(xc, bitsToBytes(newXSize), outBuf, error);
			CHECK_STATUS(fStatus, fStatus, cleanup, "xsvfSwapBytes()");
			break;

		case XSDRE:
			// Just add the XSDRE data to the end of the previous XSDR
			curXSize += newXSize;
			bStatus = bufWriteLongBE(outBuf, totOffset, curXSize, error);
			CHECK_STATUS(bStatus, FL_ALLOC_ERR, cleanup, "xsvfSwapBytes()");
			fStatus = swapBytes(xc, bitsToBytes(newXSize), outBuf, error);
			CHECK_STATUS(fStatus, fStatus, cleanup, "xsvfSwapBytes()");
			break;

		case XSTATE:
			// There doesn't seem to be much point in these commands, since the other commands have
			// implied state transitions anyway. Just make sure the TAP is initialised to be at
			// Run-Test/Idle before playing the CSVF stream.
			getNextByte(xc);
			break;

		case XENDIR:
			// Only the default XENDIR state (TAPSTATE_RUN_TEST_IDLE) is supported. Fail fast if
			// there's an attempt to switch the XENDIR state to PAUSE_IR.
			thisByte = getNextByte(xc);
			CHECK_STATUS(
				thisByte, FL_UNSUPPORTED_DATA_ERR, cleanup,
				"xsvfSwapBytes(): Only XENDIR(TAPSTATE_RUN_TEST_IDLE) is supported!");
			break;

		case XENDDR:
			// Only the default XENDDR state (TAPSTATE_RUN_TEST_IDLE) is supported. Fail fast if
			// there's an attempt to switch the XENDDR state to PAUSE_DR.
			thisByte = getNextByte(xc);
			CHECK_STATUS(
				thisByte, FL_UNSUPPORTED_DATA_ERR, cleanup,
				"xsvfSwapBytes(): Only XENDDR(TAPSTATE_RUN_TEST_IDLE) is supported!");
			break;

		default:
			// All other commands are unsupported, so fail if they're encountered.
			CHECK_STATUS(
				true, FL_UNSUPPORTED_CMD_ERR, cleanup,
				"xsvfSwapBytes(): Unsupported command 0x%02X!", thisByte);
		}
		thisByte = getNextByte(xc);
	}

	// Add the XCOMPLETE command
	bStatus = bufAppendByte(outBuf, XCOMPLETE, error);
	CHECK_STATUS(bStatus, FL_ALLOC_ERR, cleanup, "xsvfSwapBytes()");

cleanup:
	return retVal;
}
Example #4
0
DLLEXPORT(FLStatus) flFlashStandardFirmware(
	struct FLContext *handle, const char *newVidPid, const char *jtagPort,
	 uint32 eepromSize, const char *xsvfFile, const char **error)
{
	FLStatus flStatus, returnCode;
	struct Buffer i2cBuf = {0,};
	BufferStatus bStatus;
	FX2Status fxStatus;
	uint32 fwSize, xsvfSize, initSize;
	uint16 newVid, newPid, newDid;
	uint8 port, tdoBit, tdiBit, tmsBit, tckBit;
	if ( !usbValidateVidPid(newVidPid) ) {
		errRender(error, "flFlashStandardFirmware(): The supplied new VID:PID \"%s\" is invalid; it should look like 04B4:8613", newVidPid);
		FAIL(FL_USB_ERR);
	}
	newVid = (uint16)strtoul(newVidPid, NULL, 16);
	newPid = (uint16)strtoul(newVidPid+5, NULL, 16);
	newDid = (strlen(newVidPid) == 14) ? (uint16)strtoul(newVidPid+10, NULL, 16) : 0x0000;
	if ( strlen(jtagPort) != 5 ) {
		errRender(error, "flFlashStandardFirmware(): JTAG port specification must be <C|D><tdoBit><tdiBit><tmsBit><tckBit>");
		FAIL(FL_FX2_ERR);
	}
	if ( (jtagPort[0] & 0xDF) == 'A' ) {
		port = 0;
	} else if ( (jtagPort[0] & 0xDF) == 'C' ) {
		port = 2;
	} else if ( (jtagPort[0] & 0xDF) == 'D' ) {
		port = 3;
	} else {
		errRender(error, "flFlashStandardFirmware(): JTAG port specification must be <A|C|D><tdoBit><tdiBit><tmsBit><tckBit>");
		FAIL(FL_FX2_ERR);
	}
	if  (jtagPort[1] < '0' || jtagPort[1] > '7' || jtagPort[2] < '0' || jtagPort[2] > '7' || jtagPort[3] < '0' || jtagPort[3] > '7' || jtagPort[4] < '0' || jtagPort[4] > '7' ) {
		errRender(error, "flFlashStandardFirmware(): JTAG port specification must be <A|C|D><tdoBit><tdiBit><tmsBit><tckBit>");
		FAIL(FL_FX2_ERR);
	}
	tdoBit = jtagPort[1] - '0';
	tdiBit = jtagPort[2] - '0';
	tmsBit = jtagPort[3] - '0';
	tckBit = jtagPort[4] - '0';
	if (
		port == 0 &&
		(isInvalidPortABit(tdoBit) || isInvalidPortABit(tdiBit) ||
		 isInvalidPortABit(tmsBit) || isInvalidPortABit(tckBit))
	) {
		errRender(error, "flFlashStandardFirmware(): Only bits 0, 1, 3 & 7 are available for JTAG use on port A");
		FAIL(FL_FX2_ERR);
	}		
		
	bStatus = bufInitialise(&i2cBuf, 0x4000, 0x00, error);
	CHECK_STATUS(bStatus, "flFlashStandardFirmware()", FL_ALLOC_ERR);
	if ( xsvfFile ) {
		flStatus = copyFirmwareAndRewriteIDs(
			&eepromWithBootFirmware, newVid, newPid, newDid,
			port, tdoBit, tdiBit, tmsBit, tckBit,
			&i2cBuf, error);
		CHECK_STATUS(flStatus, "flFlashStandardFirmware()", flStatus);
		fwSize = i2cBuf.length;
		flStatus = convertJtagFileToCsvf(&i2cBuf, xsvfFile, error);
		CHECK_STATUS(flStatus, "flFlashStandardFirmware()", flStatus);
		xsvfSize = i2cBuf.length - fwSize;
		if ( handle->writeBuffer.length ) {
			// Write a big-endian uint24 length for the init data, then the data itself
			const uint32 length = handle->writeBuffer.length;
			if ( length > 0x20000 ) {
				errRender(
					error,
					"flFlashStandardFirmware(): Cannot cope with %lu bytes of init data",
					length);
				FAIL(FL_FX2_ERR);
			}
			bStatus = bufAppendByte(&i2cBuf, (uint8)((length>>16) & 0xFF), error);
			CHECK_STATUS(bStatus, "flFlashStandardFirmware()", FL_ALLOC_ERR);
			bStatus = bufAppendByte(&i2cBuf, (uint8)((length>>8) & 0xFF), error);
			CHECK_STATUS(bStatus, "flFlashStandardFirmware()", FL_ALLOC_ERR);
			bStatus = bufAppendByte(&i2cBuf, (uint8)(length & 0xFF), error);
			CHECK_STATUS(bStatus, "flFlashStandardFirmware()", FL_ALLOC_ERR);
			bStatus = bufAppendBlock(
				&i2cBuf, handle->writeBuffer.data, length, error);
			CHECK_STATUS(bStatus, "flFlashStandardFirmware()", FL_ALLOC_ERR);
			initSize = length + 3;
		} else {
			// Write a zero uint24 length so the firmware knows there's no init data to follow
			bStatus = bufAppendByte(&i2cBuf, 0x00, error);
			CHECK_STATUS(bStatus, "flFlashStandardFirmware()", FL_ALLOC_ERR);
			bStatus = bufAppendByte(&i2cBuf, 0x00, error);
			CHECK_STATUS(bStatus, "flFlashStandardFirmware()", FL_ALLOC_ERR);
			bStatus = bufAppendByte(&i2cBuf, 0x00, error);
			CHECK_STATUS(bStatus, "flFlashStandardFirmware()", FL_ALLOC_ERR);
			initSize = 3;
		}
	} else {