VirtualBox

source: vbox/trunk/src/VBox/Devices/Network/DevEEPROM.cpp@ 28587

Last change on this file since 28587 was 25876, checked in by vboxsync, 15 years ago

e1000: Revised EERD patch applied (http://www.virtualbox.org/ticket/6008)

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 8.4 KB
Line 
1/* $Id: DevEEPROM.cpp 25876 2010-01-18 10:54:05Z vboxsync $ */
2/** @file
3 * DevEEPROM - Microware-compatible 64x16-bit 93C46 EEPROM Emulation.
4 */
5
6/*
7 * Copyright (C) 2007 Sun Microsystems, Inc.
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
18 * Clara, CA 95054 USA or visit http://www.sun.com if you need
19 * additional information or have any questions.
20 */
21
22#define LOG_GROUP LOG_GROUP_DEV_E1000 /// @todo Add a EEPROM logging group.
23#include <VBox/log.h>
24#include <VBox/pdmdev.h>
25#include <iprt/string.h>
26#include "DevEEPROM.h"
27
28#define E1kLog(a) Log(a)
29
30/**
31 * Initialize EEPROM device.
32 *
33 * @param pu16Initial Initial EEPROM content (optional). The size of initial
34 * content must be sizeof(uint16_t)*EEPROM93C46::SIZE
35 * bytes.
36 */
37void EEPROM93C46::init(const uint16_t *pu16Initial)
38{
39 if ( pu16Initial ) {
40 memcpy(this->m_au16Data, pu16Initial, sizeof(this->m_au16Data));
41 } else {
42 memset(this->m_au16Data, 0, sizeof(this->m_au16Data));
43 }
44 m_fWriteEnabled = false;
45 m_u32InternalWires = 0;
46 m_eState = STANDBY;
47}
48
49/**
50 * Writes one word to specified location if write is enabled.
51 *
52 * @param u32Addr Address to write at
53 * @param u16Value Value to store
54 */
55void EEPROM93C46::storeWord(uint32_t u32Addr, uint16_t u16Value)
56{
57 if (m_fWriteEnabled) {
58 E1kLog(("EEPROM: Stored word %04x at %08x\n", u16Value, u32Addr));
59 m_au16Data[u32Addr] = u16Value;
60 }
61 m_u16Mask = DATA_MSB;
62}
63
64/**
65 * Reads one word at specified location.
66 *
67 * @returns True if read was successful.
68 *
69 * @param u32Addr Address to read from
70 * @param pu16Value Placeholder to store the value
71 */
72bool EEPROM93C46::readWord(uint32_t u32Addr, uint16_t *pu16Value)
73{
74 if (u32Addr < SIZE)
75 {
76 *pu16Value = m_au16Data[u32Addr];
77 return true;
78 }
79
80 return false;
81}
82
83/**
84 * Fetch next word pointer by m_u16Addr.
85 *
86 * m_u16Addr is advanced and mask is reset to support sequential reads.
87 *
88 * @returns New state
89 */
90EEPROM93C46::State EEPROM93C46::opRead()
91{
92 m_u16Word = m_au16Data[m_u16Addr++];
93 E1kLog(("EEPROM: Reading word %04x at %08x\n", m_u16Word, m_u16Addr-1));
94 m_u16Mask = DATA_MSB;
95 return WRITING_DO;
96}
97
98/**
99 * Write the value of m_u16Word to the location specified by m_u16Addr.
100 *
101 * @returns New state
102 *
103 * @remarks Need to wait for CS lower/raise to show busy/ready indication.
104 */
105EEPROM93C46::State EEPROM93C46::opWrite()
106{
107 storeWord(m_u16Addr, m_u16Word);
108 return WAITING_CS_FALL;
109}
110
111/**
112 * Overwrite the entire contents of EEPROM with the value of m_u16Word.
113 *
114 * @returns New state
115 *
116 * @remarks Need to wait for CS lower/raise to show busy/ready indication.
117 */
118EEPROM93C46::State EEPROM93C46::opWriteAll()
119{
120 for (int i = 0; i < SIZE; i++)
121 storeWord(i, m_u16Word);
122 return WAITING_CS_FALL;
123}
124
125/**
126 * Decode opcode and address from 'opAddr' member.
127 *
128 * Decodes operation and executes it immediately if possible; otherwise, stores
129 * the decoded operation and address.
130 *
131 * @returns New state
132 */
133EEPROM93C46::State EEPROM93C46::opDecode()
134{
135 switch (m_u16Word>>6) {
136 case 3: /* ERASE */
137 storeWord(m_u16Word & ADDR_MASK, 0xFFFF);
138 return WAITING_CS_FALL;
139 case 2: /* READ */
140 m_eOp = OP_READ;
141 m_u16Addr = m_u16Word & ADDR_MASK;
142 return opRead(); /* Load first word */
143 case 1: /* WRITE */
144 m_eOp = OP_WRITE;
145 m_u16Addr = m_u16Word & ADDR_MASK;
146 m_u16Word = 0;
147 m_u16Mask = DATA_MSB;
148 return READING_DI;
149 case 0:
150 switch (m_u16Word>>4) {
151 case 0: /* ERASE/WRITE DISABLE */
152 m_fWriteEnabled = false;
153 return STANDBY;
154 case 1: /* WRITE ALL */
155 m_eOp = OP_WRITE_ALL;
156 m_u16Word = 0;
157 m_u16Mask = DATA_MSB;
158 return READING_DI;
159 case 2: /* ERASE ALL */
160 /* Re-use opWriteAll */
161 m_u16Word = 0xFFFF;
162 return opWriteAll();
163 case 3: /* ERASE/WRITE ENABLE */
164 m_fWriteEnabled = true;
165 return STANDBY;
166 }
167 }
168 return m_eState;
169}
170
171/**
172 * Set bits in EEPROM 4-wire interface.
173 *
174 * @param u32Wires Values of DI, CS, SK.
175 * @remarks The value of DO bit in 'u32Wires' is ignored.
176 */
177void EEPROM93C46::write(uint32_t u32Wires)
178{
179 if (u32Wires & WIRES_CS) {
180 if (!(m_u32InternalWires & WIRES_SK) && (u32Wires & WIRES_SK)) {
181 /* Positive edge of clock */
182 if (m_eState == STANDBY) {
183 if (u32Wires & WIRES_DI) {
184 m_eState = READING_DI;
185 m_eOp = OP_DECODE;
186 m_u16Mask = OPADDR_MSB;
187 m_u16Word = 0;
188 }
189 }
190 else {
191 if (m_eState == READING_DI) {
192 if (u32Wires & WIRES_DI) {
193 m_u16Word |= m_u16Mask;
194 }
195 }
196 else if (m_eState == WRITING_DO) {
197 m_u32InternalWires &= ~WIRES_DO;
198 if (m_u16Word & m_u16Mask) {
199 m_u32InternalWires |= WIRES_DO;
200 }
201 }
202 else return;
203 /* Next bit */
204 m_u16Mask >>= 1;
205 if (m_u16Mask == 0)
206 {
207 switch (this->m_eOp)
208 {
209 case OP_READ:
210 m_eState = opRead();
211 break;
212 case OP_WRITE:
213 m_eState = opWrite();
214 break;
215 case OP_WRITE_ALL:
216 m_eState = opWriteAll();
217 break;
218 case OP_DECODE:
219 m_eState = opDecode();
220 break;
221 default:
222 ;
223 }
224 }
225 }
226 }
227 else if (m_eState == WAITING_CS_RISE) {
228 m_u32InternalWires |= WIRES_DO; /* ready */
229 m_eState = STANDBY;
230 }
231 }
232 else {
233 switch(m_eState) {
234 case WAITING_CS_FALL:
235 m_eState = WAITING_CS_RISE;
236 m_u32InternalWires &= ~WIRES_DO; /* busy */
237 break;
238 case WAITING_CS_RISE:
239 break;
240 case READING_DI:
241 m_u32InternalWires &= ~WIRES_DO; /* Clear ready/busy status from DO. */
242 /* Fall through! */
243 default:
244 m_eState = STANDBY;
245 break;
246 }
247 }
248 m_u32InternalWires &= WIRES_DO;
249 m_u32InternalWires |= u32Wires & ~WIRES_DO; /* Do not overwrite DO */
250}
251
252/**
253 * Read bits in EEPROM 4-wire interface.
254 *
255 * @returns Current values of DO, DI, CS, SK.
256 *
257 * @remarks Only DO is controlled by EEPROM, other bits are returned as they
258 * were written by 'write'.
259 */
260uint32_t EEPROM93C46::read()
261{
262 return m_u32InternalWires;
263}
264
265void EEPROM93C46::save(PSSMHANDLE pSSM)
266{
267 SSMR3PutU8( pSSM, EEPROM93C46_SAVEDSTATE_VERSION);
268 SSMR3PutU8( pSSM, m_eState);
269 SSMR3PutU8( pSSM, m_eOp);
270 SSMR3PutBool(pSSM, m_fWriteEnabled);
271 SSMR3PutU32( pSSM, m_u32InternalWires);
272 SSMR3PutU16( pSSM, m_u16Word);
273 SSMR3PutU16( pSSM, m_u16Mask);
274 SSMR3PutU16( pSSM, m_u16Addr);
275 SSMR3PutMem( pSSM, m_au16Data, sizeof(m_au16Data));
276}
277
278int EEPROM93C46::load(PSSMHANDLE pSSM)
279{
280 int rc;
281 uint8_t uVersion;
282
283 rc = SSMR3GetU8(pSSM, &uVersion);
284 AssertRCReturn(rc, rc);
285 if (uVersion != EEPROM93C46_SAVEDSTATE_VERSION)
286 return VERR_SSM_UNSUPPORTED_DATA_UNIT_VERSION;
287
288 SSMR3GetU8( pSSM, (uint8_t*)&m_eState);
289 SSMR3GetU8( pSSM, (uint8_t*)&m_eOp);
290 SSMR3GetBool(pSSM, &m_fWriteEnabled);
291 SSMR3GetU32( pSSM, &m_u32InternalWires);
292 SSMR3GetU16( pSSM, &m_u16Word);
293 SSMR3GetU16( pSSM, &m_u16Mask);
294 SSMR3GetU16( pSSM, &m_u16Addr);
295 return SSMR3GetMem( pSSM, m_au16Data, sizeof(m_au16Data));
296}
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette