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

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

upstream/dynamips-0.2.7-RC1/dev_c3600_iofpga.c revision 7 by dpavlin, Sat Oct 6 16:23:47 2007 UTC trunk/dev_c3600_iofpga.c revision 12 by dpavlin, Sat Oct 6 16:45:40 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 21  Line 21 
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 40  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 68  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,
99       EEPROM_DORD_NORMAL,
100       EEPROM_DOUT_HIGH,
101       EEPROM_DEBUG_DISABLED,
102       "Mainboard EEPROM",
103       { &eeprom_mb_def },
104  };  };
105    
106  /* NM EEPROM definition */  /* NM EEPROM definition */
107  static const struct nmc93c46_eeprom_def eeprom_nm_def = {  static const struct nmc93cX6_eeprom_def eeprom_nm_def = {
108     EEPROM_NM_CLK, EEPROM_NM_CS,     EEPROM_NM_CLK, EEPROM_NM_CS,
109     EEPROM_NM_DIN, EEPROM_NM_DOUT,     EEPROM_NM_DIN, EEPROM_NM_DOUT,
110  };  };
111    
112  /* NM EEPROM */  /* NM EEPROM */
113  static const struct nmc93c46_group eeprom_nm_group = {  static const struct nmc93cX6_group eeprom_nm_group = {
114     1, 0, "NM EEPROM", 0, { &eeprom_nm_def },     EEPROM_TYPE_NMC93C46, 1, 0,
115       EEPROM_DORD_NORMAL,
116       EEPROM_DOUT_HIGH,
117       EEPROM_DEBUG_DISABLED,
118       "NM EEPROM",
119       { &eeprom_nm_def },
120  };  };
121    
122  /* C3660 NM presence masks */  /* C3660 NM presence masks */
# Line 100  static const m_uint16_t c3660_nm_masks[6 Line 130  static const m_uint16_t c3660_nm_masks[6
130  };  };
131    
132  /* Select the current NM EEPROM */  /* Select the current NM EEPROM */
133  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)
134  {  {
135     d->router->nm_eeprom_group.eeprom[0] = &d->router->nm_bay[slot].eeprom;     struct cisco_eeprom *eeprom = NULL;
136       struct cisco_card *card;
137    
138       card = vm_slot_get_card_ptr(d->router->vm,slot);
139    
140       if (card != NULL)
141          eeprom = &card->eeprom;
142    
143       d->router->nm_eeprom_group.eeprom[0] = eeprom;
144  }  }
145    
146  /* Return the NM status register given the detected EEPROM (3620/3640) */  /* Return the NM status register given the detected EEPROM (3620/3640) */
147  static u_int nm_get_status_1(struct iofpga_data *d)  static u_int nm_get_status_1(struct c3600_iofpga_data *d)
148  {  {
149     u_int res = 0xFFFF;     u_int res = 0xFFFF;
150     int i;     int i;
151    
152     for(i=0;i<4;i++) {     for(i=0;i<4;i++) {
153        if (c3600_nm_check_eeprom(d->router,i))        if (vm_slot_get_card_ptr(d->router->vm,i))
154           res &= ~(0x1111 << i);           res &= ~(0x1111 << i);
155     }     }
156        
# Line 120  static u_int nm_get_status_1(struct iofp Line 158  static u_int nm_get_status_1(struct iofp
158  }  }
159    
160  /* Return the NM status register given the detected EEPROM (3660) */  /* Return the NM status register given the detected EEPROM (3660) */
161  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)
162  {  {
163     u_int res = 0xFFFF;     u_int res = 0xFFFF;
164     u_int start,end;     u_int start,end;
# Line 140  static u_int nm_get_status_2(struct iofp Line 178  static u_int nm_get_status_2(struct iofp
178     }     }
179    
180     for(i=start;i<=end;i++) {     for(i=start;i<=end;i++) {
181        if (c3600_nm_check_eeprom(d->router,i))        if (vm_slot_get_card_ptr(d->router->vm,i))
182           res &= c3660_nm_masks[i-1];           res &= c3660_nm_masks[i-1];
183     }     }
184        
185     return(res);     return(res);
186  }  }
187    
188    /* Update network interrupt status */
189    static inline void
190    dev_c3620_c3640_iofpga_net_update_irq(struct c3600_iofpga_data *d)
191    {
192       if (d->net_irq_status[0]) {
193          vm_set_irq(d->router->vm,C3600_NETIO_IRQ);
194       } else {
195          vm_clear_irq(d->router->vm,C3600_NETIO_IRQ);
196       }
197    }
198    
199    static inline void
200    dev_c3660_iofpga_net_update_irq(struct c3600_iofpga_data *d)
201    {
202       if (d->net_irq_status[0] || d->net_irq_status[1]) {
203          vm_set_irq(d->router->vm,C3600_NETIO_IRQ);
204       } else {
205          vm_clear_irq(d->router->vm,C3600_NETIO_IRQ);
206       }
207    }
208    
209    /* Trigger a Network IRQ for the specified slot/port */
210    void dev_c3600_iofpga_net_set_irq(struct c3600_iofpga_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,"IO_FPGA","setting NetIRQ for slot %u port %u\n",
217              slot,port);
218    #endif
219    
220       irq_dist = &net_irq_dist[slot];
221    
222       switch(c3600_chassis_get_id(d->router)) {
223          case 3620:
224          case 3640:
225             d->net_irq_status[0] |= (1 << (irq_dist->c3620_c3640_offset + port));
226             dev_c3620_c3640_iofpga_net_update_irq(d);
227             break;
228          case 3660:
229             d->net_irq_status[irq_dist->c3660_reg] |=
230                (1 << (irq_dist->c3660_offset + port));
231             dev_c3660_iofpga_net_update_irq(d);
232             break;
233       }
234    }
235    
236    /* Clear a Network IRQ for the specified slot/port */
237    void dev_c3600_iofpga_net_clear_irq(struct c3600_iofpga_data *d,
238                                        u_int slot,u_int port)
239    {
240       struct net_irq_distrib *irq_dist;
241    
242    #if DEBUG_NET_IRQ
243       vm_log(d->router->vm,"IO_FPGA","clearing NetIRQ for slot %u port %u\n",
244              slot,port);
245    #endif
246    
247       irq_dist = &net_irq_dist[slot];
248    
249       switch(c3600_chassis_get_id(d->router)) {
250          case 3620:
251          case 3640:
252             d->net_irq_status[0] &= ~(1 << (irq_dist->c3620_c3640_offset + port));
253             dev_c3620_c3640_iofpga_net_update_irq(d);
254             break;
255          case 3660:
256             d->net_irq_status[irq_dist->c3660_reg] &=
257                ~(1 << (irq_dist->c3660_offset + port));
258             dev_c3660_iofpga_net_update_irq(d);
259             break;
260       }
261    }
262    
263  /*  /*
264   * dev_c3620_c3640_iofpga_access()   * dev_c3620_c3640_iofpga_access()
265   */   */
# Line 155  dev_c3620_c3640_iofpga_access(cpu_gen_t Line 268  dev_c3620_c3640_iofpga_access(cpu_gen_t
268                                m_uint32_t offset,u_int op_size,u_int op_type,                                m_uint32_t offset,u_int op_size,u_int op_type,
269                                m_uint64_t *data)                                m_uint64_t *data)
270  {  {
271     struct iofpga_data *d = dev->priv_data;     struct c3600_iofpga_data *d = dev->priv_data;
    u_int slot;  
272    
273     if (op_type == MTS_READ)     if (op_type == MTS_READ)
274        *data = 0x0;        *data = 0x0;
# Line 197  dev_c3620_c3640_iofpga_access(cpu_gen_t Line 309  dev_c3620_c3640_iofpga_access(cpu_gen_t
309        /* Mainboard EEPROM */        /* Mainboard EEPROM */
310        case 0x0000e:        case 0x0000e:
311           if (op_type == MTS_WRITE)           if (op_type == MTS_WRITE)
312              nmc93c46_write(&d->router->mb_eeprom_group,(u_int)(*data));              nmc93cX6_write(&d->router->mb_eeprom_group,(u_int)(*data));
313           else           else
314              *data = nmc93c46_read(&d->router->mb_eeprom_group);              *data = nmc93cX6_read(&d->router->mb_eeprom_group);
315           break;           break;
316    
317        case 0x10004:  /* ??? OIR control ??? */        case 0x10004:  /* ??? OIR control ??? */
# Line 231  dev_c3620_c3640_iofpga_access(cpu_gen_t Line 343  dev_c3620_c3640_iofpga_access(cpu_gen_t
343           if (op_type == MTS_WRITE) {           if (op_type == MTS_WRITE) {
344              d->eeprom_slot = *data & 0x03;              d->eeprom_slot = *data & 0x03;
345              nm_eeprom_select(d,d->eeprom_slot);              nm_eeprom_select(d,d->eeprom_slot);
346              nmc93c46_write(&d->router->nm_eeprom_group,*data);              nmc93cX6_write(&d->router->nm_eeprom_group,*data);
347           } else {           } else {
348              *data = nmc93c46_read(&d->router->nm_eeprom_group);              *data = nmc93cX6_read(&d->router->nm_eeprom_group);
349           }           }
350           break;           break;
351    
352        /* Network interrupt status */        /* Network interrupt status */
353        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;  
   
354           if (op_type == MTS_READ)           if (op_type == MTS_READ)
355              *data = 0xFF;              *data = d->net_irq_status[0] >> 24;
356             break;
357           if (++d->net_irq_clearing_count == C3600_NET_IRQ_CLEARING_DELAY) {        case 0x20001:   /* slot 0 */
358              vm_clear_irq(d->router->vm,C3600_NETIO_IRQ);           if (op_type == MTS_READ)
359              d->net_irq_clearing_count = 0;              *data = d->net_irq_status[0] >> 16;
360           }           break;
361          case 0x20002:   /* slot 3 */
362             if (op_type == MTS_READ)
363                *data = d->net_irq_status[0] >> 8;
364             break;
365          case 0x20003:   /* slot 2 */
366             if (op_type == MTS_READ)
367                *data = d->net_irq_status[0];
368           break;           break;
369    
370        /*        /*
# Line 361  dev_c3660_iofpga_access(cpu_gen_t *cpu,s Line 474  dev_c3660_iofpga_access(cpu_gen_t *cpu,s
474                          m_uint32_t offset,u_int op_size,u_int op_type,                          m_uint32_t offset,u_int op_size,u_int op_type,
475                          m_uint64_t *data)                          m_uint64_t *data)
476  {  {
477     struct iofpga_data *d = dev->priv_data;     struct c3600_iofpga_data *d = dev->priv_data;
478     u_int slot;     u_int slot;
479    
480     if (op_type == MTS_READ)     if (op_type == MTS_READ)
# Line 462  dev_c3660_iofpga_access(cpu_gen_t *cpu,s Line 575  dev_c3660_iofpga_access(cpu_gen_t *cpu,s
575         */         */
576        case 0x10000:        case 0x10000:
577           if (op_type == MTS_WRITE)           if (op_type == MTS_WRITE)
578              nmc93c46_write(&d->router->mb_eeprom_group,(u_int)(*data));              nmc93cX6_write(&d->router->mb_eeprom_group,(u_int)(*data));
579           else           else
580              *data = nmc93c46_read(&d->router->mb_eeprom_group) | 0x80;              *data = nmc93cX6_read(&d->router->mb_eeprom_group) | 0x80;
581           break;           break;
582    
583        /* NM EEPROMs - slots 1 to 6 */        /* NM EEPROMs - slots 1 to 6 */
# Line 477  dev_c3660_iofpga_access(cpu_gen_t *cpu,s Line 590  dev_c3660_iofpga_access(cpu_gen_t *cpu,s
590           slot = (offset - 0x1000a) + 1;           slot = (offset - 0x1000a) + 1;
591    
592           if (op_type == MTS_WRITE) {           if (op_type == MTS_WRITE) {
593              nmc93c46_write(&d->router->c3660_nm_eeprom_group[slot],              nmc93cX6_write(&d->router->c3660_nm_eeprom_group[slot],
594                             (u_int)(*data));                             (u_int)(*data));
595           } else {           } else {
596              *data = nmc93c46_read(&d->router->c3660_nm_eeprom_group[slot]);              *data = nmc93cX6_read(&d->router->c3660_nm_eeprom_group[slot]);
597           }           }
598           break;           break;
599    
600        /* NM EEPROM - slot 0 */        /* NM EEPROM - slot 0 */
601        case 0x20006:        case 0x20006:
602           if (op_type == MTS_WRITE) {           if (op_type == MTS_WRITE) {
603              nmc93c46_write(&d->router->c3660_nm_eeprom_group[0],              nmc93cX6_write(&d->router->c3660_nm_eeprom_group[0],
604                             (u_int)(*data));                             (u_int)(*data));
605           } else {           } else {
606              *data = nmc93c46_read(&d->router->c3660_nm_eeprom_group[0]);              *data = nmc93cX6_read(&d->router->c3660_nm_eeprom_group[0]);
607           }           }
608           break;           break;
609    
# Line 537  dev_c3660_iofpga_access(cpu_gen_t *cpu,s Line 650  dev_c3660_iofpga_access(cpu_gen_t *cpu,s
650         */         */
651        case 0x10010:        case 0x10010:
652           if (op_type == MTS_READ)           if (op_type == MTS_READ)
653              *data = 0xFFFFFFFF;              *data = d->net_irq_status[0];
          vm_clear_irq(d->router->vm,C3600_NETIO_IRQ);  
654           break;           break;
655    
656        /*        /*
# Line 550  dev_c3660_iofpga_access(cpu_gen_t *cpu,s Line 662  dev_c3660_iofpga_access(cpu_gen_t *cpu,s
662         */                 */        
663        case 0x20010:        case 0x20010:
664           if (op_type == MTS_READ)           if (op_type == MTS_READ)
665              *data = 0x0F;              *data = d->net_irq_status[1];
666           break;           break;
667    
668        /*        /*
# Line 616  void c3600_init_eeprom_groups(c3600_t *r Line 728  void c3600_init_eeprom_groups(c3600_t *r
728     /* Initialize NM EEPROM for 3660 */     /* Initialize NM EEPROM for 3660 */
729     for(i=0;i<C3600_MAX_NM_BAYS;i++) {     for(i=0;i<C3600_MAX_NM_BAYS;i++) {
730        router->c3660_nm_eeprom_group[i] = eeprom_nm_group;        router->c3660_nm_eeprom_group[i] = eeprom_nm_group;
731        router->c3660_nm_eeprom_group[i].eeprom[0] = &router->nm_bay[i].eeprom;        router->c3660_nm_eeprom_group[i].eeprom[0] = NULL;
732     }     }
733  }  }
734    
735  /* Shutdown the IO FPGA device */  /* Shutdown the IO FPGA device */
736  void dev_c3600_iofpga_shutdown(vm_instance_t *vm,struct iofpga_data *d)  static void
737    dev_c3600_iofpga_shutdown(vm_instance_t *vm,struct c3600_iofpga_data *d)
738  {  {
739     if (d != NULL) {     if (d != NULL) {
740        /* Remove the device */        /* Remove the device */
# Line 638  void dev_c3600_iofpga_shutdown(vm_instan Line 751  void dev_c3600_iofpga_shutdown(vm_instan
751  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)
752  {  {
753     vm_instance_t *vm = router->vm;     vm_instance_t *vm = router->vm;
754     struct iofpga_data *d;     struct c3600_iofpga_data *d;
755    
756     /* Allocate private data structure */     /* Allocate private data structure */
757     if (!(d = malloc(sizeof(*d)))) {     if (!(d = malloc(sizeof(*d)))) {

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

  ViewVC Help
Powered by ViewVC 1.1.26