// Play the CSVF stream into the JTAG port. // FLStatus csvfPlay(struct FLContext *handle, const uint8 *csvfData, const char **error) { FLStatus returnCode = FL_SUCCESS; FLStatus fStatus; uint8 thisByte, numBits; uint32 numBytes; uint8 *tdoPtr, *tdiPtr; uint8 i; uint32 xsdrSize = 0; uint32 xruntest = 0; uint8 tdoMask[CSVF_BUF_SIZE]; uint8 tdiData[CSVF_BUF_SIZE]; uint8 tdoData[CSVF_BUF_SIZE]; uint8 tdoExpected[CSVF_BUF_SIZE]; char data[CSVF_BUF_SIZE*2+1]; char mask[CSVF_BUF_SIZE*2+1]; char expected[CSVF_BUF_SIZE*2+1]; uint8 *tdiAll; const uint8 *ptr = csvfData; fStatus = jtagClockFSM(handle, 0x0000001F, 6, error); // Reset TAP, goto Run-Test/Idle CHECK_STATUS(fStatus, "csvfPlay()", fStatus); thisByte = *ptr++; while ( thisByte != XCOMPLETE ) { switch ( thisByte ) { case XTDOMASK: #ifdef DEBUG printf("XTDOMASK("); #endif numBytes = bitsToBytes(xsdrSize); tdoPtr = tdoMask; while ( numBytes-- ) { thisByte = *ptr++; #ifdef DEBUG printf("%02X", thisByte); #endif *tdoPtr++ = thisByte; } #ifdef DEBUG printf(")\n"); #endif break; case XRUNTEST: xruntest = *ptr++; xruntest <<= 8; xruntest |= *ptr++; xruntest <<= 8; xruntest |= *ptr++; xruntest <<= 8; xruntest |= *ptr++; #ifdef DEBUG printf("XRUNTEST(%08X)\n", xruntest); #endif break; case XSIR: fStatus = jtagClockFSM(handle, 0x00000003, 4, error); // -> Shift-IR CHECK_STATUS(fStatus, "csvfPlay()", fStatus); numBits = *ptr++; #ifdef DEBUG printf("XSIR(%02X, ", numBits); #endif numBytes = bitsToBytes(numBits); tdiPtr = tdiData; while ( numBytes-- ) { thisByte = *ptr++; #ifdef DEBUG printf("%02X", thisByte); #endif *tdiPtr++ = thisByte; } #ifdef DEBUG printf(")\n"); #endif fStatus = jtagShift(handle, numBits, tdiData, NULL, true, error); // -> Exit1-DR CHECK_STATUS(fStatus, "csvfPlay()", fStatus); fStatus = jtagClockFSM(handle, 0x00000001, 2, error); // -> Run-Test/Idle CHECK_STATUS(fStatus, "csvfPlay()", fStatus); if ( xruntest ) { fStatus = jtagClocks(handle, xruntest, error); CHECK_STATUS(fStatus, "csvfPlay()", fStatus); } break; case XSDRSIZE: xsdrSize = *ptr++; xsdrSize <<= 8; xsdrSize |= *ptr++; xsdrSize <<= 8; xsdrSize |= *ptr++; xsdrSize <<= 8; xsdrSize |= *ptr++; #ifdef DEBUG printf("XSDRSIZE(%08X)\n", xsdrSize); #endif break; case XSDRTDO: numBytes = bitsToBytes(xsdrSize); tdiPtr = tdiData; tdoPtr = tdoExpected; while ( numBytes-- ) { *tdiPtr++ = *ptr++; *tdoPtr++ = *ptr++; } numBytes = bitsToBytes(xsdrSize); i = 0; do { fStatus = jtagClockFSM(handle, 0x00000001, 3, error); // -> Shift-DR CHECK_STATUS(fStatus, "csvfPlay()", fStatus); fStatus = jtagShift(handle, xsdrSize, tdiData, tdoData, true, error); // -> Exit1-DR CHECK_STATUS(fStatus, "csvfPlay()", fStatus); fStatus = jtagClockFSM(handle, 0x0000001A, 6, error); // -> Run-Test/Idle CHECK_STATUS(fStatus, "csvfPlay()", fStatus); if ( xruntest ) { fStatus = jtagClocks(handle, xruntest, error); CHECK_STATUS(fStatus, "csvfPlay()", fStatus); } i++; #ifdef DEBUG dumpSimple(tdoData, numBytes, data); dumpSimple(tdoMask, numBytes, mask); dumpSimple(tdoExpected, numBytes, expected); printf("XSDRTDO(attempt: %d; mask: %s; expecting: %s; got: %s)\n", i, mask, expected, data); #endif } while ( tdoMatchFailed(tdoData, tdoMask, tdoExpected, numBytes) && i < 32 ); if ( i == 32 ) { dumpSimple(tdoData, numBytes, data); dumpSimple(tdoMask, numBytes, mask); dumpSimple(tdoExpected, numBytes, expected); errRender( error, "csvfPlay(): XSDRTDO failed:\n Got: %s\n Mask: %s\n Expecting: %s", data, mask, expected); FAIL(FL_PROG_SVF_COMPARE); } break; case XSDR: #ifdef DEBUG // TODO: Need to print actual TDO data too printf("XSDR(%08X)\n", xsdrSize); #endif fStatus = jtagClockFSM(handle, 0x00000001, 3, error); // -> Shift-DR CHECK_STATUS(fStatus, "csvfPlay()", fStatus); numBytes = bitsToBytes(xsdrSize); tdiAll = malloc(numBytes); tdiPtr = tdiAll; while ( numBytes-- ) { *tdiPtr++ = *ptr++; } fStatus = jtagShift(handle, xsdrSize, tdiAll, NULL, true, error); // -> Exit1-DR free(tdiAll); CHECK_STATUS(fStatus, "csvfPlay()", fStatus); fStatus = jtagClockFSM(handle, 0x00000001, 2, error); // -> Run-Test/Idle CHECK_STATUS(fStatus, "csvfPlay()", fStatus); if ( xruntest ) { fStatus = jtagClocks(handle, xruntest, error); CHECK_STATUS(fStatus, "csvfPlay()", fStatus); } break; default: errRender(error, "csvfPlay(): Unsupported command 0x%02X", thisByte); FAIL(FL_PROG_SVF_UNKNOWN_CMD); } thisByte = *ptr++; } cleanup: return returnCode; }
// Called when a vendor command is received // uint8 handleVendorCommand(uint8 cmd) { switch(cmd) { // Set various mode bits, or fetch status information // case CMD_MODE_STATUS: if ( SETUP_TYPE == (REQDIR_HOSTTODEVICE | REQTYPE_VENDOR) ) { xdata uint16 wBits = SETUP_VALUE(); xdata uint16 wMask = SETUP_INDEX(); if ( wMask & MODE_JTAG ) { // When in JTAG mode, the JTAG lines are driven; tristate otherwise jtagSetEnabled(wBits & MODE_JTAG ? true : false); } } else { // Get STATUS: return the diagnostic byte while ( EP0CS & bmEPBUSY ); EP0BUF[0] = 'N'; // Magic bytes (my cat's name) EP0BUF[1] = 'E'; EP0BUF[2] = 'M'; EP0BUF[3] = 'I'; EP0BUF[4] = m_diagnosticCode; // Last operation diagnostic code EP0BUF[5] = (IOA & bmBIT2) ? 0 : 1; // Flags EP0BUF[6] = 0x11; // NeroJTAG endpoints EP0BUF[7] = 0x26; // CommFPGA endpoints EP0BUF[8] = 0x00; // Reserved EP0BUF[9] = 0x00; // Reserved EP0BUF[10] = 0x00; // Reserved EP0BUF[11] = 0x00; // Reserved EP0BUF[12] = 0x00; // Reserved EP0BUF[13] = 0x00; // Reserved EP0BUF[14] = 0x00; // Reserved EP0BUF[15] = 0x00; // Reserved // Return status packet to host EP0BCH = 0; SYNCDELAY; EP0BCL = 16; } return true; // Clock data into and out of the JTAG chain. Reads from EP2OUT and writes to EP4IN. // case CMD_JTAG_CLOCK_DATA: if ( SETUP_TYPE == (REQDIR_HOSTTODEVICE | REQTYPE_VENDOR) ) { EP0BCL = 0x00; // Allow host transfer in while ( EP0CS & bmEPBUSY ); // Wait for data jtagShiftBegin(*((uint32 *)EP0BUF), SETUPDAT[2]); // Init numBits & flagByte return true; // Now that numBits & flagByte are set, this operation will continue in mainLoop()... } break; // Clock an (up to) 32-bit pattern LSB-first into TMS to change JTAG TAP states // case CMD_JTAG_CLOCK_FSM: if ( SETUP_TYPE == (REQDIR_HOSTTODEVICE | REQTYPE_VENDOR) ) { EP0BCL = 0x00; // Allow host transfer in while ( EP0CS & bmEPBUSY ); // Wait for data jtagClockFSM(*((uint32 *)EP0BUF), SETUPDAT[2]); // Bit pattern, transitionCount return true; } break; // Execute a number of JTAG clocks. // case CMD_JTAG_CLOCK: if ( SETUP_TYPE == (REQDIR_HOSTTODEVICE | REQTYPE_VENDOR) ) { jtagClocks(*((uint32 *)(SETUPDAT+2))); return true; } break; // Set various mode bits, or fetch status information // case CMD_PORT_IO: if ( SETUP_TYPE == (REQDIR_DEVICETOHOST | REQTYPE_VENDOR) ) { const xdata uint8 portSelect = SETUPDAT[4]; const xdata uint8 mask = SETUPDAT[5]; xdata uint8 ddrWrite = SETUPDAT[2]; xdata uint8 portWrite = SETUPDAT[3]; //usartSendString("Got: "); //usartSendByteHex(portSelect); //usartSendByteHex(mask); //usartSendByteHex(ddrWrite); //usartSendByteHex(portWrite); //usartSendByte('\r'); if ( portSelect > 4 ) { return false; // illegal port } portWrite &= mask; ddrWrite &= mask; pins[portSelect] &= ~mask; // clear existing relevant bits pins[portSelect] |= portWrite; ddrs[portSelect] &= ~mask; ddrs[portSelect] |= ddrWrite; (*maskFunc[JTAG_PORT])(); // Get the state of the port D & B lines: while ( EP0CS & bmEPBUSY ); switch ( portSelect ) { case 0: OEA = ddrs[0]; IOA = pins[0]; EP0BUF[0] = IOA; break; case 2: OEC = ddrs[2]; IOC = pins[2]; EP0BUF[0] = IOC; break; case 3: OED = ddrs[3]; IOD = pins[3]; EP0BUF[0] = IOD; break; case 4: OEE = ddrs[4]; IOE = pins[4]; EP0BUF[0] = IOE; break; default: EP0BUF[0] = 0xAA; break; } EP0BCH = 0; SYNCDELAY; EP0BCL = 1; return true; } break; // Command to talk to the EEPROM // case CMD_READ_WRITE_EEPROM: if ( SETUP_TYPE == (REQDIR_DEVICETOHOST | REQTYPE_VENDOR) ) { // It's an IN operation - read from prom and send to host xdata uint16 address = SETUP_VALUE(); xdata uint16 length = SETUP_LENGTH(); xdata uint16 chunkSize; xdata uint8 i; while ( length ) { while ( EP0CS & bmEPBUSY ); chunkSize = length < EP0BUF_SIZE ? length : EP0BUF_SIZE; for ( i = 0; i < chunkSize; i++ ) { EP0BUF[i] = 0x23; } promRead(SETUPDAT[4], address, chunkSize, EP0BUF); EP0BCH = 0; SYNCDELAY; EP0BCL = chunkSize; address += chunkSize; length -= chunkSize; } } else if ( SETUP_TYPE == (REQDIR_HOSTTODEVICE | REQTYPE_VENDOR) ) { // It's an OUT operation - read from host and send to prom xdata uint16 address = SETUP_VALUE(); xdata uint16 length = SETUP_LENGTH(); xdata uint16 chunkSize; while ( length ) { EP0BCL = 0x00; // allow pc transfer in while ( EP0CS & bmEPBUSY ); // wait for data chunkSize = EP0BCL; promWrite(SETUPDAT[4], address, chunkSize, EP0BUF); address += chunkSize; length -= chunkSize; } } return true; case CMD_SELECTMAP: if ( SETUP_TYPE == (REQDIR_DEVICETOHOST | REQTYPE_VENDOR) ) { // return the status byte and micro-controller mode while ( EP0CS & bmEPBUSY ); // can't do this until EP0 is ready EP0BUF[0] = 0xF0; EP0BUF[1] = 0x0D; EP0BUF[2] = 0x1E; EP0BCH=0; SYNCDELAY; EP0BCL=3; } else if ( SETUP_TYPE == (REQDIR_HOSTTODEVICE | REQTYPE_VENDOR) ) { smapProgBegin(MAKEDWORD(SETUP_VALUE(), SETUP_INDEX())); } return true; } return false; // unrecognised command }