aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync/* $Id$ */
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync/** @file
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync * DevEEPROM - Microware-compatible 64x16-bit 93C46 EEPROM Emulation.
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync */
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync/*
c7814cf6e1240a519cbec0441e033d0e2470ed00vboxsync * Copyright (C) 2007-2010 Oracle Corporation
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync *
dbcf44d4b4f08f03eae2903053ed8c5264b0c23fvboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
dbcf44d4b4f08f03eae2903053ed8c5264b0c23fvboxsync * available from http://www.virtualbox.org. This file is free software;
dbcf44d4b4f08f03eae2903053ed8c5264b0c23fvboxsync * you can redistribute it and/or modify it under the terms of the GNU
dbcf44d4b4f08f03eae2903053ed8c5264b0c23fvboxsync * General Public License (GPL) as published by the Free Software
dbcf44d4b4f08f03eae2903053ed8c5264b0c23fvboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
dbcf44d4b4f08f03eae2903053ed8c5264b0c23fvboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
dbcf44d4b4f08f03eae2903053ed8c5264b0c23fvboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync */
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync#define LOG_GROUP LOG_GROUP_DEV_E1000 /// @todo Add a EEPROM logging group.
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync#include <VBox/log.h>
43747b1f0bc8302a238fb35e55857a5e9aa1933dvboxsync#include <VBox/vmm/pdmdev.h>
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync#include <iprt/string.h>
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync#include "DevEEPROM.h"
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync#define E1kLog(a) Log(a)
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync/**
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync * Initialize EEPROM device.
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync *
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync * @param pu16Initial Initial EEPROM content (optional). The size of initial
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync * content must be sizeof(uint16_t)*EEPROM93C46::SIZE
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync * bytes.
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync */
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsyncvoid EEPROM93C46::init(const uint16_t *pu16Initial)
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync{
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync if ( pu16Initial ) {
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync memcpy(this->m_au16Data, pu16Initial, sizeof(this->m_au16Data));
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync } else {
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync memset(this->m_au16Data, 0, sizeof(this->m_au16Data));
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync }
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync m_fWriteEnabled = false;
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync m_u32InternalWires = 0;
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync m_eState = STANDBY;
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync}
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync/**
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync * Writes one word to specified location if write is enabled.
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync *
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync * @param u32Addr Address to write at
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync * @param u16Value Value to store
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync */
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsyncvoid EEPROM93C46::storeWord(uint32_t u32Addr, uint16_t u16Value)
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync{
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync if (m_fWriteEnabled) {
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync E1kLog(("EEPROM: Stored word %04x at %08x\n", u16Value, u32Addr));
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync m_au16Data[u32Addr] = u16Value;
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync }
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync m_u16Mask = DATA_MSB;
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync}
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync
f0679a3d26514d6f85279a4018282ead9ff0f067vboxsync/**
f0679a3d26514d6f85279a4018282ead9ff0f067vboxsync * Reads one word at specified location.
f0679a3d26514d6f85279a4018282ead9ff0f067vboxsync *
f0679a3d26514d6f85279a4018282ead9ff0f067vboxsync * @returns True if read was successful.
f0679a3d26514d6f85279a4018282ead9ff0f067vboxsync *
f0679a3d26514d6f85279a4018282ead9ff0f067vboxsync * @param u32Addr Address to read from
f0679a3d26514d6f85279a4018282ead9ff0f067vboxsync * @param pu16Value Placeholder to store the value
f0679a3d26514d6f85279a4018282ead9ff0f067vboxsync */
f0679a3d26514d6f85279a4018282ead9ff0f067vboxsyncbool EEPROM93C46::readWord(uint32_t u32Addr, uint16_t *pu16Value)
f0679a3d26514d6f85279a4018282ead9ff0f067vboxsync{
f0679a3d26514d6f85279a4018282ead9ff0f067vboxsync if (u32Addr < SIZE)
f0679a3d26514d6f85279a4018282ead9ff0f067vboxsync {
f0679a3d26514d6f85279a4018282ead9ff0f067vboxsync *pu16Value = m_au16Data[u32Addr];
f0679a3d26514d6f85279a4018282ead9ff0f067vboxsync return true;
f0679a3d26514d6f85279a4018282ead9ff0f067vboxsync }
f0679a3d26514d6f85279a4018282ead9ff0f067vboxsync
f0679a3d26514d6f85279a4018282ead9ff0f067vboxsync return false;
f0679a3d26514d6f85279a4018282ead9ff0f067vboxsync}
f0679a3d26514d6f85279a4018282ead9ff0f067vboxsync
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync/**
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync * Fetch next word pointer by m_u16Addr.
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync *
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync * m_u16Addr is advanced and mask is reset to support sequential reads.
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync *
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync * @returns New state
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync */
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsyncEEPROM93C46::State EEPROM93C46::opRead()
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync{
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync m_u16Word = m_au16Data[m_u16Addr++];
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync E1kLog(("EEPROM: Reading word %04x at %08x\n", m_u16Word, m_u16Addr-1));
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync m_u16Mask = DATA_MSB;
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync return WRITING_DO;
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync}
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync/**
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync * Write the value of m_u16Word to the location specified by m_u16Addr.
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync *
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync * @returns New state
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync *
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync * @remarks Need to wait for CS lower/raise to show busy/ready indication.
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync */
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsyncEEPROM93C46::State EEPROM93C46::opWrite()
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync{
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync storeWord(m_u16Addr, m_u16Word);
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync return WAITING_CS_FALL;
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync}
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync/**
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync * Overwrite the entire contents of EEPROM with the value of m_u16Word.
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync *
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync * @returns New state
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync *
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync * @remarks Need to wait for CS lower/raise to show busy/ready indication.
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync */
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsyncEEPROM93C46::State EEPROM93C46::opWriteAll()
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync{
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync for (int i = 0; i < SIZE; i++)
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync storeWord(i, m_u16Word);
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync return WAITING_CS_FALL;
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync}
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync/**
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync * Decode opcode and address from 'opAddr' member.
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync *
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync * Decodes operation and executes it immediately if possible; otherwise, stores
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync * the decoded operation and address.
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync *
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync * @returns New state
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync */
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsyncEEPROM93C46::State EEPROM93C46::opDecode()
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync{
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync switch (m_u16Word>>6) {
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync case 3: /* ERASE */
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync storeWord(m_u16Word & ADDR_MASK, 0xFFFF);
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync return WAITING_CS_FALL;
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync case 2: /* READ */
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync m_eOp = OP_READ;
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync m_u16Addr = m_u16Word & ADDR_MASK;
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync return opRead(); /* Load first word */
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync case 1: /* WRITE */
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync m_eOp = OP_WRITE;
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync m_u16Addr = m_u16Word & ADDR_MASK;
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync m_u16Word = 0;
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync m_u16Mask = DATA_MSB;
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync return READING_DI;
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync case 0:
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync switch (m_u16Word>>4) {
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync case 0: /* ERASE/WRITE DISABLE */
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync m_fWriteEnabled = false;
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync return STANDBY;
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync case 1: /* WRITE ALL */
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync m_eOp = OP_WRITE_ALL;
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync m_u16Word = 0;
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync m_u16Mask = DATA_MSB;
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync return READING_DI;
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync case 2: /* ERASE ALL */
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync /* Re-use opWriteAll */
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync m_u16Word = 0xFFFF;
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync return opWriteAll();
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync case 3: /* ERASE/WRITE ENABLE */
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync m_fWriteEnabled = true;
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync return STANDBY;
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync }
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync }
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync return m_eState;
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync}
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync/**
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync * Set bits in EEPROM 4-wire interface.
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync *
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync * @param u32Wires Values of DI, CS, SK.
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync * @remarks The value of DO bit in 'u32Wires' is ignored.
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync */
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsyncvoid EEPROM93C46::write(uint32_t u32Wires)
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync{
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync if (u32Wires & WIRES_CS) {
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync if (!(m_u32InternalWires & WIRES_SK) && (u32Wires & WIRES_SK)) {
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync /* Positive edge of clock */
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync if (m_eState == STANDBY) {
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync if (u32Wires & WIRES_DI) {
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync m_eState = READING_DI;
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync m_eOp = OP_DECODE;
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync m_u16Mask = OPADDR_MSB;
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync m_u16Word = 0;
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync }
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync }
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync else {
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync if (m_eState == READING_DI) {
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync if (u32Wires & WIRES_DI) {
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync m_u16Word |= m_u16Mask;
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync }
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync }
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync else if (m_eState == WRITING_DO) {
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync m_u32InternalWires &= ~WIRES_DO;
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync if (m_u16Word & m_u16Mask) {
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync m_u32InternalWires |= WIRES_DO;
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync }
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync }
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync else return;
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync /* Next bit */
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync m_u16Mask >>= 1;
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync if (m_u16Mask == 0)
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync {
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync switch (this->m_eOp)
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync {
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync case OP_READ:
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync m_eState = opRead();
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync break;
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync case OP_WRITE:
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync m_eState = opWrite();
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync break;
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync case OP_WRITE_ALL:
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync m_eState = opWriteAll();
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync break;
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync case OP_DECODE:
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync m_eState = opDecode();
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync break;
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync default:
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync ;
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync }
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync }
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync }
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync }
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync else if (m_eState == WAITING_CS_RISE) {
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync m_u32InternalWires |= WIRES_DO; /* ready */
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync m_eState = STANDBY;
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync }
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync }
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync else {
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync switch(m_eState) {
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync case WAITING_CS_FALL:
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync m_eState = WAITING_CS_RISE;
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync m_u32InternalWires &= ~WIRES_DO; /* busy */
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync break;
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync case WAITING_CS_RISE:
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync break;
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync case READING_DI:
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync m_u32InternalWires &= ~WIRES_DO; /* Clear ready/busy status from DO. */
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync /* Fall through! */
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync default:
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync m_eState = STANDBY;
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync break;
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync }
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync }
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync m_u32InternalWires &= WIRES_DO;
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync m_u32InternalWires |= u32Wires & ~WIRES_DO; /* Do not overwrite DO */
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync}
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync/**
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync * Read bits in EEPROM 4-wire interface.
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync *
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync * @returns Current values of DO, DI, CS, SK.
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync *
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync * @remarks Only DO is controlled by EEPROM, other bits are returned as they
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync * were written by 'write'.
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync */
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsyncuint32_t EEPROM93C46::read()
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync{
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync return m_u32InternalWires;
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync}
aaf6eb788dab09bc8c3c8576c60fabc60037a483vboxsync
da7f6376d98136ac8a76f7110a452c6e56508c49vboxsyncvoid EEPROM93C46::save(PSSMHANDLE pSSM)
da7f6376d98136ac8a76f7110a452c6e56508c49vboxsync{
da7f6376d98136ac8a76f7110a452c6e56508c49vboxsync SSMR3PutU8( pSSM, EEPROM93C46_SAVEDSTATE_VERSION);
da7f6376d98136ac8a76f7110a452c6e56508c49vboxsync SSMR3PutU8( pSSM, m_eState);
da7f6376d98136ac8a76f7110a452c6e56508c49vboxsync SSMR3PutU8( pSSM, m_eOp);
da7f6376d98136ac8a76f7110a452c6e56508c49vboxsync SSMR3PutBool(pSSM, m_fWriteEnabled);
da7f6376d98136ac8a76f7110a452c6e56508c49vboxsync SSMR3PutU32( pSSM, m_u32InternalWires);
da7f6376d98136ac8a76f7110a452c6e56508c49vboxsync SSMR3PutU16( pSSM, m_u16Word);
da7f6376d98136ac8a76f7110a452c6e56508c49vboxsync SSMR3PutU16( pSSM, m_u16Mask);
da7f6376d98136ac8a76f7110a452c6e56508c49vboxsync SSMR3PutU16( pSSM, m_u16Addr);
da7f6376d98136ac8a76f7110a452c6e56508c49vboxsync SSMR3PutMem( pSSM, m_au16Data, sizeof(m_au16Data));
da7f6376d98136ac8a76f7110a452c6e56508c49vboxsync}
da7f6376d98136ac8a76f7110a452c6e56508c49vboxsync
da7f6376d98136ac8a76f7110a452c6e56508c49vboxsyncint EEPROM93C46::load(PSSMHANDLE pSSM)
da7f6376d98136ac8a76f7110a452c6e56508c49vboxsync{
e178e7e90c2d2d42c37cd65eec49f37292d2f0bbvboxsync int rc;
e178e7e90c2d2d42c37cd65eec49f37292d2f0bbvboxsync uint8_t uVersion;
da7f6376d98136ac8a76f7110a452c6e56508c49vboxsync
da7f6376d98136ac8a76f7110a452c6e56508c49vboxsync rc = SSMR3GetU8(pSSM, &uVersion);
da7f6376d98136ac8a76f7110a452c6e56508c49vboxsync AssertRCReturn(rc, rc);
da7f6376d98136ac8a76f7110a452c6e56508c49vboxsync if (uVersion != EEPROM93C46_SAVEDSTATE_VERSION)
da7f6376d98136ac8a76f7110a452c6e56508c49vboxsync return VERR_SSM_UNSUPPORTED_DATA_UNIT_VERSION;
da7f6376d98136ac8a76f7110a452c6e56508c49vboxsync
e178e7e90c2d2d42c37cd65eec49f37292d2f0bbvboxsync SSMR3GetU8( pSSM, (uint8_t*)&m_eState);
e178e7e90c2d2d42c37cd65eec49f37292d2f0bbvboxsync SSMR3GetU8( pSSM, (uint8_t*)&m_eOp);
e178e7e90c2d2d42c37cd65eec49f37292d2f0bbvboxsync SSMR3GetBool(pSSM, &m_fWriteEnabled);
e178e7e90c2d2d42c37cd65eec49f37292d2f0bbvboxsync SSMR3GetU32( pSSM, &m_u32InternalWires);
e178e7e90c2d2d42c37cd65eec49f37292d2f0bbvboxsync SSMR3GetU16( pSSM, &m_u16Word);
e178e7e90c2d2d42c37cd65eec49f37292d2f0bbvboxsync SSMR3GetU16( pSSM, &m_u16Mask);
e178e7e90c2d2d42c37cd65eec49f37292d2f0bbvboxsync SSMR3GetU16( pSSM, &m_u16Addr);
e178e7e90c2d2d42c37cd65eec49f37292d2f0bbvboxsync return SSMR3GetMem( pSSM, m_au16Data, sizeof(m_au16Data));
da7f6376d98136ac8a76f7110a452c6e56508c49vboxsync}