Exemplo n.º 1
0
static void
qxl_load_cursor_argb (ScrnInfoPtr pScrn, CursorPtr pCurs)
{
    qxl_screen_t *qxl = pScrn->driverPrivate;
    int w = pCurs->bits->width;
    int h = pCurs->bits->height;
    int size = w * h * sizeof (CARD32);

    struct QXLCursorCmd *cmd = qxl_alloc_cursor_cmd (qxl);
    struct QXLCursor *cursor =
	qxl_allocnf(qxl, sizeof(struct QXLCursor) + size);

    cursor->header.unique = 0;
    cursor->header.type = SPICE_CURSOR_TYPE_ALPHA;
    cursor->header.width = w;
    cursor->header.height = h;
    /* I wonder if we can just tell the client that the hotspot is 0, 0
     * always? The coordinates we are getting from X are for 0, 0 anyway,
     * so the question is if the client uses the hotspot for anything else?
     */
    cursor->header.hot_spot_x = pCurs->bits->xhot;
    cursor->header.hot_spot_y = pCurs->bits->yhot;

    cursor->data_size = size;
    
    cursor->chunk.next_chunk = 0;
    cursor->chunk.prev_chunk = 0;
    cursor->chunk.data_size = size;

    memcpy (cursor->chunk.data, pCurs->bits->argb, size);

#if 0
    int i, j;
    for (j = 0; j < h; ++j)
    {
	for (i = 0; i < w; ++i)
	{
	    ErrorF ("%c", (pCurs->bits->argb[j * w + i] & 0xff000000) == 0xff000000? '#' : '.');
	}

	ErrorF ("\n");
    }
#endif

    qxl->hot_x = pCurs->bits->xhot;
    qxl->hot_y = pCurs->bits->yhot;
    
    cmd->type = QXL_CURSOR_SET;
    cmd->u.set.position.x = qxl->cur_x + qxl->hot_x;
    cmd->u.set.position.y = qxl->cur_y + qxl->hot_y;
    cmd->u.set.shape = physical_address (qxl, cursor, qxl->main_mem_slot);
    cmd->u.set.visible = TRUE;

    push_cursor(qxl, cmd);
}    
Exemplo n.º 2
0
static void
push_cursor (qxl_screen_t *qxl, struct QXLCursorCmd *cursor)
{
    struct QXLCommand cmd;

    /* See comment on push_command() in qxl_driver.c */
    if (qxl->pScrn->vtSema)
    {
        cmd.type = QXL_CMD_CURSOR;
        cmd.data = physical_address (qxl, cursor, qxl->main_mem_slot);
      
        qxl_ring_push (qxl->cursor_ring, &cmd);
    }
}
Exemplo n.º 3
0
static void
qxl_update_monitors_config (qxl_screen_t *qxl)
{
    int i;
    QXLHead *head;
    xf86CrtcPtr crtc;
    qxl_output_private *qxl_output;
    QXLRam * ram = get_ram_header (qxl);

    if (check_crtc (qxl) == 0)
        return;

    qxl->monitors_config->count = 0;
    qxl->monitors_config->max_allowed = qxl->num_heads;
    for (i = 0 ; i < qxl->num_heads; ++i)
    {
	head = &qxl->monitors_config->heads[qxl->monitors_config->count];
	crtc = qxl->crtcs[i];
	qxl_output = qxl->outputs[i]->driver_private;
	head->id = i;
	head->surface_id = 0;
	head->flags = 0;

	if (!crtc->enabled || crtc->mode.CrtcHDisplay == 0 ||
	    crtc->mode.CrtcVDisplay == 0)
	{
	    head->width = head->height = head->x = head->y = 0;
	    qxl_output->status = XF86OutputStatusDisconnected;
	}
	else
	{
	    head->width = crtc->mode.CrtcHDisplay;
	    head->height = crtc->mode.CrtcVDisplay;
	    head->x = crtc->x;
	    head->y = crtc->y;
	    qxl->monitors_config->count++;
	    qxl_output->status = XF86OutputStatusConnected;
	}
    }
    /* initialize when actually used, memslots should be initialized by now */
    if (ram->monitors_config == 0)
    {
	ram->monitors_config = physical_address (qxl, qxl->monitors_config,
	                                         qxl->main_mem_slot);
    }

    qxl_io_monitors_config_async (qxl);
}
Exemplo n.º 4
0
/*=======================================================================*/
void *dma_memcpy(void *to, const void *from, __kernel_size_t n)
{
	u32 phys_from, phys_to;	
	u32 unaligned_to;
	unsigned long flags;

	DPRINTK("dma_memcopy: entering\n");

	/* This is used in the very early stages */
	if(!idma_init)
    		return asm_memmove(to, from,n);

	/* Fallback for the case that one or both buffers are not physically contiguous  */
	if(!virt_addr_valid(to) || !virt_addr_valid(from))
        {
		DPRINTK("Failing back to asm_memmove because of limitations\n");
            return asm_memmove(to,from,n);
        }	

	/* Check for Overlap */
	if (((to + n > from) && (to < from)) ||((from < to) && (from + n > to))) 
	{
		DPRINTK("overlapping copy region (0x%x, 0x%x, %lu), falling back\n",
		     to, from, (unsigned long)n);
		return asm_memmove(to, from, n);
	}

	++dma_memcpy_cnt;

	/*
	 * Ok, start addr is not cache line-aligned, so we need to make it so.
	 */
	unaligned_to = (u32)to & 31;
	if(unaligned_to)
	{
		DPRINTK("Fixing up starting address %d bytes\n", 32 - unaligned_to);

		asm_memmove(to, from, 32 - unaligned_to);

		to = (void*)((u32)to + (32 - unaligned_to));
		from = (void*)((u32)from + (32 - unaligned_to));

                /*it's ok, n supposed to be greater than 32 bytes at this point*/
		n -= (32 - unaligned_to);
	}	

        spin_lock_irqsave(&current->mm->page_table_lock, flags);
        if (idma_busy)
        {
            /*
             * The idma engine is busy,
             * might happen when dma_copy_to/from_user will call the arch_copy_to/from_user
             * which might cause a page fault, that can lead to a memcpy or memzero.
             */
            DPRINTK(" idma is busy... \n");
            spin_unlock_irqrestore(&current->mm->page_table_lock, flags);
            return asm_memmove(to, from, n);
        }
        idma_busy = 1;
     
        phys_from = physical_address((u32)from, 0);
        phys_to = physical_address((u32)to, 1);
	
    	/*
	 *  Prepare the IDMA.
	 */
	if ((!phys_from) || (!phys_to))
        {
	    /* The requested page isn't available, fall back to */
            DPRINTK(" no physical address, fall back: from %p , to %p \n", from, to);
	    idma_busy = 0;
	    spin_unlock_irqrestore(&current->mm->page_table_lock, flags);
            return asm_memmove(to, from,n);
        }
        else
        {
	    /* 
	     * Ensure that the cache is clean:
	     *      - from range must be cleaned
	     *      - to range must be invalidated
	     */
		dmac_flush_range(from, from + n);
		dmac_inv_range(to, to + n);

               
	    /* Start DMA */
            DPRINTK(" activate DMA: channel %d from %x to %x len %x\n",CPY_CHAN1, phys_from, phys_to, n);
	    mvDmaTransfer(CPY_CHAN1, phys_from, phys_to, n, 0);
#ifdef RT_DEBUG
                    dma_activations++;
#endif
	}
        
	if(wait_for_idma(CPY_CHAN1))
        {
	    BUG(); 
	}	
        
        DPRINTK("dma_memcopy(0x%x, 0x%x, %lu): exiting\n", (u32) to, (u32) from, n);

	idma_busy = 0;
	spin_unlock_irqrestore(&current->mm->page_table_lock, flags);
       
        return 0;
}
Exemplo n.º 5
0
/*=======================================================================*/
void dma_memzero(void *to, __kernel_size_t n)
{
	u32 phys_from, phys_to;	
	u32 unaligned_to;
	unsigned long flags;	

	DPRINTK("dma_memcopy: entering\n");

	/* This is used in the very early stages */
	if(!idma_init)
    		return asm_memzero(to ,n);

	/* Fallback for the case that one or both buffers are not physically contiguous  */
	if(!virt_addr_valid(to))
        {
		DPRINTK("Failing back to asm_memzero because of limitations\n");
            return asm_memzero(to ,n);
        }	

	++dma_memzero_cnt;	

	/*
	 * If buffer start addr is not cache line-aligned, so we need to make it so.
	 */
	unaligned_to = (u32)to & 31;
	if(unaligned_to)
	{
		DPRINTK("Fixing up starting address %d bytes\n", 32 - unaligned_to);

		asm_memzero(to, 32 - unaligned_to);

		to = (void*)((u32)to + (32 - unaligned_to));

                /*it's ok, n supposed to be greater than 32 bytes at this point*/
		n -= (32 - unaligned_to);
	}	

	/*
	 * If buffer end addr is not cache line-aligned, so we need to make it so.
	 */
	unaligned_to = ((u32)to + n) & 31;
	if(unaligned_to)
	{	
		u32 tmp_to = (u32)to + (n - unaligned_to);
		DPRINTK("Fixing ending alignment %d bytes\n", unaligned_to);

		asm_memzero((void *)tmp_to, unaligned_to);

                /*it's ok, n supposed to be greater than 32 bytes at this point*/
		n -= unaligned_to;
	}

	phys_from = physical_address((u32)dmaMemInitBuff, 0);
        phys_to = physical_address((u32)to, 1);

	/*
	 *  Prepare the IDMA.
	 */
	if ((!phys_from) || (!phys_to))
        {
	    /* The requested page isn't available, fall back to */
            DPRINTK(" no physical address, fall back: to %p \n", to);
            return asm_memzero(to,n);
        }

        spin_lock_irqsave(&current->mm->page_table_lock, flags);
	if (idma_busy)
	{
            /* 
	     * The idma engine is busy, 
  	     * might happen when dma_copy_to/from_user will call the arch_copy_to/from_user 
	     * which might cause a page fault, that can lead to a memcpy or memzero.	
	     */
            DPRINTK(" idma is busy... \n");
	    spin_unlock_irqrestore(&current->mm->page_table_lock, flags);
            return asm_memzero(to,n);
	}
	idma_busy = 1;

	/* Ensure that the destination revion is invalidated */
	mvOsCacheInvalidate(NULL, (void *)to, n);
	
	/* Start DMA */
        DPRINTK(" activate DMA: channel %d from %x with source hold to %x len %x\n",CPY_CHAN1, phys_from, phys_to, n);
     	mvDmaMemInit(CPY_CHAN1, phys_from, phys_to, n);
	
#ifdef RT_DEBUG
	dma_activations++;
#endif
        
	if(wait_for_idma(CPY_CHAN1))
        {
	    BUG(); 
	}	

        DPRINTK("dma_memzero(0x%x, %lu): exiting\n", (u32) to, n);

	idma_busy = 0;
	spin_unlock_irqrestore(&current->mm->page_table_lock, flags);
}
Exemplo n.º 6
0
/*=======================================================================*/
static unsigned long dma_copy(void *to, const void *from, unsigned long n, unsigned int to_user)
{
	u32 chunk,i;
	u32 k_chunk = 0;
	u32 u_chunk = 0;
	u32 phys_from, phys_to;
	
        unsigned long flags;
	u32 unaligned_to;
	u32 index = 0;
        u32 temp;

        unsigned long uaddr, kaddr;
        unsigned char kaddr_kernel_static = 0;
	DPRINTK("dma_copy: entering\n");


	/* 
      	 * The unaligned is taken care seperatly since the dst might be part of a cache line that is changed 
	 * by other process -> we must not invalidate this cache lines and we can't also flush it, since other 
	 * process (or the exception handler) might fetch the cache line before we copied it. 
	 */

	/*
	 * Ok, start addr is not cache line-aligned, so we need to make it so.
	 */
	unaligned_to = (u32)to & 31;
	if(unaligned_to)
	{
		DPRINTK("Fixing up starting address %d bytes\n", 32 - unaligned_to);

		if(to_user)
		{
		    if(__arch_copy_to_user(to, from, 32 - unaligned_to)) 
			goto exit_dma; 
		}
		else
		{
		    if(__arch_copy_from_user(to, from, 32 - unaligned_to)) 
			goto exit_dma;
		}

		temp = (u32)to + (32 - unaligned_to);
		to = (void *)temp;
		temp = (u32)from + (32 - unaligned_to);
		from = (void *)temp;

                /*it's ok, n supposed to be greater than 32 bytes at this point*/
		n -= (32 - unaligned_to);
	}

	/*
	 * Ok, we're aligned at the top, now let's check the end
	 * of the buffer and align that. After this we should have
	 * a block that is a multiple of cache line size.
	 */
	unaligned_to = ((u32)to + n) & 31;
	if(unaligned_to)
	{	
		u32 tmp_to = (u32)to + (n - unaligned_to);
		u32 tmp_from = (u32)from + (n - unaligned_to);
		DPRINTK("Fixing ending alignment %d bytes\n", unaligned_to);

		if(to_user)
		{
		    if(__arch_copy_to_user((void *)tmp_to, (void *)tmp_from, unaligned_to))
			goto exit_dma;
		}
		else
		{
		    if(__arch_copy_from_user((void *)tmp_to, (void *)tmp_from, unaligned_to))
			goto exit_dma;
		}

                /*it's ok, n supposed to be greater than 32 bytes at this point*/
		n -= unaligned_to;
	}

        if(to_user)
        {
            uaddr = (unsigned long)to;  
            kaddr = (unsigned long)from;
        }
        else
        {
             uaddr = (unsigned long)from;
             kaddr = (unsigned long)to;
        }
        if(virt_addr_valid(kaddr))
        {
            kaddr_kernel_static = 1;
            k_chunk = n;
        }
	else
	{
		DPRINTK("kernel address is not linear, fall back\n");
		goto exit_dma;
	}
         
        spin_lock_irqsave(&current->mm->page_table_lock, flags);
	if (idma_busy)
	{
	    BUG();
	}
	idma_busy = 1;
     
        i = 0;
	while(n > 0)
	{
	    if(k_chunk == 0)
	    {
                /* virtual address */
	        k_chunk = page_remainder((u32)kaddr);
		DPRINTK("kaddr reminder %d \n",k_chunk);
	    }

	    if(u_chunk == 0)
	    {
                u_chunk = page_remainder((u32)uaddr);
                DPRINTK("uaddr reminder %d \n", u_chunk);
            }
        
            chunk = ((u_chunk < k_chunk) ? u_chunk : k_chunk);
            if(n < chunk)
	    {
		chunk = n;
	    }

	    if(chunk == 0)
	    {
	    	break;
	    }
            phys_from = physical_address((u32)from, 0);
            phys_to = physical_address((u32)to, 1);
	    DPRINTK("choose chunk %d \n",chunk);
	    /* if page doesn't exist go out */
	    if ((!phys_from) || (!phys_to))
	    {
		/* The requested page isn't available, fall back to */
		DPRINTK(" no physical address, fall back: from %p , to %p \n", from, to);
		goto wait_for_idmas;
   
	    }
	    /*
	     *  Prepare the IDMA.
	     */
            if (chunk < IDMA_MIN_COPY_CHUNK)
            {
        	DPRINTK(" chunk %d too small , use memcpy \n",chunk);
                /* the "to" address might cross cache line boundary, so part of the line*/  
                /* may be subject to DMA, so we need to wait to last DMA engine to finish */
                if (index > 0)
                {
                    if(wait_for_idma(PREV_CHANNEL(current_dma_channel)))
                    {
	                BUG();
                    }
                }
                

                if(to_user) 
		{
	       	    if(__arch_copy_to_user((void *)to, (void *)from, chunk)) {
			printk("ERROR: %s %d shouldn't happen\n",__FUNCTION__, __LINE__);	
			goto wait_for_idmas;
		    }
		}
	        else
		{
	            if(__arch_copy_from_user((void *)to, (void *)from, chunk)) {
			printk("ERROR: %s %d shouldn't happen\n",__FUNCTION__, __LINE__);	
			goto wait_for_idmas;	
		    }
		}
           }
            else
            {
                /* 
	 	 * Ensure that the cache is clean:
	 	 *      - from range must be cleaned
        	 *      - to range must be invalidated
	         */
		dmac_flush_range(from, from + chunk);
		dmac_inv_range(to, to + chunk);
               
               	    if(index > 1)
		    {
		        if(wait_for_idma(current_dma_channel))
                        {
		            BUG(); 
                            goto unlock_dma;
                        }
                    }
		    /* Start DMA */
                    DPRINTK(" activate DMA: channel %d from %x to %x len %x\n",
                            current_dma_channel, phys_from, phys_to, chunk);
		    mvDmaTransfer(current_dma_channel, phys_from, phys_to, chunk, 0);
                    current_dma_channel = NEXT_CHANNEL(current_dma_channel); 
#ifdef RT_DEBUG
                    dma_activations++;
#endif
		    index++;
                }
                

		/* go to next chunk */
		from += chunk;
		to += chunk;
                kaddr += chunk;
                uaddr += chunk;
		n -= chunk;
		u_chunk -= chunk;
		k_chunk -= chunk;		
	}
        
wait_for_idmas:
        if (index > 1)
        {
	    if(wait_for_idma(current_dma_channel))
            {
	        BUG(); 
            }
        }

        if (index > 0)
        {
            if(wait_for_idma(PREV_CHANNEL(current_dma_channel)))
            {
	        BUG();
            }
        }

unlock_dma:    
	idma_busy = 0;    
        spin_unlock_irqrestore(&current->mm->page_table_lock, flags);
 exit_dma:
        
        DPRINTK("dma_copy(0x%x, 0x%x, %lu): exiting\n", (u32) to,
                (u32) from, n);
       

        if(n != 0)
        {
       	    if(to_user)
                return __arch_copy_to_user((void *)to, (void *)from, n);
	            else
                return __arch_copy_from_user((void *)to, (void *)from, n);
        }
        return 0;
}
Exemplo n.º 7
0
void spiceqxl_display_monitors_config(qxl_screen_t *qxl)
{
    spice_qxl_monitors_config_async(&qxl->display_sin, physical_address(qxl, qxl->monitors_config, 0),
                                    MEMSLOT_GROUP, 0);
}
Exemplo n.º 8
0
/*
 * n must be greater equal than 64.
 */
static unsigned long xor_dma_copy(void *to, const void *from, unsigned long n, unsigned int to_user)
{
	u32 chunk,i;
	u32 k_chunk = 0;
	u32 u_chunk = 0;
	u32 phys_from, phys_to;
	
        unsigned long flags;
	u32 unaligned_to;
	u32 index = 0;
        u32 temp;

        unsigned long uaddr, kaddr;
	int     chan1, chan2 = -1;
        int     current_channel;
        struct xor_channel_t *channel;
       
        DPRINTK("xor_dma_copy: entering\n");


        chan1 = allocate_channel();
        if (chan1 != -1)
        {
            chan2 = allocate_channel();
            if(chan2 == -1)
            {
                free_channel(&xor_channel[chan1]);
            }
        }
        if((chan1 == -1) || (chan2 == -1))
        {
            goto exit_dma;
        }
        current_channel = chan1;
	/* 
      	 * The unaligned is taken care seperatly since the dst might be part of a cache line that is changed 
	 * by other process -> we must not invalidate this cache lines and we can't also flush it, since other 
	 * process (or the exception handler) might fetch the cache line before we copied it. 
	 */

	/*
	 * Ok, start addr is not cache line-aligned, so we need to make it so.
	 */
	unaligned_to = (u32)to & 31;
	if(unaligned_to)
	{
		DPRINTK("Fixing up starting address %d bytes\n", 32 - unaligned_to);

		if(to_user)
		{
		    if(__arch_copy_to_user(to, from, 32 - unaligned_to)) 
			goto free_channels; 
		}
		else
		{
		    if(__arch_copy_from_user(to, from, 32 - unaligned_to)) 
			goto free_channels;
		}

		temp = (u32)to + (32 - unaligned_to);
		to = (void *)temp;
		temp = (u32)from + (32 - unaligned_to);
		from = (void *)temp;

                /*it's ok, n supposed to be greater than 32 bytes at this point*/
		n -= (32 - unaligned_to);
	}

	/*
	 * Ok, we're aligned at the top, now let's check the end
	 * of the buffer and align that. After this we should have
	 * a block that is a multiple of cache line size.
	 */
	unaligned_to = ((u32)to + n) & 31;
	if(unaligned_to)
	{	
		u32 tmp_to = (u32)to + (n - unaligned_to);
		u32 tmp_from = (u32)from + (n - unaligned_to);
		DPRINTK("Fixing ending alignment %d bytes\n", unaligned_to);

		if(to_user)
		{
		    if(__arch_copy_to_user((void *)tmp_to, (void *)tmp_from, unaligned_to))
			goto free_channels;
		}
		else
		{
		    if(__arch_copy_from_user((void *)tmp_to, (void *)tmp_from, unaligned_to))
			goto free_channels;
		}

                /*it's ok, n supposed to be greater than 32 bytes at this point*/
		n -= unaligned_to;
	}

        if(to_user)
        {
            uaddr = (unsigned long)to;  
            kaddr = (unsigned long)from;
        }
        else
        {
             uaddr = (unsigned long)from;
             kaddr = (unsigned long)to;
        }
        if(virt_addr_valid(kaddr))
        {
            k_chunk = n;
        }
	else
	{
		DPRINTK("kernel address is not linear, fall back\n");
		goto free_channels;		
	}
         
        spin_lock_irqsave(&current->mm->page_table_lock, flags);
     
        i = 0;
	while(n > 0)
	{
	    if(k_chunk == 0)
	    {
                /* virtual address */
	        k_chunk = page_remainder((u32)kaddr);
		DPRINTK("kaddr reminder %d \n",k_chunk);
	    }

	    if(u_chunk == 0)
	    {
                u_chunk = page_remainder((u32)uaddr);
                DPRINTK("uaddr reminder %d \n", u_chunk);
            }
        
            chunk = ((u_chunk < k_chunk) ? u_chunk : k_chunk);
            if(n < chunk)
	    {
		chunk = n;
	    }

	    if(chunk == 0)
	    {
	    	break;
	    }
            phys_from = physical_address((u32)from, 0);
            phys_to = physical_address((u32)to, 1);
	    DPRINTK("choose chunk %d \n",chunk);
	    /* if page doesn't exist go out */
	    if ((!phys_from) || (!phys_to))
	    {
		/* The requested page isn't available, fall back to */
		DPRINTK(" no physical address, fall back: from %p , to %p \n", from, to);
		goto unlock_dma;
   
	    }
	    /*
	     *  Prepare the IDMA.
	     */
            if (chunk < XOR_MIN_COPY_CHUNK)
            {
                int last_chan = chan1;   
        	DPRINTK(" chunk %d too small , use memcpy \n",chunk);
        	
        	if(current_channel == chan1)
                {   
                    last_chan = chan2;
                }
                /* the "to" address might cross cache line boundary, so part of the line*/  
                /* may be subject to DMA, so we need to wait to last DMA engine to finish */
                if(index > 0)
                    xor_waiton_eng(last_chan);

                if(to_user) 
		{
	       	    if(__arch_copy_to_user((void *)to, (void *)from, chunk)) {
			printk("ERROR: %s %d shouldn't happen\n",__FUNCTION__, __LINE__);	
			goto unlock_dma;
		    }
		}
	        else
		{
	            if(__arch_copy_from_user((void *)to, (void *)from, chunk)) {
			printk("ERROR: %s %d shouldn't happen\n",__FUNCTION__, __LINE__);	
			goto unlock_dma;	
		    }
		}
            }
            else
	    {
		
		    /* 
		    * Ensure that the cache is clean:
		    *      - from range must be cleaned
		    *      - to range must be invalidated
		    */
//		    mvOsCacheFlush(NULL, (void *)from, chunk);
		    dmac_flush_range(from, from + chunk);
		    //	    mvOsCacheInvalidate(NULL, (void *)to, chunk);
		    dmac_inv_range(to, to + chunk);
		    if(index > 0)
		    {
			xor_waiton_eng(current_channel);
		    }
		    channel = &xor_channel[current_channel];
  
		    /* Start DMA */
		    DPRINTK(" activate DMA: channel %d from %x to %x len %x\n",
                            current_channel, phys_from, phys_to, chunk);
		    channel->pDescriptor->srcAdd0 = phys_from;
		    channel->pDescriptor->phyDestAdd = phys_to;
		    channel->pDescriptor->byteCnt = chunk;
		    channel->pDescriptor->phyNextDescPtr = 0;
		    channel->pDescriptor->status = BIT31;
		    channel->chan_active = 1;

		    if( mvXorTransfer(current_channel, MV_DMA, channel->descPhyAddr) != MV_OK)
		    {
			printk(KERN_ERR "%s: DMA copy operation on channel %d failed!\n", __func__, current_channel);
			print_xor_regs(current_channel);
			BUG();
		    }
                
		    if(current_channel == chan1) 
		    {
			current_channel = chan2;
                    }
		    else
		    {
			current_channel = chan1;
		    }
#ifdef RT_DEBUG
			dma_activations++;
#endif
			index++;
		    
		}

		/* go to next chunk */
		from += chunk;
		to += chunk;
                kaddr += chunk;
                uaddr += chunk;
		n -= chunk;
		u_chunk -= chunk;
		k_chunk -= chunk;		
	}
unlock_dma:
        xor_waiton_eng(chan1);
        xor_waiton_eng(chan2);
        spin_unlock_irqrestore(&current->mm->page_table_lock, flags);
free_channels:
        free_channel(&xor_channel[chan1]);
        free_channel(&xor_channel[chan2]);

exit_dma:        
        DPRINTK("xor_dma_copy(0x%x, 0x%x, %lu): exiting\n", (u32) to,
                (u32) from, n);
       
        if(n != 0)
        {
       	    if(to_user)
                return __arch_copy_to_user((void *)to, (void *)from, n);
	            else
                return __arch_copy_from_user((void *)to, (void *)from, n);
        }
        return 0;
}
Exemplo n.º 9
0
int sc_main(int, char *[])
{
  // Silence the following deprecation warning:
  // Info: (I804) /IEEE_Std_1666/deprecated: positional binding
  // using << or , is deprecated, use () instead.


  sc_report_handler::set_actions("/IEEE_Std_1666/deprecated", SC_DO_NOTHING);

  // ************************ ICACHE ***********************************
  // ICACHE = ram_cs
  // ICACHE = ram_we
  // ICACHE = addr
  // ICACHE = ram_datain
  // ICACHE = ram_dataout
  // ICACHE = ld_valid = pid_valid
  // ICACHE = ld_data = pid_data
  sc_signal<bool>       icache_valid("ICACHE_VALID") ;

  // ************************ BIOS ***********************************
  sc_signal<bool>       ram_cs("RAM_CS") ;
  sc_signal<bool>       ram_we("RAM_WE") ;
  sc_signal<unsigned >    addr("Address") ;
  sc_signal<unsigned >    ram_datain("RAM_DATAIN") ;
  sc_signal<unsigned >    ram_dataout("RAM_DATAOUT") ;
  sc_signal<bool>       bios_valid("BIOS_VALID") ;
  const int delay_cycles = 2;

  // ************************ Paging ***********************************
  // Paging paging_din = ram_datain
  // Paging paging_csin = ram_cs
  // Paging paging_wein = ram_we
  // Paging logical_address = addr 
  sc_signal<unsigned >    icache_din("ICACHE_DIN") ;
  sc_signal<bool>       icache_validin("ICACHE_VALIDIN") ;
  sc_signal<bool>       icache_stall("ICACHE_STALL") ;
  sc_signal<unsigned >    paging_dout("PAGING_DOUT") ;
  sc_signal<bool>       paging_csout("PAGING_CSOUT") ;
  sc_signal<bool>       paging_weout("PAGING_WEOUT") ;
  sc_signal<unsigned >    physical_address("PHYSICAL_ADDRESS") ;
  // Paging dataout  = ram_dataout 
  // Paging data_valid = icache_valid
  // Paging stall_ifu = stall_fetch


  // ************************ Fetch ***********************************
  // IFU ramdata = ram_dataout
  sc_signal<unsigned >    branch_target_address("BRANCH_TARGET_ADDRESS") ;
  sc_signal<bool>       next_pc("NEXT_PC") ;
  sc_signal<bool>       branch_valid("BRANCH_VALID") ;
  sc_signal<bool>       stall_fetch("STALL_FETCH") ;
  sc_signal<bool>       pred_fetch("PRED_FETCH") ;
  // IFU ram_valid = bios_valid
  // IFU ram_cs = ram_cs
  // IFU ram_we = ram_we
  // IFU address = addr
  // IFU smc_instrction = ram_datain
  // IFU pred_branch_address = pred_branch_address
  // IFU pred_branch_valid = pred_branch_valid
  sc_signal<unsigned>   instruction("INSTRUCTION") ;
  sc_signal<bool>       instruction_valid("INSTRUCTION_VALID") ;
  sc_signal<unsigned >    program_counter("PROGRAM_COUNTER") ;
  sc_signal<bool>       branch_clear("BRANCH_CLEAR") ;
  sc_signal<bool>       pred_fetch_valid("PRED_FETCH_VALID") ;
  sc_signal<bool>       reset("RESET") ;

  // ************************ Branch ***********************************
  // BPU: fetch_inst = instruction
  // BPU: fetch_pc = program_counter
  // BPU: fetch_valid = instruction_valid
  // BPU: branch_inst_addr = branch_instruction_address
  // BPU: branch_target_address = branch_target_address
  // BPU: branch_valid = branch_valid
  sc_signal<unsigned >	pred_branch_address("PRED_BRANCH_ADDRESS");
  sc_signal<bool>       pred_branch_valid("PRED_BRANCH_VALID") ;
  sc_signal<bool>       pred_tellid("PRED_TELLID") ;
  sc_signal<unsigned>   pred_instruction("PRED_INSTRUCTION") ;
  sc_signal<bool>       pred_inst_valid("PRED_INST_VALID") ;
  sc_signal<unsigned >	pred_inst_pc("PRED_INST_PC");


  // ************************ Decode ***********************************
  // ID instruction = instruction
  // ID instruction = instruction_valid
  // ID destreg_write = out_valid
  // ID destreg_write_src = destout
  // ID clear_branch     = branch_clear 
  // ID pc = program_counter
  sc_signal<bool>       pred_on("PRED_ON") ;
  sc_signal<unsigned >	branch_instruction_address("BR_INSTRUCTION_ADDRESS");
  // ID alu_dataout = dout from EXEC 
  sc_signal<signed>     dram_dataout("DRAM_DATAOUT") ;
  sc_signal<bool>       dram_rd_valid("DRAM_RD_VALID") ;
  sc_signal<unsigned>   dram_write_src("DRAM_WRITE_SRC");
  // ID next_pc     = next_pc
  // ID branch_valid = branch_valid
  // ID branch_target_address = branch_target_address
  sc_signal<bool>       mem_access("MEM_ACCESS") ;
  sc_signal<unsigned >    mem_address("MEM_ADDRESS") ;
  sc_signal<int>        alu_op("ALU_OP") ;
  sc_signal<bool>       mem_write("MEM_WRITE") ;
  sc_signal<unsigned>   alu_src("ALU_SRC") ;
  sc_signal<bool>       reg_write("REG_WRITE") ;
  sc_signal<signed int> src_A("SRC_A") ;
  sc_signal<signed int> src_B("SRC_B") ;
  sc_signal<bool>       forward_A("FORWARD_A") ;
  sc_signal<bool>       forward_B("FORWARD_B") ;
  // ID stall_fetch = stall_fetch
  sc_signal<bool>       decode_valid("DECODE_VALID") ;
  sc_signal<bool>       float_valid("FLOAT_VALID") ;
  sc_signal<bool>       mmx_valid("MMX_VALID") ;
  sc_signal<bool>       pid_valid("PID_VALID") ;
  sc_signal<signed>     pid_data("PID_DATA") ;

  // ************************ DCACHE  ***********************************
  sc_signal<signed>       mmic_datain("MMIC_DATAIN") ;	/* DCU: datain 	*/
  sc_signal<unsigned>     mmic_statein("MMIC_STATEIN") ;/* DCU: statein */
  sc_signal<bool>     	  mmic_cs("MMIC_CS") ;		/* DCU: cs 	*/
  sc_signal<bool>     	  mmic_we("MMIC_WE") ;		/* DCU: we 	*/
  sc_signal<unsigned >      mmic_addr("MMIC_ADDR") ; /* DCU: addr	*/
  sc_signal<unsigned>     mmic_dest("MMIC_DEST") ;	/* DCU: dest 	*/
  sc_signal<unsigned>     mmic_destout("MMIC_DESTOUT") ;/* DCU: destout */
  sc_signal<signed>       mmic_dataout("MMIC_DATAOUT") ;/* DCU: dataout */
  sc_signal<bool>         mmic_out_valid("MMIC_OUT_VALID") ;/* DCU: out_valid*/
  sc_signal<unsigned>     mmic_stateout("MMIC_STATEOUT") ;/* DCU: stateout */

  // ************************ Execute ***********************************
  // EXEC in_valid = decode_valid
  sc_signal<bool>   	in_valid("IN_VALID") ;
  // EXEC opcode = alu_op
  sc_signal<bool>   	negate("NEGATE") ;
  sc_signal<int>   	add1("ADD1") ;
  sc_signal<bool>   	shift_sel("SHIFT_SEL") ;
  // EXEC dina = src_A
  // EXEC dinb = src_B
  // EXEC dest = alu_src
  sc_signal<bool>   		c("C") ;
  sc_signal<bool>   		v("V") ;
  sc_signal<bool>   		z("Z") ;
  sc_signal<signed>   		dout("DOUT") ;
  sc_signal<bool>   		out_valid("OUTPUT_VALID") ;
  sc_signal<unsigned> 		destout("DESTOUT") ;

  // ************************ Floating point ******************************
  // FPU in_valid = float_valid
  // FPU opcode = alu_op
  // FPU floata = src_A
  // FPU floatb = src_B
  // FPU dest = alu_src
  sc_signal<signed> 		fdout("FDOUT") ;
  sc_signal<bool> 		fout_valid("FOUT_VALID") ;
  sc_signal<unsigned> 		fdestout("FDESTOUT") ;
  
  // ************************ PIC *****************************************
  sc_signal<bool> 		ireq0("IREQ0") ;
  sc_signal<bool> 		ireq1("IREQ1") ;
  sc_signal<bool> 		ireq2("IREQ2") ;
  sc_signal<bool> 		ireq3("IREQ3") ;
  // PIC cs = interrupt_ack
  // PIC intack_cpu = interrupt_ack
  sc_signal<bool> 		rd_wr("RD_WR") ;
  sc_signal<bool> 		intreq("INTREQ") ;
  sc_signal<unsigned> 		vectno("VECTNO") ;
  sc_signal<bool> 		intack("INTACK") ;
  sc_signal<bool> 		intack_cpu("INTACK_CPU") ;

  // ************************ MMX ***********************************
  // MMX mmx_valid = mmx_valid
  // MMX opcode = alu_op
  // MMX mmxa = src_A
  // MMX mmxb = src_B
  // MMX dest = dest
  // MMX mmxdout = fdout
  // MMX mmxout_valid = fpu_valid
  // MMX mmxdestout = fpu_destout 

  // ************************ DSP *****************************************
  sc_signal<int> 		dsp_in1("DPS_IN1");
  sc_signal<int> 		dsp_out1("DSP_OUT1");
  sc_signal<bool> 		dsp_data_valid("DSP_DATA_VALID");
  sc_signal<bool> 		dsp_input_valid("DSP_INPUT_VALID");
  sc_signal<bool> 		dsp_data_requested("DSP_DATA_REQUESTED");

  ////////////////////////////////////////////////////////////////////////////
  // 				MAIN PROGRAM 
  ////////////////////////////////////////////////////////////////////////////
  sc_clock clk("Clock", 1, SC_NS, 0.5, 0.0, SC_NS);

  printf("/////////////////////////////////////////////////////////////////////////\n");
  printf("//  This code is written at SYNOPSYS, Inc.\n");
  printf("/////////////////////////////////////////////////////////////////////////\n");
  printf("//  Module   : main of CPU Model\n");
  printf("//  Author   : Martin Wang\n");
  printf("//  Company  : SYNOPSYS, Inc.\n");
  printf("//  Purpose  : This is a simple CPU modeling using SystemC.\n");
  printf("//             Instruction Set Architecure defined by Martin Wang.\n");
  printf("//             \n");
  printf("//           SystemC (TM) Copyright (c) 1988-2001 by Synopsys, Inc.  \n");
  printf("//             \n");
  printf("/////////////////////////////////////////////////////////////////////////\n");
  cout << "// IN THIS MACHINE Integer is " << sizeof (int) << " bytes.\n";
  cout << "// IN THIS MACHINE Floating is " << sizeof (float) << " bytes.\n";
  cout << "// IN THIS MACHINE Double is " << sizeof (double) << " bytes.\n";
  printf("//     \n");
  printf("//     \n");
  printf("//                            .,,uod8B8bou,,.\n");
  printf("//                   ..,uod8BBBBBBBBBBBBBBBBRPFT?l!i:.\n");
  printf("//              ,=m8BBBBBBBBBBBBBBBRPFT?!||||||||||||||\n");
  printf("//              !...:!TVBBBRPFT||||||||||!!^^\"\"    ||||\n");
  printf("//              !.......:!?|||||!!^^\"\"'            ||||\n");
  printf("//              !.........||||        ###  #  #    ||||\n");
  printf("//              !.........||||  ###  #  #  #  #    ||||\n");
  printf("//              !.........|||| #     #  #  #  #    ||||\n");
  printf("//              !.........|||| #     # #   #  #    ||||\n");
  printf("//              !.........|||| #     ##    #  #    ||||\n");
  printf("//              !.........|||| #     #     ###     ||||\n");
  printf("//              `.........|||| #   # #            ,||||\n");
  printf("//               .;.......||||  ###          _.-!!|||||\n");
  printf("//        .,uodWBBBBb.....||||       _.-!!|||||||||!:'\n");
  printf("//     !YBBBBBBBBBBBBBBb..!|||:..-!!|||||||!iof68BBBBBb....\n");
  printf("//     !..YBBBBBBBBBBBBBBb!!||||||||!iof68BBBBBBRPFT?!::   `.\n");
  printf("//     !....YBBBBBBBBBBBBBBbaaitf68BBBBBBRPFT?!:::::::::     `.\n");
  printf("//     !......YBBBBBBBBBBBBBBBBBBBRPFT?!::::::;:!^\"`;:::       `.\n");
  printf("//     !........YBBBBBBBBBBRPFT?!::::::::::^''...::::::;         iBBbo.\n");
  printf("//     `..........YBRPFT?!::::::::::::::::::::::::;iof68bo.      WBBBBbo.\n");
  printf("//       `..........:::::::::::::::::::::::;iof688888888888b.     `YBBBP^'\n");
  printf("//         `........::88::::::::::::;iof688888888888888888888b.     `\n");
  printf("//           `......::81:::::;iof688888888888888888888888888888b.\n");
  printf("//             `....:::;iof688888888888888888888888888888888899fT!\n");
  printf("//               `..::!8888888888888888888888888888888899fT|!^\"'\n");
  printf("//                 `' !!988888888888888888888888899fT|!^\"'\n");
  printf("//                     `!!8888888888888888899fT|!^\"'\n");
  printf("//                       `!988888888899fT|!^\"'\n");
  printf("//                         `!9899fT|!^\"'\n");
  printf("//                           `!^\"'\n");
  printf("//     \n");
  printf("//     \n");
  printf("/////////////////////////////////////////////////////////////////////////\n\n\n");
  	

  fetch 	IFU("FETCH_BLOCK");
                IFU.init_param(delay_cycles);
		IFU << ram_dataout << branch_target_address << next_pc << branch_valid
		<< stall_fetch << intreq << vectno << bios_valid << icache_valid
		<< pred_fetch << pred_branch_address << pred_branch_valid << ram_cs << ram_we 
		<< addr << ram_datain << instruction << instruction_valid << program_counter 
		<< intack_cpu << branch_clear << pred_fetch_valid << reset << clk;

  decode 	IDU("DECODE_BLOCK");
		IDU << reset << instruction << pred_instruction << instruction_valid
		<< pred_inst_valid << out_valid << destout << dout << dram_dataout
		<< dram_rd_valid << destout << fdout << fout_valid << fdestout
	        << branch_clear << dsp_data_valid << program_counter << pred_on
		<< branch_instruction_address << next_pc << branch_valid 
		<< branch_target_address << mem_access << mem_address << alu_op
		<< mem_write << alu_src << reg_write << src_A << src_B << forward_A
		<< forward_B << stall_fetch << decode_valid << float_valid << mmx_valid
		<< pid_valid << pid_data << clk;

  exec 		IEU("EXEC_BLOCK");
		IEU << reset << decode_valid << alu_op << negate << add1 << shift_sel 
		<< src_A << src_B << forward_A << forward_B << alu_src << c << v << z
		<< dout << out_valid << destout << clk;

  floating 	FPU("FLOAT_BLOCK");		// order dependent
		FPU << float_valid << alu_op << src_A << src_B << alu_src 
		<< fdout << fout_valid << fdestout << clk;

  mmxu	 	MMXU("MMX_BLOCK");
		MMXU << mmx_valid << alu_op << src_A << src_B << alu_src
		<< fdout << fout_valid << fdestout << clk;

  bios 		BIOS("BIOS_BLOCK");  
                BIOS.init_param(delay_cycles);
		BIOS.datain(ram_datain);	// order independent
                BIOS.cs(ram_cs);
		BIOS.we(ram_we);
		BIOS.addr(addr);
		BIOS.dataout(ram_dataout);
		BIOS.bios_valid(bios_valid);
		BIOS.stall_fetch(stall_fetch);
		BIOS.CLK(clk);

  paging 	PAGING("PAGING_BLOCK");
		PAGING << ram_datain << ram_cs << ram_we << addr << icache_din 
		<< icache_validin << icache_stall << paging_dout << paging_csout 
		<< paging_weout << physical_address << ram_dataout << icache_valid
		<< stall_fetch << clk ;
  	
  icache 	ICACHE("ICACHE_BLOCK"); 
		ICACHE.init_param(delay_cycles);
		ICACHE << paging_dout << paging_csout << paging_weout 	
		<< physical_address << pid_valid << pid_data << icache_din << icache_validin 
		<< icache_stall << clk;

  dcache 	DCACHE("DCACHE_BLOCK");
		DCACHE.init_param(delay_cycles);
		DCACHE << mmic_datain << mmic_statein << mmic_cs << mmic_we << mmic_addr
		<< mmic_dest << mmic_destout << mmic_dataout << mmic_out_valid << mmic_stateout << clk;

  pic		APIC("PIC_BLOCK");
		APIC << ireq0 << ireq1 << ireq2 << ireq3 <<intack_cpu << rd_wr 
		<< intack_cpu << intreq << intack << vectno;

  time_t tbuffer = time(NULL);

  sc_start();

  cout << "Time for simulation = " << (time(NULL) - tbuffer) << endl;

  return 0;	/* this is necessary */
}