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

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

upstream/dynamips-0.2.7-RC1/dev_am79c971.c revision 7 by dpavlin, Sat Oct 6 16:23:47 2007 UTC upstream/dynamips-0.2.8-RC1/dev_am79c971.c revision 11 by dpavlin, Sat Oct 6 16:33:40 2007 UTC
# Line 30  Line 30 
30  #define DEBUG_BCR_REGS   0  #define DEBUG_BCR_REGS   0
31  #define DEBUG_PCI_REGS   0  #define DEBUG_PCI_REGS   0
32  #define DEBUG_ACCESS     0  #define DEBUG_ACCESS     0
33  #define DEBUG_TRANSMIT   0  #define DEBUG_TRANSMIT   1
34  #define DEBUG_RECEIVE    0  #define DEBUG_RECEIVE    1
35  #define DEBUG_UNKNOWN    0  #define DEBUG_UNKNOWN    0
36    
37  /* AMD Am79c971 PCI vendor/product codes */  /* AMD Am79c971 PCI vendor/product codes */
# Line 126  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 172  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 203  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 219  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 325  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    
# Line 362  static void am79c971_rdp_access(cpu_gen_ Line 372  static void am79c971_rdp_access(cpu_gen_
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 389  static void am79c971_rdp_access(cpu_gen_ Line 405  static void am79c971_rdp_access(cpu_gen_
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 400  static void am79c971_rdp_access(cpu_gen_ Line 419  static void am79c971_rdp_access(cpu_gen_
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 483  static void am79c971_bdp_access(cpu_gen_ Line 502  static void am79c971_bdp_access(cpu_gen_
502           if (op_type == MTS_READ) {           if (op_type == MTS_READ) {
503              cpu_log(cpu,d->name,"read access to unknown BCR %d\n",d->rap);              cpu_log(cpu,d->name,"read access to unknown BCR %d\n",d->rap);
504           } else {           } else {
505              cpu_log(cpu,d->name,"write access to unknown BCR %d, value=0x%x\n",              cpu_log(cpu,d->name,
506                        "write access to unknown BCR %d, value=0x%x\n",
507                      d->rap,*data);                      d->rap,*data);
508           }           }
509  #endif  #endif
# Line 512  void *dev_am79c971_access(cpu_gen_t *cpu Line 532  void *dev_am79c971_access(cpu_gen_t *cpu
532     }     }
533  #endif  #endif
534    
535       AM79C971_LOCK(d);
536    
537     switch(offset) {     switch(offset) {
538        case 0x14:  /* RAP (Register Address Pointer) */        case 0x14:  /* RAP (Register Address Pointer) */
539           if (op_type == MTS_WRITE) {           if (op_type == MTS_WRITE) {
# Line 530  void *dev_am79c971_access(cpu_gen_t *cpu Line 552  void *dev_am79c971_access(cpu_gen_t *cpu
552           break;           break;
553     }     }
554    
555       AM79C971_UNLOCK(d);
556     return NULL;     return NULL;
557  }  }
558    
# Line 618  static int am79c971_receive_pkt(struct a Line 641  static int am79c971_receive_pkt(struct a
641     u_char *pkt_ptr = pkt;     u_char *pkt_ptr = pkt;
642     m_uint8_t sw_style;     m_uint8_t sw_style;
643     int i;     int i;
644      
645     /* Truncate the packet if it is too big */     /* Truncate the packet if it is too big */
646     pkt_len = m_min(pkt_len,AM79C971_MAX_PKT_SIZE);     pkt_len = m_min(pkt_len,AM79C971_MAX_PKT_SIZE);
647    
# Line 700  static int am79c971_receive_pkt(struct a Line 723  static int am79c971_receive_pkt(struct a
723     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]);
724    
725     d->csr[0] |= AM79C971_CSR0_RINT;     d->csr[0] |= AM79C971_CSR0_RINT;
726     am79c971_update_intr_flag(d);     am79c971_update_irq_status(d);
    am79c971_trigger_irq(d);  
727     return(TRUE);     return(TRUE);
728  }  }
729    
# Line 716  static int am79c971_handle_rxring(netio_ Line 738  static int am79c971_handle_rxring(netio_
738      * Don't start receive if the RX ring address has not been set      * Don't start receive if the RX ring address has not been set
739      * and if RX ON is not set.      * and if RX ON is not set.
740      */      */
741     if ((d->rx_start == 0) || !(d->csr[0] & AM79C971_CSR0_TXON))     if ((d->rx_start == 0) || !(d->csr[0] & AM79C971_CSR0_RXON))
742        return(FALSE);        return(FALSE);
743    
744  #if DEBUG_RECEIVE  #if DEBUG_RECEIVE
# Line 724  static int am79c971_handle_rxring(netio_ Line 746  static int am79c971_handle_rxring(netio_
746     mem_dump(log_file,pkt,pkt_len);     mem_dump(log_file,pkt,pkt_len);
747  #endif  #endif
748    
749       AM79C971_LOCK(d);
750    
751     /*     /*
752      * Receive only multicast/broadcast trafic + unicast traffic      * Receive only multicast/broadcast trafic + unicast traffic
753      * for this virtual machine.      * for this virtual machine.
754      */      */
755     hdr = (n_eth_hdr_t *)pkt;     hdr = (n_eth_hdr_t *)pkt;
756    
757     if (am79c971_handle_mac_addr(d,pkt))     if (am79c971_handle_mac_addr(d,pkt))
758        am79c971_receive_pkt(d,pkt,pkt_len);        am79c971_receive_pkt(d,pkt,pkt_len);
759    
760       AM79C971_UNLOCK(d);
761     return(TRUE);     return(TRUE);
762  }  }
763    
# Line 793  static int am79c971_handle_txring_single Line 819  static int am79c971_handle_txring_single
819     struct tx_desc txd0,ctxd,ntxd,*ptxd;     struct tx_desc txd0,ctxd,ntxd,*ptxd;
820     m_uint32_t tx_start,tx_current;     m_uint32_t tx_start,tx_current;
821     m_uint32_t clen,tot_len;     m_uint32_t clen,tot_len;
822      
823     if ((d->tx_start == 0) || !(d->csr[0] & AM79C971_CSR0_TXON))     if ((d->tx_start == 0) || !(d->csr[0] & AM79C971_CSR0_TXON))
824        return(FALSE);        return(FALSE);
825        
# Line 801  static int am79c971_handle_txring_single Line 827  static int am79c971_handle_txring_single
827     tx_start = tx_current = txdesc_get_current(d);     tx_start = tx_current = txdesc_get_current(d);
828     ptxd = &txd0;     ptxd = &txd0;
829     txdesc_read(d,tx_start,ptxd);     txdesc_read(d,tx_start,ptxd);
830      
831     /* If we don't own the first descriptor, we cannot transmit */     /* If we don't own the first descriptor, we cannot transmit */
832     if (!(ptxd->tmd[1] & AM79C971_TMD1_OWN))     if (!(ptxd->tmd[1] & AM79C971_TMD1_OWN))
833        return(FALSE);        return(FALSE);
834          
835  #if DEBUG_TRANSMIT  #if DEBUG_TRANSMIT
836     AM79C971_LOG(d,"am79c971_handle_txring: 1st desc: "     AM79C971_LOG(d,"am79c971_handle_txring: 1st desc: "
837                  "tmd[0]=0x%x, tmd[1]=0x%x, tmd[2]=0x%x, tmd[3]=0x%x\n",                  "tmd[0]=0x%x, tmd[1]=0x%x, tmd[2]=0x%x, tmd[3]=0x%x\n",
# Line 825  static int am79c971_handle_txring_single Line 851  static int am79c971_handle_txring_single
851        /* Copy packet data */        /* Copy packet data */
852        clen = ~((ptxd->tmd[1] & AM79C971_TMD1_LEN) - 1);        clen = ~((ptxd->tmd[1] & AM79C971_TMD1_LEN) - 1);
853        clen &= AM79C971_TMD1_LEN;        clen &= AM79C971_TMD1_LEN;
854    
855        physmem_copy_from_vm(d->vm,pkt_ptr,ptxd->tmd[0],clen);        physmem_copy_from_vm(d->vm,pkt_ptr,ptxd->tmd[0],clen);
856    
857        pkt_ptr += clen;        pkt_ptr += clen;
# Line 861  static int am79c971_handle_txring_single Line 888  static int am79c971_handle_txring_single
888        AM79C971_LOG(d,"sending packet of %u bytes\n",tot_len);        AM79C971_LOG(d,"sending packet of %u bytes\n",tot_len);
889        mem_dump(log_file,pkt,tot_len);        mem_dump(log_file,pkt,tot_len);
890  #endif  #endif
891          /* rewrite ISL header if required */
892          cisco_isl_rewrite(pkt,tot_len);
893    
894        /* send it on wire */        /* send it on wire */
895        netio_send(d->nio,pkt,tot_len);        netio_send(d->nio,pkt,tot_len);
896     }     }
# Line 871  static int am79c971_handle_txring_single Line 901  static int am79c971_handle_txring_single
901    
902     /* Generate TX interrupt */     /* Generate TX interrupt */
903     d->csr[0] |= AM79C971_CSR0_TINT;     d->csr[0] |= AM79C971_CSR0_TINT;
904     am79c971_update_intr_flag(d);     am79c971_update_irq_status(d);
    am79c971_trigger_irq(d);  
905     return(TRUE);     return(TRUE);
906  }  }
907    
# Line 881  static int am79c971_handle_txring(struct Line 910  static int am79c971_handle_txring(struct
910  {  {
911     int i;     int i;
912    
913       AM79C971_LOCK(d);
914    
915     for(i=0;i<AM79C971_TXRING_PASS_COUNT;i++)     for(i=0;i<AM79C971_TXRING_PASS_COUNT;i++)
916        if (!am79c971_handle_txring_single(d))        if (!am79c971_handle_txring_single(d))
917           break;           break;
918    
919       AM79C971_UNLOCK(d);
920     return(TRUE);     return(TRUE);
921  }  }
922    
# Line 957  dev_am79c971_init(vm_instance_t *vm,char Line 989  dev_am79c971_init(vm_instance_t *vm,char
989    
990     memset(d,0,sizeof(*d));     memset(d,0,sizeof(*d));
991     memcpy(d->mii_regs[0],mii_reg_values,sizeof(mii_reg_values));     memcpy(d->mii_regs[0],mii_reg_values,sizeof(mii_reg_values));
992       pthread_mutex_init(&d->lock,NULL);
993    
994     /* Add as PCI device */     /* Add as PCI device */
995     pci_dev = pci_dev_add(pci_bus,name,     pci_dev = pci_dev_add(pci_bus,name,
# Line 1008  void dev_am79c971_remove(struct am79c971 Line 1041  void dev_am79c971_remove(struct am79c971
1041    
1042  /* Bind a NIO to an AMD Am79c971 device */  /* Bind a NIO to an AMD Am79c971 device */
1043  int dev_am79c971_set_nio(struct am79c971_data *d,netio_desc_t *nio)  int dev_am79c971_set_nio(struct am79c971_data *d,netio_desc_t *nio)
1044  {  {  
1045     /* check that a NIO is not already bound */     /* check that a NIO is not already bound */
1046     if (d->nio != NULL)     if (d->nio != NULL)
1047        return(-1);        return(-1);

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

  ViewVC Help
Powered by ViewVC 1.1.26