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

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

upstream/dynamips-0.2.6-RC5/dev_c3725_iofpga.c revision 6 by dpavlin, Sat Oct 6 16:09:07 2007 UTC upstream/dynamips-0.2.8-RC1/dev_c3725_iofpga.c revision 11 by dpavlin, Sat Oct 6 16:33:40 2007 UTC
# 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_c3725.h"  #include "dev_c3725.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 C3725_NET_IRQ_CLEARING_DELAY  16  /* Network IRQ distribution */
45    struct net_irq_distrib  {
46       u_int reg;
47       u_int offset;
48    };
49    
50    static struct net_irq_distrib net_irq_dist[C3725_MAX_NM_BAYS] = {
51       { 0,  0 },  /* Slot 0: reg 0x26, 0x000000XX */
52       { 1,  0 },  /* Slot 1: reg 0x28, 0x0000000X */
53       { 1,  4 },  /* Slot 2: reg 0x28, 0x000000X0 */
54    };
55    
56  /* IO FPGA structure */  /* IO FPGA structure */
57  struct iofpga_data {  struct c3725_iofpga_data {
58     vm_obj_t vm_obj;     vm_obj_t vm_obj;
59     struct vdevice dev;     struct vdevice dev;
60     c3725_t *router;     c3725_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;  
61    
62     /* Interrupt mask*/     /* Network IRQ status */
63       m_uint16_t net_irq_status[2];
64    
65       /* Interrupt mask */
66     m_uint16_t intr_mask;     m_uint16_t intr_mask;
67    
68       /* WIC select */
69       u_int wic_select;
70       u_int wic_cmd_pos;
71       u_int wic_cmd_valid;
72       m_uint16_t wic_cmd[2];
73  };  };
74    
75  /* Mainboard EEPROM definition */  /* Mainboard EEPROM definition */
76  static const struct nmc93c46_eeprom_def eeprom_mb_def = {  static const struct nmc93cX6_eeprom_def eeprom_mb_def = {
77     EEPROM_MB_CLK, EEPROM_MB_CS,     EEPROM_MB_CLK, EEPROM_MB_CS,
78     EEPROM_MB_DIN, EEPROM_MB_DOUT,     EEPROM_MB_DIN, EEPROM_MB_DOUT,
79  };  };
80    
81  /* Mainboard EEPROM */  /* Mainboard EEPROM */
82  static const struct nmc93c46_group eeprom_mb_group = {  static const struct nmc93cX6_group eeprom_mb_group = {
83     1, 0, "Mainboard EEPROM", 0, { &eeprom_mb_def },     EEPROM_TYPE_NMC93C46, 1, 0,
84       EEPROM_DORD_NORMAL,
85       EEPROM_DOUT_HIGH,
86       EEPROM_DEBUG_DISABLED,
87       "Mainboard EEPROM",
88       { &eeprom_mb_def },
89  };  };
90    
91  /* NM EEPROM definition */  /* NM EEPROM definition */
92  static const struct nmc93c46_eeprom_def eeprom_nm_def = {  static const struct nmc93cX6_eeprom_def eeprom_nm_def = {
93     EEPROM_NM_CLK, EEPROM_NM_CS,     EEPROM_NM_CLK, EEPROM_NM_CS,
94     EEPROM_NM_DIN, EEPROM_NM_DOUT,     EEPROM_NM_DIN, EEPROM_NM_DOUT,
95  };  };
96    
97  /* NM EEPROM */  /* NM EEPROM */
98  static const struct nmc93c46_group eeprom_nm_group = {  static const struct nmc93cX6_group eeprom_nm_group = {
99     1, 0, "NM EEPROM", 0, { &eeprom_nm_def },     EEPROM_TYPE_NMC93C46, 1, 0,
100       EEPROM_DORD_NORMAL,
101       EEPROM_DOUT_HIGH,
102       EEPROM_DEBUG_DISABLED,
103       "NM EEPROM",
104       { &eeprom_nm_def },
105  };  };
106    
107    /* Update network interrupt status */
108    static inline void dev_c3725_iofpga_net_update_irq(struct c3725_iofpga_data *d)
109    {
110       if ((d->net_irq_status[0] != 0xFFFF) || (d->net_irq_status[1] != 0xFFFF)) {
111          vm_set_irq(d->router->vm,C3725_NETIO_IRQ);
112       } else {
113          vm_clear_irq(d->router->vm,C3725_NETIO_IRQ);
114       }
115    }
116    
117    /* Trigger a Network IRQ for the specified slot/port */
118    void dev_c3725_iofpga_net_set_irq(struct c3725_iofpga_data *d,
119                                      u_int slot,u_int port)
120    {
121       struct net_irq_distrib *irq_dist;
122    
123    #if DEBUG_NET_IRQ
124       vm_log(d->router->vm,"IO_FPGA","setting NetIRQ for slot %u port %u\n",
125              slot,port);
126    #endif
127       irq_dist = &net_irq_dist[slot];
128       d->net_irq_status[irq_dist->reg] &= ~(1 << (irq_dist->offset + port));
129       dev_c3725_iofpga_net_update_irq(d);
130    }
131    
132    /* Clear a Network IRQ for the specified slot/port */
133    void dev_c3725_iofpga_net_clear_irq(struct c3725_iofpga_data *d,
134                                        u_int slot,u_int port)
135    {
136       struct net_irq_distrib *irq_dist;
137    
138    #if DEBUG_NET_IRQ
139       vm_log(d->router->vm,"IO_FPGA","clearing NetIRQ for slot %u port %u\n",
140              slot,port);
141    #endif
142       irq_dist = &net_irq_dist[slot];
143       d->net_irq_status[irq_dist->reg] |= (1 << (irq_dist->offset + port));
144       dev_c3725_iofpga_net_update_irq(d);
145    }
146    
147    /* Read a WIC EEPROM */
148    static m_uint16_t dev_c3725_read_wic_eeprom(struct c3725_iofpga_data *d)
149    {  
150       struct cisco_eeprom *eeprom;
151       u_int wic_port;
152       u_int eeprom_offset;
153       m_uint8_t val[2];
154    
155       switch(d->wic_select) {
156          case 0x1700:
157             wic_port = 0x10;
158             break;
159          case 0x1D00:
160             wic_port = 0x20;
161             break;
162          case 0x3500:
163             wic_port = 0x30;
164             break;
165          default:
166             wic_port = 0;
167       }
168    
169       /* No WIC in slot or no EEPROM: fake an empty EEPROM */
170       if (!wic_port || !(eeprom = vm_slot_get_eeprom(d->router->vm,0,wic_port)))
171          return(0xFFFF);
172    
173       /* EEPROM offset is in the lowest 6 bits */
174       eeprom_offset = d->wic_cmd[0] & 0x3F;
175    
176       cisco_eeprom_get_byte(eeprom,eeprom_offset,&val[0]);
177       cisco_eeprom_get_byte(eeprom,eeprom_offset+1,&val[1]);
178    
179       return(((m_uint16_t)val[0] << 8) | val[1]);
180    }
181    
182  /*  /*
183   * dev_c3725_iofpga_access()   * dev_c3725_iofpga_access()
184   */   */
185  static void *  static void *
186  dev_c3725_iofpga_access(cpu_mips_t *cpu,struct vdevice *dev,  dev_c3725_iofpga_access(cpu_gen_t *cpu,struct vdevice *dev,
187                          m_uint32_t offset,u_int op_size,u_int op_type,                          m_uint32_t offset,u_int op_size,u_int op_type,
188                          m_uint64_t *data)                          m_uint64_t *data)
189  {  {
190     struct iofpga_data *d = dev->priv_data;     struct c3725_iofpga_data *d = dev->priv_data;
191    
192     if (op_type == MTS_READ)     if (op_type == MTS_READ)
193        *data = 0x0;        *data = 0x0;
# Line 99  dev_c3725_iofpga_access(cpu_mips_t *cpu, Line 195  dev_c3725_iofpga_access(cpu_mips_t *cpu,
195  #if DEBUG_ACCESS  #if DEBUG_ACCESS
196     if (op_type == MTS_READ) {     if (op_type == MTS_READ) {
197        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",
198                offset,cpu->pc,op_size);                offset,cpu_get_pc(cpu),op_size);
199     } else {     } else {
200        cpu_log(cpu,"IO_FPGA",        cpu_log(cpu,"IO_FPGA",
201                "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",
202                offset,cpu->pc,*data,op_size);                offset,cpu_get_pc(cpu),*data,op_size);
203     }     }
204  #endif  #endif
205    
# Line 120  dev_c3725_iofpga_access(cpu_mips_t *cpu, Line 216  dev_c3725_iofpga_access(cpu_mips_t *cpu,
216        /* Mainboard EEPROM */        /* Mainboard EEPROM */
217        case 0x0e:        case 0x0e:
218           if (op_type == MTS_WRITE)           if (op_type == MTS_WRITE)
219              nmc93c46_write(&d->router->mb_eeprom_group,(u_int)(*data));              nmc93cX6_write(&d->router->mb_eeprom_group,(u_int)(*data));
220           else           else
221              *data = nmc93c46_read(&d->router->mb_eeprom_group);              *data = nmc93cX6_read(&d->router->mb_eeprom_group);
222           break;           break;
223    
224        case 0x12:        case 0x12:
225           /*           /*
226            * Bit 0: 1=No WIC in slot 0 ?            * Bit 0: 1=No WIC in slot 0.
227            * Bit 1: 1=No WIC in slot 1 ?            * Bit 1: 1=No WIC in slot 1.
228            * Bit 2: 1=No WIC in slot 2 ?            * Bit 2: 1=No WIC in slot 2.
229            */            */
230           if (op_type == MTS_READ)           if (op_type == MTS_READ) {
231              *data = 0x0007;              *data = 0xFFFF;
232                
233                /* check WIC 0 */
234                if (vm_slot_check_eeprom(d->router->vm,0,0x10))
235                   *data &= ~0x01;
236    
237                /* check WIC 1 */
238                if (vm_slot_check_eeprom(d->router->vm,0,0x20))
239                   *data &= ~0x02;
240    
241                /* check WIC 2 */
242                if (vm_slot_check_eeprom(d->router->vm,0,0x30))
243                   *data &= ~0x04;
244             } else {
245                d->wic_select = *data;
246             }
247           break;           break;
248    
249        case 0x14:        case 0x14:
# Line 153  dev_c3725_iofpga_access(cpu_mips_t *cpu, Line 264  dev_c3725_iofpga_access(cpu_mips_t *cpu,
264    
265        /* WIC related: 16-bit data */        /* WIC related: 16-bit data */
266        case 0x42:        case 0x42:
267             if (op_type == MTS_READ) {
268                if (d->wic_cmd_valid) {
269                   *data = dev_c3725_read_wic_eeprom(d);
270                   d->wic_cmd_valid = FALSE;
271                } else {
272                   *data = 0xFFFF;
273                }
274             } else {
275                /*
276                 * Store the EEPROM command (in 2 words).
277                 *
278                 * For a read, we have:
279                 *    Word 0: 0x180 (nmc93c46 READ) + offset (6-bits).
280                 *    Word 1: 0 (no data).
281                 */
282                d->wic_cmd[d->wic_cmd_pos++] = *data;
283                
284                if (d->wic_cmd_pos == 2) {
285                   d->wic_cmd_pos = 0;
286                   d->wic_cmd_valid = TRUE;
287                }
288             }
289           break;           break;
290    
291        /* NM Slot 1 EEPROM */        /* NM Slot 1 EEPROM */
292        case 0x44:        case 0x44:
293           if (op_type == MTS_WRITE)           if (op_type == MTS_WRITE)
294              nmc93c46_write(&d->router->nm_eeprom_group[0],(u_int)(*data));              nmc93cX6_write(&d->router->nm_eeprom_group[0],(u_int)(*data));
295           else           else
296              *data = nmc93c46_read(&d->router->nm_eeprom_group[0]);              *data = nmc93cX6_read(&d->router->nm_eeprom_group[0]);
297           break;           break;
298    
299        /* NM Slot 2 EEPROM */        /* NM Slot 2 EEPROM */
300        case 0x46:        case 0x46:
301           if (op_type == MTS_WRITE)           if (op_type == MTS_WRITE)
302              nmc93c46_write(&d->router->nm_eeprom_group[1],(u_int)(*data));              nmc93cX6_write(&d->router->nm_eeprom_group[1],(u_int)(*data));
303           else           else
304              *data = nmc93c46_read(&d->router->nm_eeprom_group[1]);              *data = nmc93cX6_read(&d->router->nm_eeprom_group[1]);
305           break;           break;
306    
307        /* AIM EEPROM #0 */        /* AIM EEPROM #0 */
# Line 194  dev_c3725_iofpga_access(cpu_mips_t *cpu, Line 327  dev_c3725_iofpga_access(cpu_mips_t *cpu,
327           if (op_type == MTS_READ) {           if (op_type == MTS_READ) {
328              *data = 0xFFFF;              *data = 0xFFFF;
329    
330              if (c3725_nm_check_eeprom(d->router,1))              if (vm_slot_get_card_ptr(d->router->vm,1))
331                 *data &= ~0x0008;                 *data &= ~0x0008;
332    
333              if (c3725_nm_check_eeprom(d->router,2))              if (vm_slot_get_card_ptr(d->router->vm,2))
334                 *data &= ~0x0800;                 *data &= ~0x0800;
335           }           }
336           break;           break;
# Line 222  dev_c3725_iofpga_access(cpu_mips_t *cpu, Line 355  dev_c3725_iofpga_access(cpu_mips_t *cpu,
355         */         */
356        case 0x26:        case 0x26:
357           if (op_type == MTS_READ)           if (op_type == MTS_READ)
358              *data = 0xFFFE;              *data = d->net_irq_status[0];
359           break;           break;
360    
361        /*        /*
# Line 233  dev_c3725_iofpga_access(cpu_mips_t *cpu, Line 366  dev_c3725_iofpga_access(cpu_mips_t *cpu,
366         * Other bits unknown.         * Other bits unknown.
367         */         */
368        case 0x28:        case 0x28:
369           if (op_type == MTS_READ) {           if (op_type == MTS_READ)
370              *data = 0xFFEE;              *data = d->net_irq_status[1];
   
             if (++d->net_irq_clearing_count == C3725_NET_IRQ_CLEARING_DELAY) {  
                vm_clear_irq(d->router->vm,C3725_NETIO_IRQ);  
                d->net_irq_clearing_count = 0;  
             }  
          }  
371           break;           break;
372    
373        case 0x2c:        case 0x2c:
# Line 294  dev_c3725_iofpga_access(cpu_mips_t *cpu, Line 421  dev_c3725_iofpga_access(cpu_mips_t *cpu,
421           if (op_type == MTS_READ) {           if (op_type == MTS_READ) {
422              cpu_log(cpu,"IO_FPGA",              cpu_log(cpu,"IO_FPGA",
423                      "read from unknown addr 0x%x, pc=0x%llx (size=%u)\n",                      "read from unknown addr 0x%x, pc=0x%llx (size=%u)\n",
424                      offset,cpu->pc,op_size);                      offset,cpu_get_pc(cpu),op_size);
425           } else {           } else {
426              cpu_log(cpu,"IO_FPGA",              cpu_log(cpu,"IO_FPGA",
427                      "write to unknown addr 0x%x, value=0x%llx, "                      "write to unknown addr 0x%x, value=0x%llx, "
428                      "pc=0x%llx (size=%u)\n",offset,*data,cpu->pc,op_size);                      "pc=0x%llx (size=%u)\n",
429                        offset,*data,cpu_get_pc(cpu),op_size);
430           }           }
431  #endif  #endif
432     }     }
# Line 317  void c3725_init_eeprom_groups(c3725_t *r Line 445  void c3725_init_eeprom_groups(c3725_t *r
445    
446     /* EEPROM for NM slot 1 */     /* EEPROM for NM slot 1 */
447     router->nm_eeprom_group[0] = eeprom_nm_group;     router->nm_eeprom_group[0] = eeprom_nm_group;
448     router->nm_eeprom_group[0].eeprom[0] = &router->nm_bay[1].eeprom;     router->nm_eeprom_group[0].eeprom[0] = NULL;
449    
450     /* EEPROM for NM slot 2 */     /* EEPROM for NM slot 2 */
451     router->nm_eeprom_group[1] = eeprom_nm_group;     router->nm_eeprom_group[1] = eeprom_nm_group;
452     router->nm_eeprom_group[1].eeprom[0] = &router->nm_bay[2].eeprom;     router->nm_eeprom_group[1].eeprom[0] = NULL;
453  }  }
454    
455  /* Shutdown the IO FPGA device */  /* Shutdown the IO FPGA device */
456  void dev_c3725_iofpga_shutdown(vm_instance_t *vm,struct iofpga_data *d)  static void
457    dev_c3725_iofpga_shutdown(vm_instance_t *vm,struct c3725_iofpga_data *d)
458  {  {
459     if (d != NULL) {     if (d != NULL) {
460        /* Remove the device */        /* Remove the device */
# Line 342  void dev_c3725_iofpga_shutdown(vm_instan Line 471  void dev_c3725_iofpga_shutdown(vm_instan
471  int dev_c3725_iofpga_init(c3725_t *router,m_uint64_t paddr,m_uint32_t len)  int dev_c3725_iofpga_init(c3725_t *router,m_uint64_t paddr,m_uint32_t len)
472  {  {
473     vm_instance_t *vm = router->vm;     vm_instance_t *vm = router->vm;
474     struct iofpga_data *d;     struct c3725_iofpga_data *d;
475    
476     /* Allocate private data structure */     /* Allocate private data structure */
477     if (!(d = malloc(sizeof(*d)))) {     if (!(d = malloc(sizeof(*d)))) {
# Line 352  int dev_c3725_iofpga_init(c3725_t *route Line 481  int dev_c3725_iofpga_init(c3725_t *route
481    
482     memset(d,0,sizeof(*d));     memset(d,0,sizeof(*d));
483     d->router = router;     d->router = router;
484       d->net_irq_status[0] = 0xFFFF;
485       d->net_irq_status[1] = 0xFFFF;
486    
487     vm_object_init(&d->vm_obj);     vm_object_init(&d->vm_obj);
488     d->vm_obj.name = "io_fpga";     d->vm_obj.name = "io_fpga";

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

  ViewVC Help
Powered by ViewVC 1.1.26