示例#1
0
/* Read a TX descriptor */
static void txdesc_read(struct pos_oc3_data *d,m_uint32_t txd_addr,
                        struct tx_desc *txd)
{
   /* get the next descriptor from VM physical RAM */
   physmem_copy_from_vm(d->vm,txd,txd_addr,sizeof(struct tx_desc));

   /* byte-swapping */
   txd->tdes[0] = vmtoh32(txd->tdes[0]);
   txd->tdes[1] = vmtoh32(txd->tdes[1]);
}
/* Read a SDMA descriptor from memory */
static void mv64460_sdma_desc_read(struct mv64460_data *d,m_uint32_t addr,
                                   struct sdma_desc *desc)
{
   physmem_copy_from_vm(d->vm,desc,addr,sizeof(struct sdma_desc));

   /* byte-swapping */
   desc->buf_size = vmtoh32(desc->buf_size);
   desc->cmd_stat = vmtoh32(desc->cmd_stat);
   desc->next_ptr = vmtoh32(desc->next_ptr);
   desc->buf_ptr  = vmtoh32(desc->buf_ptr);
}
示例#3
0
/* Read an RX descriptor */
static void rxdesc_read(struct pos_oc3_data *d,m_uint32_t rxd_addr,
                        struct rx_desc *rxd)
{
#if DEBUG_RECEIVE
   POS_LOG(d,"reading RX descriptor at address 0x%x\n",rxd_addr);
#endif

   /* get the next descriptor from VM physical RAM */
   physmem_copy_from_vm(d->vm,rxd,rxd_addr,sizeof(struct rx_desc));

   /* byte-swapping */
   rxd->rdes[0] = vmtoh32(rxd->rdes[0]);
   rxd->rdes[1] = vmtoh32(rxd->rdes[1]);
}
/* Start TX DMA process */
static int mv64460_sdma_tx_start(struct mv64460_data *d,
                                 struct sdma_channel *chan)
{   
   u_char pkt[MV64460_MAX_PKT_SIZE],*pkt_ptr;
   struct sdma_desc txd0,ctxd,*ptxd;
   m_uint32_t tx_start,tx_current;
   m_uint32_t len,tot_len;
   int abort = FALSE;

   tx_start = tx_current = chan->sctdp;

   if (!tx_start)
      return(FALSE);

   ptxd = &txd0;
   mv64460_sdma_desc_read(d,tx_start,ptxd);

   /* If we don't own the first descriptor, we cannot transmit */
   if (!(txd0.cmd_stat & MV64460_TXDESC_OWN))
      return(FALSE);

   /* Empty packet for now */
   pkt_ptr = pkt;
   tot_len = 0;

   for(;;)
   {
      /* Copy packet data to the buffer */
      len = ptxd->buf_size & MV64460_TXDESC_BC_MASK;
      len >>= MV64460_TXDESC_BC_SHIFT;

      physmem_copy_from_vm(d->vm,pkt_ptr,ptxd->buf_ptr,len);
      pkt_ptr += len;
      tot_len += len;

      /* Clear the OWN bit if this is not the first descriptor */
      if (!(ptxd->cmd_stat & MV64460_TXDESC_F)) {
         ptxd->cmd_stat &= ~MV64460_TXDESC_OWN;
         physmem_copy_u32_to_vm(d->vm,tx_current+4,ptxd->cmd_stat);
      }

      //ptxd->buf_size &= 0xFFFF0000;
      //physmem_copy_u32_to_vm(d->vm,tx_current,ptxd->buf_size);

      tx_current = ptxd->next_ptr;

      /* Last descriptor or no more desc available ? */
      if (ptxd->cmd_stat & MV64460_TXDESC_L)
         break;

      if (!tx_current) {
         abort = TRUE;
         break;
      }

      /* Fetch the next descriptor */
      mv64460_sdma_desc_read(d,tx_current,&ctxd);
      ptxd = &ctxd;
   }

   if ((tot_len != 0) && !abort) {
#if DEBUG_SDMA
      MV64460_LOG(d,"SDMA%u: sending packet of %u bytes\n",tot_len);
      mem_dump(log_file,pkt,tot_len);
#endif
      /* send it on wire */
      mv64460_sdma_send_buffer(d,chan->id,pkt,tot_len);

      /* Signal that a TX buffer has been transmitted */
      mv64460_sdma_set_cause(d,chan->id,MV64460_SDMA_CAUSE_TXBUF0);
   }

   /* Clear the OWN flag of the first descriptor */
   txd0.cmd_stat &= ~MV64460_TXDESC_OWN;
   physmem_copy_u32_to_vm(d->vm,tx_start+4,txd0.cmd_stat);

   chan->sctdp = tx_current;

   if (abort || !tx_current) {
      mv64460_sdma_set_cause(d,chan->id,MV64460_SDMA_CAUSE_TXEND0);
      chan->sdcm &= ~MV64460_SDCMR_TXD;
   }

   /* Update interrupt status */
   mv64460_sdma_update_int_status(d);
   return(TRUE);
}
示例#5
0
/* Handle the TX ring */
static int dev_pos_oc3_handle_txring(struct pos_oc3_data *d)
{
   u_char pkt[POS_OC3_MAX_PKT_SIZE],*pkt_ptr;
   m_uint32_t clen,tot_len,norm_len;
   m_uint32_t tx_start,addr;
   struct tx_desc txd0,ctxd,*ptxd;
   int i,done = FALSE;

   if ((d->tx_start == 0) || (d->nio == NULL))
      return(FALSE);

   /* Copy the current txring descriptor */
   tx_start = d->tx_current;   
   ptxd = &txd0;
   txdesc_read(d,d->tx_current,ptxd);

   /* If we don't own the descriptor, we cannot transmit */
   if (!(txd0.tdes[0] & POS_OC3_TXDESC_OWN))
      return(FALSE);

#if DEBUG_TRANSMIT
   POS_LOG(d,"pos_oc3_handle_txring: 1st desc: tdes[0]=0x%x, tdes[1]=0x%x\n",
           ptxd->tdes[0],ptxd->tdes[1]);
#endif

   pkt_ptr = pkt;
   tot_len = 0;
   i = 0;

   do {
#if DEBUG_TRANSMIT
      POS_LOG(d,"pos_oc3_handle_txring: loop: tdes[0]=0x%x, tdes[1]=0x%x\n",
              ptxd->tdes[0],ptxd->tdes[1]);
#endif

      if (!(ptxd->tdes[0] & POS_OC3_TXDESC_OWN)) {
         POS_LOG(d,"pos_oc3_handle_txring: descriptor not owned!\n");
         return(FALSE);
      }

      clen = ptxd->tdes[0] & POS_OC3_TXDESC_LEN_MASK;

      /* Be sure that we have length not null */
      if (clen != 0) {
         addr = ptxd->tdes[1];

         norm_len = normalize_size(clen,4,0);
         physmem_copy_from_vm(d->vm,pkt_ptr,addr,norm_len);
         mem_bswap32(pkt_ptr,norm_len);
      }

      pkt_ptr += clen;
      tot_len += clen;

      /* Clear the OWN bit if this is not the first descriptor */
      if (i != 0)
         physmem_copy_u32_to_vm(d->vm,d->tx_current,0);

      /* Go to the next descriptor */
      txdesc_set_next(d,ptxd);

      /* Copy the next txring descriptor */
      if (ptxd->tdes[0] & POS_OC3_TXDESC_CONT) {
         txdesc_read(d,d->tx_current,&ctxd);
         ptxd = &ctxd;
         i++;
      } else
         done = TRUE;
   }while(!done);

   if (tot_len != 0) {
#if DEBUG_TRANSMIT
      POS_LOG(d,"sending packet of %u bytes (flags=0x%4.4x)\n",
              tot_len,txd0.tdes[0]);
      mem_dump(log_file,pkt,tot_len);
#endif   
      /* send it on wire */
      netio_send(d->nio,pkt,tot_len);
   }

   /* Clear the OWN flag of the first descriptor */
   txd0.tdes[0] &= ~POS_OC3_TXDESC_OWN;
   physmem_copy_u32_to_vm(d->vm,tx_start,txd0.tdes[0]);

   /* Interrupt on completion */
   pci_dev_trigger_irq(d->vm,d->pci_dev);
   return(TRUE);
}
/*
 * dev_remote_control_access()
 */
void *dev_remote_control_access(cpu_gen_t *cpu,struct vdevice *dev,
                                m_uint32_t offset,u_int op_size,u_int op_type,
                                m_uint64_t *data)
{
   vm_instance_t *vm = cpu->vm;
   struct remote_data *d = dev->priv_data;
   struct vdevice *storage_dev;
   size_t len;

   if (op_type == MTS_READ)
      *data = 0;

#if DEBUG_ACCESS
   if (op_type == MTS_READ) {
      cpu_log(cpu,"REMOTE","reading reg 0x%x at pc=0x%llx\n",
              offset,cpu_get_pc(cpu));
   } else {
      cpu_log(cpu,"REMOTE","writing reg 0x%x at pc=0x%llx, data=0x%llx\n",
              offset,cpu_get_pc(cpu),*data);
   }
#endif

   switch(offset) {
      /* ROM Identification tag */
      case 0x000: 
         if (op_type == MTS_READ)
            *data = ROM_ID;
         break;

      /* CPU ID */
      case 0x004: 
         if (op_type == MTS_READ)
            *data = cpu->id;
         break;

      /* Display CPU registers */
      case 0x008:
         if (op_type == MTS_WRITE)
            cpu->reg_dump(cpu);
         break;

      /* Display CPU memory info */
      case 0x00c:
         if (op_type == MTS_WRITE)
            cpu->mmu_dump(cpu);
         break;

      /* Reserved/Unused */
      case 0x010:
         break;

      /* RAM size */
      case 0x014: 
         if (op_type == MTS_READ)
            *data = vm->ram_size;
         break;

      /* ROM size */
      case 0x018: 
         if (op_type == MTS_READ)
            *data = vm->rom_size;
         break;

      /* NVRAM size */
      case 0x01c: 
         if (op_type == MTS_READ)
            *data = vm->nvram_size;
         break;             

      /* IOMEM size */
      case 0x020:
        if (op_type == MTS_READ)
            *data = vm->iomem_size;
         break;

      /* Config Register */
      case 0x024:
         if (op_type == MTS_READ)
            *data = vm->conf_reg;
         break;

      /* ELF entry point */
      case 0x028: 
         if (op_type == MTS_READ)
            *data = vm->ios_entry_point;
         break;      

      /* ELF machine id */
      case 0x02c:
         if (op_type == MTS_READ)
            *data = vm->elf_machine_id;
         break;

      /* Restart IOS Image */
      case 0x030:
         /* not implemented */
         break;

      /* Stop the virtual machine */
      case 0x034:
          // FIXME: WTF is this for?!?!?
         //vm->status = VM_STATUS_SHUTDOWN;
         break;

      /* Debugging/Log message: /!\ physical address */
      case 0x038:
         if (op_type == MTS_WRITE) {
            len = physmem_strlen(vm,*data);
            if (len < sizeof(d->con_buffer)) {
               physmem_copy_from_vm(vm,d->con_buffer,*data,len+1);
               vm_log(vm,"ROM",d->con_buffer);
            }
         }
         break;

      /* Console Buffering */
      case 0x03c:
         if (op_type == MTS_WRITE) {
            if (d->con_buf_pos < (sizeof(d->con_buffer)-1)) {
               d->con_buffer[d->con_buf_pos++] = *data & 0xFF;
               d->con_buffer[d->con_buf_pos] = 0;

               if (d->con_buffer[d->con_buf_pos-1] == '\n') {
                  vm_log(vm,"ROM","%s",d->con_buffer);
                  d->con_buf_pos = 0;
               }
            } else
               d->con_buf_pos = 0;
         }
         break;

      /* Console output */
      case 0x040:
         if (op_type == MTS_WRITE)
            vtty_put_char(vm->vtty_con,(char)*data);
         break;

      /* NVRAM address */
      case 0x044:
         if (op_type == MTS_READ) {
            if ((storage_dev = dev_get_by_name(vm,"nvram")))
               *data = storage_dev->phys_addr;

            if ((storage_dev = dev_get_by_name(vm,"ssa")))
               *data = storage_dev->phys_addr;

            if (cpu->type == CPU_TYPE_MIPS64)
               *data += MIPS_KSEG1_BASE;
         }
         break;

      /* IO memory size for Smart-Init (C3600, others ?) */
      case 0x048:
         if (op_type == MTS_READ)
            *data = vm->nm_iomem_size;
         break;

      /* Cookie position selector */
      case 0x04c:
         if (op_type == MTS_READ)
            *data = d->cookie_pos;
         else
            d->cookie_pos = *data;
         break;
         
      /* Cookie data */
      case 0x050:
         if ((op_type == MTS_READ) && (d->cookie_pos < 64))
            *data = vm->chassis_cookie[d->cookie_pos];
         break;

      /* ROMMON variable */
      case 0x054:
         if (op_type == MTS_WRITE) {
            if (d->var_buf_pos < (sizeof(d->var_buffer)-1)) {
               d->var_buffer[d->var_buf_pos++] = *data & 0xFF;
               d->var_buffer[d->var_buf_pos] = 0;
            } else
               d->var_buf_pos = 0;
         } else {
            if (d->var_buf_pos < (sizeof(d->var_buffer)-1)) {
               *data = d->var_buffer[d->var_buf_pos++];
            } else {
               d->var_buf_pos = 0;
               *data = 0;
            }
         }
         break;

      /* ROMMON variable command */
      case 0x058:
         if (op_type == MTS_WRITE) {
            switch(*data & 0xFF) {
               case ROMMON_SET_VAR:
                  d->var_status = rommon_var_add_str(&vm->rommon_vars,
                                                     d->var_buffer);
                  d->var_buf_pos = 0;
                  break;
               case ROMMON_GET_VAR:
                  d->var_status = rommon_var_get(&vm->rommon_vars,
                                                 d->var_buffer,
                                                 d->var_buffer,
                                                 sizeof(d->var_buffer));
                  d->var_buf_pos = 0;
                  break;
               case ROMMON_CLEAR_VAR_STAT:
                  d->var_buf_pos = 0;
                  break;
               default:
                  d->var_status = -1;
            }
         } else {
            *data = d->var_status;
         }
         break;
   }

   return NULL;
}