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

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

upstream/dynamips-0.2.6-RC3/dev_c3745_iofpga.c revision 4 by dpavlin, Sat Oct 6 16:06:49 2007 UTC upstream/dynamips-0.2.8-RC1/dev_c3745_iofpga.c revision 11 by dpavlin, Sat Oct 6 16:33:40 2007 UTC
# Line 1  Line 1 
1  /*  /*
2   * Cisco 3745 simulation platform.   * Cisco 3745 simulation platform.
3   * Copyright (c) 2006 Christophe Fillot (cf@utc.fr)   * Copyright (c) 2006 Christophe Fillot (cf@utc.fr)
  *  
  * This is very similar to c2691.  
4   */   */
5    
6  #include <stdio.h>  #include <stdio.h>
# Line 15  Line 13 
13  #include <pthread.h>  #include <pthread.h>
14    
15  #include "ptask.h"  #include "ptask.h"
16  #include "mips64.h"  #include "cpu.h"
17    #include "vm.h"
18  #include "dynamips.h"  #include "dynamips.h"
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_c3745.h"  #include "dev_c3745.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 Motherboard EEPROM (0x00) */  /* Definitions for Motherboard EEPROM (0x00) */
31  #define EEPROM_MB_DOUT  3  #define EEPROM_MB_DOUT  3
# Line 51  Line 51 
51  #define EEPROM_NM_CLK   2  #define EEPROM_NM_CLK   2
52  #define EEPROM_NM_CS    4  #define EEPROM_NM_CS    4
53    
54  #define C3745_NET_IRQ_CLEARING_DELAY  16  /* Network IRQ distribution */
55    struct net_irq_distrib  {
56       u_int reg;
57       u_int offset;
58    };
59    
60    static struct net_irq_distrib net_irq_dist[C3745_MAX_NM_BAYS] = {
61       { 0,  0  },  /* Slot 0: reg 0x20, 0x00XX */
62       { 1,  0  },  /* Slot 1: reg 0x22, 0x000X */
63       { 1,  4  },  /* Slot 2: reg 0x22, 0x00X0 */
64       { 1,  8  },  /* Slot 3: reg 0x22, 0x0X00 */
65       { 1,  12 },  /* Slot 4: reg 0x22, 0xX000 */
66    };
67    
68  /* IO FPGA structure */  /* IO FPGA structure */
69  struct iofpga_data {  struct c3745_iofpga_data {
70     vm_obj_t vm_obj;     vm_obj_t vm_obj;
71     struct vdevice dev;     struct vdevice dev;
72     c3745_t *router;     c3745_t *router;
73        
74     /*     /* Network IRQ status */
75      * Used to introduce a "delay" before clearing the network interrupt     m_uint16_t net_irq_status[2];
     * 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;  
76    
77     /* Interrupt mask */     /* Interrupt mask */
78     m_uint16_t intr_mask,io_mask2;     m_uint16_t intr_mask,io_mask2;
79    
80     /* EEPROM select */     /* EEPROM select */
81     u_int eeprom_select;     u_int eeprom_select;
82    
83       /* WIC select */
84       u_int wic_select;
85       u_int wic_cmd_pos;
86       u_int wic_cmd_valid;
87       m_uint16_t wic_cmd[2];
88  };  };
89    
90  /* Motherboard EEPROM definition */  /* Motherboard 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  /* I/O board EEPROM definition */  /* I/O board EEPROM definition */
97  static const struct nmc93c46_eeprom_def eeprom_io_def = {  static const struct nmc93cX6_eeprom_def eeprom_io_def = {
98     EEPROM_IO_CLK, EEPROM_IO_CS,     EEPROM_IO_CLK, EEPROM_IO_CS,
99     EEPROM_IO_DIN, EEPROM_IO_DOUT,     EEPROM_IO_DIN, EEPROM_IO_DOUT,
100  };  };
101    
102  /* Midplane EEPROM definition */  /* Midplane EEPROM definition */
103  static const struct nmc93c46_eeprom_def eeprom_mp_def = {  static const struct nmc93cX6_eeprom_def eeprom_mp_def = {
104     EEPROM_MP_CLK, EEPROM_MP_CS,     EEPROM_MP_CLK, EEPROM_MP_CS,
105     EEPROM_MP_DIN, EEPROM_MP_DOUT,     EEPROM_MP_DIN, EEPROM_MP_DOUT,
106  };  };
107    
108  /* System EEPROM group */  /* System EEPROM group */
109  static const struct nmc93c46_group eeprom_sys_group = {  static const struct nmc93cX6_group eeprom_sys_group = {
110     3, 0, "System EEPROM", 0,     EEPROM_TYPE_NMC93C46, 3, 0,
111       EEPROM_DORD_NORMAL,
112       EEPROM_DOUT_HIGH,
113       EEPROM_DEBUG_DISABLED,
114       "System EEPROM",
115     { &eeprom_mb_def, &eeprom_io_def, &eeprom_mp_def },     { &eeprom_mb_def, &eeprom_io_def, &eeprom_mp_def },
116  };  };
117    
118  /* NM EEPROM definition */  /* NM EEPROM definition */
119  static const struct nmc93c46_eeprom_def eeprom_nm_def = {  static const struct nmc93cX6_eeprom_def eeprom_nm_def = {
120     EEPROM_NM_CLK, EEPROM_NM_CS,     EEPROM_NM_CLK, EEPROM_NM_CS,
121     EEPROM_NM_DIN, EEPROM_NM_DOUT,     EEPROM_NM_DIN, EEPROM_NM_DOUT,
122  };  };
123    
124  /* NM EEPROM */  /* NM EEPROM */
125  static const struct nmc93c46_group eeprom_nm_group = {  static const struct nmc93cX6_group eeprom_nm_group = {
126     1, 0, "NM EEPROM", 0, { &eeprom_nm_def },     EEPROM_TYPE_NMC93C46, 1, 0,
127       EEPROM_DORD_NORMAL,
128       EEPROM_DOUT_HIGH,
129       EEPROM_DEBUG_DISABLED,
130       "NM EEPROM",
131       { &eeprom_nm_def },
132  };  };
133    
134    /* Update network interrupt status */
135    static inline void dev_c3745_iofpga_net_update_irq(struct c3745_iofpga_data *d)
136    {
137       if ((d->net_irq_status[0] != 0xFFFF) || (d->net_irq_status[1] != 0xFFFF)) {
138          vm_set_irq(d->router->vm,C3745_NETIO_IRQ);
139       } else {
140          vm_clear_irq(d->router->vm,C3745_NETIO_IRQ);
141       }
142    }
143    
144    /* Trigger a Network IRQ for the specified slot/port */
145    void dev_c3745_iofpga_net_set_irq(struct c3745_iofpga_data *d,
146                                      u_int slot,u_int port)
147    {
148       struct net_irq_distrib *irq_dist;
149    
150    #if DEBUG_NET_IRQ
151       vm_log(d->router->vm,"IO_FPGA","setting NetIRQ for slot %u port %u\n",
152              slot,port);
153    #endif
154       irq_dist = &net_irq_dist[slot];
155       d->net_irq_status[irq_dist->reg] &= ~(1 << (irq_dist->offset + port));
156       dev_c3745_iofpga_net_update_irq(d);
157    }
158    
159    /* Clear a Network IRQ for the specified slot/port */
160    void dev_c3745_iofpga_net_clear_irq(struct c3745_iofpga_data *d,
161                                        u_int slot,u_int port)
162    {
163       struct net_irq_distrib *irq_dist;
164    
165    #if DEBUG_NET_IRQ
166       vm_log(d->router->vm,"IO_FPGA","clearing NetIRQ for slot %u port %u\n",
167              slot,port);
168    #endif
169       irq_dist = &net_irq_dist[slot];
170       d->net_irq_status[irq_dist->reg] |= (1 << (irq_dist->offset + port));
171       dev_c3745_iofpga_net_update_irq(d);
172    }
173    
174    /* Read a WIC EEPROM */
175    static m_uint16_t dev_c3745_read_wic_eeprom(struct c3745_iofpga_data *d)
176    {  
177       struct cisco_eeprom *eeprom;
178       u_int wic_port;
179       u_int eeprom_offset;
180       m_uint8_t val[2];
181    
182       switch(d->wic_select) {
183          case 0x1700:
184             wic_port = 0x10;
185             break;
186          case 0x1D00:
187             wic_port = 0x20;
188             break;
189          case 0x3500:
190             wic_port = 0x30;
191             break;
192          default:
193             wic_port = 0;
194       }
195    
196       /* No WIC in slot or no EEPROM: fake an empty EEPROM */
197       if (!wic_port || !(eeprom = vm_slot_get_eeprom(d->router->vm,0,wic_port)))
198          return(0xFFFF);
199    
200       /* EEPROM offset is in the lowest 6 bits */
201       eeprom_offset = d->wic_cmd[0] & 0x3F;
202    
203       cisco_eeprom_get_byte(eeprom,eeprom_offset,&val[0]);
204       cisco_eeprom_get_byte(eeprom,eeprom_offset+1,&val[1]);
205    
206       return(((m_uint16_t)val[0] << 8) | val[1]);
207    }
208    
209  /*  /*
210   * dev_c3745_iofpga_access()   * dev_c3745_iofpga_access()
211   */   */
212  static void *  static void *
213  dev_c3745_iofpga_access(cpu_mips_t *cpu,struct vdevice *dev,  dev_c3745_iofpga_access(cpu_gen_t *cpu,struct vdevice *dev,
214                          m_uint32_t offset,u_int op_size,u_int op_type,                          m_uint32_t offset,u_int op_size,u_int op_type,
215                          m_uint64_t *data)                          m_uint64_t *data)
216  {  {
217     struct iofpga_data *d = dev->priv_data;     struct c3745_iofpga_data *d = dev->priv_data;
218     u_int slot;     u_int slot;
219    
220     if (op_type == MTS_READ)     if (op_type == MTS_READ)
221        *data = 0x0;        *data = 0x0;
222      
223  #if DEBUG_ACCESS  #if DEBUG_ACCESS
224     if (op_type == MTS_READ) {     if (op_type == MTS_READ) {
225        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",
226                offset,cpu->pc,op_size);                offset,cpu_get_pc(cpu),op_size);
227     } else {     } else {
228        cpu_log(cpu,"IO_FPGA",        cpu_log(cpu,"IO_FPGA",
229                "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",
230                offset,cpu->pc,*data,op_size);                offset,cpu_get_pc(cpu),*data,op_size);
231     }     }
232  #endif  #endif
233    
# Line 190  dev_c3745_iofpga_access(cpu_mips_t *cpu, Line 285  dev_c3745_iofpga_access(cpu_mips_t *cpu,
285        /* System EEPROMs */        /* System EEPROMs */
286        case 0x00000e:        case 0x00000e:
287           if (op_type == MTS_WRITE)           if (op_type == MTS_WRITE)
288              nmc93c46_write(&d->router->sys_eeprom_group,(u_int)(*data));              nmc93cX6_write(&d->router->sys_eeprom_group,(u_int)(*data));
289           else           else
290              *data = nmc93c46_read(&d->router->sys_eeprom_group);              *data = nmc93cX6_read(&d->router->sys_eeprom_group);
291           break;           break;
292    
293        /*        /*
# Line 204  dev_c3745_iofpga_access(cpu_mips_t *cpu, Line 299  dev_c3745_iofpga_access(cpu_mips_t *cpu,
299         */         */
300        case 0x000020:        case 0x000020:
301           if (op_type == MTS_READ)           if (op_type == MTS_READ)
302              *data = 0xFFFE;              *data = d->net_irq_status[0];
303           break;           break;
304    
305        /*        /*
# Line 217  dev_c3745_iofpga_access(cpu_mips_t *cpu, Line 312  dev_c3745_iofpga_access(cpu_mips_t *cpu,
312         */         */
313        case 0x000022:        case 0x000022:
314           if (op_type == MTS_READ)           if (op_type == MTS_READ)
315              *data = 0x0000;              *data = d->net_irq_status[1];
          vm_clear_irq(d->router->vm,C3745_NETIO_IRQ);  
316           break;           break;
317    
318        /*        /*
# Line 248  dev_c3745_iofpga_access(cpu_mips_t *cpu, Line 342  dev_c3745_iofpga_access(cpu_mips_t *cpu,
342           slot = (offset - 0x000040) >> 1;           slot = (offset - 0x000040) >> 1;
343    
344           if (op_type == MTS_WRITE)           if (op_type == MTS_WRITE)
345              nmc93c46_write(&d->router->nm_eeprom_group[slot],(u_int)(*data));              nmc93cX6_write(&d->router->nm_eeprom_group[slot],(u_int)(*data));
346           else           else
347              *data = nmc93c46_read(&d->router->nm_eeprom_group[slot]);              *data = nmc93cX6_read(&d->router->nm_eeprom_group[slot]);
348           break;           break;
349    
350        /* AIM slot 0 EEPROM */        /* AIM slot 0 EEPROM */
# Line 277  dev_c3745_iofpga_access(cpu_mips_t *cpu, Line 371  dev_c3745_iofpga_access(cpu_mips_t *cpu,
371           if (op_type == MTS_READ) {           if (op_type == MTS_READ) {
372              *data = 0xFFFF;              *data = 0xFFFF;
373                            
374              if (c3745_nm_check_eeprom(d->router,1))              if (vm_slot_get_card_ptr(d->router->vm,1))
375                 *data &= ~0x0100;                 *data &= ~0x0100;
376    
377              if (c3745_nm_check_eeprom(d->router,2))              if (vm_slot_get_card_ptr(d->router->vm,2))
378                 *data &= ~0x0001;                 *data &= ~0x0001;
379    
380              if (c3745_nm_check_eeprom(d->router,3))              if (vm_slot_get_card_ptr(d->router->vm,3))
381                 *data &= ~0x1000;                 *data &= ~0x1000;
382    
383              if (c3745_nm_check_eeprom(d->router,4))              if (vm_slot_get_card_ptr(d->router->vm,4))
384                 *data &= ~0x0010;                 *data &= ~0x0010;
385           }           }
386           break;           break;
387    
388        /* VWIC/WIC related */        /*
389           * VWIC/WIC related
390           * Bits 0-2: WIC presence
391           */
392        case 0x100004:        case 0x100004:
393             if (op_type == MTS_READ) {
394               *data = 0xFFFF;
395    
396               /* check WIC 0 */
397                if (vm_slot_check_eeprom(d->router->vm,0,0x10))
398                   *data &= ~0x01;
399    
400                /* check WIC 1 */
401                if (vm_slot_check_eeprom(d->router->vm,0,0x20))
402                   *data &= ~0x02;
403    
404                /* check WIC 2 */
405                if (vm_slot_check_eeprom(d->router->vm,0,0x30))
406                   *data &= ~0x04;
407             } else {
408                d->wic_select = *data;
409             }
410             break;
411    
412        case 0x100006:        case 0x100006:
       case 0x100008:  
413           if (op_type == MTS_READ)           if (op_type == MTS_READ)
414              *data = 0xFFFF;              *data = 0x0004;
415             break;
416    
417          case 0x100008:
418             if (op_type == MTS_READ) {
419                if (d->wic_cmd_valid) {
420                   *data = dev_c3745_read_wic_eeprom(d);
421                   d->wic_cmd_valid = FALSE;
422                } else {
423                   *data = 0xFFFF;
424                }
425             } else {
426                /*
427                 * Store the EEPROM command (in 2 words).
428                 *
429                 * For a read, we have:
430                 *    Word 0: 0x180 (nmc93c46 READ) + offset (6-bits).
431                 *    Word 1: 0 (no data).
432                 */
433                d->wic_cmd[d->wic_cmd_pos++] = *data;
434                
435                if (d->wic_cmd_pos == 2) {
436                   d->wic_cmd_pos = 0;
437                   d->wic_cmd_valid = TRUE;
438                }
439             }
440           break;           break;
441    
442  #if DEBUG_UNKNOWN  #if DEBUG_UNKNOWN
# Line 304  dev_c3745_iofpga_access(cpu_mips_t *cpu, Line 444  dev_c3745_iofpga_access(cpu_mips_t *cpu,
444           if (op_type == MTS_READ) {           if (op_type == MTS_READ) {
445              cpu_log(cpu,"IO_FPGA",              cpu_log(cpu,"IO_FPGA",
446                      "read from unknown addr 0x%x, pc=0x%llx (size=%u)\n",                      "read from unknown addr 0x%x, pc=0x%llx (size=%u)\n",
447                      offset,cpu->pc,op_size);                      offset,cpu_get_pc(cpu),op_size);
448           } else {           } else {
449              cpu_log(cpu,"IO_FPGA",              cpu_log(cpu,"IO_FPGA",
450                      "write to unknown addr 0x%x, value=0x%llx, "                      "write to unknown addr 0x%x, value=0x%llx, "
451                      "pc=0x%llx (size=%u)\n",offset,*data,cpu->pc,op_size);                      "pc=0x%llx (size=%u)\n",
452                        offset,*data,cpu_get_pc(cpu),op_size);
453           }           }
454  #endif  #endif
455     }     }
# Line 333  void c3745_init_eeprom_groups(c3745_t *r Line 474  void c3745_init_eeprom_groups(c3745_t *r
474     /* EEPROMs for Network Modules */     /* EEPROMs for Network Modules */
475     for(i=1;i<=4;i++) {     for(i=1;i<=4;i++) {
476        router->nm_eeprom_group[i-1] = eeprom_nm_group;        router->nm_eeprom_group[i-1] = eeprom_nm_group;
477        router->nm_eeprom_group[i-1].eeprom[0] = &router->nm_bay[i].eeprom;        router->nm_eeprom_group[i-1].eeprom[0] = NULL;
478     }     }
479  }  }
480    
481  /* Shutdown the IO FPGA device */  /* Shutdown the IO FPGA device */
482  void dev_c3745_iofpga_shutdown(vm_instance_t *vm,struct iofpga_data *d)  static void
483    dev_c3745_iofpga_shutdown(vm_instance_t *vm,struct c3745_iofpga_data *d)
484  {  {
485     if (d != NULL) {     if (d != NULL) {
486        /* Remove the device */        /* Remove the device */
# Line 355  void dev_c3745_iofpga_shutdown(vm_instan Line 497  void dev_c3745_iofpga_shutdown(vm_instan
497  int dev_c3745_iofpga_init(c3745_t *router,m_uint64_t paddr,m_uint32_t len)  int dev_c3745_iofpga_init(c3745_t *router,m_uint64_t paddr,m_uint32_t len)
498  {  {
499     vm_instance_t *vm = router->vm;     vm_instance_t *vm = router->vm;
500     struct iofpga_data *d;     struct c3745_iofpga_data *d;
501    
502     /* Allocate private data structure */     /* Allocate private data structure */
503     if (!(d = malloc(sizeof(*d)))) {     if (!(d = malloc(sizeof(*d)))) {
# Line 365  int dev_c3745_iofpga_init(c3745_t *route Line 507  int dev_c3745_iofpga_init(c3745_t *route
507    
508     memset(d,0,sizeof(*d));     memset(d,0,sizeof(*d));
509     d->router = router;     d->router = router;
510       d->net_irq_status[0] = 0xFFFF;
511       d->net_irq_status[1] = 0xFFFF;
512    
513     vm_object_init(&d->vm_obj);     vm_object_init(&d->vm_obj);
514     d->vm_obj.name = "io_fpga";     d->vm_obj.name = "io_fpga";

Legend:
Removed from v.4  
changed lines
  Added in v.11

  ViewVC Help
Powered by ViewVC 1.1.26