2 * QEMU EEPROM 24c0x emulation
4 * Copyright (c) 2009 Michel Pollet <buserror@gmail.com>
5 * Copyright (c) 2006 Aurelien Jarno
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
24 #include "eeprom24c0x.h"
27 * EEPROM 24C01 / 24C02 emulation.
29 * Emulation for serial EEPROMs:
30 * 24C01 - 1024 bit (128 x 8)
31 * 24C02 - 2048 bit (256 x 8)
32 * 24C04 - 4096 bit (512 x 8)
33 * 24C08 - 8192 bit (1024 x 8)
35 * Typical device names include Microchip 24C02SC or SGS Thomson ST24C02.
41 # define logout(fmt, args...) fprintf(stderr, "24C\t%-24s" fmt, __func__, ##args)
43 # define logout(fmt, args...) ((void)0)
46 struct _eeprom24c0x_t
{
56 uint8_t contents
[1024];
59 //typedef struct _eeprom24c0x_t eeprom24c0x_t;
62 eeprom24c0x_t
* eeprom24c0x_new(int eeprom_kind
)
64 eeprom24c0x_t
*eeprom
= (eeprom24c0x_t
*)qemu_mallocz(sizeof(eeprom24c0x_t
));
66 eeprom
->kind
= eeprom_kind
;
67 memset(eeprom
->contents
, 0xff, sizeof(eeprom
->contents
));
71 void eeprom24c0x_free(eeprom24c0x_t
*eeprom
)
73 logout("eeprom = 0x%p\n", eeprom
);
77 uint8_t *eeprom24c0x_data(eeprom24c0x_t
*eeprom
)
79 return eeprom
->contents
;
82 uint8_t eeprom24c0x_read(eeprom24c0x_t
* eeprom
)
84 logout("%u: scl = %u, sda = %u, data = 0x%02x\n",
85 eeprom
->tick
, eeprom
->scl
, eeprom
->sda
, eeprom
->data
);
89 void eeprom24c0x_write(eeprom24c0x_t
* eeprom
, int scl
, int sda
)
91 if (eeprom
->scl
&& scl
&& (eeprom
->sda
!= sda
)) {
92 logout("%u: scl = %u->%u, sda = %u->%u i2c %s\n",
93 eeprom
->tick
, eeprom
->scl
, scl
, eeprom
->sda
, sda
, sda
? "stop" : "start");
98 } else if (eeprom
->tick
== 0 && !eeprom
->ack
) {
99 /* Waiting for start. */
100 logout("%u: scl = %u->%u, sda = %u->%u wait for i2c start\n",
101 eeprom
->tick
, eeprom
->scl
, scl
, eeprom
->sda
, sda
);
102 } else if (!eeprom
->scl
&& scl
) {
103 logout("%u: scl = %u->%u, sda = %u->%u trigger bit\n",
104 eeprom
->tick
, eeprom
->scl
, scl
, eeprom
->sda
, sda
);
106 logout("\ti2c ack bit = 0\n");
109 } else if (eeprom
->sda
== sda
) {
110 uint8_t bit
= (sda
!= 0);
111 logout("\ti2c bit = %d\n", bit
);
112 if (eeprom
->tick
< 9) {
113 eeprom
->command
<<= 1;
114 eeprom
->command
+= bit
;
116 if (eeprom
->tick
== 9) {
117 logout("\tcommand 0x%04x, %s\n", eeprom
->command
, bit
? "read" : "write");
120 } else if (eeprom
->tick
< 17) {
121 if (eeprom
->command
& 1) {
122 sda
= ((eeprom
->data
& 0x80) != 0);
124 eeprom
->address
<<= 1;
125 eeprom
->address
+= bit
;
128 if (eeprom
->tick
== 17) {
129 eeprom
->data
= eeprom
->contents
[eeprom
->address
];
130 logout("\taddress 0x%04x, data 0x%02x\n", eeprom
->address
, eeprom
->data
);
134 } else if (eeprom
->tick
>= 17) {
138 logout("\tsda changed with raising scl\n");
141 logout("%u: scl = %u->%u, sda = %u->%u\n", eeprom
->tick
, eeprom
->scl
, scl
, eeprom
->sda
, sda
);