mirror of
https://gitlab.freedesktop.org/mesa/drm.git
synced 2026-01-06 15:30:20 +01:00
Sorta working (i.e., sometimes it works right) r128 pcigart implementation,
based on code from Gareth Hughes. Needs bug fixing before its ready for
general use.
This commit is contained in:
parent
61c15f4a2d
commit
e2117d5487
21 changed files with 935 additions and 75 deletions
|
|
@ -11,11 +11,11 @@
|
|||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
|
|
@ -23,12 +23,12 @@
|
|||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*
|
||||
* Authors: Rickard E. (Rik) Faith <faith@valinux.com>
|
||||
* Kevin E. Martin <martin@valinux.com>
|
||||
*
|
||||
* $XFree86: xc/programs/Xserver/hw/xfree86/os-support/linux/drm/xf86drm.c,v 1.17 2000/09/24 13:51:32 alanh Exp $
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef XFree86Server
|
||||
|
|
@ -119,7 +119,7 @@ void drmFree(void *pt)
|
|||
static char *drmStrdup(const char *s)
|
||||
{
|
||||
char *retval = NULL;
|
||||
|
||||
|
||||
if (s) {
|
||||
retval = _DRM_MALLOC(strlen(s)+1);
|
||||
strcpy(retval, s);
|
||||
|
|
@ -213,7 +213,7 @@ int drmAvailable(void)
|
|||
drmVersionPtr version;
|
||||
int retval = 0;
|
||||
int fd;
|
||||
|
||||
|
||||
if (!access("/proc/dri/0", R_OK)) return 1;
|
||||
|
||||
sprintf(dev_name, "/dev/dri-temp-%d", getpid());
|
||||
|
|
@ -408,7 +408,7 @@ drmVersionPtr drmGetVersion(int fd)
|
|||
version->date = NULL;
|
||||
version->desc_len = 0;
|
||||
version->desc = NULL;
|
||||
|
||||
|
||||
if (ioctl(fd, DRM_IOCTL_VERSION, version)) {
|
||||
drmFreeKernelVersion(version);
|
||||
return NULL;
|
||||
|
|
@ -421,7 +421,7 @@ drmVersionPtr drmGetVersion(int fd)
|
|||
version->date = drmMalloc(version->date_len + 1);
|
||||
if (version->desc_len)
|
||||
version->desc = drmMalloc(version->desc_len + 1);
|
||||
|
||||
|
||||
if (ioctl(fd, DRM_IOCTL_VERSION, version)) {
|
||||
drmFreeKernelVersion(version);
|
||||
return NULL;
|
||||
|
|
@ -503,7 +503,7 @@ int drmAddMap(int fd,
|
|||
map.offset = offset;
|
||||
#ifdef __alpha__
|
||||
/* Make sure we add the bus_base to all but shm */
|
||||
if (type != DRM_SHM)
|
||||
if (type != DRM_SHM)
|
||||
map.offset += BUS_BASE;
|
||||
#endif
|
||||
map.size = size;
|
||||
|
|
@ -519,14 +519,14 @@ int drmAddBufs(int fd, int count, int size, drmBufDescFlags flags,
|
|||
int agp_offset)
|
||||
{
|
||||
drm_buf_desc_t request;
|
||||
|
||||
|
||||
request.count = count;
|
||||
request.size = size;
|
||||
request.low_mark = 0;
|
||||
request.high_mark = 0;
|
||||
request.flags = flags;
|
||||
request.agp_start = agp_offset;
|
||||
|
||||
|
||||
if (ioctl(fd, DRM_IOCTL_ADD_BUFS, &request)) return -errno;
|
||||
return request.count;
|
||||
}
|
||||
|
|
@ -542,16 +542,16 @@ int drmMarkBufs(int fd, double low, double high)
|
|||
if (ioctl(fd, DRM_IOCTL_INFO_BUFS, &info)) return -EINVAL;
|
||||
|
||||
if (!info.count) return -EINVAL;
|
||||
|
||||
|
||||
if (!(info.list = drmMalloc(info.count * sizeof(*info.list))))
|
||||
return -ENOMEM;
|
||||
|
||||
|
||||
if (ioctl(fd, DRM_IOCTL_INFO_BUFS, &info)) {
|
||||
int retval = -errno;
|
||||
drmFree(info.list);
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
for (i = 0; i < info.count; i++) {
|
||||
info.list[i].low_mark = low * info.list[i].count;
|
||||
info.list[i].high_mark = high * info.list[i].count;
|
||||
|
|
@ -562,7 +562,7 @@ int drmMarkBufs(int fd, double low, double high)
|
|||
}
|
||||
}
|
||||
drmFree(info.list);
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -630,7 +630,7 @@ drmBufInfoPtr drmGetBufInfo(int fd)
|
|||
if (info.count) {
|
||||
if (!(info.list = drmMalloc(info.count * sizeof(*info.list))))
|
||||
return NULL;
|
||||
|
||||
|
||||
if (ioctl(fd, DRM_IOCTL_INFO_BUFS, &info)) {
|
||||
drmFree(info.list);
|
||||
return NULL;
|
||||
|
|
@ -657,7 +657,7 @@ drmBufMapPtr drmMapBufs(int fd)
|
|||
drm_buf_map_t bufs;
|
||||
drmBufMapPtr retval;
|
||||
int i;
|
||||
|
||||
|
||||
bufs.count = 0;
|
||||
bufs.list = NULL;
|
||||
if (ioctl(fd, DRM_IOCTL_MAP_BUFS, &bufs)) return NULL;
|
||||
|
|
@ -689,7 +689,7 @@ drmBufMapPtr drmMapBufs(int fd)
|
|||
int drmUnmapBufs(drmBufMapPtr bufs)
|
||||
{
|
||||
int i;
|
||||
|
||||
|
||||
for (i = 0; i < bufs->count; i++) {
|
||||
munmap(bufs->list[i].address, bufs->list[i].total);
|
||||
}
|
||||
|
|
@ -712,7 +712,7 @@ int drmDMA(int fd, drmDMAReqPtr request)
|
|||
dma.request_sizes = request->request_sizes;
|
||||
if (ioctl(fd, DRM_IOCTL_DMA, &dma)) return -errno;
|
||||
request->granted_count = dma.granted_count;
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -728,7 +728,7 @@ int drmGetLock(int fd, drmContext context, drmLockFlags flags)
|
|||
if (flags & DRM_LOCK_FLUSH_ALL) lock.flags |= _DRM_LOCK_FLUSH_ALL;
|
||||
if (flags & DRM_HALT_ALL_QUEUES) lock.flags |= _DRM_HALT_ALL_QUEUES;
|
||||
if (flags & DRM_HALT_CUR_QUEUES) lock.flags |= _DRM_HALT_CUR_QUEUES;
|
||||
|
||||
|
||||
while (ioctl(fd, DRM_IOCTL_LOCK, &lock))
|
||||
;
|
||||
return 0;
|
||||
|
|
@ -827,7 +827,7 @@ int drmGetContextFlags(int fd, drmContext context, drmContextFlagsPtr flags)
|
|||
if (ctx.flags & _DRM_CONTEXT_2DONLY) *flags |= DRM_CONTEXT_2DONLY;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int drmDestroyContext(int fd, drmContext handle)
|
||||
{
|
||||
drm_ctx_t ctx;
|
||||
|
|
@ -989,6 +989,28 @@ unsigned int drmAgpDeviceId(int fd)
|
|||
return i.id_device;
|
||||
}
|
||||
|
||||
int drmScatterGatherAlloc(int fd, unsigned long size, unsigned long *handle)
|
||||
{
|
||||
drm_scatter_gather_t sg;
|
||||
|
||||
*handle = 0;
|
||||
sg.size = size;
|
||||
sg.handle = 0;
|
||||
if (ioctl(fd, DRM_IOCTL_SG_ALLOC, &sg)) return -errno;
|
||||
*handle = sg.handle;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int drmScatterGatherFree(int fd, unsigned long handle)
|
||||
{
|
||||
drm_scatter_gather_t sg;
|
||||
|
||||
sg.size = 0;
|
||||
sg.handle = handle;
|
||||
if (ioctl(fd, DRM_IOCTL_SG_FREE, &sg)) return -errno;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int drmError(int err, const char *label)
|
||||
{
|
||||
switch (err) {
|
||||
|
|
@ -1074,7 +1096,7 @@ void *drmGetContextTag(int fd, drmContext context)
|
|||
{
|
||||
drmHashEntry *entry = drmGetEntry(fd);
|
||||
void *value;
|
||||
|
||||
|
||||
if (drmHashLookup(entry->tagTable, context, &value)) return NULL;
|
||||
|
||||
return value;
|
||||
|
|
@ -1108,7 +1130,7 @@ static void drmSIGIOHandler(int interrupt, void *closure)
|
|||
#if 0
|
||||
fprintf(stderr, "Got %s\n", buf);
|
||||
#endif
|
||||
|
||||
|
||||
for (pt = buf; *pt != ' '; ++pt); /* Find first space */
|
||||
++pt;
|
||||
old = strtol(pt, &pt, 0);
|
||||
|
|
@ -1141,7 +1163,7 @@ int drmRemoveSIGIOHandler(int fd)
|
|||
drmHashEntry *entry = drmGetEntry(fd);
|
||||
|
||||
entry->f = NULL;
|
||||
|
||||
|
||||
return xf86RemoveSIGIOHandler(fd);
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ export-objs := $(patsubst %.o,%_drv.o,$(module-list))
|
|||
#
|
||||
|
||||
lib-objs := init.o memory.o proc.o auth.o context.o drawable.o bufs.o
|
||||
lib-objs += lists.o lock.o ioctl.o fops.o vm.o dma.o ctxbitmap.o
|
||||
lib-objs += lists.o lock.o ioctl.o fops.o vm.o dma.o ctxbitmap.o scatter.o
|
||||
|
||||
ifeq ($(CONFIG_AGP),y)
|
||||
lib-objs += agpsupport.o
|
||||
|
|
@ -45,7 +45,7 @@ endif
|
|||
gamma-objs := gamma_drv.o gamma_dma.o
|
||||
tdfx-objs := tdfx_drv.o tdfx_context.o
|
||||
r128-objs := r128_drv.o r128_cce.o r128_context.o r128_bufs.o \
|
||||
r128_state.o
|
||||
r128_state.o r128_pcigart.o
|
||||
radeon-objs := radeon_drv.o radeon_cp.o radeon_context.o radeon_bufs.o \
|
||||
radeon_state.o
|
||||
ffb-objs := ffb_drv.o ffb_context.o
|
||||
|
|
|
|||
|
|
@ -109,6 +109,8 @@
|
|||
#define DRM_MEM_TOTALAGP 16
|
||||
#define DRM_MEM_BOUNDAGP 17
|
||||
#define DRM_MEM_CTXBITMAP 18
|
||||
#define DRM_MEM_SG 19
|
||||
#define DRM_MEM_SGLISTS 20
|
||||
|
||||
#define DRM_MAX_CTXBITMAP (PAGE_SIZE * 8)
|
||||
|
||||
|
|
@ -480,7 +482,8 @@ typedef struct drm_device_dma {
|
|||
unsigned long *pagelist;
|
||||
unsigned long byte_count;
|
||||
enum {
|
||||
_DRM_DMA_USE_AGP = 0x01
|
||||
_DRM_DMA_USE_AGP = 0x01,
|
||||
_DRM_DMA_USE_SG = 0x02
|
||||
} flags;
|
||||
|
||||
/* DMA support */
|
||||
|
|
@ -512,6 +515,13 @@ typedef struct drm_agp_head {
|
|||
} drm_agp_head_t;
|
||||
#endif
|
||||
|
||||
typedef struct drm_sg_mem {
|
||||
unsigned long handle;
|
||||
void *virtual;
|
||||
int pages;
|
||||
struct page **pagelist;
|
||||
} drm_sg_mem_t;
|
||||
|
||||
typedef struct drm_sigdata {
|
||||
int context;
|
||||
drm_hw_lock_t *lock;
|
||||
|
|
@ -599,6 +609,7 @@ typedef struct drm_device {
|
|||
#if defined(CONFIG_AGP) || defined(CONFIG_AGP_MODULE)
|
||||
drm_agp_head_t *agp;
|
||||
#endif
|
||||
drm_sg_mem_t *sg; /* Scatter / gather memory */
|
||||
unsigned long *ctx_bitmap;
|
||||
void *dev_private;
|
||||
drm_sigdata_t sigdata; /* For block_all_signals */
|
||||
|
|
@ -639,6 +650,9 @@ extern unsigned long drm_vm_shm_nopage_lock(struct vm_area_struct *vma,
|
|||
extern unsigned long drm_vm_dma_nopage(struct vm_area_struct *vma,
|
||||
unsigned long address,
|
||||
int write_access);
|
||||
extern unsigned long drm_vm_sg_nopage(struct vm_area_struct *vma,
|
||||
unsigned long address,
|
||||
int write_access);
|
||||
#else
|
||||
/* Return type changed in 2.3.23 */
|
||||
extern struct page *drm_vm_nopage(struct vm_area_struct *vma,
|
||||
|
|
@ -653,6 +667,9 @@ extern struct page *drm_vm_shm_nopage_lock(struct vm_area_struct *vma,
|
|||
extern struct page *drm_vm_dma_nopage(struct vm_area_struct *vma,
|
||||
unsigned long address,
|
||||
int write_access);
|
||||
extern struct page *drm_vm_sg_nopage(struct vm_area_struct *vma,
|
||||
unsigned long address,
|
||||
int write_access);
|
||||
#endif
|
||||
extern void drm_vm_open(struct vm_area_struct *vma);
|
||||
extern void drm_vm_close(struct vm_area_struct *vma);
|
||||
|
|
@ -831,5 +848,14 @@ extern int drm_agp_free_memory(agp_memory *handle);
|
|||
extern int drm_agp_bind_memory(agp_memory *handle, off_t start);
|
||||
extern int drm_agp_unbind_memory(agp_memory *handle);
|
||||
#endif
|
||||
|
||||
/* Scatter/gather memory supprt (scatter.c) */
|
||||
extern int drm_sg_alloc(struct inode *inode, struct file *filp,
|
||||
unsigned int cmd, unsigned long arg);
|
||||
extern int drm_sg_free(struct inode *inode, struct file *filp,
|
||||
unsigned int cmd, unsigned long arg);
|
||||
|
||||
#define page_to_pfn( page ) ((unsigned long)((page)-mem_map))
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -107,6 +107,8 @@ static drm_ioctl_desc_t r128_ioctls[] = {
|
|||
[DRM_IOCTL_NR(DRM_IOCTL_AGP_BIND)] = { drm_agp_bind, 1, 1 },
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_AGP_UNBIND)] = { drm_agp_unbind, 1, 1 },
|
||||
#endif
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_SG_ALLOC)] = { drm_sg_alloc, 1, 1 },
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_SG_FREE)] = { drm_sg_free, 1, 1 },
|
||||
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_R128_INIT)] = { r128_cce_init, 1, 1 },
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_R128_CCE_START)] = { r128_cce_start, 1, 1 },
|
||||
|
|
@ -309,6 +311,12 @@ static int r128_takedown(drm_device_t *dev)
|
|||
/* Do nothing here, because this is all
|
||||
handled in the AGP/GART driver. */
|
||||
break;
|
||||
case _DRM_SCATTER_GATHER:
|
||||
if(dev->sg) {
|
||||
drm_sg_cleanup(dev->sg);
|
||||
dev->sg = NULL;
|
||||
}
|
||||
break;
|
||||
}
|
||||
drm_free(map, sizeof(*map), DRM_MEM_MAPS);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ export-objs := $(patsubst %.o,%_drv.o,$(module-list))
|
|||
#
|
||||
|
||||
lib-objs := init.o memory.o proc.o auth.o context.o drawable.o bufs.o
|
||||
lib-objs += lists.o lock.o ioctl.o fops.o vm.o dma.o ctxbitmap.o
|
||||
lib-objs += lists.o lock.o ioctl.o fops.o vm.o dma.o ctxbitmap.o scatter.o
|
||||
|
||||
ifeq ($(CONFIG_AGP),y)
|
||||
lib-objs += agpsupport.o
|
||||
|
|
@ -45,7 +45,7 @@ endif
|
|||
gamma-objs := gamma_drv.o gamma_dma.o
|
||||
tdfx-objs := tdfx_drv.o tdfx_context.o
|
||||
r128-objs := r128_drv.o r128_cce.o r128_context.o r128_bufs.o \
|
||||
r128_state.o
|
||||
r128_state.o r128_pcigart.o
|
||||
radeon-objs := radeon_drv.o radeon_cp.o radeon_context.o radeon_bufs.o \
|
||||
radeon_state.o
|
||||
ffb-objs := ffb_drv.o ffb_context.o
|
||||
|
|
|
|||
|
|
@ -46,12 +46,12 @@
|
|||
# *** Setup
|
||||
|
||||
# **** End of SMP/MODVERSIONS detection
|
||||
|
||||
CC= gcc
|
||||
MODS= gamma.o tdfx.o r128.o radeon.o
|
||||
LIBS= libdrm.a
|
||||
|
||||
DRMOBJS= init.o memory.o proc.o auth.o context.o drawable.o bufs.o \
|
||||
lists.o lock.o ioctl.o fops.o vm.o dma.o ctxbitmap.o
|
||||
lists.o lock.o ioctl.o fops.o vm.o dma.o ctxbitmap.o scatter.o
|
||||
DRMHEADERS= drm.h drmP.h compat-pre24.h
|
||||
|
||||
GAMMAOBJS= gamma_drv.o gamma_dma.o
|
||||
|
|
@ -141,7 +141,8 @@ MGAHEADERS= mga_drv.h $(DRMHEADERS)
|
|||
I810OBJS= i810_drv.o i810_dma.o i810_bufs.o i810_context.o
|
||||
I810HEADERS= i810_drv.h $(DRMHEADERS)
|
||||
|
||||
R128OBJS= r128_drv.o r128_cce.o r128_bufs.o r128_context.o r128_state.o
|
||||
R128OBJS= r128_drv.o r128_cce.o r128_bufs.o r128_context.o r128_state.o \
|
||||
r128_pcigart.o
|
||||
R128HEADERS= r128_drv.h r128_drm.h $(DRMHEADERS)
|
||||
|
||||
RADEONOBJS= radeon_drv.o radeon_cp.o radeon_bufs.o radeon_context.o \
|
||||
|
|
|
|||
|
|
@ -111,6 +111,10 @@ int drm_addmap(struct inode *inode, struct file *filp, unsigned int cmd,
|
|||
map->offset = map->offset + dev->agp->base;
|
||||
break;
|
||||
#endif
|
||||
case _DRM_SCATTER_GATHER:
|
||||
if(!dev->sg) return -EINVAL;
|
||||
map->offset = map->offset + dev->sg->handle;
|
||||
break;
|
||||
default:
|
||||
drm_free(map, sizeof(*map), DRM_MEM_MAPS);
|
||||
return -EINVAL;
|
||||
|
|
|
|||
20
linux/drm.h
20
linux/drm.h
|
|
@ -124,10 +124,11 @@ typedef struct drm_control {
|
|||
} drm_control_t;
|
||||
|
||||
typedef enum drm_map_type {
|
||||
_DRM_FRAME_BUFFER = 0, /* WC (no caching), no core dump */
|
||||
_DRM_REGISTERS = 1, /* no caching, no core dump */
|
||||
_DRM_SHM = 2, /* shared, cached */
|
||||
_DRM_AGP = 3 /* AGP/GART */
|
||||
_DRM_FRAME_BUFFER = 0, /* WC (no caching), no core dump */
|
||||
_DRM_REGISTERS = 1, /* no caching, no core dump */
|
||||
_DRM_SHM = 2, /* shared, cached */
|
||||
_DRM_AGP = 3, /* AGP/GART */
|
||||
_DRM_SCATTER_GATHER = 4 /* Scatter/gather memory for PCI DMA */
|
||||
} drm_map_type_t;
|
||||
|
||||
typedef enum drm_map_flags {
|
||||
|
|
@ -192,7 +193,8 @@ typedef struct drm_buf_desc {
|
|||
int high_mark; /* High water mark */
|
||||
enum {
|
||||
_DRM_PAGE_ALIGN = 0x01, /* Align on page boundaries for DMA */
|
||||
_DRM_AGP_BUFFER = 0x02 /* Buffer is in agp space */
|
||||
_DRM_AGP_BUFFER = 0x02, /* Buffer is in agp space */
|
||||
_DRM_SG_BUFFER = 0x04 /* Scatter/gather memory buffer */
|
||||
} flags;
|
||||
unsigned long agp_start; /* Start address of where the agp buffers
|
||||
* are in the agp aperture */
|
||||
|
|
@ -298,6 +300,11 @@ typedef struct drm_agp_info {
|
|||
unsigned short id_device;
|
||||
} drm_agp_info_t;
|
||||
|
||||
typedef struct drm_scatter_gather {
|
||||
unsigned long size; /* In bytes -- will round to page boundary */
|
||||
unsigned long handle; /* Used for mapping / unmapping */
|
||||
} drm_scatter_gather_t;
|
||||
|
||||
#define DRM_IOCTL_BASE 'd'
|
||||
#define DRM_IO(nr) _IO(DRM_IOCTL_BASE,nr)
|
||||
#define DRM_IOR(nr,size) _IOR(DRM_IOCTL_BASE,nr,size)
|
||||
|
|
@ -345,6 +352,9 @@ typedef struct drm_agp_info {
|
|||
#define DRM_IOCTL_AGP_BIND DRM_IOW( 0x36, drm_agp_binding_t)
|
||||
#define DRM_IOCTL_AGP_UNBIND DRM_IOW( 0x37, drm_agp_binding_t)
|
||||
|
||||
#define DRM_IOCTL_SG_ALLOC DRM_IOW( 0x38, drm_scatter_gather_t)
|
||||
#define DRM_IOCTL_SG_FREE DRM_IOW( 0x39, drm_scatter_gather_t)
|
||||
|
||||
/* Mga specific ioctls */
|
||||
#define DRM_IOCTL_MGA_INIT DRM_IOW( 0x40, drm_mga_init_t)
|
||||
#define DRM_IOCTL_MGA_SWAP DRM_IOW( 0x41, drm_mga_swap_t)
|
||||
|
|
|
|||
28
linux/drmP.h
28
linux/drmP.h
|
|
@ -109,6 +109,8 @@
|
|||
#define DRM_MEM_TOTALAGP 16
|
||||
#define DRM_MEM_BOUNDAGP 17
|
||||
#define DRM_MEM_CTXBITMAP 18
|
||||
#define DRM_MEM_SG 19
|
||||
#define DRM_MEM_SGLISTS 20
|
||||
|
||||
#define DRM_MAX_CTXBITMAP (PAGE_SIZE * 8)
|
||||
|
||||
|
|
@ -480,7 +482,8 @@ typedef struct drm_device_dma {
|
|||
unsigned long *pagelist;
|
||||
unsigned long byte_count;
|
||||
enum {
|
||||
_DRM_DMA_USE_AGP = 0x01
|
||||
_DRM_DMA_USE_AGP = 0x01,
|
||||
_DRM_DMA_USE_SG = 0x02
|
||||
} flags;
|
||||
|
||||
/* DMA support */
|
||||
|
|
@ -512,6 +515,13 @@ typedef struct drm_agp_head {
|
|||
} drm_agp_head_t;
|
||||
#endif
|
||||
|
||||
typedef struct drm_sg_mem {
|
||||
unsigned long handle;
|
||||
void *virtual;
|
||||
int pages;
|
||||
struct page **pagelist;
|
||||
} drm_sg_mem_t;
|
||||
|
||||
typedef struct drm_sigdata {
|
||||
int context;
|
||||
drm_hw_lock_t *lock;
|
||||
|
|
@ -599,6 +609,7 @@ typedef struct drm_device {
|
|||
#if defined(CONFIG_AGP) || defined(CONFIG_AGP_MODULE)
|
||||
drm_agp_head_t *agp;
|
||||
#endif
|
||||
drm_sg_mem_t *sg; /* Scatter / gather memory */
|
||||
unsigned long *ctx_bitmap;
|
||||
void *dev_private;
|
||||
drm_sigdata_t sigdata; /* For block_all_signals */
|
||||
|
|
@ -639,6 +650,9 @@ extern unsigned long drm_vm_shm_nopage_lock(struct vm_area_struct *vma,
|
|||
extern unsigned long drm_vm_dma_nopage(struct vm_area_struct *vma,
|
||||
unsigned long address,
|
||||
int write_access);
|
||||
extern unsigned long drm_vm_sg_nopage(struct vm_area_struct *vma,
|
||||
unsigned long address,
|
||||
int write_access);
|
||||
#else
|
||||
/* Return type changed in 2.3.23 */
|
||||
extern struct page *drm_vm_nopage(struct vm_area_struct *vma,
|
||||
|
|
@ -653,6 +667,9 @@ extern struct page *drm_vm_shm_nopage_lock(struct vm_area_struct *vma,
|
|||
extern struct page *drm_vm_dma_nopage(struct vm_area_struct *vma,
|
||||
unsigned long address,
|
||||
int write_access);
|
||||
extern struct page *drm_vm_sg_nopage(struct vm_area_struct *vma,
|
||||
unsigned long address,
|
||||
int write_access);
|
||||
#endif
|
||||
extern void drm_vm_open(struct vm_area_struct *vma);
|
||||
extern void drm_vm_close(struct vm_area_struct *vma);
|
||||
|
|
@ -831,5 +848,14 @@ extern int drm_agp_free_memory(agp_memory *handle);
|
|||
extern int drm_agp_bind_memory(agp_memory *handle, off_t start);
|
||||
extern int drm_agp_unbind_memory(agp_memory *handle);
|
||||
#endif
|
||||
|
||||
/* Scatter/gather memory supprt (scatter.c) */
|
||||
extern int drm_sg_alloc(struct inode *inode, struct file *filp,
|
||||
unsigned int cmd, unsigned long arg);
|
||||
extern int drm_sg_free(struct inode *inode, struct file *filp,
|
||||
unsigned int cmd, unsigned long arg);
|
||||
|
||||
#define page_to_pfn( page ) ((unsigned long)((page)-mem_map))
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -66,6 +66,8 @@ static drm_mem_stats_t drm_mem_stats[] = {
|
|||
[DRM_MEM_TOTALAGP] = { "totalagp" },
|
||||
[DRM_MEM_BOUNDAGP] = { "boundagp" },
|
||||
[DRM_MEM_CTXBITMAP] = { "ctxbitmap"},
|
||||
[DRM_MEM_SG] = { "sg dma" },
|
||||
[DRM_MEM_SGLISTS] = { "sglist" },
|
||||
{ NULL, 0, } /* Last entry must be null */
|
||||
};
|
||||
|
||||
|
|
|
|||
10
linux/proc.c
10
linux/proc.c
|
|
@ -165,9 +165,9 @@ static int _drm_vm_info(char *buf, char **start, off_t offset, int len,
|
|||
drm_device_t *dev = (drm_device_t *)data;
|
||||
drm_map_t *map;
|
||||
/* Hardcoded from _DRM_FRAME_BUFFER,
|
||||
_DRM_REGISTERS, _DRM_SHM, and
|
||||
_DRM_AGP. */
|
||||
const char *types[] = { "FB", "REG", "SHM", "AGP" };
|
||||
_DRM_REGISTERS, _DRM_SHM,
|
||||
_DRM_AGP, and _DRM_SCATTER_GATHER. */
|
||||
const char *types[] = { "FB", "REG", "SHM", "AGP", "SG" };
|
||||
const char *type;
|
||||
int i;
|
||||
|
||||
|
|
@ -178,7 +178,7 @@ static int _drm_vm_info(char *buf, char **start, off_t offset, int len,
|
|||
"address mtrr\n\n");
|
||||
for (i = 0; i < dev->map_count; i++) {
|
||||
map = dev->maplist[i];
|
||||
if (map->type < 0 || map->type > 3) type = "??";
|
||||
if (map->type < 0 || map->type > 4) type = "??";
|
||||
else type = types[map->type];
|
||||
DRM_PROC_PRINT("%4d 0x%08lx 0x%08lx %4.4s 0x%02x 0x%08lx ",
|
||||
i,
|
||||
|
|
@ -411,7 +411,7 @@ static int _drm_vma_info(char *buf, char **start, off_t offset, int len,
|
|||
pte = pte_offset(pmd, i);
|
||||
if (pte_present(*pte)) {
|
||||
address = __pa(pte_page(*pte))
|
||||
+ (i & (PAGE_SIZE-1));
|
||||
/*+ (i & (PAGE_SIZE-1));*/
|
||||
DRM_PROC_PRINT(" 0x%08lx -> 0x%08lx"
|
||||
" %c%c%c%c%c\n",
|
||||
i,
|
||||
|
|
|
|||
|
|
@ -74,7 +74,7 @@ int r128_addbufs_agp(struct inode *inode, struct file *filp, unsigned int cmd,
|
|||
total = PAGE_SIZE << page_order;
|
||||
|
||||
byte_count = 0;
|
||||
agp_offset = dev->agp->base + request.agp_start;
|
||||
agp_offset = request.agp_start;
|
||||
|
||||
DRM_DEBUG("count: %d\n", count);
|
||||
DRM_DEBUG("order: %d\n", order);
|
||||
|
|
@ -125,7 +125,8 @@ int r128_addbufs_agp(struct inode *inode, struct file *filp, unsigned int cmd,
|
|||
buf->order = order;
|
||||
buf->used = 0;
|
||||
buf->offset = (dma->byte_count + offset);
|
||||
buf->address = (void *)(agp_offset + offset);
|
||||
buf->bus_address = agp_offset + offset;
|
||||
buf->address = (void *)(agp_offset + dev->agp->base + offset);
|
||||
buf->next = NULL;
|
||||
buf->waiting = 0;
|
||||
buf->pending = 0;
|
||||
|
|
@ -185,6 +186,152 @@ int r128_addbufs_agp(struct inode *inode, struct file *filp, unsigned int cmd,
|
|||
}
|
||||
#endif
|
||||
|
||||
int r128_addbufs_sg(struct inode *inode, struct file *filp, unsigned int cmd,
|
||||
unsigned long arg)
|
||||
{
|
||||
drm_file_t *priv = filp->private_data;
|
||||
drm_device_t *dev = priv->dev;
|
||||
drm_device_dma_t *dma = dev->dma;
|
||||
drm_buf_desc_t request;
|
||||
drm_buf_entry_t *entry;
|
||||
drm_buf_t *buf;
|
||||
unsigned long offset;
|
||||
unsigned long agp_offset;
|
||||
int count;
|
||||
int order;
|
||||
int size;
|
||||
int alignment;
|
||||
int page_order;
|
||||
int total;
|
||||
int byte_count;
|
||||
int i;
|
||||
|
||||
if (!dma) return -EINVAL;
|
||||
|
||||
if (copy_from_user(&request,
|
||||
(drm_buf_desc_t *)arg,
|
||||
sizeof(request)))
|
||||
return -EFAULT;
|
||||
|
||||
count = request.count;
|
||||
order = drm_order(request.size);
|
||||
size = 1 << order;
|
||||
|
||||
alignment = (request.flags & _DRM_PAGE_ALIGN) ? PAGE_ALIGN(size):size;
|
||||
page_order = order - PAGE_SHIFT > 0 ? order - PAGE_SHIFT : 0;
|
||||
total = PAGE_SIZE << page_order;
|
||||
|
||||
byte_count = 0;
|
||||
agp_offset = request.agp_start;
|
||||
|
||||
DRM_DEBUG("count: %d\n", count);
|
||||
DRM_DEBUG("order: %d\n", order);
|
||||
DRM_DEBUG("size: %d\n", size);
|
||||
DRM_DEBUG("agp_offset: %ld\n", agp_offset);
|
||||
DRM_DEBUG("alignment: %d\n", alignment);
|
||||
DRM_DEBUG("page_order: %d\n", page_order);
|
||||
DRM_DEBUG("total: %d\n", total);
|
||||
|
||||
if (order < DRM_MIN_ORDER || order > DRM_MAX_ORDER) return -EINVAL;
|
||||
if (dev->queue_count) return -EBUSY; /* Not while in use */
|
||||
|
||||
spin_lock(&dev->count_lock);
|
||||
if (dev->buf_use) {
|
||||
spin_unlock(&dev->count_lock);
|
||||
return -EBUSY;
|
||||
}
|
||||
atomic_inc(&dev->buf_alloc);
|
||||
spin_unlock(&dev->count_lock);
|
||||
|
||||
down(&dev->struct_sem);
|
||||
entry = &dma->bufs[order];
|
||||
if (entry->buf_count) {
|
||||
up(&dev->struct_sem);
|
||||
atomic_dec(&dev->buf_alloc);
|
||||
return -ENOMEM; /* May only call once for each order */
|
||||
}
|
||||
|
||||
entry->buflist = drm_alloc(count * sizeof(*entry->buflist),
|
||||
DRM_MEM_BUFS);
|
||||
if (!entry->buflist) {
|
||||
up(&dev->struct_sem);
|
||||
atomic_dec(&dev->buf_alloc);
|
||||
return -ENOMEM;
|
||||
}
|
||||
memset(entry->buflist, 0, count * sizeof(*entry->buflist));
|
||||
|
||||
entry->buf_size = size;
|
||||
entry->page_order = page_order;
|
||||
offset = 0;
|
||||
|
||||
for (offset = 0;
|
||||
entry->buf_count < count;
|
||||
offset += alignment, ++entry->buf_count) {
|
||||
buf = &entry->buflist[entry->buf_count];
|
||||
buf->idx = dma->buf_count + entry->buf_count;
|
||||
buf->total = alignment;
|
||||
buf->order = order;
|
||||
buf->used = 0;
|
||||
buf->offset = (dma->byte_count + offset);
|
||||
buf->bus_address = agp_offset + offset;
|
||||
buf->address = (void *)(agp_offset + dev->sg->handle + offset);
|
||||
buf->next = NULL;
|
||||
buf->waiting = 0;
|
||||
buf->pending = 0;
|
||||
init_waitqueue_head(&buf->dma_wait);
|
||||
buf->pid = 0;
|
||||
|
||||
buf->dev_priv_size = sizeof(drm_r128_buf_priv_t);
|
||||
buf->dev_private = drm_alloc(sizeof(drm_r128_buf_priv_t),
|
||||
DRM_MEM_BUFS);
|
||||
memset(buf->dev_private, 0, buf->dev_priv_size);
|
||||
|
||||
#if DRM_DMA_HISTOGRAM
|
||||
buf->time_queued = 0;
|
||||
buf->time_dispatched = 0;
|
||||
buf->time_completed = 0;
|
||||
buf->time_freed = 0;
|
||||
#endif
|
||||
|
||||
byte_count += PAGE_SIZE << page_order;
|
||||
|
||||
DRM_DEBUG("buffer %d @ %p\n",
|
||||
entry->buf_count, buf->address);
|
||||
}
|
||||
|
||||
DRM_DEBUG("byte_count: %d\n", byte_count);
|
||||
|
||||
dma->buflist = drm_realloc(dma->buflist,
|
||||
dma->buf_count * sizeof(*dma->buflist),
|
||||
(dma->buf_count + entry->buf_count)
|
||||
* sizeof(*dma->buflist),
|
||||
DRM_MEM_BUFS);
|
||||
for (i = dma->buf_count; i < dma->buf_count + entry->buf_count; i++)
|
||||
dma->buflist[i] = &entry->buflist[i - dma->buf_count];
|
||||
|
||||
dma->buf_count += entry->buf_count;
|
||||
dma->byte_count += byte_count;
|
||||
|
||||
drm_freelist_create(&entry->freelist, entry->buf_count);
|
||||
for (i = 0; i < entry->buf_count; i++) {
|
||||
drm_freelist_put(dev, &entry->freelist, &entry->buflist[i]);
|
||||
}
|
||||
|
||||
up(&dev->struct_sem);
|
||||
|
||||
request.count = entry->buf_count;
|
||||
request.size = size;
|
||||
|
||||
if (copy_to_user((drm_buf_desc_t *)arg,
|
||||
&request,
|
||||
sizeof(request)))
|
||||
return -EFAULT;
|
||||
dma->flags = _DRM_DMA_USE_SG;
|
||||
|
||||
atomic_dec(&dev->buf_alloc);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int r128_addbufs(struct inode *inode, struct file *filp, unsigned int cmd,
|
||||
unsigned long arg)
|
||||
{
|
||||
|
|
@ -193,7 +340,7 @@ int r128_addbufs(struct inode *inode, struct file *filp, unsigned int cmd,
|
|||
drm_r128_private_t *dev_priv = dev->dev_private;
|
||||
drm_buf_desc_t request;
|
||||
|
||||
if (!dev_priv || dev_priv->is_pci) return -EINVAL;
|
||||
if (!dev_priv) return -EINVAL;
|
||||
|
||||
if (copy_from_user(&request,
|
||||
(drm_buf_desc_t *)arg,
|
||||
|
|
@ -201,8 +348,14 @@ int r128_addbufs(struct inode *inode, struct file *filp, unsigned int cmd,
|
|||
return -EFAULT;
|
||||
|
||||
#if defined(CONFIG_AGP) || defined(CONFIG_AGP_MODULE)
|
||||
if (dev_priv->is_pci && (request.flags & _DRM_AGP_BUFFER))
|
||||
return -EINVAL;
|
||||
if (!dev_priv->is_pci && (request.flags & _DRM_SG_BUFFER))
|
||||
return -EINVAL;
|
||||
if (request.flags & _DRM_AGP_BUFFER)
|
||||
return r128_addbufs_agp(inode, filp, cmd, arg);
|
||||
if (request.flags & _DRM_SG_BUFFER)
|
||||
return r128_addbufs_sg(inode, filp, cmd, arg);
|
||||
else
|
||||
#endif
|
||||
return -EINVAL;
|
||||
|
|
@ -222,7 +375,7 @@ int r128_mapbufs(struct inode *inode, struct file *filp, unsigned int cmd,
|
|||
drm_buf_map_t request;
|
||||
int i;
|
||||
|
||||
if (!dma || !dev_priv || dev_priv->is_pci) return -EINVAL;
|
||||
if (!dma || !dev_priv) return -EINVAL;
|
||||
|
||||
DRM_DEBUG("\n");
|
||||
|
||||
|
|
@ -240,7 +393,8 @@ int r128_mapbufs(struct inode *inode, struct file *filp, unsigned int cmd,
|
|||
return -EFAULT;
|
||||
|
||||
if (request.count >= dma->buf_count) {
|
||||
if (dma->flags & _DRM_DMA_USE_AGP) {
|
||||
if (dma->flags & _DRM_DMA_USE_AGP ||
|
||||
dma->flags & _DRM_DMA_USE_SG) {
|
||||
drm_map_t *map;
|
||||
|
||||
map = dev_priv->buffers;
|
||||
|
|
|
|||
151
linux/r128_cce.c
151
linux/r128_cce.c
|
|
@ -37,6 +37,7 @@
|
|||
#include <linux/delay.h>
|
||||
|
||||
#define R128_FIFO_DEBUG 0
|
||||
#define DEBUG_RING_AFTER_INIT 0
|
||||
|
||||
|
||||
/* CCE microcode (from ATI) */
|
||||
|
|
@ -128,6 +129,12 @@ static void r128_status( drm_r128_private_t *dev_priv )
|
|||
(unsigned int)R128_READ( R128_PM4_MICRO_CNTL ) );
|
||||
printk( "PM4_BUFFER_CNTL = 0x%08x\n",
|
||||
(unsigned int)R128_READ( R128_PM4_BUFFER_CNTL ) );
|
||||
printk( "PM4_BUFFER_DL_WPTR = 0x%08x\n",
|
||||
(unsigned int)R128_READ( R128_PM4_BUFFER_DL_WPTR ) );
|
||||
printk( "PM4_BUFFER_DL_RPTR = 0x%08x\n",
|
||||
(unsigned int)R128_READ( R128_PM4_BUFFER_DL_RPTR ) );
|
||||
printk( "*ring.head = 0x%08x\n",
|
||||
(unsigned int)*dev_priv->ring.head );
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
@ -228,7 +235,13 @@ static int r128_do_cce_idle( drm_r128_private_t *dev_priv )
|
|||
int i;
|
||||
|
||||
for ( i = 0 ; i < dev_priv->usec_timeout ; i++ ) {
|
||||
if ( *dev_priv->ring.head == dev_priv->ring.tail ) {
|
||||
#if 0
|
||||
if ( R128_READ( R128_PM4_BUFFER_DL_WPTR ) ==
|
||||
R128_READ( R128_PM4_BUFFER_DL_RPTR ) )
|
||||
#else
|
||||
if ( *dev_priv->ring.head == dev_priv->ring.tail )
|
||||
#endif
|
||||
{
|
||||
int pm4stat = R128_READ( R128_PM4_STAT );
|
||||
if ( ( (pm4stat & R128_PM4_FIFOCNT_MASK) >=
|
||||
dev_priv->cce_fifo_size ) &&
|
||||
|
|
@ -241,7 +254,7 @@ static int r128_do_cce_idle( drm_r128_private_t *dev_priv )
|
|||
}
|
||||
|
||||
#if R128_FIFO_DEBUG
|
||||
DRM_ERROR( "failed!\n" );
|
||||
DRM_ERROR( "cce idle failed!\n" );
|
||||
r128_status( dev_priv );
|
||||
#endif
|
||||
return -EBUSY;
|
||||
|
|
@ -335,7 +348,11 @@ static void r128_cce_init_ring_buffer( drm_device_t *dev )
|
|||
/* The manual (p. 2) says this address is in "VM space". This
|
||||
* means it's an offset from the start of AGP space.
|
||||
*/
|
||||
ring_start = dev_priv->cce_ring->offset - dev->agp->base;
|
||||
if ( !dev_priv->is_pci ) {
|
||||
ring_start = dev_priv->cce_ring->offset - dev->agp->base;
|
||||
} else {
|
||||
ring_start = dev_priv->cce_ring->offset - dev->sg->handle;
|
||||
}
|
||||
R128_WRITE( R128_PM4_BUFFER_OFFSET, ring_start | R128_AGP_OFFSET );
|
||||
|
||||
R128_WRITE( R128_PM4_BUFFER_DL_WPTR, 0 );
|
||||
|
|
@ -343,8 +360,23 @@ static void r128_cce_init_ring_buffer( drm_device_t *dev )
|
|||
|
||||
/* DL_RPTR_ADDR is a physical address in AGP space. */
|
||||
*dev_priv->ring.head = 0;
|
||||
R128_WRITE( R128_PM4_BUFFER_DL_RPTR_ADDR,
|
||||
dev_priv->ring_rptr->offset );
|
||||
if ( !dev_priv->is_pci ) {
|
||||
R128_WRITE( R128_PM4_BUFFER_DL_RPTR_ADDR,
|
||||
dev_priv->ring_rptr->offset );
|
||||
} else {
|
||||
drm_sg_mem_t *entry = dev->sg;
|
||||
unsigned long tmp_ofs, page_ofs;
|
||||
|
||||
tmp_ofs = dev_priv->ring_rptr->offset - dev->sg->handle;
|
||||
page_ofs = tmp_ofs >> PAGE_SHIFT;
|
||||
|
||||
R128_WRITE( R128_PM4_BUFFER_DL_RPTR_ADDR,
|
||||
virt_to_bus(entry->pagelist[page_ofs]->virtual));
|
||||
|
||||
DRM_INFO( "ring rptr: offset=0x%08lx handle=0x%08lx\n",
|
||||
virt_to_bus(entry->pagelist[page_ofs]->virtual),
|
||||
entry->handle + tmp_ofs );
|
||||
}
|
||||
|
||||
/* Set watermark control */
|
||||
R128_WRITE( R128_PM4_BUFFER_WM_CNTL,
|
||||
|
|
@ -379,7 +411,8 @@ static int r128_do_init_cce( drm_device_t *dev, drm_r128_init_t *init )
|
|||
* Fail here so we can remove all checks for PCI cards around
|
||||
* the CCE ring code.
|
||||
*/
|
||||
if ( dev_priv->is_pci ) {
|
||||
|
||||
if ( dev_priv->is_pci && !dev->sg) {
|
||||
drm_free( dev_priv, sizeof(*dev_priv), DRM_MEM_DRIVER );
|
||||
dev->dev_private = NULL;
|
||||
return -EINVAL;
|
||||
|
|
@ -390,10 +423,12 @@ static int r128_do_init_cce( drm_device_t *dev, drm_r128_init_t *init )
|
|||
dev_priv->usec_timeout > R128_MAX_USEC_TIMEOUT ) {
|
||||
drm_free( dev_priv, sizeof(*dev_priv), DRM_MEM_DRIVER );
|
||||
dev->dev_private = NULL;
|
||||
printk("USec timeout is screwed\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
dev_priv->cce_mode = init->cce_mode;
|
||||
dev_priv->cce_secure = init->cce_secure;
|
||||
|
||||
/* GH: Simple idle check.
|
||||
*/
|
||||
|
|
@ -409,6 +444,7 @@ static int r128_do_init_cce( drm_device_t *dev, drm_r128_init_t *init )
|
|||
( init->cce_mode != R128_PM4_64BM_64VCBM_64INDBM ) ) {
|
||||
drm_free( dev_priv, sizeof(*dev_priv), DRM_MEM_DRIVER );
|
||||
dev->dev_private = NULL;
|
||||
printk("CCE mode is screwed\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
|
@ -479,9 +515,25 @@ static int r128_do_init_cce( drm_device_t *dev, drm_r128_init_t *init )
|
|||
(drm_r128_sarea_t *)((u8 *)dev_priv->sarea->handle +
|
||||
init->sarea_priv_offset);
|
||||
|
||||
DO_IOREMAP( dev_priv->cce_ring );
|
||||
DO_IOREMAP( dev_priv->ring_rptr );
|
||||
DO_IOREMAP( dev_priv->buffers );
|
||||
if(dev_priv->is_pci) {
|
||||
printk("dev->sg->virtual (cce_ring): %p\n", dev->sg->virtual);
|
||||
|
||||
dev_priv->cce_ring->handle =
|
||||
(void *)dev_priv->cce_ring->offset;
|
||||
printk("cce_ring : %p\n", dev_priv->cce_ring->handle);
|
||||
|
||||
dev_priv->ring_rptr->handle =
|
||||
(void *)dev_priv->ring_rptr->offset;
|
||||
printk("ring_rptr : %p\n", dev_priv->ring_rptr->handle);
|
||||
|
||||
dev_priv->buffers->handle = (void *)dev_priv->buffers->offset;
|
||||
printk("buffers : %p\n", dev_priv->buffers->handle);
|
||||
} else {
|
||||
DO_IOREMAP( dev_priv->cce_ring );
|
||||
DO_IOREMAP( dev_priv->ring_rptr );
|
||||
DO_IOREMAP( dev_priv->buffers );
|
||||
}
|
||||
|
||||
#if 0
|
||||
if ( !dev_priv->is_pci ) {
|
||||
DO_IOREMAP( dev_priv->agp_textures );
|
||||
|
|
@ -507,10 +559,83 @@ static int r128_do_init_cce( drm_device_t *dev, drm_r128_init_t *init )
|
|||
R128_WRITE( R128_LAST_DISPATCH_REG,
|
||||
dev_priv->sarea_priv->last_dispatch );
|
||||
|
||||
if ( dev_priv->is_pci && r128_pcigart_init( dev ) < 0) {
|
||||
DRM_ERROR( "failed to init PCIGART!\n" );
|
||||
drm_free( dev_priv, sizeof(*dev_priv),
|
||||
DRM_MEM_DRIVER );
|
||||
dev->dev_private = NULL;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
printk("Initializing ring buffer\n");
|
||||
r128_cce_init_ring_buffer( dev );
|
||||
printk("Initializing microcode\n");
|
||||
r128_cce_load_microcode( dev_priv );
|
||||
printk("Reseting engine\n");
|
||||
r128_do_engine_reset( dev );
|
||||
|
||||
printk("Waiting for idle\n");
|
||||
r128_do_wait_for_idle( dev_priv );
|
||||
|
||||
{
|
||||
printk( "GUI_STAT = 0x%08x\n",
|
||||
(unsigned int)R128_READ( R128_GUI_STAT ) );
|
||||
printk( "PM4_STAT = 0x%08x\n",
|
||||
(unsigned int)R128_READ( R128_PM4_STAT ) );
|
||||
printk( "PM4_BUFFER_DL_WPTR = 0x%08x\n",
|
||||
(unsigned int)R128_READ( R128_PM4_BUFFER_DL_WPTR ) );
|
||||
printk( "PM4_BUFFER_DL_RPTR = 0x%08x\n",
|
||||
(unsigned int)R128_READ( R128_PM4_BUFFER_DL_RPTR ) );
|
||||
printk( "PM4_MICRO_CNTL = 0x%08x\n",
|
||||
(unsigned int)R128_READ( R128_PM4_MICRO_CNTL ) );
|
||||
printk( "PM4_BUFFER_CNTL = 0x%08x\n",
|
||||
(unsigned int)R128_READ( R128_PM4_BUFFER_CNTL ) );
|
||||
printk( "PM4_BUFFER_OFFSET = 0x%08x\n",
|
||||
(unsigned int)R128_READ( R128_PM4_BUFFER_OFFSET ) );
|
||||
printk( "PM4_BUFFER_DL_RPTR_ADDR = 0x%08x\n",
|
||||
(unsigned int)R128_READ( R128_PM4_BUFFER_DL_RPTR_ADDR ));
|
||||
printk( "PCI_GART_PAGE = 0x%08x\n",
|
||||
(unsigned int)R128_READ( R128_PCI_GART_PAGE ) );
|
||||
printk( "BM_CHUNK_0_VAL = 0x%08x\n",
|
||||
(unsigned int)R128_READ( R128_BM_CHUNK_0_VAL ) );
|
||||
}
|
||||
|
||||
#ifdef DEBUG_RING_AFTER_INIT
|
||||
{
|
||||
int last_dispatch;
|
||||
RING_LOCALS;
|
||||
|
||||
r128_do_cce_start( dev_priv );
|
||||
|
||||
printk("Doing a test write to dispatch register\n");
|
||||
|
||||
BEGIN_RING( 2 );
|
||||
OUT_RING( CCE_PACKET0( R128_LAST_DISPATCH_REG, 0 ) );
|
||||
OUT_RING( 0xcafebabe );
|
||||
ADVANCE_RING();
|
||||
|
||||
r128_do_cce_flush( dev_priv );
|
||||
r128_do_cce_idle( dev_priv );
|
||||
last_dispatch = R128_READ( R128_LAST_DISPATCH_REG );
|
||||
printk("last_dispatch = 0x%x\n", last_dispatch);
|
||||
|
||||
BEGIN_RING( 2 );
|
||||
OUT_RING( CCE_PACKET0( R128_LAST_DISPATCH_REG, 0 ) );
|
||||
OUT_RING( 0 );
|
||||
ADVANCE_RING();
|
||||
|
||||
r128_do_cce_flush( dev_priv );
|
||||
r128_do_cce_idle( dev_priv );
|
||||
last_dispatch = R128_READ( R128_LAST_DISPATCH_REG );
|
||||
printk("last_dispatch 2 = 0x%x\n", last_dispatch);
|
||||
|
||||
r128_do_wait_for_idle( dev_priv );
|
||||
r128_do_engine_reset( dev );
|
||||
r128_do_wait_for_idle( dev_priv );
|
||||
}
|
||||
#endif
|
||||
|
||||
printk("Returning zero\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -519,9 +644,11 @@ static int r128_do_cleanup_cce( drm_device_t *dev )
|
|||
if ( dev->dev_private ) {
|
||||
drm_r128_private_t *dev_priv = dev->dev_private;
|
||||
|
||||
DO_IOREMAPFREE( dev_priv->cce_ring );
|
||||
DO_IOREMAPFREE( dev_priv->ring_rptr );
|
||||
DO_IOREMAPFREE( dev_priv->buffers );
|
||||
if(!dev_priv->is_pci) {
|
||||
DO_IOREMAPFREE( dev_priv->cce_ring );
|
||||
DO_IOREMAPFREE( dev_priv->ring_rptr );
|
||||
DO_IOREMAPFREE( dev_priv->buffers );
|
||||
}
|
||||
#if 0
|
||||
if ( !dev_priv->is_pci ) {
|
||||
DO_IOREMAPFREE( dev_priv->agp_textures );
|
||||
|
|
|
|||
|
|
@ -107,6 +107,8 @@ static drm_ioctl_desc_t r128_ioctls[] = {
|
|||
[DRM_IOCTL_NR(DRM_IOCTL_AGP_BIND)] = { drm_agp_bind, 1, 1 },
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_AGP_UNBIND)] = { drm_agp_unbind, 1, 1 },
|
||||
#endif
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_SG_ALLOC)] = { drm_sg_alloc, 1, 1 },
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_SG_FREE)] = { drm_sg_free, 1, 1 },
|
||||
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_R128_INIT)] = { r128_cce_init, 1, 1 },
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_R128_CCE_START)] = { r128_cce_start, 1, 1 },
|
||||
|
|
@ -309,6 +311,12 @@ static int r128_takedown(drm_device_t *dev)
|
|||
/* Do nothing here, because this is all
|
||||
handled in the AGP/GART driver. */
|
||||
break;
|
||||
case _DRM_SCATTER_GATHER:
|
||||
if(dev->sg) {
|
||||
drm_sg_cleanup(dev->sg);
|
||||
dev->sg = NULL;
|
||||
}
|
||||
break;
|
||||
}
|
||||
drm_free(map, sizeof(*map), DRM_MEM_MAPS);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -59,6 +59,7 @@ typedef struct drm_r128_private {
|
|||
|
||||
int cce_mode;
|
||||
int cce_fifo_size;
|
||||
int cce_secure;
|
||||
int cce_running;
|
||||
|
||||
drm_r128_freelist_t *head;
|
||||
|
|
@ -90,6 +91,9 @@ typedef struct drm_r128_private {
|
|||
u32 depth_pitch_offset_c;
|
||||
u32 span_pitch_offset_c;
|
||||
|
||||
void *pci_gart_page;
|
||||
unsigned long phys_pci_gart_page;
|
||||
|
||||
drm_map_t *sarea;
|
||||
drm_map_t *fb;
|
||||
drm_map_t *mmio;
|
||||
|
|
@ -216,6 +220,11 @@ extern int r128_context_switch_complete(drm_device_t *dev, int new);
|
|||
#define R128_AUX3_SC_TOP 0x168c
|
||||
#define R128_AUX3_SC_BOTTOM 0x1690
|
||||
|
||||
#define R128_BM_CHUNK_0_VAL 0x0a18
|
||||
# define R128_BM_PTR_FORCE_TO_PCI (1 << 21)
|
||||
# define R128_BM_PM4_RD_FORCE_TO_PCI (1 << 22)
|
||||
# define R128_BM_GLOBAL_FORCE_TO_PCI (1 << 23)
|
||||
|
||||
#define R128_BRUSH_DATA0 0x1480
|
||||
#define R128_BUS_CNTL 0x0030
|
||||
# define R128_BUS_MASTER_DIS (1 << 6)
|
||||
|
|
@ -275,6 +284,7 @@ extern int r128_context_switch_complete(drm_device_t *dev, int new);
|
|||
# define R128_PC_FLUSH_ALL 0x00ff
|
||||
# define R128_PC_BUSY (1 << 31)
|
||||
|
||||
#define R128_PCI_GART_PAGE 0x017c
|
||||
#define R128_PRIM_TEX_CNTL_C 0x1cb0
|
||||
|
||||
#define R128_SCALE_3D_CNTL 0x1a00
|
||||
|
|
|
|||
156
linux/r128_pcigart.c
Normal file
156
linux/r128_pcigart.c
Normal file
|
|
@ -0,0 +1,156 @@
|
|||
/* r128_pcigart.c -- Rage 128 PCI GART support -*- linux-c -*-
|
||||
* Created: Wed Dec 13 21:52:19 2000 by gareth@valinux.com
|
||||
*
|
||||
* Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* Authors:
|
||||
* Gareth Hughes <gareth@valinux.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#define __NO_VERSION__
|
||||
#include "drmP.h"
|
||||
#include "r128_drv.h"
|
||||
|
||||
#include <linux/interrupt.h> /* For task queue support */
|
||||
#include <linux/delay.h>
|
||||
|
||||
|
||||
|
||||
|
||||
static unsigned long r128_alloc_pages( void )
|
||||
{
|
||||
unsigned long address;
|
||||
unsigned long addr_end;
|
||||
struct page *page;
|
||||
|
||||
DRM_INFO( "%s\n", __FUNCTION__ );
|
||||
|
||||
address = __get_free_pages( GFP_KERNEL, 3 );
|
||||
if ( address == 0UL ) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
addr_end = address + ((PAGE_SIZE * (1 << 3)) - 1);
|
||||
for (page = virt_to_page(address);
|
||||
page <= virt_to_page(addr_end);
|
||||
page++) {
|
||||
atomic_inc( &page->count );
|
||||
SetPageReserved( page );
|
||||
}
|
||||
|
||||
DRM_INFO( "%s: returning 0x%08lx\n", __FUNCTION__, address );
|
||||
return address;
|
||||
}
|
||||
|
||||
static void r128_free_pages( unsigned long address )
|
||||
{
|
||||
unsigned long addr_end;
|
||||
struct page *page;
|
||||
|
||||
DRM_INFO( "%s\n", __FUNCTION__ );
|
||||
if ( !address ) return;
|
||||
|
||||
addr_end = address + ((PAGE_SIZE * (1 << 3)) - 1);
|
||||
|
||||
for (page = virt_to_page(address);
|
||||
page <= virt_to_page(addr_end);
|
||||
page++) {
|
||||
atomic_dec( &page->count );
|
||||
ClearPageReserved( page );
|
||||
}
|
||||
|
||||
free_pages( address , 3 );
|
||||
}
|
||||
|
||||
int r128_pcigart_init( drm_device_t *dev )
|
||||
{
|
||||
drm_r128_private_t *dev_priv = dev->dev_private;
|
||||
drm_sg_mem_t *entry = dev->sg;
|
||||
unsigned long address;
|
||||
unsigned long pages;
|
||||
u32 *pci_gart;
|
||||
int i;
|
||||
DRM_INFO( "%s\n", __FUNCTION__ );
|
||||
|
||||
#if 0
|
||||
dev_priv->phys_pci_gart_page = 0;
|
||||
dev_priv->pci_gart_page = NULL;
|
||||
|
||||
return 0;
|
||||
#endif
|
||||
|
||||
if ( !entry ) {
|
||||
DRM_ERROR( "no scatter/gather memory!\n" );
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* 32 MB aperture is the largest size */
|
||||
pages = ( entry->pages <= 8192 )
|
||||
? entry->pages : 8192;
|
||||
|
||||
address = r128_alloc_pages();
|
||||
|
||||
|
||||
if ( !address ) {
|
||||
DRM_ERROR( "cannot allocate PCI GART page!\n" );
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
dev_priv->pci_gart_page = dev_priv->phys_pci_gart_page = address;
|
||||
|
||||
DRM_INFO( "%s: phys=0x%08lx virt=%p\n",
|
||||
__FUNCTION__, dev_priv->phys_pci_gart_page,
|
||||
dev_priv->pci_gart_page );
|
||||
|
||||
pci_gart = (u32 *)dev_priv->pci_gart_page;
|
||||
|
||||
for ( i = 0; i < 8192 ; i++) pci_gart[i] = 0;
|
||||
for ( i = 0 ; i < pages ; i++ ) {
|
||||
pci_gart[i] = virt_to_bus( entry->pagelist[i]->virtual );
|
||||
}
|
||||
|
||||
DRM_INFO( "%s: writing PCI_GART_PAGE...\n", __FUNCTION__ );
|
||||
R128_WRITE( R128_PCI_GART_PAGE, virt_to_bus((void *)address) );
|
||||
DRM_INFO( "%s: writing PCI_GART_PAGE... done.\n", __FUNCTION__ );
|
||||
|
||||
asm volatile ( "wbinvd" ::: "memory" );
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int r128_pcigart_cleanup( drm_device_t *dev )
|
||||
{
|
||||
drm_r128_private_t *dev_priv = dev->dev_private;
|
||||
DRM_INFO( "%s\n", __FUNCTION__ );
|
||||
#if 0
|
||||
if ( dev_priv->pci_gart_page ) {
|
||||
iounmap( dev_priv->pci_gart_page );
|
||||
}
|
||||
#endif
|
||||
if ( dev_priv->phys_pci_gart_page ) {
|
||||
r128_free_pages( dev_priv->phys_pci_gart_page );
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -613,7 +613,10 @@ static void r128_cce_dispatch_vertex( drm_device_t *dev,
|
|||
drm_r128_buf_priv_t *buf_priv = buf->dev_private;
|
||||
drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
|
||||
int format = sarea_priv->vc_format;
|
||||
int offset = buf->bus_address;
|
||||
/*
|
||||
int offset = dev_priv->buffers->offset + buf->offset - dev->agp->base;
|
||||
*/
|
||||
int size = buf->used;
|
||||
int prim = buf_priv->prim;
|
||||
int i = 0;
|
||||
|
|
@ -705,8 +708,7 @@ static void r128_cce_dispatch_indirect( drm_device_t *dev,
|
|||
r128_update_ring_snapshot( dev_priv );
|
||||
|
||||
if ( start != end ) {
|
||||
int offset = (dev_priv->buffers->offset - dev->agp->base
|
||||
+ buf->offset + start);
|
||||
int offset = (buf->bus_address + start);
|
||||
int dwords = (end - start + 3) / sizeof(u32);
|
||||
|
||||
/* Indirect buffer data must be an even number of
|
||||
|
|
@ -766,11 +768,12 @@ static void r128_cce_dispatch_indices( drm_device_t *dev,
|
|||
int start, int end,
|
||||
int count )
|
||||
{
|
||||
drm_device_dma_t *dma = dev->dma;
|
||||
drm_r128_private_t *dev_priv = dev->dev_private;
|
||||
drm_r128_buf_priv_t *buf_priv = buf->dev_private;
|
||||
drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
|
||||
int format = sarea_priv->vc_format;
|
||||
int offset = dev_priv->buffers->offset - dev->agp->base;
|
||||
int offset;
|
||||
int prim = buf_priv->prim;
|
||||
u32 *data;
|
||||
int dwords;
|
||||
|
|
@ -778,6 +781,10 @@ static void r128_cce_dispatch_indices( drm_device_t *dev,
|
|||
RING_LOCALS;
|
||||
DRM_DEBUG( "indices: s=%d e=%d c=%d\n", start, end, count );
|
||||
|
||||
if(dma->flags == _DRM_DMA_USE_SG)
|
||||
offset = dev_priv->buffers->offset - dev->sg->handle;
|
||||
else offset = dev_priv->buffers->offset - dev->agp->base;
|
||||
|
||||
r128_update_ring_snapshot( dev_priv );
|
||||
|
||||
if ( 0 )
|
||||
|
|
@ -1449,7 +1456,7 @@ int r128_cce_vertex( struct inode *inode, struct file *filp,
|
|||
DRM_ERROR( "%s called without lock held\n", __FUNCTION__ );
|
||||
return -EINVAL;
|
||||
}
|
||||
if ( !dev_priv || dev_priv->is_pci ) {
|
||||
if ( !dev_priv ) {
|
||||
DRM_ERROR( "%s called with a PCI card\n", __FUNCTION__ );
|
||||
return -EINVAL;
|
||||
}
|
||||
|
|
@ -1512,7 +1519,7 @@ int r128_cce_indices( struct inode *inode, struct file *filp,
|
|||
DRM_ERROR( "%s called without lock held\n", __FUNCTION__ );
|
||||
return -EINVAL;
|
||||
}
|
||||
if ( !dev_priv || dev_priv->is_pci ) {
|
||||
if ( !dev_priv ) {
|
||||
DRM_ERROR( "%s called with a PCI card\n", __FUNCTION__ );
|
||||
return -EINVAL;
|
||||
}
|
||||
|
|
|
|||
211
linux/scatter.c
Normal file
211
linux/scatter.c
Normal file
|
|
@ -0,0 +1,211 @@
|
|||
/* scatter.c -- IOCTLs to manage scatter/gather memory -*- linux-c -*-
|
||||
* Created: Mon Dec 18 23:20:54 2000 by gareth@valinux.com
|
||||
*
|
||||
* Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* Authors:
|
||||
* Gareth Hughes <gareth@valinux.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#define __NO_VERSION__
|
||||
#include <linux/config.h>
|
||||
#include "drmP.h"
|
||||
#include <linux/wrapper.h>
|
||||
|
||||
#define DEBUG_SCATTER 1
|
||||
|
||||
static void drm_sg_cleanup( drm_sg_mem_t *entry )
|
||||
{
|
||||
int i;
|
||||
|
||||
for ( i = 0 ; i < entry->pages ; i++ ) {
|
||||
ClearPageReserved( entry->pagelist[i] );
|
||||
}
|
||||
|
||||
vfree( entry->virtual );
|
||||
|
||||
drm_free( entry->pagelist,
|
||||
entry->pages * sizeof(*entry->pagelist),
|
||||
DRM_MEM_PAGES );
|
||||
drm_free( entry,
|
||||
sizeof(*entry),
|
||||
DRM_MEM_SGLISTS );
|
||||
}
|
||||
|
||||
static inline long usec( void )
|
||||
{
|
||||
struct timeval tv;
|
||||
|
||||
do_gettimeofday( &tv );
|
||||
|
||||
return (tv.tv_sec & 0x7ff) * 1000000 + tv.tv_usec;
|
||||
}
|
||||
|
||||
int drm_sg_alloc( struct inode *inode, struct file *filp,
|
||||
unsigned int cmd, unsigned long arg )
|
||||
{
|
||||
drm_file_t *priv = filp->private_data;
|
||||
drm_device_t *dev = priv->dev;
|
||||
drm_scatter_gather_t request;
|
||||
drm_sg_mem_t *entry;
|
||||
unsigned long pages;
|
||||
pgd_t *pgd;
|
||||
pmd_t *pmd;
|
||||
pte_t *pte;
|
||||
int i, j;
|
||||
DRM_INFO( "%s\n", __FUNCTION__ );
|
||||
|
||||
if ( dev->sg ) return -EINVAL;
|
||||
|
||||
if ( copy_from_user( &request,
|
||||
(drm_scatter_gather_t *)arg,
|
||||
sizeof(request) ) )
|
||||
return -EFAULT;
|
||||
|
||||
entry = drm_alloc( sizeof(*entry), DRM_MEM_SGLISTS );
|
||||
if ( !entry ) return -ENOMEM;
|
||||
|
||||
memset( entry, 0, sizeof(*entry) );
|
||||
|
||||
pages = (request.size + PAGE_SIZE - 1) / PAGE_SIZE;
|
||||
DRM_DEBUG( "sg size=%ld pages=%ld\n", request.size, pages );
|
||||
|
||||
entry->pages = pages;
|
||||
entry->pagelist = drm_alloc( pages * sizeof(*entry->pagelist),
|
||||
DRM_MEM_PAGES );
|
||||
if ( !entry->pagelist ) {
|
||||
drm_free( entry, sizeof(*entry), DRM_MEM_SGLISTS );
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/* FIXME: We should really have a kernel call for this...
|
||||
*/
|
||||
entry->virtual = __vmalloc( (pages << PAGE_SHIFT),
|
||||
GFP_KERNEL,
|
||||
PAGE_KERNEL);
|
||||
if ( !entry->virtual ) {
|
||||
drm_free( entry->pagelist,
|
||||
entry->pages * sizeof(*entry->pagelist),
|
||||
DRM_MEM_PAGES );
|
||||
drm_free( entry,
|
||||
sizeof(*entry),
|
||||
DRM_MEM_SGLISTS );
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/* This also forces the mapping of COW pages, so our page list
|
||||
* will be valid. Please don't remove it...
|
||||
*/
|
||||
memset( entry->virtual, 0, pages << PAGE_SHIFT );
|
||||
|
||||
entry->handle = (unsigned long)entry->virtual;
|
||||
|
||||
DRM_DEBUG( "sg alloc handle = %08lx\n", entry->handle );
|
||||
DRM_DEBUG( "sg alloc virtual = %p\n", entry->virtual );
|
||||
|
||||
for ( i = entry->handle, j = 0 ; j < pages ; i += PAGE_SIZE, j++ ) {
|
||||
pgd = pgd_offset_k( i );
|
||||
pmd = pmd_offset( pgd, i );
|
||||
pte = pte_offset( pmd, i );
|
||||
|
||||
entry->pagelist[j]= pte_page( *pte );
|
||||
SetPageReserved( entry->pagelist[j] );
|
||||
|
||||
if ( j < 16 ) {
|
||||
DRM_DEBUG("0x%08lx (page %lu) => 0x%08lx\n",
|
||||
i, j,
|
||||
(unsigned long)entry->pagelist[j]->virtual);
|
||||
}
|
||||
}
|
||||
|
||||
request.handle = entry->handle;
|
||||
|
||||
if ( copy_to_user( (drm_scatter_gather_t *)arg,
|
||||
&request,
|
||||
sizeof(request) ) ) {
|
||||
drm_sg_cleanup( entry );
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
dev->sg = entry;
|
||||
|
||||
#ifdef DEBUG_SCATTER
|
||||
/* Verify that each page points to its virtual address, and vice
|
||||
* versa.
|
||||
*/
|
||||
{
|
||||
int error = 0;
|
||||
|
||||
for(i = 0; i < pages; i++) {
|
||||
unsigned long *tmp;
|
||||
|
||||
tmp = (unsigned long *)entry->pagelist[i]->virtual;
|
||||
for(j = 0; j < PAGE_SIZE / sizeof(unsigned long); j++, tmp++) {
|
||||
*tmp = 0xcafebabe;
|
||||
}
|
||||
tmp = (unsigned long *)((u8 *)entry->virtual +
|
||||
(PAGE_SIZE * i));
|
||||
for(j = 0; j < PAGE_SIZE / sizeof(unsigned long); j++, tmp++) {
|
||||
if(*tmp != 0xcafebabe && error == 0) {
|
||||
error = 1;
|
||||
printk("Scatter allocation error, pagelist"
|
||||
" does not match virtual mapping\n");
|
||||
}
|
||||
}
|
||||
tmp = (unsigned long *)entry->pagelist[i]->virtual;
|
||||
for(j = 0; j < PAGE_SIZE / sizeof(unsigned long); j++, tmp++) {
|
||||
*tmp = 0;
|
||||
}
|
||||
}
|
||||
if(error == 0) printk("Scatter allocation matches pagelist\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int drm_sg_free( struct inode *inode, struct file *filp,
|
||||
unsigned int cmd, unsigned long arg )
|
||||
{
|
||||
drm_file_t *priv = filp->private_data;
|
||||
drm_device_t *dev = priv->dev;
|
||||
drm_scatter_gather_t request;
|
||||
drm_sg_mem_t *entry;
|
||||
|
||||
if ( copy_from_user( &request,
|
||||
(drm_scatter_gather_t *)arg,
|
||||
sizeof(request) ) )
|
||||
return -EFAULT;
|
||||
|
||||
entry = dev->sg;
|
||||
dev->sg = NULL;
|
||||
|
||||
if ( !entry || entry->handle != request.handle ) return -EINVAL;
|
||||
|
||||
DRM_INFO( "sg free virtual = %p\n", entry->virtual );
|
||||
|
||||
drm_sg_cleanup( entry );
|
||||
|
||||
return 0;
|
||||
}
|
||||
68
linux/vm.c
68
linux/vm.c
|
|
@ -56,6 +56,12 @@ struct vm_operations_struct drm_vm_dma_ops = {
|
|||
close: drm_vm_close,
|
||||
};
|
||||
|
||||
struct vm_operations_struct drm_vm_sg_ops = {
|
||||
nopage: drm_vm_sg_nopage,
|
||||
open: drm_vm_open,
|
||||
close: drm_vm_close,
|
||||
};
|
||||
|
||||
#if LINUX_VERSION_CODE < 0x020317
|
||||
unsigned long drm_vm_nopage(struct vm_area_struct *vma,
|
||||
unsigned long address,
|
||||
|
|
@ -172,6 +178,49 @@ struct page *drm_vm_dma_nopage(struct vm_area_struct *vma,
|
|||
#endif
|
||||
}
|
||||
|
||||
#if LINUX_VERSION_CODE < 0x020317
|
||||
unsigned long drm_vm_sg_nopage(struct vm_area_struct *vma,
|
||||
unsigned long address,
|
||||
int write_access)
|
||||
#else
|
||||
/* Return type changed in 2.3.23 */
|
||||
struct page *drm_vm_sg_nopage(struct vm_area_struct *vma,
|
||||
unsigned long address,
|
||||
int write_access)
|
||||
#endif
|
||||
{
|
||||
#if LINUX_VERSION_CODE >= 0x020300
|
||||
drm_map_t *map = (drm_map_t *)vma->vm_private_data;
|
||||
#else
|
||||
drm_map_t *map = (drm_map_t *)vma->vm_pte;
|
||||
#endif
|
||||
drm_file_t *priv = vma->vm_file->private_data;
|
||||
drm_device_t *dev = priv->dev;
|
||||
drm_sg_mem_t *entry = dev->sg;
|
||||
unsigned long offset;
|
||||
unsigned long map_offset;
|
||||
unsigned long page_offset;
|
||||
struct page *page;
|
||||
|
||||
if (!entry) return NOPAGE_SIGBUS; /* Error */
|
||||
if (address > vma->vm_end) return NOPAGE_SIGBUS; /* Disallow mremap */
|
||||
if (!entry->pagelist) return NOPAGE_OOM ; /* Nothing allocated */
|
||||
|
||||
|
||||
offset = address - vma->vm_start;
|
||||
map_offset = map->offset - dev->sg->handle;
|
||||
page_offset = (offset >> PAGE_SHIFT) + (map_offset >> PAGE_SHIFT);
|
||||
page = entry->pagelist[page_offset];
|
||||
atomic_inc(&page->count); /* Dec. by kernel */
|
||||
|
||||
|
||||
#if LINUX_VERSION_CODE < 0x020317
|
||||
return (unsigned long)virt_to_phys(page->virtual);
|
||||
#else
|
||||
return page;
|
||||
#endif
|
||||
}
|
||||
|
||||
void drm_vm_open(struct vm_area_struct *vma)
|
||||
{
|
||||
drm_file_t *priv = vma->vm_file->private_data;
|
||||
|
|
@ -311,6 +360,12 @@ int drm_mmap(struct file *filp, struct vm_area_struct *vma)
|
|||
#endif
|
||||
}
|
||||
|
||||
if (map->type == _DRM_SCATTER_GATHER) {
|
||||
DRM_DEBUG("%s: scatter/gather\n", __FUNCTION__);
|
||||
DRM_DEBUG("start = 0x%lx, end = 0x%lx, offset = 0x%lx\n",
|
||||
vma->vm_start, vma->vm_end, VM_OFFSET(vma));
|
||||
}
|
||||
|
||||
switch (map->type) {
|
||||
case _DRM_FRAME_BUFFER:
|
||||
case _DRM_REGISTERS:
|
||||
|
|
@ -354,6 +409,15 @@ int drm_mmap(struct file *filp, struct vm_area_struct *vma)
|
|||
DRM_KERNEL advisory is supported. */
|
||||
vma->vm_flags |= VM_LOCKED;
|
||||
break;
|
||||
case _DRM_SCATTER_GATHER:
|
||||
vma->vm_ops = &drm_vm_sg_ops;
|
||||
#if LINUX_VERSION_CODE >= 0x020300
|
||||
vma->vm_private_data = (void *)map;
|
||||
#else
|
||||
vma->vm_pte = (unsigned long)map;
|
||||
#endif
|
||||
vma->vm_flags |= VM_LOCKED;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL; /* This should never happen. */
|
||||
}
|
||||
|
|
@ -366,5 +430,9 @@ int drm_mmap(struct file *filp, struct vm_area_struct *vma)
|
|||
#endif
|
||||
vma->vm_file = filp; /* Needed for drm_vm_open() */
|
||||
drm_vm_open(vma);
|
||||
|
||||
if(map->type == _DRM_SCATTER_GATHER) {
|
||||
DRM_DEBUG("%s: scatter/gather done.\n", __FUNCTION__);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -124,10 +124,11 @@ typedef struct drm_control {
|
|||
} drm_control_t;
|
||||
|
||||
typedef enum drm_map_type {
|
||||
_DRM_FRAME_BUFFER = 0, /* WC (no caching), no core dump */
|
||||
_DRM_REGISTERS = 1, /* no caching, no core dump */
|
||||
_DRM_SHM = 2, /* shared, cached */
|
||||
_DRM_AGP = 3 /* AGP/GART */
|
||||
_DRM_FRAME_BUFFER = 0, /* WC (no caching), no core dump */
|
||||
_DRM_REGISTERS = 1, /* no caching, no core dump */
|
||||
_DRM_SHM = 2, /* shared, cached */
|
||||
_DRM_AGP = 3, /* AGP/GART */
|
||||
_DRM_SCATTER_GATHER = 4 /* Scatter/gather memory for PCI DMA */
|
||||
} drm_map_type_t;
|
||||
|
||||
typedef enum drm_map_flags {
|
||||
|
|
@ -192,7 +193,8 @@ typedef struct drm_buf_desc {
|
|||
int high_mark; /* High water mark */
|
||||
enum {
|
||||
_DRM_PAGE_ALIGN = 0x01, /* Align on page boundaries for DMA */
|
||||
_DRM_AGP_BUFFER = 0x02 /* Buffer is in agp space */
|
||||
_DRM_AGP_BUFFER = 0x02, /* Buffer is in agp space */
|
||||
_DRM_SG_BUFFER = 0x04 /* Scatter/gather memory buffer */
|
||||
} flags;
|
||||
unsigned long agp_start; /* Start address of where the agp buffers
|
||||
* are in the agp aperture */
|
||||
|
|
@ -298,6 +300,11 @@ typedef struct drm_agp_info {
|
|||
unsigned short id_device;
|
||||
} drm_agp_info_t;
|
||||
|
||||
typedef struct drm_scatter_gather {
|
||||
unsigned long size; /* In bytes -- will round to page boundary */
|
||||
unsigned long handle; /* Used for mapping / unmapping */
|
||||
} drm_scatter_gather_t;
|
||||
|
||||
#define DRM_IOCTL_BASE 'd'
|
||||
#define DRM_IO(nr) _IO(DRM_IOCTL_BASE,nr)
|
||||
#define DRM_IOR(nr,size) _IOR(DRM_IOCTL_BASE,nr,size)
|
||||
|
|
@ -345,6 +352,9 @@ typedef struct drm_agp_info {
|
|||
#define DRM_IOCTL_AGP_BIND DRM_IOW( 0x36, drm_agp_binding_t)
|
||||
#define DRM_IOCTL_AGP_UNBIND DRM_IOW( 0x37, drm_agp_binding_t)
|
||||
|
||||
#define DRM_IOCTL_SG_ALLOC DRM_IOW( 0x38, drm_scatter_gather_t)
|
||||
#define DRM_IOCTL_SG_FREE DRM_IOW( 0x39, drm_scatter_gather_t)
|
||||
|
||||
/* Mga specific ioctls */
|
||||
#define DRM_IOCTL_MGA_INIT DRM_IOW( 0x40, drm_mga_init_t)
|
||||
#define DRM_IOCTL_MGA_SWAP DRM_IOW( 0x41, drm_mga_swap_t)
|
||||
|
|
|
|||
20
shared/drm.h
20
shared/drm.h
|
|
@ -124,10 +124,11 @@ typedef struct drm_control {
|
|||
} drm_control_t;
|
||||
|
||||
typedef enum drm_map_type {
|
||||
_DRM_FRAME_BUFFER = 0, /* WC (no caching), no core dump */
|
||||
_DRM_REGISTERS = 1, /* no caching, no core dump */
|
||||
_DRM_SHM = 2, /* shared, cached */
|
||||
_DRM_AGP = 3 /* AGP/GART */
|
||||
_DRM_FRAME_BUFFER = 0, /* WC (no caching), no core dump */
|
||||
_DRM_REGISTERS = 1, /* no caching, no core dump */
|
||||
_DRM_SHM = 2, /* shared, cached */
|
||||
_DRM_AGP = 3, /* AGP/GART */
|
||||
_DRM_SCATTER_GATHER = 4 /* Scatter/gather memory for PCI DMA */
|
||||
} drm_map_type_t;
|
||||
|
||||
typedef enum drm_map_flags {
|
||||
|
|
@ -192,7 +193,8 @@ typedef struct drm_buf_desc {
|
|||
int high_mark; /* High water mark */
|
||||
enum {
|
||||
_DRM_PAGE_ALIGN = 0x01, /* Align on page boundaries for DMA */
|
||||
_DRM_AGP_BUFFER = 0x02 /* Buffer is in agp space */
|
||||
_DRM_AGP_BUFFER = 0x02, /* Buffer is in agp space */
|
||||
_DRM_SG_BUFFER = 0x04 /* Scatter/gather memory buffer */
|
||||
} flags;
|
||||
unsigned long agp_start; /* Start address of where the agp buffers
|
||||
* are in the agp aperture */
|
||||
|
|
@ -298,6 +300,11 @@ typedef struct drm_agp_info {
|
|||
unsigned short id_device;
|
||||
} drm_agp_info_t;
|
||||
|
||||
typedef struct drm_scatter_gather {
|
||||
unsigned long size; /* In bytes -- will round to page boundary */
|
||||
unsigned long handle; /* Used for mapping / unmapping */
|
||||
} drm_scatter_gather_t;
|
||||
|
||||
#define DRM_IOCTL_BASE 'd'
|
||||
#define DRM_IO(nr) _IO(DRM_IOCTL_BASE,nr)
|
||||
#define DRM_IOR(nr,size) _IOR(DRM_IOCTL_BASE,nr,size)
|
||||
|
|
@ -345,6 +352,9 @@ typedef struct drm_agp_info {
|
|||
#define DRM_IOCTL_AGP_BIND DRM_IOW( 0x36, drm_agp_binding_t)
|
||||
#define DRM_IOCTL_AGP_UNBIND DRM_IOW( 0x37, drm_agp_binding_t)
|
||||
|
||||
#define DRM_IOCTL_SG_ALLOC DRM_IOW( 0x38, drm_scatter_gather_t)
|
||||
#define DRM_IOCTL_SG_FREE DRM_IOW( 0x39, drm_scatter_gather_t)
|
||||
|
||||
/* Mga specific ioctls */
|
||||
#define DRM_IOCTL_MGA_INIT DRM_IOW( 0x40, drm_mga_init_t)
|
||||
#define DRM_IOCTL_MGA_SWAP DRM_IOW( 0x41, drm_mga_swap_t)
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue