/[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

Annotation of /trunk/nmc93c46.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 7 - (hide annotations)
Sat Oct 6 16:23:47 2007 UTC (16 years, 5 months ago) by dpavlin
Original Path: upstream/dynamips-0.2.7-RC1/nmc93c46.c
File MIME type: text/plain
File size: 5048 byte(s)
dynamips-0.2.7-RC1

1 dpavlin 1 /*
2 dpavlin 7 * Cisco router simulation platform.
3 dpavlin 1 * 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 dpavlin 4 printf("nmc93c46: %s(%d): read addr=%x (%d), val = %4.4x\n",
126     g->description,group_id,addr,addr,
127 dpavlin 1 g->state[group_id].cmd_val);
128     #endif
129    
130     pos = g->state[group_id].dataout_pos++;
131 dpavlin 3 eeprom = g->eeprom[group_id];
132 dpavlin 1
133 dpavlin 3 if (eeprom && eeprom->data && (addr < eeprom->len)) {
134     g->state[group_id].dataout_val = eeprom->data[addr] & (1 << pos);
135 dpavlin 1 } 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 dpavlin 4 if (!(g->eeprom_reg & (1 << g->def[i]->select_bit)))
182     continue;
183    
184 dpavlin 1 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