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

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

upstream/dynamips-0.2.6-RC1/dev_dec21140.c revision 2 by dpavlin, Sat Oct 6 16:03:58 2007 UTC upstream/dynamips-0.2.8-RC1/dev_dec21140.c revision 11 by dpavlin, Sat Oct 6 16:33:40 2007 UTC
# Line 1  Line 1 
1  /*    /*  
2   * Cisco C7200 (Predator) DEC21140 Module.   * Cisco router simlation platform.
3   * Copyright (C) 2005,2006 Christophe Fillot.  All rights reserved.   * Copyright (C) 2005,2006 Christophe Fillot.  All rights reserved.
4   *   *
5   * DEC21140 FastEthernet chip emulation.   * DEC21140 FastEthernet chip emulation.
# Line 31  Line 31 
31    
32  #include "crc.h"  #include "crc.h"
33  #include "utils.h"  #include "utils.h"
34  #include "mips64.h"  #include "cpu.h"
35    #include "vm.h"
36  #include "dynamips.h"  #include "dynamips.h"
37  #include "memory.h"  #include "memory.h"
38  #include "device.h"  #include "device.h"
# Line 65  Line 66 
66  #define DEC21140_CSR_NR  16  #define DEC21140_CSR_NR  16
67    
68  /* CSR5: Status Register */  /* CSR5: Status Register */
69  #define DEC21140_CSR5_TI          0x00000001  #define DEC21140_CSR5_TI          0x00000001  /* TX Interrupt */
70  #define DEC21140_CSR5_RI          0x00000040  #define DEC21140_CSR5_TPS         0x00000002  /* TX Process Stopped */
71    #define DEC21140_CSR5_TU          0x00000004  /* TX Buffer Unavailable */
72    #define DEC21140_CSR5_TJT         0x00000008  /* TX Jabber Timeout */
73    #define DEC21140_CSR5_UNF         0x00000020  /* TX Underflow */
74    #define DEC21140_CSR5_RI          0x00000040  /* RX Interrupt */
75    #define DEC21140_CSR5_RU          0x00000080  /* RX Buffer Unavailable */
76    #define DEC21140_CSR5_RPS         0x00000100  /* RX Process Stopped */
77    #define DEC21140_CSR5_RWT         0x00000200  /* RX Watchdog Timeout */
78    #define DEC21140_CSR5_GTE         0x00000800  /* Gen Purpose Timer Expired */
79    #define DEC21140_CSR5_FBE         0x00002000  /* Fatal Bus Error */
80    #define DEC21140_CSR5_AIS         0x00008000  /* Abnormal Interrupt Summary */
81    #define DEC21140_CSR5_NIS         0x00010000  /* Normal Interrupt Summary */
82    
83    #define DEC21140_NIS_BITS \
84       (DEC21140_CSR5_TI|DEC21140_CSR5_RI|DEC21140_CSR5_TU)
85    
86    #define DEC21140_AIS_BITS \
87       (DEC21140_CSR5_TPS|DEC21140_CSR5_TJT|DEC21140_CSR5_UNF| \
88        DEC21140_CSR5_RU|DEC21140_CSR5_RPS|DEC21140_CSR5_RWT| \
89        DEC21140_CSR5_GTE|DEC21140_CSR5_FBE)
90    
91  #define DEC21140_CSR5_RS_SHIFT    17  #define DEC21140_CSR5_RS_SHIFT    17
92  #define DEC21140_CSR5_TS_SHIFT    20  #define DEC21140_CSR5_TS_SHIFT    20
93    
# Line 166  struct dec21140_data { Line 187  struct dec21140_data {
187  /* Log a dec21140 message */  /* Log a dec21140 message */
188  #define DEC21140_LOG(d,msg...) vm_log((d)->vm,(d)->name,msg)  #define DEC21140_LOG(d,msg...) vm_log((d)->vm,(d)->name,msg)
189    
 /*  
  * ISL rewrite.  
  *  
  * See: http://www.cisco.com/en/US/tech/tk389/tk390/technologies_tech_note09186a0080094665.shtml  
  */  
 static void dec21140_isl_rewrite(m_uint8_t *pkt,m_uint32_t tot_len)  
 {  
    static m_uint8_t isl_xaddr[N_ETH_ALEN] = { 0x01,0x00,0x0c,0x00,0x10,0x00 };  
    u_int real_offset,real_len;  
    n_eth_hdr_t *hdr;  
    m_uint32_t ifcs;  
   
    hdr = (n_eth_hdr_t *)pkt;  
    if (!memcmp(&hdr->daddr,isl_xaddr,N_ETH_ALEN)) {  
       real_offset = N_ETH_HLEN + N_ISL_HDR_SIZE;  
       real_len    = ntohs(hdr->type);  
       real_len    -= (N_ISL_HDR_SIZE + 4);  
     
       if ((real_offset+real_len) > tot_len)  
          return;  
     
       /* Rewrite the destination MAC address */  
       hdr->daddr.eth_addr_byte[4] = 0x00;  
   
       /* Compute the internal FCS on the encapsulated packet */  
       ifcs = crc32_compute(0xFFFFFFFF,pkt+real_offset,real_len);  
       pkt[tot_len-4] = ifcs & 0xff;  
       pkt[tot_len-3] = (ifcs >> 8) & 0xff;  
       pkt[tot_len-2] = (ifcs >> 16) & 0xff;  
       pkt[tot_len-1] = ifcs >> 24;  
    }  
 }  
   
190  /* Check if a packet must be delivered to the emulated chip */  /* Check if a packet must be delivered to the emulated chip */
191  static inline int dec21140_handle_mac_addr(struct dec21140_data *d,  static inline int dec21140_handle_mac_addr(struct dec21140_data *d,
192                                             m_uint8_t *pkt)                                             m_uint8_t *pkt)
# Line 206  static inline int dec21140_handle_mac_ad Line 194  static inline int dec21140_handle_mac_ad
194     n_eth_hdr_t *hdr = (n_eth_hdr_t *)pkt;     n_eth_hdr_t *hdr = (n_eth_hdr_t *)pkt;
195     int i;     int i;
196    
    /* Ignore traffic sent by us */  
    for(i=0;i<d->mac_addr_count;i++)  
       if (!memcmp(&d->mac_addr[i],&hdr->saddr,N_ETH_ALEN))  
          return(FALSE);  
   
197     /* Accept systematically frames if we are running is promiscuous mode */     /* Accept systematically frames if we are running is promiscuous mode */
198     if (d->csr[6] & DEC21140_CSR6_PROMISC)     if (d->csr[6] & DEC21140_CSR6_PROMISC)
199        return(TRUE);        return(TRUE);
# Line 397  static void mii_newbit(struct dec21140_d Line 380  static void mii_newbit(struct dec21140_d
380  #endif  #endif
381  }  }
382    
383    /* Update the interrupt status */
384    static inline void dev_dec21140_update_irq_status(struct dec21140_data *d)
385    {
386       int trigger = FALSE;
387       m_uint32_t csr5;
388    
389       /* Work on a temporary copy of csr5 */
390       csr5 = d->csr[5];
391      
392       /* Compute Interrupt Summary */
393       csr5 &= ~(DEC21140_CSR5_AIS|DEC21140_CSR5_NIS);
394    
395       if (csr5 & DEC21140_NIS_BITS) {
396          csr5 |= DEC21140_CSR5_NIS;
397          trigger = TRUE;
398       }
399    
400       if (csr5 & DEC21140_AIS_BITS) {
401          csr5 |= DEC21140_CSR5_AIS;
402          trigger = TRUE;
403       }
404    
405       d->csr[5] = csr5;
406      
407       if (trigger)
408          pci_dev_trigger_irq(d->vm,d->pci_dev);
409       else
410          pci_dev_clear_irq(d->vm,d->pci_dev);
411    }
412    
413  /*  /*
414   * dev_dec21140_access()   * dev_dec21140_access()
415   */   */
416  void *dev_dec21140_access(cpu_mips_t *cpu,struct vdevice *dev,  void *dev_dec21140_access(cpu_gen_t *cpu,struct vdevice *dev,
417                            m_uint32_t offset,u_int op_size,u_int op_type,                            m_uint32_t offset,u_int op_size,u_int op_type,
418                            m_uint64_t *data)                            m_uint64_t *data)
419  {  {
# Line 430  void *dev_dec21140_access(cpu_mips_t *cp Line 443  void *dev_dec21140_access(cpu_mips_t *cp
443              if (d->csr[6] & DEC21140_CSR6_START_TX)              if (d->csr[6] & DEC21140_CSR6_START_TX)
444                 *data |= 0x03 << DEC21140_CSR5_TS_SHIFT;                 *data |= 0x03 << DEC21140_CSR5_TS_SHIFT;
445                    
446              *data |= d->csr[5] & (DEC21140_CSR5_TI|DEC21140_CSR5_RI);              *data |= d->csr[5];
447              break;              break;
448    
449           case 8:           case 8:
450              /* CSR8 is cleared when read */              /* CSR8 is cleared when read (missed frame counter) */
451              d->csr[reg] = 0;              d->csr[reg] = 0;
452                *data = 0;
453              break;              break;
454                            
455           default:           default:
# Line 445  void *dev_dec21140_access(cpu_mips_t *cp Line 459  void *dev_dec21140_access(cpu_mips_t *cp
459  #if DEBUG_CSR_REGS  #if DEBUG_CSR_REGS
460        cpu_log(cpu,d->name,"write CSR%u value 0x%x\n",reg,(m_uint32_t)*data);        cpu_log(cpu,d->name,"write CSR%u value 0x%x\n",reg,(m_uint32_t)*data);
461  #endif  #endif
       d->csr[reg] = *data;  
   
462        switch(reg) {        switch(reg) {
463           case 3:           case 3:
464                d->csr[reg] = *data;
465              d->rx_current = d->csr[reg];              d->rx_current = d->csr[reg];
466              break;              break;
467           case 4:           case 4:
468                d->csr[reg] = *data;
469              d->tx_current = d->csr[reg];              d->tx_current = d->csr[reg];
470              break;              break;
471             case 5:
472                d->csr[reg] &= ~(*data);
473                dev_dec21140_update_irq_status(d);
474                break;
475           case 9:           case 9:
476              /*              /*
477               * CSR9, probably they want to mess with MII PHY               * CSR9, probably they want to mess with MII PHY
# Line 465  void *dev_dec21140_access(cpu_mips_t *cp Line 483  void *dev_dec21140_access(cpu_mips_t *cp
483               *               *
484               * Also it makes "sh contr f0/0" happy.               * Also it makes "sh contr f0/0" happy.
485               */               */
486              if ((*data&~DEC21140_CSR9_TX_BIT) == (DEC21140_CSR9_MII_READ|              d->csr[reg] = *data;
487    
488                if ((*data & ~DEC21140_CSR9_TX_BIT) == (DEC21140_CSR9_MII_READ|
489                   DEC21140_CSR9_READ|DEC21140_CSR9_MDC_CLOCK)) {                   DEC21140_CSR9_READ|DEC21140_CSR9_MDC_CLOCK)) {
490                 /*                 /*
491                  * read, pop one bit from mii_outbits                  * read, pop one bit from mii_outbits
# Line 483  void *dev_dec21140_access(cpu_mips_t *cp Line 503  void *dev_dec21140_access(cpu_mips_t *cp
503                 mii_newbit(d,(*data&DEC21140_CSR9_TX_BIT) ? 1 : 0);                             mii_newbit(d,(*data&DEC21140_CSR9_TX_BIT) ? 1 : 0);            
504              }              }
505              break;              break;
506    
507             default:
508                d->csr[reg] = *data;
509        }        }
510     }     }
511    
# Line 510  static m_uint32_t rxdesc_get_next(struct Line 533  static m_uint32_t rxdesc_get_next(struct
533     return(nrxd_addr);     return(nrxd_addr);
534  }  }
535    
536  /* Read an RX descriptor */  /* Read a RX descriptor */
537  static void rxdesc_read(struct dec21140_data *d,m_uint32_t rxd_addr,  static void rxdesc_read(struct dec21140_data *d,m_uint32_t rxd_addr,
538                          struct rx_desc *rxd)                          struct rx_desc *rxd)
539  {  {
# Line 650  static int dev_dec21140_receive_pkt(stru Line 673  static int dev_dec21140_receive_pkt(stru
673    
674     /* Indicate that we have a frame ready */     /* Indicate that we have a frame ready */
675     d->csr[5] |= DEC21140_CSR5_RI;     d->csr[5] |= DEC21140_CSR5_RI;
676       dev_dec21140_update_irq_status(d);
    /* Generate IRQ on CPU */  
    pci_dev_trigger_irq(d->vm,d->pci_dev);  
677     return(TRUE);     return(TRUE);
678  }  }
679    
# Line 678  static int dev_dec21140_handle_rxring(ne Line 699  static int dev_dec21140_handle_rxring(ne
699      * for this virtual machine.      * for this virtual machine.
700      */      */
701     if (dec21140_handle_mac_addr(d,pkt))     if (dec21140_handle_mac_addr(d,pkt))
702        dev_dec21140_receive_pkt(d,pkt,pkt_len);        return(dev_dec21140_receive_pkt(d,pkt,pkt_len));
703    
704     return(TRUE);     return(FALSE);
705  }  }
706    
707  /* Read a TX descriptor */  /* Read a TX descriptor */
# Line 729  static int dev_dec21140_handle_txring_si Line 750  static int dev_dec21140_handle_txring_si
750     /* Copy the current txring descriptor */     /* Copy the current txring descriptor */
751     tx_start = d->tx_current;       tx_start = d->tx_current;  
752     ptxd = &txd0;     ptxd = &txd0;
753     txdesc_read(d,d->tx_current,ptxd);     txdesc_read(d,tx_start,ptxd);
754    
755     /* If we don't own the first descriptor, we cannot transmit */     /* If we don't own the first descriptor, we cannot transmit */
756     if (!(txd0.tdes[0] & DEC21140_TXDESC_OWN))     if (!(txd0.tdes[0] & DEC21140_TXDESC_OWN))
# Line 818  static int dev_dec21140_handle_txring_si Line 839  static int dev_dec21140_handle_txring_si
839        mem_dump(log_file,pkt,tot_len);        mem_dump(log_file,pkt,tot_len);
840  #endif  #endif
841        /* rewrite ISL header if required */        /* rewrite ISL header if required */
842        dec21140_isl_rewrite(pkt,tot_len);        cisco_isl_rewrite(pkt,tot_len);
843    
844        /* send it on wire */        /* send it on wire */
845        netio_send(d->nio,pkt,tot_len);        netio_send(d->nio,pkt,tot_len);
# Line 827  static int dev_dec21140_handle_txring_si Line 848  static int dev_dec21140_handle_txring_si
848   clear_txd0_own_bit:   clear_txd0_own_bit:
849     /* Clear the OWN flag of the first descriptor */     /* Clear the OWN flag of the first descriptor */
850     physmem_copy_u32_to_vm(d->vm,tx_start,0);     physmem_copy_u32_to_vm(d->vm,tx_start,0);
851      
852     /* Interrupt on completion ? */     /* Interrupt on completion ? */
853     if (!(txd0.tdes[1] & DEC21140_TXDESC_IC)) {     if (txd0.tdes[1] & DEC21140_TXDESC_IC) {      
854        d->csr[5] |= DEC21140_CSR5_TI;        d->csr[5] |= DEC21140_CSR5_TI;
855        pci_dev_trigger_irq(d->vm,d->pci_dev);        dev_dec21140_update_irq_status(d);
856     }     }
857        
858     return(TRUE);     return(TRUE);
# Line 854  static int dev_dec21140_handle_txring(st Line 875  static int dev_dec21140_handle_txring(st
875   *   *
876   * Read a PCI register.   * Read a PCI register.
877   */   */
878  static m_uint32_t pci_dec21140_read(cpu_mips_t *cpu,struct pci_device *dev,  static m_uint32_t pci_dec21140_read(cpu_gen_t *cpu,struct pci_device *dev,
879                                      int reg)                                      int reg)
880  {    {  
881     struct dec21140_data *d = dev->priv_data;     struct dec21140_data *d = dev->priv_data;
# Line 880  static m_uint32_t pci_dec21140_read(cpu_ Line 901  static m_uint32_t pci_dec21140_read(cpu_
901   *   *
902   * Write a PCI register.   * Write a PCI register.
903   */   */
904  static void pci_dec21140_write(cpu_mips_t *cpu,struct pci_device *dev,  static void pci_dec21140_write(cpu_gen_t *cpu,struct pci_device *dev,
905                                 int reg,m_uint32_t value)                                 int reg,m_uint32_t value)
906  {  {
907     struct dec21140_data *d = dev->priv_data;     struct dec21140_data *d = dev->priv_data;

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

  ViewVC Help
Powered by ViewVC 1.1.26