32
32
#include "sysemu/block-backend.h"
33
33
#include "sysemu/cpu-timers.h"
34
34
#include "migration/vmstate.h"
35
+ #include "../otp.h"
36
+ #include "trace.h"
35
37
36
38
#define TYPE_AT21CSXX "at21csxx"
37
39
44
46
#define AT21_OP_SSM 0xD
45
47
#define AT21_OP_HSM 0xE
46
48
47
- #define ICOUNT_PER_US 168
49
+ // Empirically determined based on the bootloader code and its NOP()s... :-/
50
+ #define ICOUNT_PER_US_INITIAL 124
48
51
49
52
#define DEV_ADDR 0
50
53
#define DEV_SIZE 128
@@ -80,11 +83,15 @@ struct AT21CSxxState {
80
83
81
84
QEMUTimer * line_release ;
82
85
86
+ uint32_t refined_icount ;
87
+ bool icount_enabled ;
88
+
83
89
int64_t low_start , high_start ;
84
90
uint8_t bit_counter ;
85
91
uint8_t byte_in , byte_out ;
86
92
uint8_t sio_state ;
87
93
94
+
88
95
uint8_t byte_count ;
89
96
uint8_t address_pointer ;
90
97
@@ -122,6 +129,7 @@ static void at21csxx_line_release(void *opaque)
122
129
123
130
static bool at21csxx_process_byte (AT21CSxxState * s , uint8_t byte )
124
131
{
132
+ trace_at21csxx_byte_in (s -> byte_count , byte );
125
133
switch (s -> byte_count )
126
134
{
127
135
case 0 :
@@ -131,6 +139,7 @@ static bool at21csxx_process_byte(AT21CSxxState *s, uint8_t byte)
131
139
if (s -> cmd .def .read )
132
140
{
133
141
s -> sio_state = SIO_DOUT ;
142
+ trace_at21csxx_read_mode ();
134
143
}
135
144
switch (s -> cmd .def .opcode )
136
145
{
@@ -147,39 +156,49 @@ static bool at21csxx_process_byte(AT21CSxxState *s, uint8_t byte)
147
156
if (byte < DEV_SIZE )
148
157
{
149
158
s -> address_pointer = byte ;
159
+ trace_at21csxx_address_set (s -> address_pointer );
150
160
s -> byte_count ++ ;
151
161
return true;
152
162
}
153
163
return false;
154
164
default :
165
+ trace_at21csxx_data_write (s -> address_pointer , byte );
155
166
s -> data [s -> address_pointer ++ ] = byte ;
156
167
s -> address_pointer %= DEV_SIZE ;
157
168
return true;
158
169
}
159
170
}
160
171
161
172
static void at21csxx_sio (void * opaque , int n , int level ) {
173
+ trace_at21csxx_sio_level (level );
162
174
AT21CSxxState * s = AT21CSXX (opaque );
175
+ const uint32_t ICOUNT_PER_US = s -> icount_enabled ? s -> refined_icount : 1000 ;
163
176
if (!level )
164
177
{
165
- s -> low_start = icount_get_raw ();
178
+
179
+ s -> low_start = s -> icount_enabled ? icount_get_raw () : qemu_clock_get_ns (QEMU_CLOCK_VIRTUAL );
166
180
int64_t tHigh = s -> low_start - s -> high_start ;
181
+ trace_at21csxx_sio_high_icount (tHigh );
167
182
if (tHigh > 500 * ICOUNT_PER_US )
168
183
{
169
- // printf("AT21 Start cond\n" );
184
+ trace_at21csxx_start_condition ( );
170
185
s -> sio_state = SIO_IDLE ;
171
186
}
172
187
return ;
173
188
}
174
189
175
- s -> high_start = icount_get_raw ();
190
+ s -> high_start = s -> icount_enabled ? icount_get_raw () : qemu_clock_get_ns ( QEMU_CLOCK_VIRTUAL );
176
191
177
192
int64_t tLow = s -> high_start - s -> low_start ;
178
193
179
- if (tLow > 150 * ICOUNT_PER_US )
194
+ trace_at21csxx_sio_low_icount (tLow );
195
+
196
+ if (tLow >= 150 * ICOUNT_PER_US )
180
197
{
181
198
s -> bit_counter = 0 ;
182
199
s -> byte_in = 0 ;
200
+ trace_at21csxx_enter_discovery ();
201
+ qemu_set_irq (s -> irq , 1 );
183
202
s -> sio_state = SIO_DISC ;
184
203
return ;
185
204
}
@@ -193,7 +212,7 @@ static void at21csxx_sio(void* opaque, int n, int level) {
193
212
{
194
213
qemu_irq_lower (s -> irq );
195
214
timer_mod (s -> line_release , qemu_clock_get_ns (QEMU_CLOCK_VIRTUAL ) + NS_SCALE (6000 )); // 2-6 us from the datasheet
196
- // printf("Discovery ack\n" );
215
+ trace_at21csxx_discovery_ack ( );
197
216
s -> sio_state = SIO_IDLE ;
198
217
}
199
218
break ;
@@ -208,6 +227,7 @@ static void at21csxx_sio(void* opaque, int n, int level) {
208
227
case SIO_DIN :
209
228
if (logic_one || logic_zero )
210
229
{
230
+ trace_at21csxx_bit_logic_val (s -> bit_counter , logic_one , logic_zero );
211
231
if (s -> bit_counter < 8 )
212
232
{
213
233
s -> byte_in <<= 1 ;
@@ -218,12 +238,13 @@ static void at21csxx_sio(void* opaque, int n, int level) {
218
238
}
219
239
else
220
240
{
241
+ trace_at21csxx_bit_duration_error (s -> bit_counter , tLow );
221
242
// printf("w1 Bus unhandled low duration: %"PRId64" instructions\n", tLow);
222
243
}
223
244
if (s -> bit_counter == 8 )
224
245
{
225
246
bool send_ack = at21csxx_process_byte (s , s -> byte_in );
226
- // printf("Byte in: %02x - %s\n", s->byte_in, send_ack? "ACK" : "NACK");
247
+ //printf("Byte in: %02x - %s\n", s->byte_in, send_ack? "ACK" : "NACK");
227
248
s -> byte_in = 0 ;
228
249
qemu_set_irq (s -> irq , !send_ack );
229
250
timer_mod (s -> line_release , qemu_clock_get_ns (QEMU_CLOCK_VIRTUAL ) + NS_SCALE (2000 )); // 2-6 us from the datasheet
@@ -238,14 +259,15 @@ static void at21csxx_sio(void* opaque, int n, int level) {
238
259
{
239
260
case AT21_OP_EEA :
240
261
s -> byte_out = s -> data [s -> address_pointer ++ ];
241
- printf ( "AT21CSxx: Sending byte@ %02x: %02x\n" , s -> address_pointer - 1 , s -> byte_out );
262
+ trace_at21csxx_data_read ( s -> address_pointer - 1 , s -> byte_out );
242
263
break ;
243
264
default :
244
265
printf ("AT21 Unhandled read opcode %x\n" , s -> cmd .def .opcode );
245
266
break ;
246
267
}
247
268
/* fallthru */
248
269
case 1 ... 7 :
270
+ trace_at21csxx_sio_out (s -> bit_counter , s -> byte_out & 0x80 );
249
271
qemu_set_irq (s -> irq , (s -> byte_out & 0x80 ) > 0 );
250
272
s -> bit_counter ++ ;
251
273
s -> byte_out <<= 1 ;
@@ -285,6 +307,12 @@ static void at21csxx_realize(DeviceState *dev, Error **errp)
285
307
printf ("WARNING: icount is disabled. AT21CSxx EEPROM will NOT WORK!\n" );
286
308
printf ("WARNING: use -icount [number] to enable it.\n" );
287
309
}
310
+ else
311
+ {
312
+ s -> icount_enabled = true;
313
+ }
314
+ #else
315
+ s -> icount_enabled = icount_enabled ();
288
316
#endif
289
317
if (s -> blk ) {
290
318
@@ -313,12 +341,14 @@ static void at21csxx_realize(DeviceState *dev, Error **errp)
313
341
else
314
342
{
315
343
// Add some fake data just to avoid 400 re-read attempts during boot... :(
316
- s -> data [0 ] = 0x00 ;
317
- s -> data [1 ] = 0x20 ;
318
- s -> data [2 ] = 0x00 ;
319
- s -> data [3 ] = 0x01 ;
320
- s -> data [8 ] = '0' ;
321
- s -> data [9 ] = '0' ;
344
+ OTP_v2 * otp = (OTP_v2 * ) s -> data ;
345
+ otp -> version = 2 ;
346
+ otp -> size = sizeof (OTP_v2 );
347
+ otp -> bomID = 31 ; // Last variant that uses table 5... ;)
348
+ // Should keep the bootloader happy:
349
+ otp -> datamatrix [0 ] = '0' ;
350
+ otp -> datamatrix [1 ] = '0' ;
351
+
322
352
}
323
353
}
324
354
@@ -336,6 +366,7 @@ static void at21csxx_init(Object *obj)
336
366
337
367
static Property at21csxx_eeprom_props [] = {
338
368
DEFINE_PROP_DRIVE ("drive" , AT21CSxxState , blk ),
369
+ DEFINE_PROP_UINT32 ("icount-per-us" , AT21CSxxState , refined_icount , ICOUNT_PER_US_INITIAL ),
339
370
DEFINE_PROP_END_OF_LIST ()
340
371
};
341
372
0 commit comments