// 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; }
// 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; }