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

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

upstream/dynamips-0.2.6-RC4/dev_mueslix.c revision 5 by dpavlin, Sat Oct 6 16:08:03 2007 UTC upstream/dynamips-0.2.8-RC1/dev_mueslix.c revision 11 by dpavlin, Sat Oct 6 16:33:40 2007 UTC
# Line 1  Line 1 
1  /*    /*  
2   * Cisco C7200 (Predator) Simulation Platform.   * Cisco router simulation platform.
3   * Copyright (C) 2005,2006 Christophe Fillot.  All rights reserved.   * Copyright (C) 2005,2006 Christophe Fillot.  All rights reserved.
4   *   *
5   * Serial Interfaces (Mueslix).   * Serial Interfaces (Mueslix).
# Line 36  Line 36 
36  #include <errno.h>  #include <errno.h>
37  #include <assert.h>  #include <assert.h>
38    
39  #include "mips64.h"  #include "cpu.h"
40    #include "vm.h"
41  #include "dynamips.h"  #include "dynamips.h"
42  #include "memory.h"  #include "memory.h"
43  #include "device.h"  #include "device.h"
# Line 95  Line 96 
96  #define MUESLIX_XYMEM_LEN     0x100  #define MUESLIX_XYMEM_LEN     0x100
97    
98  /* Maximum packet size */  /* Maximum packet size */
99  #define MUESLIX_MAX_PKT_SIZE  2048  #define MUESLIX_MAX_PKT_SIZE  18000
100    
101  /* Send up to 16 packets in a TX ring scan pass */  /* Send up to 16 packets in a TX ring scan pass */
102  #define MUESLIX_TXRING_PASS_COUNT  16  #define MUESLIX_TXRING_PASS_COUNT  16
# Line 108  Line 109 
109  #define MUESLIX_RXDESC_IGNORED    0x08000000  /* Ignored */  #define MUESLIX_RXDESC_IGNORED    0x08000000  /* Ignored */
110  #define MUESLIX_RXDESC_ABORT      0x04000000  /* Abort */  #define MUESLIX_RXDESC_ABORT      0x04000000  /* Abort */
111  #define MUESLIX_RXDESC_CRC        0x02000000  /* CRC error */  #define MUESLIX_RXDESC_CRC        0x02000000  /* CRC error */
112  #define MUESLIX_RXDESC_LEN_MASK   0xfff  #define MUESLIX_RXDESC_LEN_MASK   0xffff
113    
114  /* TX descriptors */  /* TX descriptors */
115  #define MUESLIX_TXDESC_OWN        0x80000000  /* Ownership */  #define MUESLIX_TXDESC_OWN        0x80000000  /* Ownership */
# Line 120  Line 121 
121  #define MUESLIX_TXDESC_PAD        0x00c00000  /* Sort of padding info ? */  #define MUESLIX_TXDESC_PAD        0x00c00000  /* Sort of padding info ? */
122  #define MUESLIX_TXDESC_PAD_SHIFT  22  #define MUESLIX_TXDESC_PAD_SHIFT  22
123    
124  #define MUESLIX_TXDESC_LEN_MASK   0xfff  #define MUESLIX_TXDESC_LEN_MASK   0xffff
125    
126  /* RX Descriptor */  /* RX Descriptor */
127  struct rx_desc {  struct rx_desc {
# Line 140  struct mueslix_channel { Line 141  struct mueslix_channel {
141     /* Channel ID */     /* Channel ID */
142     u_int id;     u_int id;
143    
    /* RX/TX status */  
    u_int rx_tx_status;  
   
144     /* Channel status (0=disabled) */     /* Channel status (0=disabled) */
145     u_int status;     u_int status;
146    
147       /* CRC control register */
148       u_int crc_ctrl_reg;
149    
150       /* CRC size */
151       u_int crc_size;
152    
153     /* NetIO descriptor */     /* NetIO descriptor */
154     netio_desc_t *nio;     netio_desc_t *nio;
155    
# Line 165  struct mueslix_channel { Line 169  struct mueslix_channel {
169  /* Mueslix Data */  /* Mueslix Data */
170  struct mueslix_data {  struct mueslix_data {
171     char *name;     char *name;
172      
173       /* Lock */
174       pthread_mutex_t lock;
175    
176       /* IRQ status and mask */
177       m_uint32_t irq_status,irq_mask;
178       u_int irq_clearing_count;
179    
180     /* TPU options */     /* TPU options */
181     m_uint32_t tpu_options;     m_uint32_t tpu_options;
182    
# Line 203  static m_uint32_t channel_offset[MUESLIX Line 214  static m_uint32_t channel_offset[MUESLIX
214     MUESLIX_CHANNEL2_OFFSET, MUESLIX_CHANNEL3_OFFSET,     MUESLIX_CHANNEL2_OFFSET, MUESLIX_CHANNEL3_OFFSET,
215  };  };
216    
217    /* Lock/Unlock primitives */
218    #define MUESLIX_LOCK(d)    pthread_mutex_lock(&(d)->lock)
219    #define MUESLIX_UNLOCK(d)  pthread_mutex_unlock(&(d)->lock)
220    
221  /* Log a Mueslix message */  /* Log a Mueslix message */
222  #define MUESLIX_LOG(d,msg...) vm_log((d)->vm,(d)->name,msg)  #define MUESLIX_LOG(d,msg...) vm_log((d)->vm,(d)->name,msg)
223    
# Line 213  static inline int dev_mueslix_is_rx_tx_e Line 228  static inline int dev_mueslix_is_rx_tx_e
228     return((d->channel_enable_mask >> (id << 1)) & 0x03);     return((d->channel_enable_mask >> (id << 1)) & 0x03);
229  }  }
230    
231    /* Update IRQ status */
232    static inline void dev_mueslix_update_irq_status(struct mueslix_data *d)
233    {
234       if (d->irq_status & d->irq_mask)
235          pci_dev_trigger_irq(d->vm,d->pci_dev);
236       else {
237          if (++d->irq_clearing_count == 3) {
238             pci_dev_clear_irq(d->vm,d->pci_dev);
239             d->irq_clearing_count = 0;
240          }
241       }
242    }
243    
244  /*  /*
245   * Access to channel registers.   * Access to channel registers.
246   */   */
247  void dev_mueslix_chan_access(cpu_mips_t *cpu,struct mueslix_channel *channel,  void dev_mueslix_chan_access(cpu_gen_t *cpu,struct mueslix_channel *channel,
248                               m_uint32_t offset,u_int op_size,u_int op_type,                               m_uint32_t offset,u_int op_size,u_int op_type,
249                               m_uint64_t *data)                               m_uint64_t *data)
250  {  {
251     switch(offset) {     switch(offset) {
252          case 0x00: /* CRC control register ? */
253             if (op_type == MTS_READ) {
254                *data = channel->crc_ctrl_reg;
255             } else {
256                channel->crc_ctrl_reg = *data;
257                
258                switch(channel->crc_ctrl_reg) {
259                   case 0x08:
260                   case 0x0a:
261                      channel->crc_size = channel->crc_ctrl_reg - 0x06;
262                      break;
263    
264                   default:
265                      MUESLIX_LOG(channel->parent,"channel %u: unknown value "
266                                  "for CRC ctrl reg 0x%4.4x\n",
267                                  channel->id,channel->crc_ctrl_reg);
268    
269                      channel->crc_size = 2;
270                }
271                MUESLIX_LOG(channel->parent,
272                            "channel %u: CRC size set to 0x%4.4x\n",
273                            channel->id,channel->crc_size);
274             }
275             break;
276    
277        case 0x60: /* signals ? */        case 0x60: /* signals ? */
278           if ((op_type == MTS_READ) && (channel->nio != NULL))           if ((op_type == MTS_READ) && (channel->nio != NULL))
279              *data = 0xFFFFFFFF;              *data = 0xFFFFFFFF;
# Line 318  static void tpu_cm1_handle_cmd(struct mu Line 371  static void tpu_cm1_handle_cmd(struct mu
371  /*  /*
372   * dev_mueslix_access()   * dev_mueslix_access()
373   */   */
374  void *dev_mueslix_access(cpu_mips_t *cpu,struct vdevice *dev,m_uint32_t offset,  void *dev_mueslix_access(cpu_gen_t *cpu,struct vdevice *dev,m_uint32_t offset,
375                           u_int op_size,u_int op_type,m_uint64_t *data)                           u_int op_size,u_int op_type,m_uint64_t *data)
376  {  {
377     struct mueslix_data *d = dev->priv_data;     struct mueslix_data *d = dev->priv_data;
    struct mueslix_channel *channel;  
    m_uint32_t irq_status;  
378     int i;     int i;
379    
380  #if DEBUG_ACCESS >= 2  #if DEBUG_ACCESS >= 2
381     if (op_type == MTS_READ) {     if (op_type == MTS_READ) {
382        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",
383                offset,cpu->pc,op_size);                offset,cpu_get_pc(cpu),op_size);
384     } else {     } else {
385        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, "
386                "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);
387     }     }
388  #endif  #endif
389    
# Line 360  void *dev_mueslix_access(cpu_mips_t *cpu Line 411  void *dev_mueslix_access(cpu_mips_t *cpu
411        if ((offset >= channel_offset[i]) &&        if ((offset >= channel_offset[i]) &&
412            (offset < (channel_offset[i] + MUESLIX_CHANNEL_LEN)))            (offset < (channel_offset[i] + MUESLIX_CHANNEL_LEN)))
413     {     {
414          MUESLIX_LOCK(d);
415        dev_mueslix_chan_access(cpu,&d->channel[i],        dev_mueslix_chan_access(cpu,&d->channel[i],
416                                offset - channel_offset[i],                                offset - channel_offset[i],
417                                op_size,op_type,data);                                op_size,op_type,data);
418          MUESLIX_UNLOCK(d);
419        return NULL;        return NULL;
420     }     }
421    
422       MUESLIX_LOCK(d);
423    
424     /* Generic case */     /* Generic case */
425     switch(offset) {     switch(offset) {
426        /* this reg is accessed when an interrupt occurs */        /* this reg is accessed when an interrupt occurs */
427        case 0x0:        case 0x0:
428           if (op_type == MTS_READ) {           if (op_type == MTS_READ) {
429              irq_status = 0;              *data = d->irq_status;
   
             for(i=0;i<MUESLIX_NR_CHANNELS;i++) {  
                channel = &d->channel[i];  
   
                if ((dev_mueslix_is_rx_tx_enabled(d,i) & MUESLIX_TX_ENABLE) &&  
                    (channel->rx_tx_status & MUESLIX_CHANNEL_STATUS_RX))  
                   irq_status |= MUESLIX_RX_IRQ << i;  
   
                if ((dev_mueslix_is_rx_tx_enabled(d,i) & MUESLIX_TX_ENABLE) &&  
                    (channel->rx_tx_status & MUESLIX_CHANNEL_STATUS_TX))  
                   irq_status |= MUESLIX_TX_IRQ << i;  
             }  
   
             /*  
              * Hack: we re-trigger an interrupt here. This was necessary  
              * because the Mueslix driver was not working properly with  
              * a C3620 platform.  
              */  
             if (irq_status)  
                pci_dev_trigger_irq(d->vm,d->pci_dev);    
   
             *data = irq_status;  
430           } else {           } else {
431              for(i=0;i<MUESLIX_NR_CHANNELS;i++) {              d->irq_status &= ~(*data);
432                 channel = &d->channel[i];              dev_mueslix_update_irq_status(d);
                channel->rx_tx_status = 0;  
             }  
433           }           }
434           break;           break;
435    
436        /* maybe interrupt mask */        /* Maybe interrupt mask */
437        case 0x10:        case 0x10:
438           if (op_type == MTS_READ)           if (op_type == MTS_READ) {
439              *data = 0x2FF;              *data = d->irq_mask;
440             } else {
441                d->irq_mask = *data;
442                dev_mueslix_update_irq_status(d);
443             }
444           break;           break;
445    
446        case 0x14:        case 0x14:
# Line 415  void *dev_mueslix_access(cpu_mips_t *cpu Line 450  void *dev_mueslix_access(cpu_mips_t *cpu
450  #if DEBUG_ACCESS  #if DEBUG_ACCESS
451              cpu_log(cpu,d->name,              cpu_log(cpu,d->name,
452                      "channel_enable_mask = 0x%5.5llx at pc=0x%llx\n",                      "channel_enable_mask = 0x%5.5llx at pc=0x%llx\n",
453                      *data,cpu->pc);                      *data,cpu_get_pc(cpu));
454  #endif  #endif
455              d->channel_enable_mask = *data;              d->channel_enable_mask = *data;
456           }           }
# Line 448  void *dev_mueslix_access(cpu_mips_t *cpu Line 483  void *dev_mueslix_access(cpu_mips_t *cpu
483  #if DEBUG_ACCESS  #if DEBUG_ACCESS
484           if (op_type == MTS_WRITE) {           if (op_type == MTS_WRITE) {
485              cpu_log(cpu,d->name,"cmd_reg = 0x%5.5llx at pc=0x%llx\n",              cpu_log(cpu,d->name,"cmd_reg = 0x%5.5llx at pc=0x%llx\n",
486                      *data,cpu->pc);                      *data,cpu_get_pc(cpu));
487           }           }
488  #endif  #endif
489           switch(d->chip_mode) {           switch(d->chip_mode) {
# Line 475  void *dev_mueslix_access(cpu_mips_t *cpu Line 510  void *dev_mueslix_access(cpu_mips_t *cpu
510           if (op_type == MTS_READ) {           if (op_type == MTS_READ) {
511              cpu_log(cpu,d->name,              cpu_log(cpu,d->name,
512                      "read from unknown addr 0x%x, pc=0x%llx (size=%u)\n",                      "read from unknown addr 0x%x, pc=0x%llx (size=%u)\n",
513                      offset,cpu->pc,op_size);                      offset,cpu_get_pc(cpu),op_size);
514           } else {           } else {
515              cpu_log(cpu,d->name,              cpu_log(cpu,d->name,
516                      "write to unknown addr 0x%x, value=0x%llx, "                      "write to unknown addr 0x%x, value=0x%llx, "
517                      "pc=0x%llx (size=%u)\n",offset,*data,cpu->pc,op_size);                      "pc=0x%llx (size=%u)\n",
518                        offset,*data,cpu_get_pc(cpu),op_size);
519           }           }
520  #endif  #endif
521     }     }
522    
523       MUESLIX_UNLOCK(d);
524     return NULL;     return NULL;
525  }  }
526    
# Line 607  static void dev_mueslix_receive_pkt(stru Line 644  static void dev_mueslix_receive_pkt(stru
644        /* We have finished if the complete packet has been stored */        /* We have finished if the complete packet has been stored */
645        if (tot_len == 0) {        if (tot_len == 0) {
646           rxdc->rdes[0] = MUESLIX_RXDESC_LS;           rxdc->rdes[0] = MUESLIX_RXDESC_LS;
647           rxdc->rdes[0] |= cp_len;           rxdc->rdes[0] |= cp_len + channel->crc_size + 1;
648    
649           if (i != 0)           if (i != 0)
650              physmem_copy_u32_to_vm(d->vm,channel->rx_current,rxdc->rdes[0]);              physmem_copy_u32_to_vm(d->vm,channel->rx_current,rxdc->rdes[0]);
# Line 652  static void dev_mueslix_receive_pkt(stru Line 689  static void dev_mueslix_receive_pkt(stru
689     /* Indicate that we have a frame ready (XXX something to do ?) */     /* Indicate that we have a frame ready (XXX something to do ?) */
690    
691     /* Generate IRQ on CPU */     /* Generate IRQ on CPU */
692     channel->rx_tx_status |= MUESLIX_CHANNEL_STATUS_RX;     d->irq_status |= MUESLIX_RX_IRQ << channel->id;
693     pci_dev_trigger_irq(d->vm,d->pci_dev);     dev_mueslix_update_irq_status(d);
694  }  }
695    
696  /* Handle the Mueslix RX ring of the specified channel */  /* Handle the Mueslix RX ring of the specified channel */
697  static int dev_mueslix_handle_rxring(netio_desc_t *nio,  static int dev_mueslix_handle_rxring(netio_desc_t *nio,
698                                       u_char *pkt,ssize_t pkt_len,                                       u_char *pkt,ssize_t pkt_len,
699                                       struct mueslix_channel *channel)                                       struct mueslix_channel *channel)
700  {  {  
 #if DEBUG_RECEIVE  
701     struct mueslix_data *d = channel->parent;     struct mueslix_data *d = channel->parent;
702    
703    #if DEBUG_RECEIVE
704     MUESLIX_LOG(d,"channel %u: receiving a packet of %d bytes\n",     MUESLIX_LOG(d,"channel %u: receiving a packet of %d bytes\n",
705                 channel->id,pkt_len);                 channel->id,pkt_len);
706     mem_dump(log_file,pkt,pkt_len);     mem_dump(log_file,pkt,pkt_len);
707  #endif  #endif
708    
709     dev_mueslix_receive_pkt(channel,pkt,pkt_len);     MUESLIX_LOCK(d);
710       if (dev_mueslix_is_rx_tx_enabled(d,channel->id) & MUESLIX_RX_ENABLE)
711          dev_mueslix_receive_pkt(channel,pkt,pkt_len);
712       MUESLIX_UNLOCK(d);
713     return(TRUE);     return(TRUE);
714  }  }
715    
# Line 766  static int dev_mueslix_handle_txring_sin Line 806  static int dev_mueslix_handle_txring_sin
806        /* Be sure that we have length not null */        /* Be sure that we have length not null */
807        if (clen != 0) {        if (clen != 0) {
808           //printf("pkt_ptr = %p, ptxd->tdes[1] = 0x%x, clen = %d\n",           //printf("pkt_ptr = %p, ptxd->tdes[1] = 0x%x, clen = %d\n",
809           //pkt_ptr, ptxd->tdes[1], clen);           //       pkt_ptr, ptxd->tdes[1], clen);
810           physmem_copy_from_vm(d->vm,pkt_ptr,ptxd->tdes[1],clen);           physmem_copy_from_vm(d->vm,pkt_ptr,ptxd->tdes[1],clen);
811        }        }
812    
# Line 797  static int dev_mueslix_handle_txring_sin Line 837  static int dev_mueslix_handle_txring_sin
837    
838        pad = ptxd->tdes[0] & MUESLIX_TXDESC_PAD;        pad = ptxd->tdes[0] & MUESLIX_TXDESC_PAD;
839        pad >>= MUESLIX_TXDESC_PAD_SHIFT;        pad >>= MUESLIX_TXDESC_PAD_SHIFT;
840        tot_len += (pad - 1) & 0x03;        tot_len -= (4 - pad) & 0x03;
841    
842        /* send it on wire */        /* send it on wire */
843        netio_send(channel->nio,pkt,tot_len);        netio_send(channel->nio,pkt,tot_len);
844     }     }
# Line 807  static int dev_mueslix_handle_txring_sin Line 847  static int dev_mueslix_handle_txring_sin
847     physmem_copy_u32_to_vm(d->vm,tx_start,0);     physmem_copy_u32_to_vm(d->vm,tx_start,0);
848    
849     /* Interrupt on completion ? */     /* Interrupt on completion ? */
850     channel->rx_tx_status |= MUESLIX_CHANNEL_STATUS_TX;     d->irq_status |= MUESLIX_TX_IRQ << channel->id;
851     pci_dev_trigger_irq(d->vm,d->pci_dev);       dev_mueslix_update_irq_status(d);
852     return(TRUE);     return(TRUE);
853  }  }
854    
855  /* Handle the TX ring of a specific channel */  /* Handle the TX ring of a specific channel */
856  static int dev_mueslix_handle_txring(struct mueslix_channel *channel)  static int dev_mueslix_handle_txring(struct mueslix_channel *channel)
857  {  {
858     int i;     struct mueslix_data *d = channel->parent;
859       int res,i;
860    
861     for(i=0;i<MUESLIX_TXRING_PASS_COUNT;i++)     if (!dev_mueslix_is_rx_tx_enabled(d,channel->id) & MUESLIX_TX_ENABLE)
862        if (!dev_mueslix_handle_txring_single(channel))        return(FALSE);
863    
864       for(i=0;i<MUESLIX_TXRING_PASS_COUNT;i++) {
865          MUESLIX_LOCK(d);
866          res = dev_mueslix_handle_txring_single(channel);
867          MUESLIX_UNLOCK(d);
868        
869          if (!res)
870           break;           break;
871       }
872    
873     return(TRUE);     return(TRUE);
874  }  }
875    
876  /* pci_mueslix_read() */  /* pci_mueslix_read() */
877  static m_uint32_t pci_mueslix_read(cpu_mips_t *cpu,struct pci_device *dev,  static m_uint32_t pci_mueslix_read(cpu_gen_t *cpu,struct pci_device *dev,
878                                     int reg)                                     int reg)
879  {    {  
880     struct mueslix_data *d = dev->priv_data;     struct mueslix_data *d = dev->priv_data;
# Line 841  static m_uint32_t pci_mueslix_read(cpu_m Line 890  static m_uint32_t pci_mueslix_read(cpu_m
890  }  }
891    
892  /* pci_mueslix_write() */  /* pci_mueslix_write() */
893  static void pci_mueslix_write(cpu_mips_t *cpu,struct pci_device *dev,  static void pci_mueslix_write(cpu_gen_t *cpu,struct pci_device *dev,
894                                int reg,m_uint32_t value)                                int reg,m_uint32_t value)
895  {    {  
896     struct mueslix_data *d = dev->priv_data;     struct mueslix_data *d = dev->priv_data;
# Line 871  dev_mueslix_init(vm_instance_t *vm,char Line 920  dev_mueslix_init(vm_instance_t *vm,char
920     }     }
921    
922     memset(d,0,sizeof(*d));     memset(d,0,sizeof(*d));
923       pthread_mutex_init(&d->lock,NULL);
924     d->chip_mode = chip_mode;     d->chip_mode = chip_mode;
925    
926     for(i=0;i<MUESLIX_NR_CHANNELS;i++)     for(i=0;i<MUESLIX_NR_CHANNELS;i++) {
927        d->channel[i].id = i;        d->channel[i].id = i;
928          d->channel[i].parent = d;
929       }
930    
931     /* Add as PCI device */     /* Add as PCI device */
932     pci_dev = pci_dev_add(pci_bus,name,     pci_dev = pci_dev_add(pci_bus,name,
# Line 937  int dev_mueslix_set_nio(struct mueslix_d Line 989  int dev_mueslix_set_nio(struct mueslix_d
989    
990     /* define the new NIO */     /* define the new NIO */
991     channel->nio = nio;     channel->nio = nio;
    channel->parent = d;  
992     channel->tx_tid = ptask_add((ptask_callback)dev_mueslix_handle_txring,     channel->tx_tid = ptask_add((ptask_callback)dev_mueslix_handle_txring,
993                                 channel,NULL);                                 channel,NULL);
994     netio_rxl_add(nio,(netio_rx_handler_t)dev_mueslix_handle_rxring,     netio_rxl_add(nio,(netio_rx_handler_t)dev_mueslix_handle_rxring,

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

  ViewVC Help
Powered by ViewVC 1.1.26