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

Diff of /trunk/dev_c2691_iofpga.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

upstream/dynamips-0.2.7-RC1/dev_c2691_iofpga.c revision 7 by dpavlin, Sat Oct 6 16:23:47 2007 UTC trunk/dev_c2691_iofpga.c revision 12 by dpavlin, Sat Oct 6 16:45:40 2007 UTC
# Line 1  Line 1 
1  /*  /*
2   * Cisco 2691 simulation platform.   * Cisco router simulation platform.
3   * Copyright (c) 2006 Christophe Fillot (cf@utc.fr)   * Copyright (c) 2006 Christophe Fillot (cf@utc.fr)
4   */   */
5    
# Line 19  Line 19 
19  #include "memory.h"  #include "memory.h"
20  #include "device.h"  #include "device.h"
21  #include "dev_vtty.h"  #include "dev_vtty.h"
22  #include "nmc93c46.h"  #include "nmc93cX6.h"
23  #include "dev_c2691.h"  #include "dev_c2691.h"
24    
25  /* Debugging flags */  /* Debugging flags */
26  #define DEBUG_UNKNOWN   1  #define DEBUG_UNKNOWN   1
27  #define DEBUG_ACCESS    0  #define DEBUG_ACCESS    0
28    #define DEBUG_NET_IRQ   0
29    
30  /* Definitions for Mainboard EEPROM */  /* Definitions for Mainboard EEPROM */
31  #define EEPROM_MB_DOUT  3  #define EEPROM_MB_DOUT  3
# Line 38  Line 39 
39  #define EEPROM_NM_CLK   2  #define EEPROM_NM_CLK   2
40  #define EEPROM_NM_CS    4  #define EEPROM_NM_CS    4
41    
42  #define C2691_NET_IRQ_CLEARING_DELAY  16  /* Network IRQ distribution */
43    struct net_irq_distrib  {
44       u_int reg;
45       u_int offset;
46    };
47    
48    static struct net_irq_distrib net_irq_dist[C2691_MAX_NM_BAYS] = {
49       { 0,  0 },  /* Slot 0: reg 0x26, 0x000000XX */
50       { 1,  0 },  /* Slot 1: reg 0x28, 0x000000XX */
51    };
52    
53  /* IO FPGA structure */  /* IO FPGA structure */
54  struct iofpga_data {  struct c2691_iofpga_data {
55     vm_obj_t vm_obj;     vm_obj_t vm_obj;
56     struct vdevice dev;     struct vdevice dev;
57     c2691_t *router;     c2691_t *router;
     
    /*  
     * Used to introduce a "delay" before clearing the network interrupt  
     * on 3620/3640 platforms. Added due to a packet loss when using an  
     * Ethernet NM on these platforms.  
     *  
     * Anyway, we should rely on the device information with appropriate IRQ  
     * routing.  
     */  
    int net_irq_clearing_count;  
58    
59     /* Interrupt mask*/     /* Network IRQ status */
60       m_uint16_t net_irq_status[2];
61      
62       /* Interrupt mask */
63     m_uint16_t intr_mask;     m_uint16_t intr_mask;
64    
65       /* WIC select */
66       u_int wic_select;
67       u_int wic_cmd_pos;
68       u_int wic_cmd_valid;
69       m_uint16_t wic_cmd[2];
70  };  };
71    
72  /* Mainboard EEPROM definition */  /* Mainboard EEPROM definition */
73  static const struct nmc93c46_eeprom_def eeprom_mb_def = {  static const struct nmc93cX6_eeprom_def eeprom_mb_def = {
74     EEPROM_MB_CLK, EEPROM_MB_CS,     EEPROM_MB_CLK, EEPROM_MB_CS,
75     EEPROM_MB_DIN, EEPROM_MB_DOUT,     EEPROM_MB_DIN, EEPROM_MB_DOUT,
76  };  };
77    
78  /* Mainboard EEPROM */  /* Mainboard EEPROM */
79  static const struct nmc93c46_group eeprom_mb_group = {  static const struct nmc93cX6_group eeprom_mb_group = {
80     1, 0, "Mainboard EEPROM", 0, { &eeprom_mb_def },     EEPROM_TYPE_NMC93C46, 1, 0,
81       EEPROM_DORD_NORMAL,
82       EEPROM_DOUT_HIGH,
83       EEPROM_DEBUG_DISABLED,
84       "Mainboard EEPROM",
85       { &eeprom_mb_def },
86  };  };
87    
88  /* NM EEPROM definition */  /* NM EEPROM definition */
89  static const struct nmc93c46_eeprom_def eeprom_nm_def = {  static const struct nmc93cX6_eeprom_def eeprom_nm_def = {
90     EEPROM_NM_CLK, EEPROM_NM_CS,     EEPROM_NM_CLK, EEPROM_NM_CS,
91     EEPROM_NM_DIN, EEPROM_NM_DOUT,     EEPROM_NM_DIN, EEPROM_NM_DOUT,
92  };  };
93    
94  /* NM EEPROM */  /* NM EEPROM */
95  static const struct nmc93c46_group eeprom_nm_group = {  static const struct nmc93cX6_group eeprom_nm_group = {
96     1, 0, "NM EEPROM", 0, { &eeprom_nm_def },     EEPROM_TYPE_NMC93C46, 1, 0,
97       EEPROM_DORD_NORMAL,
98       EEPROM_DOUT_HIGH,
99       EEPROM_DEBUG_DISABLED,
100       "NM EEPROM",
101       { &eeprom_nm_def },
102  };  };
103    
104    /* Update network interrupt status */
105    static inline void dev_c2691_iofpga_net_update_irq(struct c2691_iofpga_data *d)
106    {
107       if ((d->net_irq_status[0] != 0xFFFF) || (d->net_irq_status[1] != 0xFFFF)) {
108          vm_set_irq(d->router->vm,C2691_NETIO_IRQ);
109       } else {
110          vm_clear_irq(d->router->vm,C2691_NETIO_IRQ);
111       }
112    }
113    
114    /* Trigger a Network IRQ for the specified slot/port */
115    void dev_c2691_iofpga_net_set_irq(struct c2691_iofpga_data *d,
116                                      u_int slot,u_int port)
117    {
118       struct net_irq_distrib *irq_dist;
119    
120    #if DEBUG_NET_IRQ
121       vm_log(d->router->vm,"IO_FPGA","setting NetIRQ for slot %u port %u\n",
122              slot,port);
123    #endif
124       irq_dist = &net_irq_dist[slot];
125       d->net_irq_status[irq_dist->reg] &= ~(1 << (irq_dist->offset + port));
126       dev_c2691_iofpga_net_update_irq(d);
127    }
128    
129    /* Clear a Network IRQ for the specified slot/port */
130    void dev_c2691_iofpga_net_clear_irq(struct c2691_iofpga_data *d,
131                                        u_int slot,u_int port)
132    {
133       struct net_irq_distrib *irq_dist;
134    
135    #if DEBUG_NET_IRQ
136       vm_log(d->router->vm,"IO_FPGA","clearing NetIRQ for slot %u port %u\n",
137              slot,port);
138    #endif
139       irq_dist = &net_irq_dist[slot];
140       d->net_irq_status[irq_dist->reg] |= (1 << (irq_dist->offset + port));
141       dev_c2691_iofpga_net_update_irq(d);
142    }
143    
144    /* Read a WIC EEPROM */
145    static m_uint16_t dev_c2691_read_wic_eeprom(struct c2691_iofpga_data *d)
146    {  
147       struct cisco_eeprom *eeprom;
148       u_int wic_port;
149       u_int eeprom_offset;
150       m_uint8_t val[2];
151    
152       switch(d->wic_select) {
153          case 0x1700:
154             wic_port = 0x10;
155             break;
156          case 0x1D00:
157             wic_port = 0x20;
158             break;
159          case 0x3500:
160             wic_port = 0x30;
161             break;
162          default:
163             wic_port = 0;
164       }
165    
166       /* No WIC in slot or no EEPROM: fake an empty EEPROM */
167       if (!wic_port || !(eeprom = vm_slot_get_eeprom(d->router->vm,0,wic_port)))
168          return(0xFFFF);
169    
170       /* EEPROM offset is in the lowest 6 bits */
171       eeprom_offset = d->wic_cmd[0] & 0x3F;
172    
173       cisco_eeprom_get_byte(eeprom,eeprom_offset,&val[0]);
174       cisco_eeprom_get_byte(eeprom,eeprom_offset+1,&val[1]);
175    
176       return(((m_uint16_t)val[0] << 8) | val[1]);
177    }
178    
179  /*  /*
180   * dev_c2691_iofpga_access()   * dev_c2691_iofpga_access()
181   */   */
# Line 90  dev_c2691_iofpga_access(cpu_gen_t *cpu,s Line 184  dev_c2691_iofpga_access(cpu_gen_t *cpu,s
184                          m_uint32_t offset,u_int op_size,u_int op_type,                          m_uint32_t offset,u_int op_size,u_int op_type,
185                          m_uint64_t *data)                          m_uint64_t *data)
186  {  {
187     struct iofpga_data *d = dev->priv_data;     struct c2691_iofpga_data *d = dev->priv_data;
188    
189     if (op_type == MTS_READ)     if (op_type == MTS_READ)
190        *data = 0x0;        *data = 0x0;
# Line 119  dev_c2691_iofpga_access(cpu_gen_t *cpu,s Line 213  dev_c2691_iofpga_access(cpu_gen_t *cpu,s
213        /* Mainboard EEPROM */        /* Mainboard EEPROM */
214        case 0x0e:        case 0x0e:
215           if (op_type == MTS_WRITE)           if (op_type == MTS_WRITE)
216              nmc93c46_write(&d->router->mb_eeprom_group,(u_int)(*data));              nmc93cX6_write(&d->router->mb_eeprom_group,(u_int)(*data));
217           else           else
218              *data = nmc93c46_read(&d->router->mb_eeprom_group);              *data = nmc93cX6_read(&d->router->mb_eeprom_group);
219           break;           break;
220    
221        case 0x12:        case 0x12:
222           /*           /*
223            * Bit 0: 1=No WIC in slot 0 ?            * Bit 0: 1=No WIC in slot 0.
224            * Bit 1: 1=No WIC in slot 1 ?            * Bit 1: 1=No WIC in slot 1.
225            * Bit 2: 1=No WIC in slot 2 ?            * Bit 2: 1=No WIC in slot 2.
226            */            */
227           if (op_type == MTS_READ)           if (op_type == MTS_READ) {
228              *data = 0x0007;              *data = 0xFFFF;
229                
230                /* check WIC 0 */
231                if (vm_slot_check_eeprom(d->router->vm,0,0x10))
232                   *data &= ~0x01;
233    
234                /* check WIC 1 */
235                if (vm_slot_check_eeprom(d->router->vm,0,0x20))
236                   *data &= ~0x02;
237    
238                /* check WIC 2 */
239                if (vm_slot_check_eeprom(d->router->vm,0,0x30))
240                   *data &= ~0x04;
241             } else {
242                d->wic_select = *data;
243             }
244           break;           break;
245    
246        case 0x14:        case 0x14:
# Line 152  dev_c2691_iofpga_access(cpu_gen_t *cpu,s Line 261  dev_c2691_iofpga_access(cpu_gen_t *cpu,s
261    
262        /* WIC related: 16-bit data */        /* WIC related: 16-bit data */
263        case 0x42:        case 0x42:
264             if (op_type == MTS_READ) {
265                if (d->wic_cmd_valid) {
266                   *data = dev_c2691_read_wic_eeprom(d);
267                   d->wic_cmd_valid = FALSE;
268                } else {
269                   *data = 0xFFFF;
270                }
271             } else {
272                /*
273                 * Store the EEPROM command (in 2 words).
274                 *
275                 * For a read, we have:
276                 *    Word 0: 0x180 (nmc93c46 READ) + offset (6-bits).
277                 *    Word 1: 0 (no data).
278                 */
279                d->wic_cmd[d->wic_cmd_pos++] = *data;
280                
281                if (d->wic_cmd_pos == 2) {
282                   d->wic_cmd_pos = 0;
283                   d->wic_cmd_valid = TRUE;
284                }
285             }
286           break;           break;
287    
288        /* NM Slot 1 EEPROM */        /* NM Slot 1 EEPROM */
289        case 0x44:        case 0x44:
290           if (op_type == MTS_WRITE)           if (op_type == MTS_WRITE)
291              nmc93c46_write(&d->router->nm_eeprom_group,(u_int)(*data));              nmc93cX6_write(&d->router->nm_eeprom_group,(u_int)(*data));
292           else           else
293              *data = nmc93c46_read(&d->router->nm_eeprom_group);              *data = nmc93cX6_read(&d->router->nm_eeprom_group);
294           break;           break;
295    
296        /* AIM EEPROM #0 */        /* AIM EEPROM #0 */
# Line 184  dev_c2691_iofpga_access(cpu_gen_t *cpu,s Line 315  dev_c2691_iofpga_access(cpu_gen_t *cpu,s
315           if (op_type == MTS_READ) {           if (op_type == MTS_READ) {
316              *data = 0xFFFF;              *data = 0xFFFF;
317    
318              if (c2691_nm_check_eeprom(d->router,1))              if (vm_slot_get_card_ptr(d->router->vm,1))
319                 *data &= ~0x08;                 *data &= ~0x08;
320           }           }
321           break;           break;
# Line 208  dev_c2691_iofpga_access(cpu_gen_t *cpu,s Line 339  dev_c2691_iofpga_access(cpu_gen_t *cpu,s
339         * Other bits unknown.         * Other bits unknown.
340         */         */
341        case 0x26:        case 0x26:
342           if (op_type == MTS_READ) {           if (op_type == MTS_READ)
343              *data = 0xFFFE;              *data = d->net_irq_status[0];
             vm_clear_irq(d->router->vm,C2691_NETIO_IRQ);  
          }  
344           break;           break;
345    
346        /*        /*
# Line 221  dev_c2691_iofpga_access(cpu_gen_t *cpu,s Line 350  dev_c2691_iofpga_access(cpu_gen_t *cpu,s
350         * Other bits unknown.         * Other bits unknown.
351         */         */
352        case 0x28:        case 0x28:
353           if (op_type == MTS_READ) {           if (op_type == MTS_READ)
354              *data = 0xFFFE;              *data = d->net_irq_status[1];
             vm_clear_irq(d->router->vm,C2691_NETIO_IRQ);  
          }  
355           break;           break;
356    
357        case 0x2c:        case 0x2c:
# Line 302  void c2691_init_eeprom_groups(c2691_t *r Line 429  void c2691_init_eeprom_groups(c2691_t *r
429    
430     /* EEPROM for NM slot 1 */     /* EEPROM for NM slot 1 */
431     router->nm_eeprom_group = eeprom_nm_group;     router->nm_eeprom_group = eeprom_nm_group;
432     router->nm_eeprom_group.eeprom[0] = &router->nm_bay[1].eeprom;     router->nm_eeprom_group.eeprom[0] = NULL;
433  }  }
434    
435  /* Shutdown the IO FPGA device */  /* Shutdown the IO FPGA device */
436  void dev_c2691_iofpga_shutdown(vm_instance_t *vm,struct iofpga_data *d)  static void
437    dev_c2691_iofpga_shutdown(vm_instance_t *vm,struct c2691_iofpga_data *d)
438  {  {
439     if (d != NULL) {     if (d != NULL) {
440        /* Remove the device */        /* Remove the device */
# Line 323  void dev_c2691_iofpga_shutdown(vm_instan Line 451  void dev_c2691_iofpga_shutdown(vm_instan
451  int dev_c2691_iofpga_init(c2691_t *router,m_uint64_t paddr,m_uint32_t len)  int dev_c2691_iofpga_init(c2691_t *router,m_uint64_t paddr,m_uint32_t len)
452  {  {
453     vm_instance_t *vm = router->vm;     vm_instance_t *vm = router->vm;
454     struct iofpga_data *d;     struct c2691_iofpga_data *d;
455    
456     /* Allocate private data structure */     /* Allocate private data structure */
457     if (!(d = malloc(sizeof(*d)))) {     if (!(d = malloc(sizeof(*d)))) {
# Line 333  int dev_c2691_iofpga_init(c2691_t *route Line 461  int dev_c2691_iofpga_init(c2691_t *route
461    
462     memset(d,0,sizeof(*d));     memset(d,0,sizeof(*d));
463     d->router = router;     d->router = router;
464       d->net_irq_status[0] = 0xFFFF;
465       d->net_irq_status[1] = 0xFFFF;
466    
467     vm_object_init(&d->vm_obj);     vm_object_init(&d->vm_obj);
468     d->vm_obj.name = "io_fpga";     d->vm_obj.name = "io_fpga";

Legend:
Removed from v.7  
changed lines
  Added in v.12

  ViewVC Help
Powered by ViewVC 1.1.26