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

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

upstream/dynamips-0.2.6-RC4/dev_am79c971.c revision 5 by dpavlin, Sat Oct 6 16:08:03 2007 UTC upstream/dynamips-0.2.7-RC2/dev_am79c971.c revision 8 by dpavlin, Sat Oct 6 16:24:54 2007 UTC
# Line 1  Line 1 
1  /*    /*  
2   * Cisco C7200 (Predator) AMD Am79c971 Module.   * Cisco router simulation platform.
3   * Copyright (C) 2006 Christophe Fillot.  All rights reserved.   * Copyright (C) 2006 Christophe Fillot.  All rights reserved.
4   *   *
5   * AMD Am79c971 FastEthernet chip emulation.   * AMD Am79c971 FastEthernet chip emulation.
# Line 15  Line 15 
15  #include <assert.h>  #include <assert.h>
16    
17  #include "utils.h"  #include "utils.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"
# Line 125  struct tx_desc { Line 126  struct tx_desc {
126  struct am79c971_data {  struct am79c971_data {
127     char *name;     char *name;
128    
129       /* Lock */
130       pthread_mutex_t lock;
131      
132     /* Interface type (10baseT or 100baseTX) */     /* Interface type (10baseT or 100baseTX) */
133     int type;     int type;
134    
135       /* RX/TX clearing count */
136       int rx_tx_clear_count;
137    
138     /* Current RAP (Register Address Pointer) value */     /* Current RAP (Register Address Pointer) value */
139     m_uint8_t rap;     m_uint8_t rap;
140    
# Line 171  struct am79c971_data { Line 178  struct am79c971_data {
178  /* Log an am79c971 message */  /* Log an am79c971 message */
179  #define AM79C971_LOG(d,msg...) vm_log((d)->vm,(d)->name,msg)  #define AM79C971_LOG(d,msg...) vm_log((d)->vm,(d)->name,msg)
180    
181    /* Lock/Unlock primitives */
182    #define AM79C971_LOCK(d)    pthread_mutex_lock(&(d)->lock)
183    #define AM79C971_UNLOCK(d)  pthread_mutex_unlock(&(d)->lock)
184    
185  static m_uint16_t mii_reg_values[32] = {  static m_uint16_t mii_reg_values[32] = {
186     0x1000, 0x782D, 0x2000, 0x5C01, 0x01E1, 0x0000, 0x0000, 0x0000,     0x1000, 0x782D, 0x0013, 0x78E2, 0x01E1, 0xC9E1, 0x000F, 0x2001,
187       0x0000, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
188       0x0104, 0x4780, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
189       0x0000, 0x0000, 0x00C8, 0x0000, 0xFFFF, 0x0000, 0x0000, 0x0000,
190    
191    #if 0
192       0x1000, 0x782D, 0x0013, 0x78e2, 0x01E1, 0xC9E1, 0x0000, 0x0000,
193     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
194     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x8060,     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x8060,
195     0x8020, 0x0820, 0x0000, 0x3800, 0xA3B9, 0x0000, 0x0000, 0x0000,     0x8023, 0x0820, 0x0000, 0x3800, 0xA3B9, 0x0000, 0x0000, 0x0000,
196    #endif
197  };  };
198    
199  /* Read a MII register */  /* Read a MII register */
# Line 202  static inline int am79c971_handle_mac_ad Line 219  static inline int am79c971_handle_mac_ad
219  {  {
220     n_eth_hdr_t *hdr = (n_eth_hdr_t *)pkt;     n_eth_hdr_t *hdr = (n_eth_hdr_t *)pkt;
221    
222     /* Accept systematically frames if we are running is promiscuous mode */     /* Accept systematically frames if we are running in promiscuous mode */
223     if (d->csr[15] & AM79C971_CSR15_PROM)     if (d->csr[15] & AM79C971_CSR15_PROM)
224        return(TRUE);        return(TRUE);
225    
# Line 218  static inline int am79c971_handle_mac_ad Line 235  static inline int am79c971_handle_mac_ad
235  }  }
236    
237  /* Update the Interrupt Flag bit of csr0 */  /* Update the Interrupt Flag bit of csr0 */
238  static void am79c971_update_intr_flag(struct am79c971_data *d)  static void am79c971_update_irq_status(struct am79c971_data *d)
239  {  {
240     m_uint32_t mask;     m_uint32_t mask;
241    
242     mask = d->csr[3] & AM79C971_CSR3_IM_MASK;     /* Bits set in CR3 disable the specified interrupts */
243       mask = AM79C971_CSR3_IM_MASK & ~(d->csr[3] & AM79C971_CSR3_IM_MASK);
244        
245     if (d->csr[0] & mask)     if (d->csr[0] & mask)
246        d->csr[0] |= AM79C971_CSR0_INTR;        d->csr[0] |= AM79C971_CSR0_INTR;
247  }     else
248          d->csr[0] &= ~AM79C971_CSR0_INTR;
249    
250  /* Trigger an interrupt */     if ((d->csr[0] & (AM79C971_CSR0_INTR|AM79C971_CSR0_IENA)) ==
251  static int am79c971_trigger_irq(struct am79c971_data *d)         (AM79C971_CSR0_INTR|AM79C971_CSR0_IENA))
252  {     {
    if (d->csr[0] & (AM79C971_CSR0_INTR|AM79C971_CSR0_IENA)) {  
253        pci_dev_trigger_irq(d->vm,d->pci_dev);        pci_dev_trigger_irq(d->vm,d->pci_dev);
254        return(TRUE);     } else {
255          pci_dev_clear_irq(d->vm,d->pci_dev);
256     }     }
   
    return(FALSE);  
257  }  }
258    
259  /* Update RX/TX ON bits of csr0 */  /* Update RX/TX ON bits of csr0 */
# Line 324  static int am79c971_fetch_init_block(str Line 341  static int am79c971_fetch_init_block(str
341     /* Update RX/TX ON bits of csr0 since csr15 has been modified */     /* Update RX/TX ON bits of csr0 since csr15 has been modified */
342     am79c971_update_rx_tx_on_bits(d);     am79c971_update_rx_tx_on_bits(d);
343     AM79C971_LOG(d,"CSR0 = 0x%4.4x\n",d->csr[0]);     AM79C971_LOG(d,"CSR0 = 0x%4.4x\n",d->csr[0]);
   
    am79c971_update_intr_flag(d);  
   
    if (am79c971_trigger_irq(d))  
       AM79C971_LOG(d,"triggering IDON interrupt\n");  
   
344     return(0);     return(0);
345  }  }
346    
347  /* RDP (Register Data Port) access */  /* RDP (Register Data Port) access */
348  static void am79c971_rdp_access(cpu_mips_t *cpu,struct am79c971_data *d,  static void am79c971_rdp_access(cpu_gen_t *cpu,struct am79c971_data *d,
349                                  u_int op_type,m_uint64_t *data)                                  u_int op_type,m_uint64_t *data)
350  {  {
351     m_uint32_t mask;     m_uint32_t mask;
# Line 361  static void am79c971_rdp_access(cpu_mips Line 372  static void am79c971_rdp_access(cpu_mips
372                 //AM79C971_LOG(d,"stopping interface!\n");                 //AM79C971_LOG(d,"stopping interface!\n");
373                 d->csr[0] = AM79C971_CSR0_STOP;                 d->csr[0] = AM79C971_CSR0_STOP;
374                 d->tx_pos = d->rx_pos = 0;                 d->tx_pos = d->rx_pos = 0;
375                   am79c971_update_irq_status(d);
376                 break;                 break;
377              }              }
378                            
379              /* These bits are cleared when set to 1 */              /* These bits are cleared when set to 1 */
380              mask  = AM79C971_CSR0_BABL | AM79C971_CSR0_CERR;              mask  = AM79C971_CSR0_BABL | AM79C971_CSR0_CERR;
381              mask |= AM79C971_CSR0_MISS | AM79C971_CSR0_MERR;              mask |= AM79C971_CSR0_MISS | AM79C971_CSR0_MERR;
             mask |= AM79C971_CSR0_RINT | AM79C971_CSR0_TINT;  
382              mask |= AM79C971_CSR0_IDON;              mask |= AM79C971_CSR0_IDON;
383    
384                if (++d->rx_tx_clear_count == 3) {
385                   mask |= AM79C971_CSR0_RINT | AM79C971_CSR0_TINT;
386                   d->rx_tx_clear_count = 0;
387                }
388    
389              d->csr[0] &= ~(*data & mask);              d->csr[0] &= ~(*data & mask);
390    
391              /* Save the Interrupt Enable bit */              /* Save the Interrupt Enable bit */
# Line 388  static void am79c971_rdp_access(cpu_mips Line 405  static void am79c971_rdp_access(cpu_mips
405                 d->csr[0] &= ~AM79C971_CSR0_STOP;                 d->csr[0] &= ~AM79C971_CSR0_STOP;
406                 am79c971_update_rx_tx_on_bits(d);                 am79c971_update_rx_tx_on_bits(d);
407              }              }
408    
409                /* Update IRQ status */
410                am79c971_update_irq_status(d);
411           }           }
412           break;           break;
413    
# Line 399  static void am79c971_rdp_access(cpu_mips Line 419  static void am79c971_rdp_access(cpu_mips
419           } else {           } else {
420              *data = (d->tx_l2len << 12) | (d->rx_l2len << 8);              *data = (d->tx_l2len << 12) | (d->rx_l2len << 8);
421           }           }
422           break;           break;            
423    
424        case 15:  /* CSR15: Mode */        case 15:  /* CSR15: Mode */
425           if (op_type == MTS_WRITE) {           if (op_type == MTS_WRITE) {
# Line 442  static void am79c971_rdp_access(cpu_mips Line 462  static void am79c971_rdp_access(cpu_mips
462  }  }
463    
464  /* BDP (BCR Data Port) access */  /* BDP (BCR Data Port) access */
465  static void am79c971_bdp_access(cpu_mips_t *cpu,struct am79c971_data *d,  static void am79c971_bdp_access(cpu_gen_t *cpu,struct am79c971_data *d,
466                                  u_int op_type,m_uint64_t *data)                                  u_int op_type,m_uint64_t *data)
467  {  {
468     u_int mii_phy,mii_reg;     u_int mii_phy,mii_reg;
# Line 492  static void am79c971_bdp_access(cpu_mips Line 512  static void am79c971_bdp_access(cpu_mips
512  /*  /*
513   * dev_am79c971_access()   * dev_am79c971_access()
514   */   */
515  void *dev_am79c971_access(cpu_mips_t *cpu,struct vdevice *dev,  void *dev_am79c971_access(cpu_gen_t *cpu,struct vdevice *dev,
516                            m_uint32_t offset,u_int op_size,u_int op_type,                            m_uint32_t offset,u_int op_size,u_int op_type,
517                            m_uint64_t *data)                            m_uint64_t *data)
518  {  {
# Line 504  void *dev_am79c971_access(cpu_mips_t *cp Line 524  void *dev_am79c971_access(cpu_mips_t *cp
524  #if DEBUG_ACCESS  #if DEBUG_ACCESS
525     if (op_type == MTS_READ) {     if (op_type == MTS_READ) {
526        cpu_log(cpu,d->name,"read  access to offset=0x%x, pc=0x%llx, size=%u\n",        cpu_log(cpu,d->name,"read  access to offset=0x%x, pc=0x%llx, size=%u\n",
527                offset,cpu->pc,op_size);                offset,cpu_get_pc(cpu),op_size);
528     } else {     } else {
529        cpu_log(cpu,d->name,"write access to offset=0x%x, pc=0x%llx, "        cpu_log(cpu,d->name,"write access to offset=0x%x, pc=0x%llx, "
530                "val=0x%llx, size=%u\n",offset,cpu->pc,*data,op_size);                "val=0x%llx, size=%u\n",offset,cpu_get_pc(cpu),*data,op_size);
531     }     }
532  #endif  #endif
533    
534       AM79C971_LOCK(d);
535    
536     switch(offset) {     switch(offset) {
537        case 0x14:  /* RAP (Register Address Pointer) */        case 0x14:  /* RAP (Register Address Pointer) */
538           if (op_type == MTS_WRITE) {           if (op_type == MTS_WRITE) {
# Line 529  void *dev_am79c971_access(cpu_mips_t *cp Line 551  void *dev_am79c971_access(cpu_mips_t *cp
551           break;           break;
552     }     }
553    
554       AM79C971_UNLOCK(d);
555     return NULL;     return NULL;
556  }  }
557    
# Line 617  static int am79c971_receive_pkt(struct a Line 640  static int am79c971_receive_pkt(struct a
640     u_char *pkt_ptr = pkt;     u_char *pkt_ptr = pkt;
641     m_uint8_t sw_style;     m_uint8_t sw_style;
642     int i;     int i;
643      
644     /* Truncate the packet if it is too big */     /* Truncate the packet if it is too big */
645     pkt_len = m_min(pkt_len,AM79C971_MAX_PKT_SIZE);     pkt_len = m_min(pkt_len,AM79C971_MAX_PKT_SIZE);
646    
# Line 699  static int am79c971_receive_pkt(struct a Line 722  static int am79c971_receive_pkt(struct a
722     physmem_copy_u32_to_vm(d->vm,rx_start+4,rxd0.rmd[1]);     physmem_copy_u32_to_vm(d->vm,rx_start+4,rxd0.rmd[1]);
723    
724     d->csr[0] |= AM79C971_CSR0_RINT;     d->csr[0] |= AM79C971_CSR0_RINT;
725     am79c971_update_intr_flag(d);     am79c971_update_irq_status(d);
    am79c971_trigger_irq(d);  
726     return(TRUE);     return(TRUE);
727  }  }
728    
# Line 723  static int am79c971_handle_rxring(netio_ Line 745  static int am79c971_handle_rxring(netio_
745     mem_dump(log_file,pkt,pkt_len);     mem_dump(log_file,pkt,pkt_len);
746  #endif  #endif
747    
748       AM79C971_LOCK(d);
749    
750     /*     /*
751      * Receive only multicast/broadcast trafic + unicast traffic      * Receive only multicast/broadcast trafic + unicast traffic
752      * for this virtual machine.      * for this virtual machine.
# Line 731  static int am79c971_handle_rxring(netio_ Line 755  static int am79c971_handle_rxring(netio_
755     if (am79c971_handle_mac_addr(d,pkt))     if (am79c971_handle_mac_addr(d,pkt))
756        am79c971_receive_pkt(d,pkt,pkt_len);        am79c971_receive_pkt(d,pkt,pkt_len);
757    
758       AM79C971_UNLOCK(d);
759     return(TRUE);     return(TRUE);
760  }  }
761    
# Line 824  static int am79c971_handle_txring_single Line 849  static int am79c971_handle_txring_single
849        /* Copy packet data */        /* Copy packet data */
850        clen = ~((ptxd->tmd[1] & AM79C971_TMD1_LEN) - 1);        clen = ~((ptxd->tmd[1] & AM79C971_TMD1_LEN) - 1);
851        clen &= AM79C971_TMD1_LEN;        clen &= AM79C971_TMD1_LEN;
852    
853        physmem_copy_from_vm(d->vm,pkt_ptr,ptxd->tmd[0],clen);        physmem_copy_from_vm(d->vm,pkt_ptr,ptxd->tmd[0],clen);
854    
855        pkt_ptr += clen;        pkt_ptr += clen;
# Line 870  static int am79c971_handle_txring_single Line 896  static int am79c971_handle_txring_single
896    
897     /* Generate TX interrupt */     /* Generate TX interrupt */
898     d->csr[0] |= AM79C971_CSR0_TINT;     d->csr[0] |= AM79C971_CSR0_TINT;
899     am79c971_update_intr_flag(d);     am79c971_update_irq_status(d);
    am79c971_trigger_irq(d);  
900     return(TRUE);     return(TRUE);
901  }  }
902    
# Line 880  static int am79c971_handle_txring(struct Line 905  static int am79c971_handle_txring(struct
905  {  {
906     int i;     int i;
907    
908       AM79C971_LOCK(d);
909    
910     for(i=0;i<AM79C971_TXRING_PASS_COUNT;i++)     for(i=0;i<AM79C971_TXRING_PASS_COUNT;i++)
911        if (!am79c971_handle_txring_single(d))        if (!am79c971_handle_txring_single(d))
912           break;           break;
913    
914       AM79C971_UNLOCK(d);
915     return(TRUE);     return(TRUE);
916  }  }
917    
# Line 892  static int am79c971_handle_txring(struct Line 920  static int am79c971_handle_txring(struct
920   *   *
921   * Read a PCI register.   * Read a PCI register.
922   */   */
923  static m_uint32_t pci_am79c971_read(cpu_mips_t *cpu,struct pci_device *dev,  static m_uint32_t pci_am79c971_read(cpu_gen_t *cpu,struct pci_device *dev,
924                                      int reg)                                      int reg)
925  {    {  
926     struct am79c971_data *d = dev->priv_data;     struct am79c971_data *d = dev->priv_data;
# Line 918  static m_uint32_t pci_am79c971_read(cpu_ Line 946  static m_uint32_t pci_am79c971_read(cpu_
946   *   *
947   * Write a PCI register.   * Write a PCI register.
948   */   */
949  static void pci_am79c971_write(cpu_mips_t *cpu,struct pci_device *dev,  static void pci_am79c971_write(cpu_gen_t *cpu,struct pci_device *dev,
950                                 int reg,m_uint32_t value)                                 int reg,m_uint32_t value)
951  {  {
952     struct am79c971_data *d = dev->priv_data;     struct am79c971_data *d = dev->priv_data;
# Line 956  dev_am79c971_init(vm_instance_t *vm,char Line 984  dev_am79c971_init(vm_instance_t *vm,char
984    
985     memset(d,0,sizeof(*d));     memset(d,0,sizeof(*d));
986     memcpy(d->mii_regs[0],mii_reg_values,sizeof(mii_reg_values));     memcpy(d->mii_regs[0],mii_reg_values,sizeof(mii_reg_values));
987       pthread_mutex_init(&d->lock,NULL);
988    
989     /* Add as PCI device */     /* Add as PCI device */
990     pci_dev = pci_dev_add(pci_bus,name,     pci_dev = pci_dev_add(pci_bus,name,

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

  ViewVC Help
Powered by ViewVC 1.1.26