/[dynamips]/upstream/dynamips-0.2.6-RC2/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

Annotation of /upstream/dynamips-0.2.6-RC2/nmc93c46.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3 - (hide annotations)
Sat Oct 6 16:05:34 2007 UTC (13 years, 3 months ago) by dpavlin
File MIME type: text/plain
File size: 5063 byte(s)
dynamips-0.2.6-RC2

1 dpavlin 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 dpavlin 3 struct cisco_eeprom *eeprom;
59 dpavlin 1 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), 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 dpavlin 3 eeprom = g->eeprom[group_id];
134 dpavlin 1
135 dpavlin 3 if (eeprom && eeprom->data && (addr < eeprom->len)) {
136     g->state[group_id].dataout_val = eeprom->data[addr] & (1 << pos);
137 dpavlin 1 } 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