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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1 - (show annotations)
Sat Oct 6 16:01:44 2007 UTC (12 years, 2 months ago) by dpavlin
File MIME type: text/plain
File size: 5052 byte(s)
import 0.2.5 from upstream

1 /*
2 * Cisco 7200 (Predator) 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 u_int cmd,op,addr,pos;
59 u_int clk_bit, din_bit;
60 m_uint16_t *data;
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), data=%4.4x, "
126 "val = %4.4x\n",
127 g->description,group_id,
128 addr,addr,g->def[group_id]->data[addr],
129 g->state[group_id].cmd_val);
130 #endif
131
132 pos = g->state[group_id].dataout_pos++;
133 data = g->def[group_id]->data;
134
135 if ((data != NULL) && (addr < g->def[group_id]->data_len)) {
136 g->state[group_id].dataout_val = data[addr] & (1 << pos);
137 } else {
138 /* access out of bounds */
139 g->state[group_id].dataout_val = (1 << pos);
140 }
141
142 if (g->state[group_id].dataout_pos == NMC93C46_CMD_DATALEN) {
143 g->state[group_id].state = EEPROM_STATE_INACTIVE;
144 g->state[group_id].dataout_pos = 0;
145 }
146 break;
147
148 #if DEBUG_EEPROM
149 default:
150 printf("nmc93c46: unhandled state %d\n",g->state[group_id].state);
151 #endif
152 }
153 }
154
155 /* Check clock set for all group */
156 void nmc93c46_check_clk(struct nmc93c46_group *g,u_int old,u_int new)
157 {
158 int i;
159
160 for(i=0;i<g->nr_eeprom;i++)
161 nmc93c46_check_clk_group(g,i,old,new);
162 }
163
164 /* Handle write */
165 void nmc93c46_write(struct nmc93c46_group *g,u_int data)
166 {
167 u_int new = data, old = g->eeprom_reg;
168
169 nmc93c46_check_cs(g,old,new);
170 nmc93c46_check_clk(g,old,new);
171 g->eeprom_reg = new;
172 }
173
174 /* Handle read */
175 u_int nmc93c46_read(struct nmc93c46_group *g)
176 {
177 u_int res;
178 int i;
179
180 res = g->eeprom_reg;
181
182 for(i=0;i<g->nr_eeprom;i++) {
183 if (g->state[i].dataout_val)
184 res |= 1 << g->def[i]->dout_bit;
185 else
186 res &= ~(1 << g->def[i]->dout_bit);
187 }
188
189 return(res);
190 }
191

  ViewVC Help
Powered by ViewVC 1.1.26