/* Byte-oriented write */ static GOOD_OR_BAD OW_w_mem(const BYTE * data, size_t size, off_t offset, const struct parsedname *pn) { BYTE scratch[_DS2430A_MEM_SIZE]; BYTE vr[] = { _1W_READ_SCRATCHPAD, BYTE_MASK(offset), }; BYTE of[] = { _1W_WRITE_SCRATCHPAD, BYTE_MASK(offset), }; BYTE cp[] = { _1W_COPY_SCRATCHPAD, _1W_COPY_SCRATCHPAD_VALIDATION_KEY, }; struct transaction_log t[] = { TRXN_START, TRXN_WRITE2(of), TRXN_WRITE(data, size), TRXN_START, TRXN_WRITE2(vr), TRXN_READ(scratch, size), TRXN_COMPARE(data,scratch,size), TRXN_START, TRXN_WRITE2(cp), TRXN_DELAY(10), TRXN_END, }; /* load scratch pad if incomplete write */ if ( size != _DS2430A_MEM_SIZE ) { RETURN_BAD_IF_BAD( OW_r_mem( scratch, 0, 0x00, pn)) ; } /* write data to scratchpad */ /* read back the scratchpad */ /* copy scratchpad to memory */ return BUS_transaction(t, pn); }
/* Call will not span "page" */ static GOOD_OR_BAD OW_r_memory(BYTE * data, size_t size, off_t offset, struct parsedname *pn) { BYTE location_setup[2] = { BYTE_MASK(offset), BYTE_MASK(size), }; // 500uS RETURN_BAD_IF_BAD( OW_w_scratch(location_setup, 2, pn)) ; RETURN_BAD_IF_BAD( LCD_byte(_LCD_COMMAND_EEPROM_READ_TO_SCRATCH, 1, pn)) ; return OW_r_scratch(data, BYTE_MASK(size), pn); }
/** * Set value of RAX in guest register set. * @param guest_regs Guest register set. * @param value_new New value to be written. * @param size Access size (1, 2 or 4 bytes). * * @private */ static void set_rax_reg(struct registers *guest_regs, u32 value_new, u8 size) { u64 value_old = guest_regs->rax; /* 32-bit access is special, since it clears all the upper * part of RAX. Another types of access leave it intact */ u64 mask = (size == 4 ? BYTE_MASK(8) : BYTE_MASK(size)); guest_regs->rax = (value_old & ~mask) | (value_new & mask); }
static GOOD_OR_BAD OW_r_app(BYTE * data, size_t size, off_t offset, const struct parsedname *pn) { BYTE c3[] = { _1W_READ_APPLICATION_REGISTER, BYTE_MASK(offset), }; struct transaction_log t[] = { TRXN_START, TRXN_WRITE2(c3), TRXN_READ(data, size), TRXN_END, }; return BUS_transaction(t, pn) ; }
/* Byte-oriented write */ static GOOD_OR_BAD OW_r_mem( BYTE * data, size_t size, off_t offset, const struct parsedname *pn) { BYTE fo[] = { _1W_READ_MEMORY, BYTE_MASK(offset), }; struct transaction_log t[] = { TRXN_START, TRXN_WRITE2(fo), TRXN_READ( data, size ) , TRXN_END, }; return BUS_transaction(t, pn); }
// set up default device ID static void GetDefaultDeviceName(BYTE * dn, const BYTE * sn, const struct connection_in * in) { switch (get_busmode(in)) { case bus_tester: // "bus number" dn[1] = BYTE_MASK(in->master.tester.index >> 0) ; dn[2] = BYTE_MASK(in->master.tester.index >> 8) ; // repeat family code dn[3] = sn[0] ; // family code complement dn[4] = BYTE_INVERSE(sn[0]) ; // "device" number dn[5] = BYTE_MASK(DirblobElements(&(in->master.fake.main)) >> 0) ; dn[6] = BYTE_MASK(DirblobElements(&(in->master.fake.main)) >> 8) ; break ; case bus_fake: case bus_mock: default: // only for compiler warning dn[1] = BYTE_MASK(rand()) ; dn[2] = BYTE_MASK(rand()) ; dn[3] = BYTE_MASK(rand()) ; dn[4] = BYTE_MASK(rand()) ; dn[5] = BYTE_MASK(rand()) ; dn[6] = BYTE_MASK(rand()) ; break ; } }
// Test the address bus wiring by writing/reading data to address 0x1, // then shifting adress to the left and repeating. // // Note that to be complete, this test should verify that the data // wasn't written to any other address than the address under // test. For simplicity (assuming a single RAM), this code does NOT // perform this check. // // Returns FALSE if fails and fills out the MemError struct. Returns // TRUE if successful. BOOL TestWalkingOnesAddress32(uint32 *addr, int size, MemError *pError) { volatile uint8 *ptr; uint32 offset; uint8 data, value; int i; int addrSize, addrMask; // Determine number of address bits addrSize = 0; for(addrMask = 1; addrMask <= size; addrMask = (addrMask << 1) |1) { addrSize++; } addrMask >>= 1; offset = 1; data = 0xA5; // Run test for single walking 1 for(i = 0; i < addrSize; i++) { // Determine new address ptr = (volatile uint8 *)((uint32)addr + offset); // Write current data value *ptr = data; // Readback and verify value = *ptr & BYTE_MASK(offset); if(value != (data & BYTE_MASK(offset))) { FillError(pError, (uint32)ptr, value, data & BYTE_MASK(offset), 1); return FALSE; } // Walk address to the left by 1 bit offset <<= 1; } offset = (~1) & addrMask; // Run test for single walking 0 for(i = 2; i < addrSize; i++) { // Determine new address ptr = (volatile uint8 *)((uint32)addr + offset); // Write current data value *ptr = data; // Readback and verify value = *ptr & BYTE_MASK(offset); if(value != (data & BYTE_MASK(offset))) { FillError(pError, (uint32)ptr, value, data & BYTE_MASK(offset), 1); return FALSE; } // Walk address to the left by 1 bit offset = ((offset << 1) | 1) & addrMask; } return TRUE; }
/* Call will not span "page" */ static GOOD_OR_BAD OW_w_memory(BYTE * data, size_t size, off_t offset, struct parsedname *pn) { BYTE location_and_buffer[1 + _LCD_PAGE_SIZE] = { BYTE_MASK(offset), }; if (size == 0) { return gbGOOD; } memcpy(&location_and_buffer[1], data, size); // 4mS/byte RETURN_BAD_IF_BAD(OW_w_scratch(location_and_buffer, size + 1, pn)) ; return LCD_byte(_LCD_COMMAND_EEPROM_WRITE_FROM_SCRATCH, 4 * size, pn) ; }
/* write 4 or 5 byte number */ static GOOD_OR_BAD OW_w_ulong(uint64_t * L, size_t size, off_t offset, struct parsedname *pn) { BYTE data[5] = { 0x00, 0x00, 0x00, 0x00, 0x00, }; if (size > 5) { return -ERANGE; } data[0] = BYTE_MASK(L[0]); data[1] = BYTE_MASK(L[0] >> 8); data[2] = BYTE_MASK(L[0] >> 16); data[3] = BYTE_MASK(L[0] >> 24); data[4] = BYTE_MASK(L[0] >> 32); if (OW_w_mem(data, size, offset, pn)) { return gbBAD; } return gbGOOD; }
/* Extra 8 bytes, (for counter) too -- discarded */ GOOD_OR_BAD COMMON_read_memory_toss_counter(struct one_wire_query *owq, size_t page, size_t pagesize) { off_t offset = OWQ_offset(owq) + page * pagesize; BYTE p[3 + pagesize + 8 + 2]; int rest = pagesize - (offset % pagesize); struct transaction_log t[] = { TRXN_START, TRXN_WR_CRC16(p, 3, rest + 8), TRXN_END, }; p[0] = _1W_READ_A5; p[1] = BYTE_MASK(offset); p[2] = BYTE_MASK(offset >> 8); RETURN_BAD_IF_BAD(BUS_transaction(t, PN(owq))) ; memcpy(OWQ_buffer(owq), &p[3], OWQ_size(owq)); Set_OWQ_length(owq); return gbGOOD; }
/* read up to end of page to CRC16 -- 0xA5 code */ static GOOD_OR_BAD OW_r_crc16(BYTE code, struct one_wire_query *owq, size_t page, size_t pagesize) { off_t offset = OWQ_offset(owq) + page * pagesize; size_t size = OWQ_size(owq); BYTE p[3 + pagesize + 2]; int rest = pagesize - (offset % pagesize); struct transaction_log t[] = { TRXN_START, TRXN_WR_CRC16(p, 3, rest), TRXN_END, }; p[0] = code; p[1] = BYTE_MASK(offset); p[2] = BYTE_MASK(offset >> 8); RETURN_BAD_IF_BAD(BUS_transaction(t, PN(owq))) ; memcpy(OWQ_buffer(owq), &p[3], size); Set_OWQ_length(owq); return gbGOOD; }
/** * Get value of RAX from guest register set. * @param guest_regs Guest register set. * @param size Access size (1, 2 or 4 bytes). * * @return Register value. * * @private */ static u32 get_rax_reg(struct registers *guest_regs, u8 size) { return guest_regs->rax & BYTE_MASK(size); }
// Writes bytes to memory in groups of 4 to non-consecutive byte // addresses. Tests the capability of the memory to correctly perform // byte writes. // // Returns FALSE and fills the MemError struct if the operation // fails. Returns TRUE if successful. BOOL TestByteWrite(uint32 *addr, int size, MemError *pError) { volatile uint8 *ptr; uint8 *startPtr, *endPtr; const register uint8 valAA = 0xAA; const register uint8 val55 = 0x55; const register uint8 val00 = 0x00; const register uint8 valFF = 0xFF; register uint8 val0, val1, val2, val3; uint8 value; ptr = (uint8 *)addr; startPtr = (uint8 *)addr; endPtr = ((uint8 *)addr) + size; // TEST BYTE WRITE ENABLE OPERATION // if(!ZeroAndVerify((uint32 *)ptr, pError)) return FALSE; // Test byte write of 0th byte ptr[0] = valFF; value = ptr[0] & BYTE_MASK(0); if(value != (valFF & BYTE_MASK(0))) { FillError(pError, (uint32)ptr, value, valFF & BYTE_MASK(0), 1); return FALSE; } if(!ZeroAndVerify((uint32 *)ptr, pError)) return FALSE; // Test byte write of 3rd byte ptr[3] = valFF; value = ptr[3] & BYTE_MASK(3); if(value != (valFF & BYTE_MASK(3))) { FillError(pError, (uint32)ptr+3, value, valFF & BYTE_MASK(3), 1); return FALSE; } if(!ZeroAndVerify((uint32 *)ptr, pError)) return FALSE; // Test byte write of 1st byte ptr[1] = valFF; value = ptr[1] & BYTE_MASK(1); if(value != (valFF & BYTE_MASK(1))) { FillError(pError, (uint32)ptr+1, value, valFF & BYTE_MASK(1), 1); return FALSE; } if(!ZeroAndVerify((uint32 *)ptr, pError)) return FALSE; // Test byte write of 2rd byte ptr[2] = valFF; value = ptr[2] & BYTE_MASK(2); if(value != (valFF & BYTE_MASK(2))) { FillError(pError, (uint32)ptr+2, value, valFF & BYTE_MASK(2), 1); return FALSE; } if(!ZeroAndVerify((uint32 *)ptr, pError)) return FALSE; // TEST BYTE WRITES OVER WHOLE MEMORY // // Write bytes to memory for(ptr = startPtr; ptr < endPtr; ptr += 4) { ptr[0] = val55; ptr[3] = valAA; ptr[1] = val00; ptr[2] = valFF; } // Verify correct values were written by doing byte reads for(ptr = startPtr; ptr < endPtr; ptr += 4) { val0 = ptr[0] & BYTE_MASK(0); val1 = ptr[1] & BYTE_MASK(1); val2 = ptr[2] & BYTE_MASK(2); val3 = ptr[3] & BYTE_MASK(3); if(val0 != (val55 & BYTE_MASK(0))) { FillError(pError, (uint32)ptr, val0, val55 & BYTE_MASK(0), 1); return FALSE; } if(val1 != (val00 & BYTE_MASK(1))) { FillError(pError, (uint32)ptr+1, val1, val00 & BYTE_MASK(1), 1); return FALSE; } if(val2 != (valFF & BYTE_MASK(2))) { FillError(pError, (uint32)ptr+2, val2, valFF & BYTE_MASK(2), 1); return FALSE; } if(val3 != (valAA & BYTE_MASK(3))) { FillError(pError, (uint32)ptr+3, val3, valAA & BYTE_MASK(3), 1); return FALSE; } } // Write opposite bytes to memory for(ptr = startPtr; ptr < endPtr; ptr += 4) { ptr[0] = valAA; ptr[3] = val55; ptr[1] = valFF; ptr[2] = val00; } // Verify correct values were written by doing byte reads for(ptr = startPtr; ptr < endPtr; ptr += 4) { val0 = ptr[0] & BYTE_MASK(0); val1 = ptr[1] & BYTE_MASK(1); val2 = ptr[2] & BYTE_MASK(2); val3 = ptr[3] & BYTE_MASK(3); if(val0 != (valAA & BYTE_MASK(0))) { FillError(pError, (uint32)ptr, val0, valAA & BYTE_MASK(0), 1); return FALSE; } if(val1 != (valFF & BYTE_MASK(1))) { FillError(pError, (uint32)ptr+1, val1, valFF & BYTE_MASK(1), 1); return FALSE; } if(val2 != (val00 & BYTE_MASK(2))) { FillError(pError, (uint32)ptr+2, val2, val00 & BYTE_MASK(2), 1); return FALSE; } if(val3 != (val55 & BYTE_MASK(3))) { FillError(pError, (uint32)ptr+3, val3, val55 & BYTE_MASK(3), 1); return FALSE; } } return TRUE; }
// Tests writting the the following addresses in succession: 0xA..A, // 0x5..5, 0xF..F, 0x0..0 (where the address width is appropriate for // memory size). This checks that even with rapid change in address // bits still delivers correct address to memory. // // Note: addr is forced to a word boundary. // // Returns FALSE if fails and fills out the MemError struct. Returns // TRUE if successful. BOOL TestAddressPounding32(uint32 *addr, int size, MemError *pError) { volatile uint8 *ptra; volatile uint8 *ptrb; volatile uint8 *ptrc; volatile uint8 *ptrd; int8 aMask, bMask, cMask, dMask; uint32 addrMask; uint8 value; int addrSize; const register uint32 vala = 0xA5; const register uint32 valb = 0x5A; // Determine number of address bits addrSize = 0; for(addrMask = 1; addrMask <= size; addrMask = (addrMask << 1) | 1) { addrSize++; } addrMask >>= 1; // Initialize pointers to use addr = (uint32 *)((uint32)addr & (~3)); // Force to word boundary ptra = (uint8 *)addr; ptrb = (uint8 *)((uint32)addr + (0x55555555 & addrMask)); ptrc = (uint8 *)((uint32)addr + (0xAAAAAAAA & addrMask)); ptrd = (uint8 *)((uint32)addr + (0xFFFFFFFF & addrMask)); aMask = BYTE_MASK(0); bMask = BYTE_MASK(0x55555555); cMask = BYTE_MASK(0xAAAAAAAA); dMask = BYTE_MASK(0xFFFFFFFF); // Write values *ptra = vala; *ptrb = vala; *ptrc = vala; *ptrd = vala; // Verify value = (*ptra & aMask); if(value != (vala & aMask)) { FillError(pError, (uint32)ptra, value, vala & aMask, 1); return FALSE; } value = (*ptrb & bMask); if(value != (vala & bMask)) { FillError(pError, (uint32)ptrb, value, vala & bMask, 1); return FALSE; } value = (*ptrc & cMask); if(value != (vala & cMask)) { FillError(pError, (uint32)ptrc, value, vala & cMask, 1); return FALSE; } value = (*ptrd & dMask); if(value != (vala & dMask)) { FillError(pError, (uint32)ptrd, value, vala & dMask, 1); return FALSE; } // Write values *ptra = valb; *ptrb = valb; *ptrc = valb; *ptrd = valb; value = (*ptra & aMask); if(value != (valb & aMask)) { FillError(pError, (uint32)ptra, value, valb & aMask, 1); return FALSE; } value = (*ptrb & bMask); if(value != (valb & bMask)) { FillError(pError, (uint32)ptrb, value, valb & bMask, 1); return FALSE; } value = (*ptrc & cMask); if(value != (valb & cMask)) { FillError(pError, (uint32)ptrc, value, valb & cMask, 1); return FALSE; } value = (*ptrd & dMask); if(value != (valb & dMask)) { FillError(pError, (uint32)ptrd, value, valb & dMask, 1); return FALSE; } return TRUE; }
static ZERO_OR_ERROR FS_w_data(struct one_wire_query *owq) { return GB_to_Z_OR_E(OW_w_data((BYTE) (BYTE_MASK(OWQ_U(owq))), PN(owq))) ; }