/[dynamips]/upstream/dynamips-0.2.7-RC2/nmc93cX6.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Contents of /upstream/dynamips-0.2.7-RC2/nmc93cX6.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 8 - (show annotations)
Sat Oct 6 16:24:54 2007 UTC (12 years, 1 month ago) by dpavlin
File MIME type: text/plain
File size: 5786 byte(s)
dynamips-0.2.7-RC2

1 /*
2 * Cisco router simulation platform.
3 * Copyright (c) 2005,2006 Christophe Fillot (cf@utc.fr)
4 *
5 * NMC93C46/NMC93C56 Serial EEPROM.
6 */
7
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <string.h>
11 #include <unistd.h>
12
13 #include "nmc93cX6.h"
14
15 #define DEBUG_EEPROM 0
16
17 /* Internal states */
18 enum {
19 EEPROM_STATE_INACTIVE = 0,
20 EEPROM_STATE_WAIT_CMD,
21 EEPROM_STATE_DATAOUT,
22 };
23
24 /* Get command length for the specified group */
25 static u_int nmc94cX6_get_cmd_len(struct nmc93cX6_group *g)
26 {
27 switch(g->eeprom_type) {
28 case EEPROM_TYPE_NMC93C46:
29 return(NMC93C46_CMD_BITLEN);
30 case EEPROM_TYPE_NMC93C56:
31 return(NMC93C56_CMD_BITLEN);
32 default:
33 return(0);
34 }
35 }
36
37 /* Extract EEPROM data address */
38 static u_int nmc94cX6_get_addr(struct nmc93cX6_group *g,u_int cmd)
39 {
40 switch(g->eeprom_type) {
41 case EEPROM_TYPE_NMC93C46:
42 return((cmd >> 3) & 0x3f);
43 case EEPROM_TYPE_NMC93C56:
44 return(m_reverse_u8((cmd >> 3) & 0xff));
45 default:
46 return(0);
47 }
48 }
49
50 /* Check chip select */
51 static void nmc93cX6_check_cs(struct nmc93cX6_group *g,u_int old,u_int new)
52 {
53 int i,res;
54
55 for(i=0;i<g->nr_eeprom;i++)
56 {
57 g->state[i].dataout_val = 1;
58
59 if (g->debug)
60 {
61 printf("EEPROM %s(%d): check_cs: check_bit(old,new,select_bit) "
62 "[%8.8x, %8.8x, %d (mask = %8.8x)] = %d\n",
63 g->description, i,
64 old, new, g->def[i]->select_bit, 1 << g->def[i]->select_bit,
65 check_bit(old,new,g->def[i]->select_bit));
66 }
67
68 if ((res = check_bit(old,new,g->def[i]->select_bit)) != 0) {
69 g->state[i].cmd_len = 0; /* no bit for command sent now */
70 g->state[i].cmd_val = 0;
71
72 if (res == 2)
73 g->state[i].state = EEPROM_STATE_WAIT_CMD;
74 else
75 g->state[i].state = EEPROM_STATE_INACTIVE;
76 }
77 }
78 }
79
80 /* Check clock set for a specific group */
81 static void nmc93cX6_check_clk_group(struct nmc93cX6_group *g,int group_id,
82 u_int old,u_int new)
83 {
84 struct cisco_eeprom *eeprom;
85 u_int cmd,op,addr,pos;
86 u_int clk_bit, din_bit;
87 u_int cmd_len;
88
89 clk_bit = g->def[group_id]->clock_bit;
90 din_bit = g->def[group_id]->din_bit;
91
92 if (g->debug)
93 {
94 printf("EEPROM %s(%d): check_clk: check_bit(old,new,select_bit) "
95 "[%8.8x, %8.8x, %d (mask = %8.8x)] = %d\n",
96 g->description, group_id,
97 old,new, clk_bit, 1 << clk_bit, check_bit(old,new,clk_bit));
98 }
99
100 /* CLK bit set ? */
101 if (check_bit(old,new,clk_bit) != 2)
102 return;
103
104 switch(g->state[group_id].state)
105 {
106 case EEPROM_STATE_WAIT_CMD:
107 /* Read DATAIN bit */
108 if (new & (1 << din_bit))
109 g->state[group_id].cmd_val |= (1 << g->state[group_id].cmd_len);
110
111 g->state[group_id].cmd_len++;
112
113 cmd_len = nmc94cX6_get_cmd_len(g);
114
115 /* Command is complete ? */
116 if ((g->state[group_id].cmd_len == cmd_len) &&
117 (g->state[group_id].cmd_val & 1))
118 {
119 #if DEBUG_EEPROM
120 printf("nmc93cX6: %s(%d): command = %x\n",
121 g->description,group_id,g->state[group_id].cmd_val);
122 #endif
123 g->state[group_id].cmd_len = 0;
124
125 /* we have the command! extract the opcode */
126 cmd = g->state[group_id].cmd_val;
127 op = cmd & 0x7;
128
129 switch(op) {
130 case NMC93CX6_CMD_READ:
131 g->state[group_id].state = EEPROM_STATE_DATAOUT;
132 g->state[group_id].dataout_pos = 0;
133 break;
134 #if DEBUG_EEPROM
135 default:
136 printf("nmc93cX6: unhandled opcode %d\n",op);
137 #endif
138 }
139 }
140
141 break;
142
143 case EEPROM_STATE_DATAOUT:
144 /*
145 * user want to read data. we read 16-bits.
146 * extract address (6 bits) from command.
147 */
148
149 cmd = g->state[group_id].cmd_val;
150 addr = nmc94cX6_get_addr(g,cmd);
151
152 #if DEBUG_EEPROM
153 if (g->state[group_id].dataout_pos == 0)
154 printf("nmc93cX6: %s(%d): read addr=%x (%d), val = %4.4x\n",
155 g->description,group_id,addr,addr,
156 g->state[group_id].cmd_val);
157 #endif
158
159 pos = g->state[group_id].dataout_pos++;
160 eeprom = g->eeprom[group_id];
161
162 if (eeprom && eeprom->data && (addr < eeprom->len)) {
163 g->state[group_id].dataout_val = eeprom->data[addr] & (1 << pos);
164 } else {
165 /* access out of bounds */
166 g->state[group_id].dataout_val = (1 << pos);
167 }
168
169 if (g->state[group_id].dataout_pos == NMC93CX6_CMD_DATALEN) {
170 g->state[group_id].state = EEPROM_STATE_INACTIVE;
171 g->state[group_id].dataout_pos = 0;
172 }
173 break;
174
175 #if DEBUG_EEPROM
176 default:
177 printf("nmc93cX6: unhandled state %d\n",g->state[group_id].state);
178 #endif
179 }
180 }
181
182 /* Check clock set for all group */
183 void nmc93cX6_check_clk(struct nmc93cX6_group *g,u_int old,u_int new)
184 {
185 int i;
186
187 for(i=0;i<g->nr_eeprom;i++)
188 nmc93cX6_check_clk_group(g,i,old,new);
189 }
190
191 /* Handle write */
192 void nmc93cX6_write(struct nmc93cX6_group *g,u_int data)
193 {
194 u_int new = data, old = g->eeprom_reg;
195
196 nmc93cX6_check_cs(g,old,new);
197 nmc93cX6_check_clk(g,old,new);
198 g->eeprom_reg = new;
199 }
200
201 /* Handle read */
202 u_int nmc93cX6_read(struct nmc93cX6_group *g)
203 {
204 u_int res;
205 int i;
206
207 res = g->eeprom_reg;
208
209 for(i=0;i<g->nr_eeprom;i++) {
210 if (!(g->eeprom_reg & (1 << g->def[i]->select_bit)))
211 continue;
212
213 if (g->state[i].dataout_val)
214 res |= 1 << g->def[i]->dout_bit;
215 else
216 res &= ~(1 << g->def[i]->dout_bit);
217 }
218
219 return(res);
220 }
221

  ViewVC Help
Powered by ViewVC 1.1.26