/[dynamips]/trunk/dev_c7200_mpfpga.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_c7200_mpfpga.c

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

upstream/dynamips-0.2.6-RC2/dev_c7200_mpfpga.c revision 3 by dpavlin, Sat Oct 6 16:05:34 2007 UTC trunk/dev_c7200_mpfpga.c revision 12 by dpavlin, Sat Oct 6 16:45:40 2007 UTC
# Line 1  Line 1 
1  /*  /*
2   * Cisco 7200 (Predator) simulation platform.   * Cisco router simulation platform.
3   * Copyright (c) 2005,2006 Christophe Fillot (cf@utc.fr)   * Copyright (c) 2005-2007 Christophe Fillot (cf@utc.fr)
4   *   *
5   * Cisco C7200 (Predator) Midplane FPGA.   * Cisco c7200 Midplane FPGA.
6   */   */
7    
8  #include <stdio.h>  #include <stdio.h>
9  #include <stdlib.h>  #include <stdlib.h>
10  #include <string.h>  #include <string.h>
11    
12  #include "mips64.h"  #include "cpu.h"
13    #include "vm.h"
14  #include "dynamips.h"  #include "dynamips.h"
15  #include "memory.h"  #include "memory.h"
16  #include "device.h"  #include "device.h"
17  #include "nmc93c46.h"  #include "nmc93cX6.h"
18  #include "dev_c7200.h"  #include "dev_c7200.h"
19    
20  #define DEBUG_UNKNOWN  1  #define DEBUG_UNKNOWN  1
21  #define DEBUG_ACCESS   0  #define DEBUG_ACCESS   0
22  #define DEBUG_OIR      0  #define DEBUG_NET_IRQ  0
23    #define DEBUG_OIR      1
24    
25  /*  /*
26   * Definitions for Port Adapter Status.   * Definitions for Port Adapter Status.
# Line 86  Line 88 
88  #define BAY6_EEPROM_DOUT_BIT     22  #define BAY6_EEPROM_DOUT_BIT     22
89    
90  /* PA Bay EEPROM definitions */  /* PA Bay EEPROM definitions */
91  static const struct nmc93c46_eeprom_def eeprom_bay_def[C7200_MAX_PA_BAYS] = {  static const struct nmc93cX6_eeprom_def eeprom_bay_def[C7200_MAX_PA_BAYS] = {
92     /* Bay 0 */     /* Bay 0 */
93     { BAY0_EEPROM_CLOCK_BIT , BAY0_EEPROM_SELECT_BIT,     { BAY0_EEPROM_CLOCK_BIT , BAY0_EEPROM_SELECT_BIT,
94       BAY0_EEPROM_DIN_BIT   , BAY0_EEPROM_DOUT_BIT,       BAY0_EEPROM_DIN_BIT   , BAY0_EEPROM_DOUT_BIT,
# Line 124  static const struct nmc93c46_eeprom_def Line 126  static const struct nmc93c46_eeprom_def
126  };  };
127    
128  /* EEPROM group #1 (Bays 0, 1, 3, 4) */  /* EEPROM group #1 (Bays 0, 1, 3, 4) */
129  static const struct nmc93c46_group eeprom_bays_g1 = {  static const struct nmc93cX6_group eeprom_bays_g1 = {
130     4, 0, "PA Bays (Group #1) EEPROM", FALSE,     EEPROM_TYPE_NMC93C46, 4, 0,
131       EEPROM_DORD_NORMAL,
132       EEPROM_DOUT_HIGH,
133       EEPROM_DEBUG_DISABLED,
134       "PA Bays (Group #1) EEPROM",
135     { &eeprom_bay_def[0], &eeprom_bay_def[1],     { &eeprom_bay_def[0], &eeprom_bay_def[1],
136       &eeprom_bay_def[3], &eeprom_bay_def[4],       &eeprom_bay_def[3], &eeprom_bay_def[4],
137     },     },
138  };  };
139    
140  /* EEPROM group #2 (Bays 2, 5, 6) */  /* EEPROM group #2 (Bays 2, 5, 6) */
141  static const struct nmc93c46_group eeprom_bays_g2 = {  static const struct nmc93cX6_group eeprom_bays_g2 = {
142     3, 0, "PA Bays (Group #2) EEPROM", FALSE,     EEPROM_TYPE_NMC93C46, 3, 0,
143       EEPROM_DORD_NORMAL,
144       EEPROM_DOUT_HIGH,
145       EEPROM_DEBUG_DISABLED,
146       "PA Bays (Group #2) EEPROM",
147     { &eeprom_bay_def[2], &eeprom_bay_def[5], &eeprom_bay_def[6] },     { &eeprom_bay_def[2], &eeprom_bay_def[5], &eeprom_bay_def[6] },
148  };  };
149    
150    /* Network IRQ distribution */
151    struct net_irq_distrib  {
152       u_int reg;
153       u_int offset;
154    };
155    
156    static struct net_irq_distrib net_irq_dist[C7200_MAX_PA_BAYS] = {
157       { 0,  0 },  /* Slot 0: reg 0x10, 0x000000XX */
158       { 0,  8 },  /* Slot 1: reg 0x10, 0x0000XX00 */
159       { 1,  8 },  /* Slot 2: reg 0x18, 0x0000XX00 */
160       { 0, 24 },  /* Slot 3: reg 0x10, 0xXX000000 */
161       { 0, 16 },  /* Slot 4: reg 0x10, 0x00XX0000 */
162       { 1, 24 },  /* Slot 5: reg 0x18, 0xXX000000 */
163       { 1, 16 },  /* Slot 6: reg 0x18, 0x00XX0000 */
164    };
165    
166  /* Midplane FPGA private data */  /* Midplane FPGA private data */
167  struct mpfpga_data {  struct c7200_mpfpga_data {
168     vm_obj_t vm_obj;     vm_obj_t vm_obj;
169     struct vdevice dev;     struct vdevice dev;
170    
171     c7200_t *router;     c7200_t *router;
172     m_uint32_t pa_status_reg;     m_uint32_t pa_status_reg;
173     m_uint32_t pa_ctrl_reg;     m_uint32_t pa_ctrl_reg;
174    
175       m_uint32_t net_irq_status[2];
176       m_uint32_t net_irq_mask[2];
177  };  };
178    
179    /* Update network interrupt status */
180    static inline void dev_c7200_mpfpga_net_update_irq(struct c7200_mpfpga_data *d)
181    {
182       int status;
183    
184       status = (d->net_irq_status[0] & d->net_irq_mask[0]) ||
185          (d->net_irq_status[1] & d->net_irq_mask[1]);
186      
187       if (status) {
188          vm_set_irq(d->router->vm,C7200_NETIO_IRQ);
189       } else {
190          vm_clear_irq(d->router->vm,C7200_NETIO_IRQ);
191       }
192    }
193    
194    /* Trigger a Network IRQ for the specified slot/port */
195    void dev_c7200_mpfpga_net_set_irq(struct c7200_mpfpga_data *d,
196                                      u_int slot,u_int port)
197    {
198       struct net_irq_distrib *irq_dist;
199    
200    #if DEBUG_NET_IRQ
201       vm_log(d->router->vm,"MP_FPGA","setting NetIRQ for slot %u port %u\n",
202              slot,port);
203    #endif
204       irq_dist = &net_irq_dist[slot];
205       d->net_irq_status[irq_dist->reg] |= 1 << (irq_dist->offset + port);
206       dev_c7200_mpfpga_net_update_irq(d);
207    }
208    
209    /* Clear a Network IRQ for the specified slot/port */
210    void dev_c7200_mpfpga_net_clear_irq(struct c7200_mpfpga_data *d,
211                                        u_int slot,u_int port)
212    {
213       struct net_irq_distrib *irq_dist;
214    
215    #if DEBUG_NET_IRQ
216       vm_log(d->router->vm,"MP_FPGA","clearing NetIRQ for slot %u port %u\n",
217              slot,port);
218    #endif
219       irq_dist = &net_irq_dist[slot];
220       d->net_irq_status[irq_dist->reg] &= ~(1 << (irq_dist->offset + port));
221       dev_c7200_mpfpga_net_update_irq(d);
222    }
223    
224  /* Update Port Adapter Status */  /* Update Port Adapter Status */
225  static void pa_update_status_reg(struct mpfpga_data *d)  static void pa_update_status_reg(struct c7200_mpfpga_data *d)
226  {  {
227     m_uint32_t res = 0;     m_uint32_t res = 0;
228    
229     /* PA Power. Bay 0 is always powered */     /* PA Power. Bay 0 is always powered */
230     res |= PCI_BAY0_5V_OK | PCI_BAY0_3V_OK;     res |= PCI_BAY0_5V_OK | PCI_BAY0_3V_OK;
231      
232     /* We fake power on bays defined by the final user */     /* We fake power on bays defined by the final user */
233     if (c7200_pa_check_eeprom(d->router,1))     if (vm_slot_check_eeprom(d->router->vm,1,0))
234        res |= PCI_BAY1_5V_OK | PCI_BAY1_3V_OK;        res |= PCI_BAY1_5V_OK | PCI_BAY1_3V_OK;
235        
236     if (c7200_pa_check_eeprom(d->router,2))     if (vm_slot_check_eeprom(d->router->vm,2,0))
237        res |= PCI_BAY2_5V_OK | PCI_BAY2_3V_OK;        res |= PCI_BAY2_5V_OK | PCI_BAY2_3V_OK;
238    
239     if (c7200_pa_check_eeprom(d->router,3))     if (vm_slot_check_eeprom(d->router->vm,3,0))
240        res |= PCI_BAY3_5V_OK | PCI_BAY3_3V_OK;        res |= PCI_BAY3_5V_OK | PCI_BAY3_3V_OK;
241        
242     if (c7200_pa_check_eeprom(d->router,4))     if (vm_slot_check_eeprom(d->router->vm,4,0))
243        res |= PCI_BAY4_5V_OK | PCI_BAY4_3V_OK;        res |= PCI_BAY4_5V_OK | PCI_BAY4_3V_OK;
244    
245     if (c7200_pa_check_eeprom(d->router,5))     if (vm_slot_check_eeprom(d->router->vm,5,0))
246        res |= PCI_BAY5_5V_OK | PCI_BAY5_3V_OK;        res |= PCI_BAY5_5V_OK | PCI_BAY5_3V_OK;
247                
248     if (c7200_pa_check_eeprom(d->router,6))     if (vm_slot_check_eeprom(d->router->vm,6,0))
249        res |= PCI_BAY6_5V_OK | PCI_BAY6_3V_OK;        res |= PCI_BAY6_5V_OK | PCI_BAY6_3V_OK;
250    
251     d->pa_status_reg = res;     d->pa_status_reg = res;
# Line 182  static void pa_update_status_reg(struct Line 254  static void pa_update_status_reg(struct
254  /*  /*
255   * dev_mpfpga_access()   * dev_mpfpga_access()
256   */   */
257  void *dev_c7200_mpfpga_access(cpu_mips_t *cpu,struct vdevice *dev,  void *dev_c7200_mpfpga_access(cpu_gen_t *cpu,struct vdevice *dev,
258                                m_uint32_t offset,u_int op_size,u_int op_type,                                m_uint32_t offset,u_int op_size,u_int op_type,
259                                m_uint64_t *data)                                m_uint64_t *data)
260  {  {
261     struct mpfpga_data *d = dev->priv_data;     struct c7200_mpfpga_data *d = dev->priv_data;
262    
263     if (op_type == MTS_READ)     if (op_type == MTS_READ)
264        *data = 0x0;        *data = 0x0;
# Line 198  void *dev_c7200_mpfpga_access(cpu_mips_t Line 270  void *dev_c7200_mpfpga_access(cpu_mips_t
270  #if DEBUG_ACCESS  #if DEBUG_ACCESS
271     if (op_type == MTS_READ) {     if (op_type == MTS_READ) {
272        cpu_log(cpu,"MP_FPGA","reading reg 0x%x at pc=0x%llx (size=%u)\n",        cpu_log(cpu,"MP_FPGA","reading reg 0x%x at pc=0x%llx (size=%u)\n",
273                offset,cpu->pc,op_size);                offset,cpu_get_pc(cpu),op_size);
274     } else {     } else {
275        cpu_log(cpu,"MP_FPGA",        cpu_log(cpu,"MP_FPGA",
276                "writing reg 0x%x at pc=0x%llx, data=0x%llx (size=%u)\n",                "writing reg 0x%x at pc=0x%llx, data=0x%llx (size=%u)\n",
277                offset,cpu->pc,*data,op_size);                offset,cpu_get_pc(cpu),*data,op_size);
278     }     }
279  #endif  #endif
280    
281     switch(offset) {           switch(offset) {
282        case 0x10:  /* interrupt mask, should be done more efficiently */        /* Interrupt status for slots 0, 1, 3, 4 */
283          case 0x10:
284        case 0x11:        case 0x11:
285        case 0x12:        case 0x12:
286        case 0x13:        case 0x13:
287           if (op_type == MTS_READ) {           if (op_type == MTS_READ)
288              *data = 0xFFFFFFFF;              *data = d->net_irq_status[0];
             vm_clear_irq(d->router->vm,C7200_NETIO_IRQ);  
          }  
289           break;           break;
290    
291        case 0x18:  /* interrupt mask, should be done more efficiently */        /* Interrupt status for slots 2, 5, 6 */
292          case 0x18:
293        case 0x19:        case 0x19:
294        case 0x1a:        case 0x1a:
295          case 0x1b:
296             if (op_type == MTS_READ)
297                *data = d->net_irq_status[1];
298             break;
299    
300          /* Interrupt mask for slots 0, 1, 3, 4 */
301          case 0x20:
302           if (op_type == MTS_READ) {           if (op_type == MTS_READ) {
303              *data = 0xFFFFFFFF;              *data = d->net_irq_mask[0];
304              vm_clear_irq(d->router->vm,C7200_NETIO_IRQ);           } else {
305                d->net_irq_mask[0] = *data;
306                dev_c7200_mpfpga_net_update_irq(d);
307             }
308             break;
309    
310          /* Interrupt mask for slots 2, 5, 6 */
311          case 0x28:
312             if (op_type == MTS_READ) {
313                *data = d->net_irq_mask[1];
314             } else {
315                d->net_irq_mask[1] = *data;
316                dev_c7200_mpfpga_net_update_irq(d);
317           }           }
318           break;           break;
319    
# Line 239  void *dev_c7200_mpfpga_access(cpu_mips_t Line 330  void *dev_c7200_mpfpga_access(cpu_mips_t
330           if (op_type == MTS_READ)           if (op_type == MTS_READ)
331              *data = 0x66666600 & d->pa_status_reg;              *data = 0x66666600 & d->pa_status_reg;
332    
333           mips64_clear_irq(cpu,C7200_PA_MGMT_IRQ);           vm_clear_irq(d->router->vm,C7200_PA_MGMT_IRQ);
334           break;           break;
335    
336        case 0x48:  /* ??? (test) */        case 0x48:  /* ??? (test) */
# Line 258  void *dev_c7200_mpfpga_access(cpu_mips_t Line 349  void *dev_c7200_mpfpga_access(cpu_mips_t
349           if (op_type == MTS_READ) {           if (op_type == MTS_READ) {
350  #if DEBUG_OIR  #if DEBUG_OIR
351              cpu_log(cpu,"MP_FPGA","reading reg 0x%x at pc=0x%llx, val=0x%x\n",              cpu_log(cpu,"MP_FPGA","reading reg 0x%x at pc=0x%llx, val=0x%x\n",
352                      offset,cpu->pc,d->router->oir_status);                      offset,cpu_get_pc(cpu),d->router->oir_status);
353  #endif  #endif
354              *data = d->router->oir_status;              *data = d->router->oir_status;
355                vm_clear_irq(d->router->vm,C7200_OIR_IRQ);
356           } else {           } else {
357  #if DEBUG_OIR  #if DEBUG_OIR
358              cpu_log(cpu,"MP_FPGA","writing reg 0x%x at pc=0x%llx "              cpu_log(cpu,"MP_FPGA","writing reg 0x%x at pc=0x%llx "
359                      "(data=0x%llx)\n",offset,cpu->pc,*data);                      "(data=0x%llx)\n",offset,cpu_get_pc(cpu),*data);
360  #endif  #endif
361              d->router->oir_status &= ~(*data);              d->router->oir_status &= ~(*data);
362              vm_clear_irq(d->router->vm,C7200_OIR_IRQ);                                  vm_clear_irq(d->router->vm,C7200_OIR_IRQ);                    
# Line 278  void *dev_c7200_mpfpga_access(cpu_mips_t Line 370  void *dev_c7200_mpfpga_access(cpu_mips_t
370        case 0x78:        case 0x78:
371           if (op_type == MTS_READ) {           if (op_type == MTS_READ) {
372  #if DEBUG_OIR  #if DEBUG_OIR
373              cpu_log(cpu,"MP_FPGA","reading 0x78 at pc=0x%llx\n",cpu->pc);              cpu_log(cpu,"MP_FPGA","reading 0x78 at pc=0x%llx\n",
374                        cpu_get_pc(cpu));
375  #endif  #endif
376              *data = 0x00;              *data = 0x00;
377           } else {           } else {
378  #if DEBUG_OIR  #if DEBUG_OIR
379              cpu_log(cpu,"MP_FPGA","writing reg 0x78 at pc=0x%llx "              cpu_log(cpu,"MP_FPGA","writing reg 0x78 at pc=0x%llx "
380                    "(data=0x%llx)\n",cpu->pc,*data);                    "(data=0x%llx)\n",cpu_get_pc(cpu),*data);
381  #endif  #endif
382           }           }
383           break;           break;
# Line 308  void *dev_c7200_mpfpga_access(cpu_mips_t Line 401  void *dev_c7200_mpfpga_access(cpu_mips_t
401    
402        case 0x60:   /* EEPROM for PA in slots 0,1,3,4 */        case 0x60:   /* EEPROM for PA in slots 0,1,3,4 */
403           if (op_type == MTS_WRITE)           if (op_type == MTS_WRITE)
404              nmc93c46_write(&d->router->pa_eeprom_g1,*data);              nmc93cX6_write(&d->router->pa_eeprom_g1,*data);
405           else           else
406              *data = nmc93c46_read(&d->router->pa_eeprom_g1);              *data = nmc93cX6_read(&d->router->pa_eeprom_g1);
407           break;           break;
408    
409        case 0x68:   /* EEPROM for PA in slots 2,5,6 */        case 0x68:   /* EEPROM for PA in slots 2,5,6 */
410           if (op_type == MTS_WRITE)           if (op_type == MTS_WRITE)
411              nmc93c46_write(&d->router->pa_eeprom_g2,*data);              nmc93cX6_write(&d->router->pa_eeprom_g2,*data);
412           else           else
413              *data = nmc93c46_read(&d->router->pa_eeprom_g2);              *data = nmc93cX6_read(&d->router->pa_eeprom_g2);
414           break;           break;
415    
416        case 0x7b:  /* ??? */        case 0x7b:  /* ??? */
# Line 327  void *dev_c7200_mpfpga_access(cpu_mips_t Line 420  void *dev_c7200_mpfpga_access(cpu_mips_t
420        default:        default:
421           if (op_type == MTS_READ) {           if (op_type == MTS_READ) {
422              cpu_log(cpu,"MP_FPGA","read from addr 0x%x, pc=0x%llx\n",              cpu_log(cpu,"MP_FPGA","read from addr 0x%x, pc=0x%llx\n",
423                      offset,cpu->pc);                      offset,cpu_get_pc(cpu));
424           } else {           } else {
425              cpu_log(cpu,"MP_FPGA","write to addr 0x%x, value=0x%llx, "              cpu_log(cpu,"MP_FPGA","write to addr 0x%x, value=0x%llx, "
426                      "pc=0x%llx\n",offset,*data,cpu->pc);                      "pc=0x%llx\n",offset,*data,cpu_get_pc(cpu));
427           }           }
428  #endif  #endif
429     }     }
# Line 339  void *dev_c7200_mpfpga_access(cpu_mips_t Line 432  void *dev_c7200_mpfpga_access(cpu_mips_t
432  }  }
433    
434  /* Initialize EEPROM groups */  /* Initialize EEPROM groups */
435  static void init_eeprom_groups(c7200_t *router)  void c7200_init_mp_eeprom_groups(c7200_t *router)
436  {  {
437     /* Group 1: bays 0, 1, 3, 4 */     /* Group 1: bays 0, 1, 3, 4 */
438     router->pa_eeprom_g1 = eeprom_bays_g1;     router->pa_eeprom_g1 = eeprom_bays_g1;
439     router->pa_eeprom_g1.eeprom[0] = &router->pa_bay[0].eeprom;     router->pa_eeprom_g1.eeprom[0] = NULL;
440     router->pa_eeprom_g1.eeprom[1] = &router->pa_bay[1].eeprom;     router->pa_eeprom_g1.eeprom[1] = NULL;
441     router->pa_eeprom_g1.eeprom[2] = &router->pa_bay[3].eeprom;     router->pa_eeprom_g1.eeprom[2] = NULL;
442     router->pa_eeprom_g1.eeprom[3] = &router->pa_bay[4].eeprom;     router->pa_eeprom_g1.eeprom[3] = NULL;
443    
444     /* Group 2: bays 2, 5, 6 */     /* Group 2: bays 2, 5, 6 */
445     router->pa_eeprom_g2 = eeprom_bays_g2;     router->pa_eeprom_g2 = eeprom_bays_g2;
446     router->pa_eeprom_g2.eeprom[0] = &router->pa_bay[2].eeprom;     router->pa_eeprom_g2.eeprom[0] = NULL;
447     router->pa_eeprom_g2.eeprom[1] = &router->pa_bay[5].eeprom;     router->pa_eeprom_g2.eeprom[1] = NULL;
448     router->pa_eeprom_g2.eeprom[2] = &router->pa_bay[6].eeprom;     router->pa_eeprom_g2.eeprom[2] = NULL;
449  }  }
450    
451  /* Shutdown the MP FPGA device */  /* Shutdown the MP FPGA device */
452  void dev_c7200_mpfpga_shutdown(vm_instance_t *vm,struct mpfpga_data *d)  static void
453    dev_c7200_mpfpga_shutdown(vm_instance_t *vm,struct c7200_mpfpga_data *d)
454  {  {
455     if (d != NULL) {     if (d != NULL) {
456        /* Remove the device */        /* Remove the device */
# Line 367  void dev_c7200_mpfpga_shutdown(vm_instan Line 461  void dev_c7200_mpfpga_shutdown(vm_instan
461     }     }
462  }  }
463    
464  /*  /* Create the c7200 Midplane FPGA */
  * dev_c7200_mpfpga_init()  
  */  
465  int dev_c7200_mpfpga_init(c7200_t *router,m_uint64_t paddr,m_uint32_t len)  int dev_c7200_mpfpga_init(c7200_t *router,m_uint64_t paddr,m_uint32_t len)
466  {    {  
467     struct mpfpga_data *d;     struct c7200_mpfpga_data *d;
468    
469     /* Allocate private data structure */     /* Allocate private data structure */
470     if (!(d = malloc(sizeof(*d)))) {     if (!(d = malloc(sizeof(*d)))) {
# Line 382  int dev_c7200_mpfpga_init(c7200_t *route Line 474  int dev_c7200_mpfpga_init(c7200_t *route
474    
475     memset(d,0,sizeof(*d));     memset(d,0,sizeof(*d));
476     d->router = router;     d->router = router;
     
    /* Initialize EEPROMs */  
    init_eeprom_groups(router);  
477    
478     vm_object_init(&d->vm_obj);     vm_object_init(&d->vm_obj);
479     d->vm_obj.name = "mp_fpga";     d->vm_obj.name = "mp_fpga";

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

  ViewVC Help
Powered by ViewVC 1.1.26