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

Annotation of /trunk/nmc93cX6.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 10 - (hide annotations)
Sat Oct 6 16:29:14 2007 UTC (16 years, 5 months ago) by dpavlin
Original Path: upstream/dynamips-0.2.7/nmc93cX6.c
File MIME type: text/plain
File size: 5786 byte(s)
dynamips-0.2.7

1 dpavlin 8 /*
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