⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 savage_bci.c

📁 底层驱动开发
💻 C
📖 第 1 页 / 共 3 页
字号:
		SAVAGE_DMA_PAGE_SIZE;	uint32_t *dma_ptr;	unsigned int i;	DRM_DEBUG("cur=%u, cur->used=%u, n=%u, rest=%u, nr_pages=%u\n",		  cur, dev_priv->dma_pages[cur].used, n, rest, nr_pages);	if (cur + nr_pages < dev_priv->nr_dma_pages) {		dma_ptr = (uint32_t *)dev_priv->cmd_dma->handle +			cur*SAVAGE_DMA_PAGE_SIZE +			dev_priv->dma_pages[cur].used;		if (n < rest)			rest = n;		dev_priv->dma_pages[cur].used += rest;		n -= rest;		cur++;	} else {		dev_priv->dma_flush(dev_priv);		nr_pages = (n + SAVAGE_DMA_PAGE_SIZE-1) / SAVAGE_DMA_PAGE_SIZE;		for (i = cur; i < dev_priv->nr_dma_pages; ++i) {			dev_priv->dma_pages[i].age = dev_priv->last_dma_age;			dev_priv->dma_pages[i].used = 0;			dev_priv->dma_pages[i].flushed = 0;		}		dma_ptr = (uint32_t *)dev_priv->cmd_dma->handle;		dev_priv->first_dma_page = cur = 0;	}	for (i = cur; nr_pages > 0; ++i, --nr_pages) {#if SAVAGE_DMA_DEBUG		if (dev_priv->dma_pages[i].used) {			DRM_ERROR("unflushed page %u: used=%u\n",				  i, dev_priv->dma_pages[i].used);		}#endif		if (n > SAVAGE_DMA_PAGE_SIZE)			dev_priv->dma_pages[i].used = SAVAGE_DMA_PAGE_SIZE;		else			dev_priv->dma_pages[i].used = n;		n -= SAVAGE_DMA_PAGE_SIZE;	}	dev_priv->current_dma_page = --i;	DRM_DEBUG("cur=%u, cur->used=%u, n=%u\n",		  i, dev_priv->dma_pages[i].used, n);	savage_dma_wait(dev_priv, dev_priv->current_dma_page);	return dma_ptr;}static void savage_dma_flush(drm_savage_private_t *dev_priv){	unsigned int first = dev_priv->first_dma_page;	unsigned int cur = dev_priv->current_dma_page;	uint16_t event;	unsigned int wrap, pad, align, len, i;	unsigned long phys_addr;	BCI_LOCALS;	if (first == cur &&	    dev_priv->dma_pages[cur].used == dev_priv->dma_pages[cur].flushed)		return;	/* pad length to multiples of 2 entries	 * align start of next DMA block to multiles of 8 entries */	pad = -dev_priv->dma_pages[cur].used & 1;	align = -(dev_priv->dma_pages[cur].used + pad) & 7;	DRM_DEBUG("first=%u, cur=%u, first->flushed=%u, cur->used=%u, "		  "pad=%u, align=%u\n",		  first, cur, dev_priv->dma_pages[first].flushed,		  dev_priv->dma_pages[cur].used, pad, align);	/* pad with noops */	if (pad) {		uint32_t *dma_ptr = (uint32_t *)dev_priv->cmd_dma->handle +			cur * SAVAGE_DMA_PAGE_SIZE +			dev_priv->dma_pages[cur].used;		dev_priv->dma_pages[cur].used += pad;		while(pad != 0) {			*dma_ptr++ = BCI_CMD_WAIT;			pad--;		}	}	DRM_MEMORYBARRIER();	/* do flush ... */	phys_addr = dev_priv->cmd_dma->offset +		(first * SAVAGE_DMA_PAGE_SIZE +		 dev_priv->dma_pages[first].flushed) * 4;	len = (cur - first) * SAVAGE_DMA_PAGE_SIZE +		dev_priv->dma_pages[cur].used -		dev_priv->dma_pages[first].flushed;	DRM_DEBUG("phys_addr=%lx, len=%u\n",		  phys_addr | dev_priv->dma_type, len);	BEGIN_BCI(3);	BCI_SET_REGISTERS(SAVAGE_DMABUFADDR, 1);	BCI_WRITE(phys_addr | dev_priv->dma_type);	BCI_DMA(len);	/* fix alignment of the start of the next block */	dev_priv->dma_pages[cur].used += align;	/* age DMA pages */	event = savage_bci_emit_event(dev_priv, 0);	wrap = dev_priv->event_wrap;	for (i = first; i < cur; ++i) {		SET_AGE(&dev_priv->dma_pages[i].age, event, wrap);		dev_priv->dma_pages[i].used = 0;		dev_priv->dma_pages[i].flushed = 0;	}	/* age the current page only when it's full */	if (dev_priv->dma_pages[cur].used == SAVAGE_DMA_PAGE_SIZE) {		SET_AGE(&dev_priv->dma_pages[cur].age, event, wrap);		dev_priv->dma_pages[cur].used = 0;		dev_priv->dma_pages[cur].flushed = 0;		/* advance to next page */		cur++;		if (cur == dev_priv->nr_dma_pages)			cur = 0;		dev_priv->first_dma_page = dev_priv->current_dma_page = cur;	} else {		dev_priv->first_dma_page = cur;		dev_priv->dma_pages[cur].flushed = dev_priv->dma_pages[i].used;	}	SET_AGE(&dev_priv->last_dma_age, event, wrap);	DRM_DEBUG("first=cur=%u, cur->used=%u, cur->flushed=%u\n", cur,		  dev_priv->dma_pages[cur].used,		  dev_priv->dma_pages[cur].flushed);}static void savage_fake_dma_flush(drm_savage_private_t *dev_priv){	unsigned int i, j;	BCI_LOCALS;	if (dev_priv->first_dma_page == dev_priv->current_dma_page &&	    dev_priv->dma_pages[dev_priv->current_dma_page].used == 0)		return;	DRM_DEBUG("first=%u, cur=%u, cur->used=%u\n",		  dev_priv->first_dma_page, dev_priv->current_dma_page,		  dev_priv->dma_pages[dev_priv->current_dma_page].used);	for (i = dev_priv->first_dma_page;	     i <= dev_priv->current_dma_page && dev_priv->dma_pages[i].used;	     ++i) {		uint32_t *dma_ptr = (uint32_t *)dev_priv->cmd_dma->handle +			i * SAVAGE_DMA_PAGE_SIZE;#if SAVAGE_DMA_DEBUG		/* Sanity check: all pages except the last one must be full. */		if (i < dev_priv->current_dma_page &&		    dev_priv->dma_pages[i].used != SAVAGE_DMA_PAGE_SIZE) {			DRM_ERROR("partial DMA page %u: used=%u",				  i, dev_priv->dma_pages[i].used);		}#endif		BEGIN_BCI(dev_priv->dma_pages[i].used);		for (j = 0; j < dev_priv->dma_pages[i].used; ++j) {			BCI_WRITE(dma_ptr[j]);		}		dev_priv->dma_pages[i].used = 0;	}	/* reset to first page */	dev_priv->first_dma_page = dev_priv->current_dma_page = 0;}/* * Initalize mappings. On Savage4 and SavageIX the alignment * and size of the aperture is not suitable for automatic MTRR setup * in drm_addmap. Therefore we do it manually before the maps are * initialized. We also need to take care of deleting the MTRRs in * postcleanup. */int savage_preinit(drm_device_t *dev, unsigned long chipset){	drm_savage_private_t *dev_priv;	unsigned long mmio_base, fb_base, fb_size, aperture_base;	/* fb_rsrc and aper_rsrc aren't really used currently, but still exist	 * in case we decide we need information on the BAR for BSD in the	 * future.	 */	unsigned int fb_rsrc, aper_rsrc;	int ret = 0;	dev_priv = drm_alloc(sizeof(drm_savage_private_t), DRM_MEM_DRIVER);	if (dev_priv == NULL)		return DRM_ERR(ENOMEM);	memset(dev_priv, 0, sizeof(drm_savage_private_t));	dev->dev_private = (void *)dev_priv;	dev_priv->chipset = (enum savage_family)chipset;	dev_priv->mtrr[0].handle = -1;	dev_priv->mtrr[1].handle = -1;	dev_priv->mtrr[2].handle = -1;	if (S3_SAVAGE3D_SERIES(dev_priv->chipset)) {		fb_rsrc = 0;		fb_base = drm_get_resource_start(dev, 0);		fb_size = SAVAGE_FB_SIZE_S3;		mmio_base = fb_base + SAVAGE_FB_SIZE_S3;		aper_rsrc = 0;		aperture_base = fb_base + SAVAGE_APERTURE_OFFSET;		/* this should always be true */		if (drm_get_resource_len(dev, 0) == 0x08000000) {			/* Don't make MMIO write-cobining! We need 3			 * MTRRs. */			dev_priv->mtrr[0].base = fb_base;			dev_priv->mtrr[0].size = 0x01000000;			dev_priv->mtrr[0].handle = mtrr_add(				dev_priv->mtrr[0].base, dev_priv->mtrr[0].size,				MTRR_TYPE_WRCOMB, 1);			dev_priv->mtrr[1].base = fb_base+0x02000000;			dev_priv->mtrr[1].size = 0x02000000;			dev_priv->mtrr[1].handle = mtrr_add(				dev_priv->mtrr[1].base, dev_priv->mtrr[1].size,				MTRR_TYPE_WRCOMB, 1);			dev_priv->mtrr[2].base = fb_base+0x04000000;			dev_priv->mtrr[2].size = 0x04000000;			dev_priv->mtrr[2].handle = mtrr_add(				dev_priv->mtrr[2].base, dev_priv->mtrr[2].size,				MTRR_TYPE_WRCOMB, 1);		} else {			DRM_ERROR("strange pci_resource_len %08lx\n",				  drm_get_resource_len(dev, 0));		}	} else if (chipset != S3_SUPERSAVAGE && chipset != S3_SAVAGE2000) {		mmio_base = drm_get_resource_start(dev, 0);		fb_rsrc = 1;		fb_base = drm_get_resource_start(dev, 1);		fb_size = SAVAGE_FB_SIZE_S4;		aper_rsrc = 1;		aperture_base = fb_base + SAVAGE_APERTURE_OFFSET;		/* this should always be true */		if (drm_get_resource_len(dev, 1) == 0x08000000) {			/* Can use one MTRR to cover both fb and			 * aperture. */			dev_priv->mtrr[0].base = fb_base;			dev_priv->mtrr[0].size = 0x08000000;			dev_priv->mtrr[0].handle = mtrr_add(				dev_priv->mtrr[0].base, dev_priv->mtrr[0].size,				MTRR_TYPE_WRCOMB, 1);		} else {			DRM_ERROR("strange pci_resource_len %08lx\n",				  drm_get_resource_len(dev, 1));		}	} else {		mmio_base = drm_get_resource_start(dev, 0);		fb_rsrc = 1;		fb_base = drm_get_resource_start(dev, 1);		fb_size = drm_get_resource_len(dev, 1);		aper_rsrc = 2;		aperture_base = drm_get_resource_start(dev, 2);		/* Automatic MTRR setup will do the right thing. */	}	ret = drm_addmap(dev, mmio_base, SAVAGE_MMIO_SIZE, _DRM_REGISTERS,			 _DRM_READ_ONLY, &dev_priv->mmio);	if (ret)		return ret;	ret = drm_addmap(dev, fb_base, fb_size, _DRM_FRAME_BUFFER,			 _DRM_WRITE_COMBINING, &dev_priv->fb);	if (ret)		return ret;	ret = drm_addmap(dev, aperture_base, SAVAGE_APERTURE_SIZE,			 _DRM_FRAME_BUFFER, _DRM_WRITE_COMBINING,			 &dev_priv->aperture);	if (ret)		return ret;	return ret;}/* * Delete MTRRs and free device-private data. */int savage_postcleanup(drm_device_t *dev){	drm_savage_private_t *dev_priv = dev->dev_private;	int i;	for (i = 0; i < 3; ++i)		if (dev_priv->mtrr[i].handle >= 0)			mtrr_del(dev_priv->mtrr[i].handle,				 dev_priv->mtrr[i].base,				 dev_priv->mtrr[i].size);	drm_free(dev_priv, sizeof(drm_savage_private_t), DRM_MEM_DRIVER);	return 0;}static int savage_do_init_bci(drm_device_t *dev, drm_savage_init_t *init){	drm_savage_private_t *dev_priv = dev->dev_private;	if (init->fb_bpp != 16 && init->fb_bpp != 32) {		DRM_ERROR("invalid frame buffer bpp %d!\n", init->fb_bpp);		return DRM_ERR(EINVAL);	}	if (init->depth_bpp != 16 && init->depth_bpp != 32) {		DRM_ERROR("invalid depth buffer bpp %d!\n", init->fb_bpp);		return DRM_ERR(EINVAL);	}	if (init->dma_type != SAVAGE_DMA_AGP &&	    init->dma_type != SAVAGE_DMA_PCI) {		DRM_ERROR("invalid dma memory type %d!\n", init->dma_type);		return DRM_ERR(EINVAL);	}	dev_priv->cob_size = init->cob_size;	dev_priv->bci_threshold_lo = init->bci_threshold_lo;	dev_priv->bci_threshold_hi = init->bci_threshold_hi;	dev_priv->dma_type = init->dma_type;	dev_priv->fb_bpp = init->fb_bpp;	dev_priv->front_offset = init->front_offset;	dev_priv->front_pitch = init->front_pitch;	dev_priv->back_offset = init->back_offset;	dev_priv->back_pitch = init->back_pitch;	dev_priv->depth_bpp = init->depth_bpp;	dev_priv->depth_offset = init->depth_offset;	dev_priv->depth_pitch = init->depth_pitch;	dev_priv->texture_offset = init->texture_offset;	dev_priv->texture_size = init->texture_size;	DRM_GETSAREA();	if (!dev_priv->sarea) {		DRM_ERROR("could not find sarea!\n");		savage_do_cleanup_bci(dev);		return DRM_ERR(EINVAL);	}	if (init->status_offset != 0) {		dev_priv->status = drm_core_findmap(dev, init->status_offset);		if (!dev_priv->status) {			DRM_ERROR("could not find shadow status region!\n");			savage_do_cleanup_bci(dev);			return DRM_ERR(EINVAL);		}	} else {		dev_priv->status = NULL;	}	if (dev_priv->dma_type == SAVAGE_DMA_AGP && init->buffers_offset) {		dev->agp_buffer_map = drm_core_findmap(dev,						       init->buffers_offset);		if (!dev->agp_buffer_map) {			DRM_ERROR("could not find DMA buffer region!\n");			savage_do_cleanup_bci(dev);			return DRM_ERR(EINVAL);		}		drm_core_ioremap(dev->agp_buffer_map, dev);		if (!dev->agp_buffer_map) {			DRM_ERROR("failed to ioremap DMA buffer region!\n");			savage_do_cleanup_bci(dev);			return DRM_ERR(ENOMEM);		}	}	if (init->agp_textures_offset) {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -