/[dynamips]/upstream/dynamips-0.2.7-RC2/dev_c3600_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 /upstream/dynamips-0.2.7-RC2/dev_c3600_iofpga.c

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

upstream/dynamips-0.2.6-RC5/dev_c3600_iofpga.c revision 6 by dpavlin, Sat Oct 6 16:09:07 2007 UTC upstream/dynamips-0.2.7-RC2/dev_c3600_iofpga.c revision 8 by dpavlin, Sat Oct 6 16:24:54 2007 UTC
# Line 1  Line 1 
1  /*  /*
2   * Cisco 3600 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   * TODO: Online Insertion/Removal (OIR).   * TODO: Online Insertion/Removal (OIR).
# Line 15  Line 15 
15  #include <pthread.h>  #include <pthread.h>
16    
17  #include "ptask.h"  #include "ptask.h"
18  #include "mips64.h"  #include "cpu.h"
19    #include "vm.h"
20  #include "dynamips.h"  #include "dynamips.h"
21  #include "memory.h"  #include "memory.h"
22  #include "device.h"  #include "device.h"
23  #include "dev_vtty.h"  #include "dev_vtty.h"
24  #include "nmc93c46.h"  #include "nmc93cX6.h"
25  #include "dev_c3600.h"  #include "dev_c3600.h"
26    
27  /* Debugging flags */  /* Debugging flags */
28  #define DEBUG_UNKNOWN   1  #define DEBUG_UNKNOWN   1
29  #define DEBUG_ACCESS    0  #define DEBUG_ACCESS    0
30    #define DEBUG_NET_IRQ   0
31    
32  /* Definitions for Mainboard EEPROM */  /* Definitions for Mainboard EEPROM */
33  #define EEPROM_MB_DOUT  3  #define EEPROM_MB_DOUT  3
# Line 39  Line 41 
41  #define EEPROM_NM_CLK   2  #define EEPROM_NM_CLK   2
42  #define EEPROM_NM_CS    4  #define EEPROM_NM_CS    4
43    
44  #define C3600_NET_IRQ_CLEARING_DELAY  16  /* Network IRQ distribution */
45    struct net_irq_distrib  {
46       u_int c3620_c3640_offset;
47       u_int c3660_reg;
48       u_int c3660_offset;
49    };
50    
51    /*
52     * Network IRQ distribution for c3620/c3640
53     *
54     *  Slot 0 | 3620/3640: reg 0x20001 | 3660: reg 0x20010, offset 0
55     *  Slot 1 | 3620/3640: reg 0x20000 | 3660: reg 0x10010, offset 24
56     *  Slot 2 | 3640     : reg 0x20003 | 3660: reg 0x10010, offset 16
57     *  Slot 3 | 3640     : reg 0x20002 | 3660: reg 0x10010, offset 28
58     *  Slot 4 | 3620/3640: N/A         | 3660: reg 0x10010, offset 20
59     *  Slot 5 | 3620/3640: N/A         | 3660: reg 0x10010, offset 8
60     *  Slot 6 | 3620/3640: N/A         | 3660: reg 0x10010, offset 0
61     */
62    static struct net_irq_distrib net_irq_dist[C3600_MAX_NM_BAYS] = {
63       { 16, 1, 0  },
64       { 24, 0, 24 },
65       {  0, 0, 16 },
66       {  8, 0, 28 },
67       { 32, 0, 20 },
68       { 32, 0, 8  },
69       { 32, 0, 0  },
70    };
71    
72  /* IO FPGA structure */  /* IO FPGA structure */
73  struct iofpga_data {  struct c3600_iofpga_data {
74     vm_obj_t vm_obj;     vm_obj_t vm_obj;
75     struct vdevice dev;     struct vdevice dev;
76     c3600_t *router;     c3600_t *router;
77        
78     /*     /* Network IRQ status */
79      * Used to introduce a "delay" before clearing the network interrupt     m_uint32_t net_irq_status[2];
80      * 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;  
     
81     /* Slot select for EEPROM access */     /* Slot select for EEPROM access */
82     u_int eeprom_slot;     u_int eeprom_slot;
83    
# Line 67  struct iofpga_data { Line 88  struct iofpga_data {
88  };  };
89    
90  /* Mainboard EEPROM definition */  /* Mainboard EEPROM definition */
91  static const struct nmc93c46_eeprom_def eeprom_mb_def = {  static const struct nmc93cX6_eeprom_def eeprom_mb_def = {
92     EEPROM_MB_CLK, EEPROM_MB_CS,     EEPROM_MB_CLK, EEPROM_MB_CS,
93     EEPROM_MB_DIN, EEPROM_MB_DOUT,     EEPROM_MB_DIN, EEPROM_MB_DOUT,
94  };  };
95    
96  /* Mainboard EEPROM */  /* Mainboard EEPROM */
97  static const struct nmc93c46_group eeprom_mb_group = {  static const struct nmc93cX6_group eeprom_mb_group = {
98     1, 0, "Mainboard EEPROM", 0, { &eeprom_mb_def },     EEPROM_TYPE_NMC93C46, 1, 0, "Mainboard EEPROM", 0, { &eeprom_mb_def },
99  };  };
100    
101  /* NM EEPROM definition */  /* NM EEPROM definition */
102  static const struct nmc93c46_eeprom_def eeprom_nm_def = {  static const struct nmc93cX6_eeprom_def eeprom_nm_def = {
103     EEPROM_NM_CLK, EEPROM_NM_CS,     EEPROM_NM_CLK, EEPROM_NM_CS,
104     EEPROM_NM_DIN, EEPROM_NM_DOUT,     EEPROM_NM_DIN, EEPROM_NM_DOUT,
105  };  };
106    
107  /* NM EEPROM */  /* NM EEPROM */
108  static const struct nmc93c46_group eeprom_nm_group = {  static const struct nmc93cX6_group eeprom_nm_group = {
109     1, 0, "NM EEPROM", 0, { &eeprom_nm_def },     EEPROM_TYPE_NMC93C46, 1, 0, "NM EEPROM", 0, { &eeprom_nm_def },
110  };  };
111    
112  /* C3660 NM presence masks */  /* C3660 NM presence masks */
# Line 99  static const m_uint16_t c3660_nm_masks[6 Line 120  static const m_uint16_t c3660_nm_masks[6
120  };  };
121    
122  /* Select the current NM EEPROM */  /* Select the current NM EEPROM */
123  static void nm_eeprom_select(struct iofpga_data *d,u_int slot)  static void nm_eeprom_select(struct c3600_iofpga_data *d,u_int slot)
124  {  {
125     d->router->nm_eeprom_group.eeprom[0] = &d->router->nm_bay[slot].eeprom;     d->router->nm_eeprom_group.eeprom[0] = &d->router->nm_bay[slot].eeprom;
126  }  }
127    
128  /* Return the NM status register given the detected EEPROM (3620/3640) */  /* Return the NM status register given the detected EEPROM (3620/3640) */
129  static u_int nm_get_status_1(struct iofpga_data *d)  static u_int nm_get_status_1(struct c3600_iofpga_data *d)
130  {  {
131     u_int res = 0xFFFF;     u_int res = 0xFFFF;
132     int i;     int i;
# Line 119  static u_int nm_get_status_1(struct iofp Line 140  static u_int nm_get_status_1(struct iofp
140  }  }
141    
142  /* Return the NM status register given the detected EEPROM (3660) */  /* Return the NM status register given the detected EEPROM (3660) */
143  static u_int nm_get_status_2(struct iofpga_data *d,u_int pos)  static u_int nm_get_status_2(struct c3600_iofpga_data *d,u_int pos)
144  {  {
145     u_int res = 0xFFFF;     u_int res = 0xFFFF;
146     u_int start,end;     u_int start,end;
# Line 146  static u_int nm_get_status_2(struct iofp Line 167  static u_int nm_get_status_2(struct iofp
167     return(res);     return(res);
168  }  }
169    
170    /* Update network interrupt status */
171    static inline void
172    dev_c3620_c3640_iofpga_net_update_irq(struct c3600_iofpga_data *d)
173    {
174       if (d->net_irq_status[0]) {
175          vm_set_irq(d->router->vm,C3600_NETIO_IRQ);
176       } else {
177          vm_clear_irq(d->router->vm,C3600_NETIO_IRQ);
178       }
179    }
180    
181    static inline void
182    dev_c3660_iofpga_net_update_irq(struct c3600_iofpga_data *d)
183    {
184       if (d->net_irq_status[0] || d->net_irq_status[1]) {
185          vm_set_irq(d->router->vm,C3600_NETIO_IRQ);
186       } else {
187          vm_clear_irq(d->router->vm,C3600_NETIO_IRQ);
188       }
189    }
190    
191    /* Trigger a Network IRQ for the specified slot/port */
192    void dev_c3600_iofpga_net_set_irq(struct c3600_iofpga_data *d,
193                                      u_int slot,u_int port)
194    {
195       struct net_irq_distrib *irq_dist;
196    
197    #if DEBUG_NET_IRQ
198       vm_log(d->router->vm,"IO_FPGA","setting NetIRQ for slot %u port %u\n",
199              slot,port);
200    #endif
201    
202       irq_dist = &net_irq_dist[slot];
203    
204       switch(c3600_chassis_get_id(d->router)) {
205          case 3620:
206          case 3640:
207             d->net_irq_status[0] |= (1 << (irq_dist->c3620_c3640_offset + port));
208             dev_c3620_c3640_iofpga_net_update_irq(d);
209             break;
210          case 3660:
211             d->net_irq_status[irq_dist->c3660_reg] |=
212                (1 << (irq_dist->c3660_offset + port));
213             dev_c3660_iofpga_net_update_irq(d);
214             break;
215       }
216    }
217    
218    /* Clear a Network IRQ for the specified slot/port */
219    void dev_c3600_iofpga_net_clear_irq(struct c3600_iofpga_data *d,
220                                        u_int slot,u_int port)
221    {
222       struct net_irq_distrib *irq_dist;
223    
224    #if DEBUG_NET_IRQ
225       vm_log(d->router->vm,"IO_FPGA","clearing NetIRQ for slot %u port %u\n",
226              slot,port);
227    #endif
228    
229       irq_dist = &net_irq_dist[slot];
230    
231       switch(c3600_chassis_get_id(d->router)) {
232          case 3620:
233          case 3640:
234             d->net_irq_status[0] &= ~(1 << (irq_dist->c3620_c3640_offset + port));
235             dev_c3620_c3640_iofpga_net_update_irq(d);
236             break;
237          case 3660:
238             d->net_irq_status[irq_dist->c3660_reg] &=
239                ~(1 << (irq_dist->c3660_offset + port));
240             dev_c3660_iofpga_net_update_irq(d);
241             break;
242       }
243    }
244    
245  /*  /*
246   * dev_c3620_c3640_iofpga_access()   * dev_c3620_c3640_iofpga_access()
247   */   */
248  static void *  static void *
249  dev_c3620_c3640_iofpga_access(cpu_mips_t *cpu,struct vdevice *dev,  dev_c3620_c3640_iofpga_access(cpu_gen_t *cpu,struct vdevice *dev,
250                                m_uint32_t offset,u_int op_size,u_int op_type,                                m_uint32_t offset,u_int op_size,u_int op_type,
251                                m_uint64_t *data)                                m_uint64_t *data)
252  {  {
253     struct iofpga_data *d = dev->priv_data;     struct c3600_iofpga_data *d = dev->priv_data;
    u_int slot;  
254    
255     if (op_type == MTS_READ)     if (op_type == MTS_READ)
256        *data = 0x0;        *data = 0x0;
# Line 164  dev_c3620_c3640_iofpga_access(cpu_mips_t Line 259  dev_c3620_c3640_iofpga_access(cpu_mips_t
259     if (offset != 0x0c) {     if (offset != 0x0c) {
260        if (op_type == MTS_READ) {        if (op_type == MTS_READ) {
261           cpu_log(cpu,"IO_FPGA","reading reg 0x%x at pc=0x%llx (size=%u)\n",           cpu_log(cpu,"IO_FPGA","reading reg 0x%x at pc=0x%llx (size=%u)\n",
262                   offset,cpu->pc,op_size);                   offset,cpu_get_pc(cpu),op_size);
263        } else {        } else {
264           cpu_log(cpu,"IO_FPGA",           cpu_log(cpu,"IO_FPGA",
265                   "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",
266                   offset,cpu->pc,*data,op_size);                   offset,cpu_get_pc(cpu),*data,op_size);
267        }        }
268     }     }
269  #endif  #endif
# Line 196  dev_c3620_c3640_iofpga_access(cpu_mips_t Line 291  dev_c3620_c3640_iofpga_access(cpu_mips_t
291        /* Mainboard EEPROM */        /* Mainboard EEPROM */
292        case 0x0000e:        case 0x0000e:
293           if (op_type == MTS_WRITE)           if (op_type == MTS_WRITE)
294              nmc93c46_write(&d->router->mb_eeprom_group,(u_int)(*data));              nmc93cX6_write(&d->router->mb_eeprom_group,(u_int)(*data));
295           else           else
296              *data = nmc93c46_read(&d->router->mb_eeprom_group);              *data = nmc93cX6_read(&d->router->mb_eeprom_group);
297           break;           break;
298    
299        case 0x10004:  /* ??? OIR control ??? */        case 0x10004:  /* ??? OIR control ??? */
# Line 230  dev_c3620_c3640_iofpga_access(cpu_mips_t Line 325  dev_c3620_c3640_iofpga_access(cpu_mips_t
325           if (op_type == MTS_WRITE) {           if (op_type == MTS_WRITE) {
326              d->eeprom_slot = *data & 0x03;              d->eeprom_slot = *data & 0x03;
327              nm_eeprom_select(d,d->eeprom_slot);              nm_eeprom_select(d,d->eeprom_slot);
328              nmc93c46_write(&d->router->nm_eeprom_group,*data);              nmc93cX6_write(&d->router->nm_eeprom_group,*data);
329           } else {           } else {
330              *data = nmc93c46_read(&d->router->nm_eeprom_group);              *data = nmc93cX6_read(&d->router->nm_eeprom_group);
331           }           }
332           break;           break;
333    
334        /* Network interrupt status */        /* Network interrupt status */
335        case 0x20000:        case 0x20000:   /* slot 1 */
       case 0x20001:  
       case 0x20002:  
       case 0x20003:  
          /* XXX This doesn't seem to be correct (at least on 3620) */  
          slot = offset - 0x20000;  
   
336           if (op_type == MTS_READ)           if (op_type == MTS_READ)
337              *data = 0xFF;              *data = d->net_irq_status[0] >> 24;
338             break;
339           if (++d->net_irq_clearing_count == C3600_NET_IRQ_CLEARING_DELAY) {        case 0x20001:   /* slot 0 */
340              vm_clear_irq(d->router->vm,C3600_NETIO_IRQ);           if (op_type == MTS_READ)
341              d->net_irq_clearing_count = 0;              *data = d->net_irq_status[0] >> 16;
342           }           break;
343          case 0x20002:   /* slot 3 */
344             if (op_type == MTS_READ)
345                *data = d->net_irq_status[0] >> 8;
346             break;
347          case 0x20003:   /* slot 2 */
348             if (op_type == MTS_READ)
349                *data = d->net_irq_status[0];
350           break;           break;
351    
352        /*        /*
# Line 339  dev_c3620_c3640_iofpga_access(cpu_mips_t Line 435  dev_c3620_c3640_iofpga_access(cpu_mips_t
435           if (op_type == MTS_READ) {           if (op_type == MTS_READ) {
436              cpu_log(cpu,"IO_FPGA",              cpu_log(cpu,"IO_FPGA",
437                      "read from unknown addr 0x%x, pc=0x%llx (size=%u)\n",                      "read from unknown addr 0x%x, pc=0x%llx (size=%u)\n",
438                      offset,cpu->pc,op_size);                      offset,cpu_get_pc(cpu),op_size);
439           } else {           } else {
440              cpu_log(cpu,"IO_FPGA",              cpu_log(cpu,"IO_FPGA",
441                      "write to unknown addr 0x%x, value=0x%llx, "                      "write to unknown addr 0x%x, value=0x%llx, "
442                      "pc=0x%llx (size=%u)\n",offset,*data,cpu->pc,op_size);                      "pc=0x%llx (size=%u)\n",
443                        offset,*data,cpu_get_pc(cpu),op_size);
444           }           }
445  #endif  #endif
446     }     }
# Line 355  dev_c3620_c3640_iofpga_access(cpu_mips_t Line 452  dev_c3620_c3640_iofpga_access(cpu_mips_t
452   * dev_c3660_iofpga_access()   * dev_c3660_iofpga_access()
453   */   */
454  static void *  static void *
455  dev_c3660_iofpga_access(cpu_mips_t *cpu,struct vdevice *dev,  dev_c3660_iofpga_access(cpu_gen_t *cpu,struct vdevice *dev,
456                          m_uint32_t offset,u_int op_size,u_int op_type,                          m_uint32_t offset,u_int op_size,u_int op_type,
457                          m_uint64_t *data)                          m_uint64_t *data)
458  {  {
459     struct iofpga_data *d = dev->priv_data;     struct c3600_iofpga_data *d = dev->priv_data;
460     u_int slot;     u_int slot;
461    
462     if (op_type == MTS_READ)     if (op_type == MTS_READ)
# Line 369  dev_c3660_iofpga_access(cpu_mips_t *cpu, Line 466  dev_c3660_iofpga_access(cpu_mips_t *cpu,
466     if (offset != 0x0c) {     if (offset != 0x0c) {
467        if (op_type == MTS_READ) {        if (op_type == MTS_READ) {
468           cpu_log(cpu,"IO_FPGA","reading reg 0x%x at pc=0x%llx (size=%u)\n",           cpu_log(cpu,"IO_FPGA","reading reg 0x%x at pc=0x%llx (size=%u)\n",
469                   offset,cpu->pc,op_size);                   offset,cpu_get_pc(cpu),op_size);
470        } else {        } else {
471           cpu_log(cpu,"IO_FPGA",           cpu_log(cpu,"IO_FPGA",
472                   "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",
473                   offset,cpu->pc,*data,op_size);                   offset,cpu_get_pc(cpu),*data,op_size);
474        }        }
475     }     }
476  #endif  #endif
# Line 460  dev_c3660_iofpga_access(cpu_mips_t *cpu, Line 557  dev_c3660_iofpga_access(cpu_mips_t *cpu,
557         */         */
558        case 0x10000:        case 0x10000:
559           if (op_type == MTS_WRITE)           if (op_type == MTS_WRITE)
560              nmc93c46_write(&d->router->mb_eeprom_group,(u_int)(*data));              nmc93cX6_write(&d->router->mb_eeprom_group,(u_int)(*data));
561           else           else
562              *data = nmc93c46_read(&d->router->mb_eeprom_group) | 0x80;              *data = nmc93cX6_read(&d->router->mb_eeprom_group) | 0x80;
563           break;           break;
564    
565        /* NM EEPROMs - slots 1 to 6 */        /* NM EEPROMs - slots 1 to 6 */
# Line 475  dev_c3660_iofpga_access(cpu_mips_t *cpu, Line 572  dev_c3660_iofpga_access(cpu_mips_t *cpu,
572           slot = (offset - 0x1000a) + 1;           slot = (offset - 0x1000a) + 1;
573    
574           if (op_type == MTS_WRITE) {           if (op_type == MTS_WRITE) {
575              nmc93c46_write(&d->router->c3660_nm_eeprom_group[slot],              nmc93cX6_write(&d->router->c3660_nm_eeprom_group[slot],
576                             (u_int)(*data));                             (u_int)(*data));
577           } else {           } else {
578              *data = nmc93c46_read(&d->router->c3660_nm_eeprom_group[slot]);              *data = nmc93cX6_read(&d->router->c3660_nm_eeprom_group[slot]);
579           }           }
580           break;           break;
581    
582        /* NM EEPROM - slot 0 */        /* NM EEPROM - slot 0 */
583        case 0x20006:        case 0x20006:
584           if (op_type == MTS_WRITE) {           if (op_type == MTS_WRITE) {
585              nmc93c46_write(&d->router->c3660_nm_eeprom_group[0],              nmc93cX6_write(&d->router->c3660_nm_eeprom_group[0],
586                             (u_int)(*data));                             (u_int)(*data));
587           } else {           } else {
588              *data = nmc93c46_read(&d->router->c3660_nm_eeprom_group[0]);              *data = nmc93cX6_read(&d->router->c3660_nm_eeprom_group[0]);
589           }           }
590           break;           break;
591    
# Line 535  dev_c3660_iofpga_access(cpu_mips_t *cpu, Line 632  dev_c3660_iofpga_access(cpu_mips_t *cpu,
632         */         */
633        case 0x10010:        case 0x10010:
634           if (op_type == MTS_READ)           if (op_type == MTS_READ)
635              *data = 0xFFFFFFFF;              *data = d->net_irq_status[0];
          vm_clear_irq(d->router->vm,C3600_NETIO_IRQ);  
636           break;           break;
637    
638        /*        /*
# Line 548  dev_c3660_iofpga_access(cpu_mips_t *cpu, Line 644  dev_c3660_iofpga_access(cpu_mips_t *cpu,
644         */                 */        
645        case 0x20010:        case 0x20010:
646           if (op_type == MTS_READ)           if (op_type == MTS_READ)
647              *data = 0x0F;              *data = d->net_irq_status[1];
648           break;           break;
649    
650        /*        /*
# Line 583  dev_c3660_iofpga_access(cpu_mips_t *cpu, Line 679  dev_c3660_iofpga_access(cpu_mips_t *cpu,
679           if (op_type == MTS_READ) {           if (op_type == MTS_READ) {
680              cpu_log(cpu,"IO_FPGA",              cpu_log(cpu,"IO_FPGA",
681                      "read from unknown addr 0x%x, pc=0x%llx (size=%u)\n",                      "read from unknown addr 0x%x, pc=0x%llx (size=%u)\n",
682                      offset,cpu->pc,op_size);                      offset,cpu_get_pc(cpu),op_size);
683           } else {           } else {
684              cpu_log(cpu,"IO_FPGA",              cpu_log(cpu,"IO_FPGA",
685                      "write to unknown addr 0x%x, value=0x%llx, "                      "write to unknown addr 0x%x, value=0x%llx, "
686                      "pc=0x%llx (size=%u)\n",offset,*data,cpu->pc,op_size);                      "pc=0x%llx (size=%u)\n",
687                        offset,*data,cpu_get_pc(cpu),op_size);
688           }           }
689  #endif  #endif
690     }     }
# Line 618  void c3600_init_eeprom_groups(c3600_t *r Line 715  void c3600_init_eeprom_groups(c3600_t *r
715  }  }
716    
717  /* Shutdown the IO FPGA device */  /* Shutdown the IO FPGA device */
718  void dev_c3600_iofpga_shutdown(vm_instance_t *vm,struct iofpga_data *d)  static void
719    dev_c3600_iofpga_shutdown(vm_instance_t *vm,struct c3600_iofpga_data *d)
720  {  {
721     if (d != NULL) {     if (d != NULL) {
722        /* Remove the device */        /* Remove the device */
# Line 635  void dev_c3600_iofpga_shutdown(vm_instan Line 733  void dev_c3600_iofpga_shutdown(vm_instan
733  int dev_c3600_iofpga_init(c3600_t *router,m_uint64_t paddr,m_uint32_t len)  int dev_c3600_iofpga_init(c3600_t *router,m_uint64_t paddr,m_uint32_t len)
734  {  {
735     vm_instance_t *vm = router->vm;     vm_instance_t *vm = router->vm;
736     struct iofpga_data *d;     struct c3600_iofpga_data *d;
737    
738     /* Allocate private data structure */     /* Allocate private data structure */
739     if (!(d = malloc(sizeof(*d)))) {     if (!(d = malloc(sizeof(*d)))) {

Legend:
Removed from v.6  
changed lines
  Added in v.8

  ViewVC Help
Powered by ViewVC 1.1.26