/[dynamips]/trunk/nmc93c46.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 /trunk/nmc93c46.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 12 - (show annotations)
Sat Oct 6 16:45:40 2007 UTC (11 years, 10 months ago) by dpavlin
File MIME type: text/plain
File size: 5048 byte(s)
make working copy

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

  ViewVC Help
Powered by ViewVC 1.1.26