diff --git a/bsd-core/Makefile b/bsd-core/Makefile index 57f4e127..ff26c762 100644 --- a/bsd-core/Makefile +++ b/bsd-core/Makefile @@ -1,17 +1,5 @@ # $FreeBSD$ -KMOD = drm -SRCS = init.c memory.c auth.c context.c drawable.c bufs.c \ - lists.c lock.c ioctl.c fops.c vm.c dma.c sysctl.c -SRCS += tdfx_drv.c tdfx_context.c -SRCS += device_if.h bus_if.h pci_if.h -CFLAGS += ${DEBUG_FLAGS} -KERN = /usr/src/sys +SUBDIR = drm tdfx gamma -@: - ln -sf /sys @ - -machine: - ln -sf /sys/i386/include machine - -.include +.include diff --git a/bsd-core/drmP.h b/bsd-core/drmP.h index be8ecd13..0ab33349 100644 --- a/bsd-core/drmP.h +++ b/bsd-core/drmP.h @@ -48,6 +48,7 @@ #include #include #include +#include #include "drm.h" @@ -58,6 +59,7 @@ typedef u_int32_t spinlock_t; #define atomic_read(p) (*(p)) #define atomic_inc(p) atomic_add_int(p, 1) #define atomic_dec(p) atomic_subtract_int(p, 1) +#define atomic_add(n, p) atomic_add_int(p, n) #define atomic_sub(n, p) atomic_subtract_int(p, n) /* Fake this */ @@ -359,7 +361,8 @@ typedef struct drm_device { const char *name; /* Simple driver name */ char *unique; /* Unique identifier: e.g., busid */ int unique_len; /* Length of unique field */ - dev_t device; /* Device number for mknod */ + device_t device; /* Device instance from newbus */ + dev_t devnode; /* Device number for mknod */ char *devname; /* For /proc/interrupts */ int blocked; /* Blocked due to VC switch? */ @@ -409,7 +412,8 @@ typedef struct drm_device { drm_device_dma_t *dma; /* Optional pointer for DMA support */ /* Context support */ - int irq; /* Interrupt used by board */ + struct resource *irq; /* Interrupt used by board */ + void *irqh; /* Handle from bus_setup_intr */ __volatile__ int context_flag; /* Context swapping flag */ __volatile__ int interrupt_flag;/* Interruption handler flag */ __volatile__ int dma_flag; /* DMA dispatch flag */ diff --git a/bsd-core/tdfx/Makefile b/bsd-core/tdfx/Makefile new file mode 100644 index 00000000..7f212c21 --- /dev/null +++ b/bsd-core/tdfx/Makefile @@ -0,0 +1,16 @@ +# $FreeBSD$ + +KMOD = tdfx +SRCS = tdfx_drv.c tdfx_context.c +SRCS += device_if.h bus_if.h pci_if.h +CFLAGS += ${DEBUG_FLAGS} -I.. +KERN = /usr/src/sys +KMODDEPS = drm + +@: + ln -sf /sys @ + +machine: + ln -sf /sys/i386/include machine + +.include diff --git a/bsd/Makefile b/bsd/Makefile index 57f4e127..ff26c762 100644 --- a/bsd/Makefile +++ b/bsd/Makefile @@ -1,17 +1,5 @@ # $FreeBSD$ -KMOD = drm -SRCS = init.c memory.c auth.c context.c drawable.c bufs.c \ - lists.c lock.c ioctl.c fops.c vm.c dma.c sysctl.c -SRCS += tdfx_drv.c tdfx_context.c -SRCS += device_if.h bus_if.h pci_if.h -CFLAGS += ${DEBUG_FLAGS} -KERN = /usr/src/sys +SUBDIR = drm tdfx gamma -@: - ln -sf /sys @ - -machine: - ln -sf /sys/i386/include machine - -.include +.include diff --git a/bsd/Makefile.bsd b/bsd/Makefile.bsd index 57f4e127..ff26c762 100644 --- a/bsd/Makefile.bsd +++ b/bsd/Makefile.bsd @@ -1,17 +1,5 @@ # $FreeBSD$ -KMOD = drm -SRCS = init.c memory.c auth.c context.c drawable.c bufs.c \ - lists.c lock.c ioctl.c fops.c vm.c dma.c sysctl.c -SRCS += tdfx_drv.c tdfx_context.c -SRCS += device_if.h bus_if.h pci_if.h -CFLAGS += ${DEBUG_FLAGS} -KERN = /usr/src/sys +SUBDIR = drm tdfx gamma -@: - ln -sf /sys @ - -machine: - ln -sf /sys/i386/include machine - -.include +.include diff --git a/bsd/drm.h b/bsd/drm.h index 82d3e543..af3c14d0 100644 --- a/bsd/drm.h +++ b/bsd/drm.h @@ -56,6 +56,19 @@ typedef unsigned int drm_context_t; typedef unsigned int drm_drawable_t; typedef unsigned int drm_magic_t; +/* Warning: If you change this structure, make sure you change + * XF86DRIClipRectRec in the server as well */ + +typedef struct drm_clip_rect { + unsigned short x1; + unsigned short y1; + unsigned short x2; + unsigned short y2; +} drm_clip_rect_t; + +/* Seperate include files for the i810/mga specific structures */ +#include "mga_drm.h" +#include "i810_drm.h" typedef struct drm_version { int version_major; /* Major version */ @@ -160,8 +173,11 @@ typedef struct drm_buf_desc { int low_mark; /* Low water mark */ int high_mark; /* High water mark */ enum { - DRM_PAGE_ALIGN = 0x01 /* Align on page boundaries for DMA */ + _DRM_PAGE_ALIGN = 0x01, /* Align on page boundaries for DMA */ + _DRM_AGP_BUFFER = 0x02 /* Buffer is in agp space */ } flags; + unsigned long agp_start; /* Start address of where the agp buffers + * are in the agp aperture */ } drm_buf_desc_t; typedef struct drm_buf_info { @@ -232,6 +248,38 @@ typedef struct drm_irq_busid { int funcnum; } drm_irq_busid_t; +typedef struct drm_agp_mode { + unsigned long mode; +} drm_agp_mode_t; + + /* For drm_agp_alloc -- allocated a buffer */ +typedef struct drm_agp_buffer { + unsigned long size; /* In bytes -- will round to page boundary */ + unsigned long handle; /* Used for BIND/UNBIND ioctls */ + unsigned long type; /* Type of memory to allocate */ + unsigned long physical; /* Physical used by i810 */ +} drm_agp_buffer_t; + + /* For drm_agp_bind */ +typedef struct drm_agp_binding { + unsigned long handle; /* From drm_agp_buffer */ + unsigned long offset; /* In bytes -- will round to page boundary */ +} drm_agp_binding_t; + +typedef struct drm_agp_info { + int agp_version_major; + int agp_version_minor; + unsigned long mode; + unsigned long aperture_base; /* physical address */ + unsigned long aperture_size; /* bytes */ + unsigned long memory_allowed; /* bytes */ + unsigned long memory_used; + + /* PCI information */ + unsigned short id_vendor; + unsigned short id_device; +} drm_agp_info_t; + #define DRM_IOCTL_BASE 'd' #define DRM_IOCTL_NR(n) ((n) & 0xff) #define DRM_IO(nr) _IO(DRM_IOCTL_BASE,nr) @@ -271,4 +319,28 @@ typedef struct drm_irq_busid { #define DRM_IOCTL_UNLOCK DRM_IOW( 0x2b, drm_lock_t) #define DRM_IOCTL_FINISH DRM_IOW( 0x2c, drm_lock_t) +#define DRM_IOCTL_AGP_ACQUIRE DRM_IO( 0x30) +#define DRM_IOCTL_AGP_RELEASE DRM_IO( 0x31) +#define DRM_IOCTL_AGP_ENABLE DRM_IOR( 0x32, drm_agp_mode_t) +#define DRM_IOCTL_AGP_INFO DRM_IOW( 0x33, drm_agp_info_t) +#define DRM_IOCTL_AGP_ALLOC DRM_IOWR(0x34, drm_agp_buffer_t) +#define DRM_IOCTL_AGP_FREE DRM_IOW( 0x35, drm_agp_buffer_t) +#define DRM_IOCTL_AGP_BIND DRM_IOWR(0x36, drm_agp_binding_t) +#define DRM_IOCTL_AGP_UNBIND DRM_IOW( 0x37, drm_agp_binding_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) +#define DRM_IOCTL_MGA_CLEAR DRM_IOW( 0x42, drm_mga_clear_t) +#define DRM_IOCTL_MGA_ILOAD DRM_IOW( 0x43, drm_mga_iload_t) +#define DRM_IOCTL_MGA_VERTEX DRM_IOW( 0x44, drm_mga_vertex_t) +#define DRM_IOCTL_MGA_FLUSH DRM_IOW( 0x45, drm_lock_t ) + +/* I810 specific ioctls */ +#define DRM_IOCTL_I810_INIT DRM_IOW( 0x40, drm_i810_init_t) +#define DRM_IOCTL_I810_VERTEX DRM_IOW( 0x41, drm_i810_vertex_t) +#define DRM_IOCTL_I810_DMA DRM_IOW( 0x42, drm_i810_general_t) +#define DRM_IOCTL_I810_FLUSH DRM_IO ( 0x43) +#define DRM_IOCTL_I810_GETAGE DRM_IO ( 0x44) + #endif diff --git a/bsd/drm/Makefile b/bsd/drm/Makefile new file mode 100644 index 00000000..6735d3c3 --- /dev/null +++ b/bsd/drm/Makefile @@ -0,0 +1,16 @@ +# $FreeBSD$ + +KMOD = drm +SRCS = init.c memory.c auth.c context.c drawable.c bufs.c \ + lists.c lock.c ioctl.c fops.c vm.c dma.c sysctl.c +SRCS += device_if.h bus_if.h pci_if.h +CFLAGS += ${DEBUG_FLAGS} -I.. +KERN = /usr/src/sys + +@: + ln -sf /sys @ + +machine: + ln -sf /sys/i386/include machine + +.include diff --git a/bsd/auth.c b/bsd/drm/auth.c similarity index 100% rename from bsd/auth.c rename to bsd/drm/auth.c diff --git a/bsd/bufs.c b/bsd/drm/bufs.c similarity index 99% rename from bsd/bufs.c rename to bsd/drm/bufs.c index e4f7ae3d..c74b4de5 100644 --- a/bsd/bufs.c +++ b/bsd/drm/bufs.c @@ -169,7 +169,7 @@ int drm_addbufs(dev_t kdev, u_long cmd, caddr_t data, if (order < DRM_MIN_ORDER || order > DRM_MAX_ORDER) return EINVAL; if (dev->queue_count) return EBUSY; /* Not while in use */ - alignment = (request.flags & DRM_PAGE_ALIGN) ? round_page(size) :size; + alignment = (request.flags & _DRM_PAGE_ALIGN) ? round_page(size) :size; page_order = order - PAGE_SHIFT > 0 ? order - PAGE_SHIFT : 0; total = PAGE_SIZE << page_order; diff --git a/bsd/context.c b/bsd/drm/context.c similarity index 100% rename from bsd/context.c rename to bsd/drm/context.c diff --git a/bsd/dma.c b/bsd/drm/dma.c similarity index 99% rename from bsd/dma.c rename to bsd/drm/dma.c index 3cba6bc8..149f4593 100644 --- a/bsd/dma.c +++ b/bsd/drm/dma.c @@ -206,7 +206,7 @@ int drm_context_switch(drm_device_t *dev, int old, int new) } #if DRM_DMA_HISTOGRAM - nanotime(&dev->ctx_start); + getnanotime(&dev->ctx_start); #endif DRM_DEBUG("Context switch from %d to %d\n", old, new); @@ -262,7 +262,7 @@ int drm_context_switch_complete(drm_device_t *dev, int new) #if DRM_DMA_HISTOGRAM { struct timespec ts; - nanotime(&ts); + getnanotime(&ts); timespecsub(&ts, &dev->ctx_start); atomic_inc(&dev->histo.ctx[drm_histogram_slot(&ts)]); } @@ -372,7 +372,7 @@ int drm_dma_enqueue(drm_device_t *dev, drm_dma_t *d) if (!_DRM_LOCK_IS_HELD(context)) { DRM_ERROR("No lock held during \"while locked\"" " request\n"); - return -EINVAL; + return EINVAL; } if (d->context != _DRM_LOCKING_CONTEXT(context) && _DRM_LOCKING_CONTEXT(context) != DRM_KERNEL_CONTEXT) { @@ -380,7 +380,7 @@ int drm_dma_enqueue(drm_device_t *dev, drm_dma_t *d) " \"while locked\" request\n", _DRM_LOCKING_CONTEXT(context), d->context); - return -EINVAL; + return EINVAL; } q = dev->queuelist[DRM_KERNEL_CONTEXT]; while_locked = 1; diff --git a/bsd/drawable.c b/bsd/drm/drawable.c similarity index 100% rename from bsd/drawable.c rename to bsd/drm/drawable.c diff --git a/bsd/drmstat.c b/bsd/drm/drmstat.c similarity index 100% rename from bsd/drmstat.c rename to bsd/drm/drmstat.c diff --git a/bsd/fops.c b/bsd/drm/fops.c similarity index 100% rename from bsd/fops.c rename to bsd/drm/fops.c diff --git a/bsd/init.c b/bsd/drm/init.c similarity index 100% rename from bsd/init.c rename to bsd/drm/init.c diff --git a/bsd/ioctl.c b/bsd/drm/ioctl.c similarity index 100% rename from bsd/ioctl.c rename to bsd/drm/ioctl.c diff --git a/bsd/lists.c b/bsd/drm/lists.c similarity index 100% rename from bsd/lists.c rename to bsd/drm/lists.c diff --git a/bsd/lock.c b/bsd/drm/lock.c similarity index 100% rename from bsd/lock.c rename to bsd/drm/lock.c diff --git a/bsd/memory.c b/bsd/drm/memory.c similarity index 100% rename from bsd/memory.c rename to bsd/drm/memory.c diff --git a/bsd/proc.c b/bsd/drm/proc.c similarity index 100% rename from bsd/proc.c rename to bsd/drm/proc.c diff --git a/bsd/sysctl.c b/bsd/drm/sysctl.c similarity index 97% rename from bsd/sysctl.c rename to bsd/drm/sysctl.c index 762dae5a..7c736abf 100644 --- a/bsd/sysctl.c +++ b/bsd/drm/sysctl.c @@ -33,7 +33,7 @@ #include "drmP.h" #include -SYSCTL_NODE(_hw, OID_AUTO, graphics, CTLFLAG_RW, 0, "DRI Graphics"); +SYSCTL_NODE(_hw, OID_AUTO, dri, CTLFLAG_RW, 0, "DRI Graphics"); static int drm_name_info SYSCTL_HANDLER_ARGS; static int drm_vm_info SYSCTL_HANDLER_ARGS; @@ -81,7 +81,7 @@ int drm_sysctl_init(drm_device_t *dev) /* Find the next free slot under hw.graphics */ i = 0; - SLIST_FOREACH(oid, &sysctl__hw_graphics_children, oid_link) { + SLIST_FOREACH(oid, &sysctl__hw_dri_children, oid_link) { if (i <= oid->oid_arg2) i = oid->oid_arg2 + 1; } @@ -94,7 +94,7 @@ int drm_sysctl_init(drm_device_t *dev) info->name[1] = 0; oid = &info->oids[DRM_SYSCTL_ENTRIES]; bzero(oid, sizeof(*oid)); - oid->oid_parent = &sysctl__hw_graphics_children; + oid->oid_parent = &sysctl__hw_dri_children; oid->oid_number = OID_AUTO; oid->oid_kind = CTLTYPE_NODE | CTLFLAG_RW; oid->oid_arg1 = &info->list; @@ -145,9 +145,9 @@ static int drm_name_info SYSCTL_HANDLER_ARGS if (dev->unique) { DRM_SYSCTL_PRINT("%s 0x%x %s\n", - dev->name, dev2udev(dev->device), dev->unique); + dev->name, dev2udev(dev->devnode), dev->unique); } else { - DRM_SYSCTL_PRINT("%s 0x%x\n", dev->name, dev2udev(dev->device)); + DRM_SYSCTL_PRINT("%s 0x%x\n", dev->name, dev2udev(dev->devnode)); } SYSCTL_OUT(req, "", 1); @@ -255,7 +255,7 @@ static int drm_queues_info SYSCTL_HANDLER_ARGS } /* drm_bufs_info is called whenever a process reads - /dev/drm//bufs. */ + hw.dri.0.bufs. */ static int _drm_bufs_info SYSCTL_HANDLER_ARGS { diff --git a/bsd/vm.c b/bsd/drm/vm.c similarity index 100% rename from bsd/vm.c rename to bsd/drm/vm.c diff --git a/bsd/drmP.h b/bsd/drmP.h index be8ecd13..0ab33349 100644 --- a/bsd/drmP.h +++ b/bsd/drmP.h @@ -48,6 +48,7 @@ #include #include #include +#include #include "drm.h" @@ -58,6 +59,7 @@ typedef u_int32_t spinlock_t; #define atomic_read(p) (*(p)) #define atomic_inc(p) atomic_add_int(p, 1) #define atomic_dec(p) atomic_subtract_int(p, 1) +#define atomic_add(n, p) atomic_add_int(p, n) #define atomic_sub(n, p) atomic_subtract_int(p, n) /* Fake this */ @@ -359,7 +361,8 @@ typedef struct drm_device { const char *name; /* Simple driver name */ char *unique; /* Unique identifier: e.g., busid */ int unique_len; /* Length of unique field */ - dev_t device; /* Device number for mknod */ + device_t device; /* Device instance from newbus */ + dev_t devnode; /* Device number for mknod */ char *devname; /* For /proc/interrupts */ int blocked; /* Blocked due to VC switch? */ @@ -409,7 +412,8 @@ typedef struct drm_device { drm_device_dma_t *dma; /* Optional pointer for DMA support */ /* Context support */ - int irq; /* Interrupt used by board */ + struct resource *irq; /* Interrupt used by board */ + void *irqh; /* Handle from bus_setup_intr */ __volatile__ int context_flag; /* Context swapping flag */ __volatile__ int interrupt_flag;/* Interruption handler flag */ __volatile__ int dma_flag; /* DMA dispatch flag */ diff --git a/bsd/gamma/Makefile b/bsd/gamma/Makefile new file mode 100644 index 00000000..777f3325 --- /dev/null +++ b/bsd/gamma/Makefile @@ -0,0 +1,16 @@ +# $FreeBSD$ + +KMOD = gamma +SRCS = gamma_drv.c gamma_dma.c +SRCS += device_if.h bus_if.h pci_if.h +CFLAGS += ${DEBUG_FLAGS} -I.. +KERN = /usr/src/sys +KMODDEPS = drm + +@: + ln -sf /sys @ + +machine: + ln -sf /sys/i386/include machine + +.include diff --git a/bsd/gamma_dma.c b/bsd/gamma/gamma_dma.c similarity index 77% rename from bsd/gamma_dma.c rename to bsd/gamma/gamma_dma.c index 88e8a7c1..8ac27aa0 100644 --- a/bsd/gamma_dma.c +++ b/bsd/gamma/gamma_dma.c @@ -33,8 +33,11 @@ #include "drmP.h" #include "gamma_drv.h" -#include /* For task queue support */ - +#include +#include +#include +#include +#include /* WARNING!!! MAGIC NUMBER!!! The number of regions already added to the kernel must be specified here. Currently, the number is 2. This must @@ -79,16 +82,17 @@ #define GAMMA_SYNC 0x8c40 #define GAMMA_SYNC_TAG 0x0188 -static inline void gamma_dma_dispatch(drm_device_t *dev, unsigned long address, - unsigned long length) +static __inline void gamma_dma_dispatch(drm_device_t *dev, + vm_offset_t address, + vm_size_t length) { - GAMMA_WRITE(GAMMA_DMAADDRESS, virt_to_phys((void *)address)); + GAMMA_WRITE(GAMMA_DMAADDRESS, vtophys(address)); while (GAMMA_READ(GAMMA_GCOMMANDSTATUS) != 4) ; GAMMA_WRITE(GAMMA_DMACOUNT, length / 4); } -static inline void gamma_dma_quiescent(drm_device_t *dev) +static __inline void gamma_dma_quiescent(drm_device_t *dev) { while (GAMMA_READ(GAMMA_DMACOUNT)) ; @@ -112,20 +116,20 @@ static inline void gamma_dma_quiescent(drm_device_t *dev) } while (GAMMA_READ(GAMMA_OUTPUTFIFO + 0x10000) != GAMMA_SYNC_TAG); } -static inline void gamma_dma_ready(drm_device_t *dev) +static __inline void gamma_dma_ready(drm_device_t *dev) { while (GAMMA_READ(GAMMA_DMACOUNT)) ; } -static inline int gamma_dma_is_ready(drm_device_t *dev) +static __inline int gamma_dma_is_ready(drm_device_t *dev) { return !GAMMA_READ(GAMMA_DMACOUNT); } -static void gamma_dma_service(int irq, void *device, struct pt_regs *regs) +static void gamma_dma_service(void *arg) { - drm_device_t *dev = (drm_device_t *)device; + drm_device_t *dev = (drm_device_t *)arg; drm_device_dma_t *dma = dev->dma; atomic_inc(&dev->total_irq); @@ -144,9 +148,11 @@ static void gamma_dma_service(int irq, void *device, struct pt_regs *regs) } clear_bit(0, &dev->dma_flag); +#if 0 /* Dispatch new buffer */ queue_task(&dev->tq, &tq_immediate); mark_bh(IMMEDIATE_BH); +#endif } } @@ -159,22 +165,22 @@ static int gamma_do_dma(drm_device_t *dev, int locked) int retcode = 0; drm_device_dma_t *dma = dev->dma; #if DRM_DMA_HISTOGRAM - cycles_t dma_start, dma_stop; + struct timespec dma_start, dma_stop; #endif if (test_and_set_bit(0, &dev->dma_flag)) { atomic_inc(&dma->total_missed_dma); - return -EBUSY; + return EBUSY; } #if DRM_DMA_HISTOGRAM - dma_start = get_cycles(); + getnanotime(&dma_start); #endif if (!dma->next_buffer) { DRM_ERROR("No next_buffer\n"); clear_bit(0, &dev->dma_flag); - return -EINVAL; + return EINVAL; } buf = dma->next_buffer; @@ -188,7 +194,7 @@ static int gamma_do_dma(drm_device_t *dev, int locked) drm_clear_next_buffer(dev); drm_free_buffer(dev, buf); clear_bit(0, &dev->dma_flag); - return -EINVAL; + return EINVAL; } if (!length) { @@ -201,7 +207,7 @@ static int gamma_do_dma(drm_device_t *dev, int locked) if (!gamma_dma_is_ready(dev)) { clear_bit(0, &dev->dma_flag); - return -EBUSY; + return EBUSY; } if (buf->while_locked) { @@ -215,7 +221,7 @@ static int gamma_do_dma(drm_device_t *dev, int locked) DRM_KERNEL_CONTEXT)) { atomic_inc(&dma->total_missed_lock); clear_bit(0, &dev->dma_flag); - return -EBUSY; + return EBUSY; } } @@ -227,7 +233,7 @@ static int gamma_do_dma(drm_device_t *dev, int locked) drm_clear_next_buffer(dev); drm_free_buffer(dev, buf); } - retcode = -EBUSY; + retcode = EBUSY; goto cleanup; /* POST: we will wait for the context @@ -242,7 +248,7 @@ static int gamma_do_dma(drm_device_t *dev, int locked) buf->waiting = 0; buf->list = DRM_LIST_PEND; #if DRM_DMA_HISTOGRAM - buf->time_dispatched = get_cycles(); + getnanotime(&buf->time_dispatched); #endif gamma_dma_dispatch(dev, address, length); @@ -263,19 +269,15 @@ cleanup: clear_bit(0, &dev->dma_flag); #if DRM_DMA_HISTOGRAM - dma_stop = get_cycles(); - atomic_inc(&dev->histo.dma[drm_histogram_slot(dma_stop - dma_start)]); + getnanotime(&dma_stop); + timespecsub(&dma_stop, &dma_start); + atomic_inc(&dev->histo.ctx[drm_histogram_slot(&dma_stop)]); #endif return retcode; } -static void gamma_dma_schedule_timer_wrapper(unsigned long dev) -{ - gamma_dma_schedule((drm_device_t *)dev, 0); -} - -static void gamma_dma_schedule_tq_wrapper(void *dev) +static void gamma_dma_schedule_wrapper(void *dev) { gamma_dma_schedule(dev, 0); } @@ -291,24 +293,24 @@ int gamma_dma_schedule(drm_device_t *dev, int locked) int expire = 20; drm_device_dma_t *dma = dev->dma; #if DRM_DMA_HISTOGRAM - cycles_t schedule_start; + struct timespec schedule_start; #endif if (test_and_set_bit(0, &dev->interrupt_flag)) { /* Not reentrant */ atomic_inc(&dma->total_missed_sched); - return -EBUSY; + return EBUSY; } missed = atomic_read(&dma->total_missed_sched); #if DRM_DMA_HISTOGRAM - schedule_start = get_cycles(); + getnanotime(&schedule_start); #endif again: if (dev->context_flag) { clear_bit(0, &dev->interrupt_flag); - return -EBUSY; + return EBUSY; } if (dma->next_buffer) { /* Unsent buffer that was previously @@ -324,7 +326,7 @@ again: } else { do { next = drm_select_queue(dev, - gamma_dma_schedule_timer_wrapper); + gamma_dma_schedule_wrapper); if (next >= 0) { q = dev->queuelist[next]; buf = drm_waitlist_get(&q->waitlist); @@ -358,14 +360,19 @@ again: clear_bit(0, &dev->interrupt_flag); #if DRM_DMA_HISTOGRAM - atomic_inc(&dev->histo.schedule[drm_histogram_slot(get_cycles() - - schedule_start)]); + { + struct timespec ts; + getnanotime(&ts); + timespecsub(&ts, &schedule_start); + atomic_inc(&dev->histo.schedule[drm_histogram_slot(&ts)]); + } #endif return retcode; } static int gamma_dma_priority(drm_device_t *dev, drm_dma_t *d) { + struct proc *p = curproc; unsigned long address; unsigned long length; int must_free = 0; @@ -375,21 +382,20 @@ static int gamma_dma_priority(drm_device_t *dev, drm_dma_t *d) drm_buf_t *buf; drm_buf_t *last_buf = NULL; drm_device_dma_t *dma = dev->dma; - DECLARE_WAITQUEUE(entry, current); + static int never; /* Turn off interrupt handling */ while (test_and_set_bit(0, &dev->interrupt_flag)) { - schedule(); - if (signal_pending(current)) return -EINTR; + retcode = tsleep(&never, PZERO|PCATCH, "gamp1", 1); + if (retcode) + return retcode; } if (!(d->flags & _DRM_DMA_WHILE_LOCKED)) { while (!drm_lock_take(&dev->lock.hw_lock->lock, DRM_KERNEL_CONTEXT)) { - schedule(); - if (signal_pending(current)) { - clear_bit(0, &dev->interrupt_flag); - return -EINTR; - } + retcode = tsleep(&never, PZERO|PCATCH, "gamp2", 1); + if (retcode) + return retcode; } ++must_free; } @@ -403,16 +409,16 @@ static int gamma_dma_priority(drm_device_t *dev, drm_dma_t *d) continue; } buf = dma->buflist[ idx ]; - if (buf->pid != current->pid) { + if (buf->pid != p->p_pid) { DRM_ERROR("Process %d using buffer owned by %d\n", - current->pid, buf->pid); - retcode = -EINVAL; + p->p_pid, buf->pid); + retcode = EINVAL; goto cleanup; } if (buf->list != DRM_LIST_NONE) { DRM_ERROR("Process %d using %d's buffer on list %d\n", - current->pid, buf->pid, buf->list); - retcode = -EINVAL; + p->p_pid, buf->pid, buf->list); + retcode = EINVAL; goto cleanup; } /* This isn't a race condition on @@ -433,14 +439,14 @@ static int gamma_dma_priority(drm_device_t *dev, drm_dma_t *d) DRM_ERROR("Sending pending buffer:" " buffer %d, offset %d\n", d->send_indices[i], i); - retcode = -EINVAL; + retcode = EINVAL; goto cleanup; } if (buf->waiting) { DRM_ERROR("Sending waiting buffer:" " buffer %d, offset %d\n", d->send_indices[i], i); - retcode = -EINVAL; + retcode = EINVAL; goto cleanup; } buf->pending = 1; @@ -448,8 +454,7 @@ static int gamma_dma_priority(drm_device_t *dev, drm_dma_t *d) if (dev->last_context != buf->context && !(dev->queuelist[buf->context]->flags & _DRM_CONTEXT_PRESERVED)) { - add_wait_queue(&dev->context_wait, &entry); - current->state = TASK_INTERRUPTIBLE; + atomic_inc(&dev->context_wait); /* PRE: dev->last_context != buf->context */ drm_context_switch(dev, dev->last_context, buf->context); @@ -458,13 +463,11 @@ static int gamma_dma_priority(drm_device_t *dev, drm_dma_t *d) when dev->last_context == buf->context. NOTE WE HOLD THE LOCK THROUGHOUT THIS TIME! */ - schedule(); - current->state = TASK_RUNNING; - remove_wait_queue(&dev->context_wait, &entry); - if (signal_pending(current)) { - retcode = -EINTR; + retcode = tsleep(&dev->context_wait, PZERO|PCATCH, + "gamctx", 0); + atomic_dec(&dev->context_wait); + if (retcode) goto cleanup; - } if (dev->last_context != buf->context) { DRM_ERROR("Context mismatch: %d %d\n", dev->last_context, @@ -473,7 +476,7 @@ static int gamma_dma_priority(drm_device_t *dev, drm_dma_t *d) } #if DRM_DMA_HISTOGRAM - buf->time_queued = get_cycles(); + getnanotime(&buf->time_queued); buf->time_dispatched = buf->time_queued; #endif gamma_dma_dispatch(dev, address, length); @@ -505,43 +508,40 @@ cleanup: static int gamma_dma_send_buffers(drm_device_t *dev, drm_dma_t *d) { - DECLARE_WAITQUEUE(entry, current); + struct proc *p = curproc; drm_buf_t *last_buf = NULL; int retcode = 0; drm_device_dma_t *dma = dev->dma; - if (d->flags & _DRM_DMA_BLOCK) { - last_buf = dma->buflist[d->send_indices[d->send_count-1]]; - add_wait_queue(&last_buf->dma_wait, &entry); - } if ((retcode = drm_dma_enqueue(dev, d))) { - if (d->flags & _DRM_DMA_BLOCK) - remove_wait_queue(&last_buf->dma_wait, &entry); return retcode; } gamma_dma_schedule(dev, 0); if (d->flags & _DRM_DMA_BLOCK) { - DRM_DEBUG("%d waiting\n", current->pid); - current->state = TASK_INTERRUPTIBLE; + last_buf = dma->buflist[d->send_indices[d->send_count-1]]; + atomic_inc(&last_buf->dma_wait); + } + + if (d->flags & _DRM_DMA_BLOCK) { + DRM_DEBUG("%d waiting\n", p->p_pid); for (;;) { + retcode = tsleep(&last_buf->dma_wait, PZERO|PCATCH, + "gamdw", 0); if (!last_buf->waiting && !last_buf->pending) break; /* finished */ - schedule(); - if (signal_pending(current)) { - retcode = -EINTR; /* Can't restart */ + if (retcode) break; - } } - current->state = TASK_RUNNING; - DRM_DEBUG("%d running\n", current->pid); - remove_wait_queue(&last_buf->dma_wait, &entry); + + DRM_DEBUG("%d running\n", p->p_pid); + atomic_dec(&last_buf->dma_wait); if (!retcode || (last_buf->list==DRM_LIST_PEND && !last_buf->pending)) { - if (!waitqueue_active(&last_buf->dma_wait)) { + if (!last_buf->dma_wait) { drm_free_buffer(dev, last_buf); } } @@ -554,39 +554,37 @@ static int gamma_dma_send_buffers(drm_device_t *dev, drm_dma_t *d) last_buf->idx, last_buf->list, last_buf->pid, - current->pid); + p->p_pid); } } return retcode; } -int gamma_dma(struct inode *inode, struct file *filp, unsigned int cmd, - unsigned long arg) +int gamma_dma(dev_t kdev, u_long cmd, caddr_t data, int flags, struct proc *p) { - drm_file_t *priv = filp->private_data; - drm_device_t *dev = priv->dev; + drm_device_t *dev = kdev->si_drv1; drm_device_dma_t *dma = dev->dma; int retcode = 0; drm_dma_t d; - copy_from_user_ret(&d, (drm_dma_t *)arg, sizeof(d), -EFAULT); + d = *(drm_dma_t *) data; DRM_DEBUG("%d %d: %d send, %d req\n", - current->pid, d.context, d.send_count, d.request_count); + p->p_pid, d.context, d.send_count, d.request_count); if (d.context == DRM_KERNEL_CONTEXT || d.context >= dev->queue_slots) { DRM_ERROR("Process %d using context %d\n", - current->pid, d.context); - return -EINVAL; + p->p_pid, d.context); + return EINVAL; } if (d.send_count < 0 || d.send_count > dma->buf_count) { DRM_ERROR("Process %d trying to send %d buffers (of %d max)\n", - current->pid, d.send_count, dma->buf_count); - return -EINVAL; + p->p_pid, d.send_count, dma->buf_count); + return EINVAL; } if (d.request_count < 0 || d.request_count > dma->buf_count) { DRM_ERROR("Process %d trying to get %d buffers (of %d max)\n", - current->pid, d.request_count, dma->buf_count); - return -EINVAL; + p->p_pid, d.request_count, dma->buf_count); + return EINVAL; } if (d.send_count) { @@ -603,25 +601,23 @@ int gamma_dma(struct inode *inode, struct file *filp, unsigned int cmd, } DRM_DEBUG("%d returning, granted = %d\n", - current->pid, d.granted_count); - copy_to_user_ret((drm_dma_t *)arg, &d, sizeof(d), -EFAULT); + p->p_pid, d.granted_count); + *(drm_dma_t *) data = d; return retcode; } int gamma_irq_install(drm_device_t *dev, int irq) { + int rid; int retcode; - if (!irq) return -EINVAL; + if (!irq) return EINVAL; - down(&dev->struct_sem); if (dev->irq) { - up(&dev->struct_sem); - return -EBUSY; + lockmgr(&dev->dev_lock, LK_RELEASE, 0, curproc); + return EBUSY; } - dev->irq = irq; - up(&dev->struct_sem); DRM_DEBUG("%d\n", irq); @@ -633,25 +629,28 @@ int gamma_irq_install(drm_device_t *dev, int irq) dev->dma->next_queue = NULL; dev->dma->this_buffer = NULL; +#if 0 dev->tq.next = NULL; dev->tq.sync = 0; dev->tq.routine = gamma_dma_schedule_tq_wrapper; dev->tq.data = dev; - - +#endif /* Before installing handler */ GAMMA_WRITE(GAMMA_GCOMMANDMODE, 0); GAMMA_WRITE(GAMMA_GDMACONTROL, 0); /* Install handler */ - if ((retcode = request_irq(dev->irq, - gamma_dma_service, - 0, - dev->devname, - dev))) { - down(&dev->struct_sem); + rid = 0; + dev->irq = bus_alloc_resource(dev->device, SYS_RES_IRQ, &rid, + 0, ~0, 1, RF_SHAREABLE); + if (!dev->irq) + return ENOENT; + + retcode = bus_setup_intr(dev->device, dev->irq, INTR_TYPE_TTY, + gamma_dma_service, dev, &dev->irqh); + if (retcode) { + bus_release_resource(dev->device, SYS_RES_IRQ, 0, dev->irq); dev->irq = 0; - up(&dev->struct_sem); return retcode; } @@ -665,35 +664,31 @@ int gamma_irq_install(drm_device_t *dev, int irq) int gamma_irq_uninstall(drm_device_t *dev) { - int irq; + if (!dev->irq) + return EINVAL; + + DRM_DEBUG("%ld\n", rman_get_start(dev->irq)); - down(&dev->struct_sem); - irq = dev->irq; - dev->irq = 0; - up(&dev->struct_sem); - - if (!irq) return -EINVAL; - - DRM_DEBUG("%d\n", irq); - GAMMA_WRITE(GAMMA_GDELAYTIMER, 0); GAMMA_WRITE(GAMMA_COMMANDINTENABLE, 0); GAMMA_WRITE(GAMMA_GINTENABLE, 0); - free_irq(irq, dev); + bus_teardown_intr(dev->device, dev->irq, dev->irqh); + bus_release_resource(dev->device, SYS_RES_IRQ, 0, dev->irq); + dev->irq = 0; + return 0; } -int gamma_control(struct inode *inode, struct file *filp, unsigned int cmd, - unsigned long arg) +int gamma_control(dev_t kdev, u_long cmd, caddr_t data, + int flags, struct proc *p) { - drm_file_t *priv = filp->private_data; - drm_device_t *dev = priv->dev; + drm_device_t *dev = kdev->si_drv1; drm_control_t ctl; int retcode; - copy_from_user_ret(&ctl, (drm_control_t *)arg, sizeof(ctl), -EFAULT); + ctl = *(drm_control_t *) data; switch (ctl.func) { case DRM_INST_HANDLER: @@ -705,40 +700,38 @@ int gamma_control(struct inode *inode, struct file *filp, unsigned int cmd, return retcode; break; default: - return -EINVAL; + return EINVAL; } return 0; } -int gamma_lock(struct inode *inode, struct file *filp, unsigned int cmd, - unsigned long arg) +int gamma_lock(dev_t kdev, u_long cmd, caddr_t data, int flags, struct proc *p) { - drm_file_t *priv = filp->private_data; - drm_device_t *dev = priv->dev; - DECLARE_WAITQUEUE(entry, current); + drm_device_t *dev = kdev->si_drv1; int ret = 0; drm_lock_t lock; drm_queue_t *q; #if DRM_DMA_HISTOGRAM - cycles_t start; + struct timespec start; - dev->lck_start = start = get_cycles(); + getnanotime(&start); + dev->lck_start = start; #endif - copy_from_user_ret(&lock, (drm_lock_t *)arg, sizeof(lock), -EFAULT); + lock = *(drm_lock_t *) data; if (lock.context == DRM_KERNEL_CONTEXT) { DRM_ERROR("Process %d using kernel context %d\n", - current->pid, lock.context); - return -EINVAL; + p->p_pid, lock.context); + return EINVAL; } DRM_DEBUG("%d (pid %d) requests lock (0x%08x), flags = 0x%08x\n", - lock.context, current->pid, dev->lock.hw_lock->lock, + lock.context, p->p_pid, dev->lock.hw_lock->lock, lock.flags); if (lock.context < 0 || lock.context >= dev->queue_count) - return -EINVAL; + return EINVAL; q = dev->queuelist[lock.context]; ret = drm_flush_block_and_flush(dev, lock.context, lock.flags); @@ -746,26 +739,29 @@ int gamma_lock(struct inode *inode, struct file *filp, unsigned int cmd, if (!ret) { if (_DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock) != lock.context) { - long j = jiffies - dev->lock.lock_time; + long j = ticks - dev->lock.lock_time; if (j > 0 && j <= DRM_LOCK_SLICE) { /* Can't take lock if we just had it and there is contention. */ - current->state = TASK_INTERRUPTIBLE; - schedule_timeout(j); + static int never; + ret = tsleep(&never, PZERO|PCATCH, + "gaml1", j); + if (ret) + return ret; } } - add_wait_queue(&dev->lock.lock_queue, &entry); + atomic_inc(&dev->lock.lock_queue); for (;;) { if (!dev->lock.hw_lock) { /* Device has been unregistered */ - ret = -EINTR; + ret = EINTR; break; } if (drm_lock_take(&dev->lock.hw_lock->lock, lock.context)) { - dev->lock.pid = current->pid; - dev->lock.lock_time = jiffies; + dev->lock.pid = p->p_pid; + dev->lock.lock_time = ticks; atomic_inc(&dev->total_locks); atomic_inc(&q->total_locks); break; /* Got lock */ @@ -773,15 +769,12 @@ int gamma_lock(struct inode *inode, struct file *filp, unsigned int cmd, /* Contention */ atomic_inc(&dev->total_sleeps); - current->state = TASK_INTERRUPTIBLE; - schedule(); - if (signal_pending(current)) { - ret = -ERESTARTSYS; + ret = tsleep(&dev->lock.lock_queue, PZERO|PCATCH, + "gaml2", 0); + if (ret) break; - } } - current->state = TASK_RUNNING; - remove_wait_queue(&dev->lock.lock_queue, &entry); + atomic_dec(&dev->lock.lock_queue); } drm_flush_unblock(dev, lock.context, lock.flags); /* cleanup phase */ @@ -795,7 +788,12 @@ int gamma_lock(struct inode *inode, struct file *filp, unsigned int cmd, DRM_DEBUG("%d %s\n", lock.context, ret ? "interrupted" : "has lock"); #if DRM_DMA_HISTOGRAM - atomic_inc(&dev->histo.lacq[drm_histogram_slot(get_cycles() - start)]); + { + struct timespec ts; + getnanotime(&ts); + timespecsub(&ts, &start); + atomic_inc(&dev->histo.lacq[drm_histogram_slot(&ts)]); + } #endif return ret; diff --git a/bsd/gamma_drv.c b/bsd/gamma/gamma_drv.c similarity index 86% rename from bsd/gamma_drv.c rename to bsd/gamma/gamma_drv.c index e8865587..d278031a 100644 --- a/bsd/gamma_drv.c +++ b/bsd/gamma/gamma_drv.c @@ -32,6 +32,62 @@ #include "drmP.h" #include "gamma_drv.h" +#include + +static int gamma_init(device_t nbdev); +static void gamma_cleanup(device_t nbdev); + +static int gamma_probe(device_t dev) +{ + const char *s = 0; + + switch (pci_get_devid(dev)) { + case 0x00083d3d: + s = "3D Labs Gamma graphics accelerator"; + break; + } + + if (s) { + device_set_desc(dev, s); + return 0; + } + + return ENXIO; +} + +static int gamma_attach(device_t dev) +{ + gamma_init(dev); + return 0; +} + +static int gamma_detach(device_t dev) +{ + gamma_cleanup(dev); + return 0; +} + +static device_method_t gamma_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, gamma_probe), + DEVMETHOD(device_attach, gamma_attach), + DEVMETHOD(device_detach, gamma_detach), + + { 0, 0 } +}; + +static driver_t gamma_driver = { + "drm", + gamma_methods, + sizeof(drm_device_t), +}; + +static devclass_t gamma_devclass; +#define GAMMA_SOFTC(unit) \ + ((drm_device_t *) devclass_get_softc(gamma_devclass, unit)) + +DRIVER_MODULE(if_gamma, pci, gamma_driver, gamma_devclass, 0, 0); + #define GAMMA_NAME "gamma" #define GAMMA_DESC "3dlabs GMX 2000" #define GAMMA_DATE "19990830" @@ -39,8 +95,6 @@ #define GAMMA_MINOR 0 #define GAMMA_PATCHLEVEL 5 -static drm_device_t gamma_device; - #define CDEV_MAJOR 200 static struct cdevsw gamma_cdevsw = { @@ -259,21 +313,19 @@ gamma_takedown(drm_device_t *dev) if (dev->lock.hw_lock) { dev->lock.hw_lock = NULL; /* SHM removed */ dev->lock.pid = 0; -#if 0 - wake_up_interruptible(&dev->lock.lock_queue); -#endif + wakeup(&dev->lock.lock_queue); } lockmgr(&dev->dev_lock, LK_RELEASE, 0, curproc); return 0; } -/* gamma_init is called via SYSINIT at module load time */ +/* gamma_init is called via gamma_attach at module load time */ -static void -gamma_init(void *arg) +static int +gamma_init(device_t nbdev) { - drm_device_t *dev = &gamma_device; + drm_device_t *dev = device_get_softc(nbdev); DRM_DEBUG("\n"); @@ -291,16 +343,17 @@ gamma_init(void *arg) return retcode; } #endif - dev->device = make_dev(&gamma_cdevsw, - /* gamma_misc.minor */ 0, - DRM_DEV_UID, - DRM_DEV_GID, - DRM_DEV_MODE, - GAMMA_NAME); + dev->device = nbdev; + dev->devnode = make_dev(&gamma_cdevsw, + device_get_unit(nbdev), + DRM_DEV_UID, + DRM_DEV_GID, + DRM_DEV_MODE, + GAMMA_NAME); dev->name = GAMMA_NAME; drm_mem_init(); - drm_proc_init(dev); + drm_sysctl_init(dev); DRM_INFO("Initialized %s %d.%d.%d %s on minor %d\n", GAMMA_NAME, @@ -308,21 +361,21 @@ gamma_init(void *arg) GAMMA_MINOR, GAMMA_PATCHLEVEL, GAMMA_DATE, - /* gamma_misc.minor */ 0); + device_get_unit(nbdev)); + + return 0; } -SYSINIT(gamma_init, SI_SUB_DRIVERS, SI_ORDER_ANY, gamma_init, 0); - -/* gamma_cleanup is called via SYSUNINIT at module unload time. */ +/* gamma_cleanup is called via gamma_detach at module unload time. */ static void -gamma_cleanup(void *arg) +gamma_cleanup(device_t nbdev) { - drm_device_t *dev = &gamma_device; + drm_device_t *dev = device_get_softc(nbdev); DRM_DEBUG("\n"); - drm_proc_cleanup(); + drm_sysctl_cleanup(dev); #if 0 if (misc_deregister(&gamma_misc)) { DRM_ERROR("Cannot unload module\n"); @@ -374,27 +427,31 @@ int gamma_version(struct inode *inode, struct file *filp, unsigned int cmd, int gamma_open(dev_t kdev, int flags, int fmt, struct proc *p) { - drm_device_t *dev = &gamma_device; + drm_device_t *dev = GAMMA_SOFTC(minor(kdev)); int retcode = 0; DRM_DEBUG("open_count = %d\n", dev->open_count); + + device_busy(dev->device); if (!(retcode = drm_open_helper(kdev, flags, fmt, p, dev))) { atomic_inc(&dev->total_open); simple_lock(&dev->count_lock); if (!dev->open_count++) { simple_unlock(&dev->count_lock); - return gamma_setup(dev); + retcode = gamma_setup(dev); } simple_unlock(&dev->count_lock); } + if (retcode) + device_unbusy(dev->device); + return retcode; } int gamma_close(dev_t kdev, int flags, int fmt, struct proc *p) { - drm_file_t *priv = kdev->si_drv1; - drm_device_t *dev = priv->dev; + drm_device_t *dev = kdev->si_drv1; int retcode = 0; DRM_DEBUG("open_count = %d\n", dev->open_count); @@ -410,6 +467,7 @@ gamma_close(dev_t kdev, int flags, int fmt, struct proc *p) return EBUSY; } simple_unlock(&dev->count_lock); + device_unbusy(dev->device); return gamma_takedown(dev); } simple_unlock(&dev->count_lock); @@ -423,12 +481,18 @@ int gamma_ioctl(dev_t kdev, u_long cmd, caddr_t data, int flags, struct proc *p) { int nr = DRM_IOCTL_NR(cmd); - drm_file_t *priv = kdev->si_drv1; - drm_device_t *dev = priv->dev; + drm_device_t *dev = kdev->si_drv1; + drm_file_t *priv; int retcode = 0; drm_ioctl_desc_t *ioctl; d_ioctl_t *func; + priv = drm_find_file_by_proc(dev, p); + if (!priv) { + DRM_DEBUG("can't find authenticator\n"); + return EINVAL; + } + atomic_inc(&dev->ioctl_count); atomic_inc(&dev->total_ioctl); ++priv->ioctl_count; @@ -468,8 +532,7 @@ gamma_ioctl(dev_t kdev, u_long cmd, caddr_t data, int flags, struct proc *p) int gamma_unlock(dev_t kdev, u_long cmd, caddr_t data, int flags, struct proc *p) { - drm_file_t *priv = kdev->si_drv1; - drm_device_t *dev = priv->dev; + drm_device_t *dev = kdev->si_drv1; drm_lock_t *lockp = (drm_lock_t *) data; if (lockp->context == DRM_KERNEL_CONTEXT) { diff --git a/bsd/gamma_drv.h b/bsd/gamma/gamma_drv.h similarity index 100% rename from bsd/gamma_drv.h rename to bsd/gamma/gamma_drv.h diff --git a/bsd/i810_drm.h b/bsd/i810_drm.h new file mode 100644 index 00000000..0754874c --- /dev/null +++ b/bsd/i810_drm.h @@ -0,0 +1,93 @@ +#ifndef _I810_DRM_H_ +#define _I810_DRM_H_ + +/* WARNING: These defines must be the same as what the Xserver uses. + * if you change them, you must change the defines in the Xserver. + */ + +/* Might one day want to support the client-side ringbuffer code again. + */ +#ifndef _I810_DEFINES_ +#define _I810_DEFINES_ + +#define I810_USE_BATCH 1 +#define I810_DMA_BUF_ORDER 12 +#define I810_DMA_BUF_SZ (1< + * Keith Whitwell + * + * $XFree86$ + */ + +#ifndef _MGA_DRM_H_ +#define _MGA_DRM_H_ + +/* WARNING: If you change any of these defines, make sure to change the + * defines in the Xserver file (xf86drmMga.h) + */ +#ifndef _MGA_DEFINES_ +#define _MGA_DEFINES_ +#define MGA_F 0x1 /* fog */ +#define MGA_A 0x2 /* alpha */ +#define MGA_S 0x4 /* specular */ +#define MGA_T2 0x8 /* multitexture */ + +#define MGA_WARP_TGZ 0 +#define MGA_WARP_TGZF (MGA_F) +#define MGA_WARP_TGZA (MGA_A) +#define MGA_WARP_TGZAF (MGA_F|MGA_A) +#define MGA_WARP_TGZS (MGA_S) +#define MGA_WARP_TGZSF (MGA_S|MGA_F) +#define MGA_WARP_TGZSA (MGA_S|MGA_A) +#define MGA_WARP_TGZSAF (MGA_S|MGA_F|MGA_A) +#define MGA_WARP_T2GZ (MGA_T2) +#define MGA_WARP_T2GZF (MGA_T2|MGA_F) +#define MGA_WARP_T2GZA (MGA_T2|MGA_A) +#define MGA_WARP_T2GZAF (MGA_T2|MGA_A|MGA_F) +#define MGA_WARP_T2GZS (MGA_T2|MGA_S) +#define MGA_WARP_T2GZSF (MGA_T2|MGA_S|MGA_F) +#define MGA_WARP_T2GZSA (MGA_T2|MGA_S|MGA_A) +#define MGA_WARP_T2GZSAF (MGA_T2|MGA_S|MGA_F|MGA_A) + +#define MGA_MAX_G400_PIPES 16 +#define MGA_MAX_G200_PIPES 8 /* no multitex */ + +#define MGA_MAX_WARP_PIPES MGA_MAX_G400_PIPES + +#define MGA_CARD_TYPE_G200 1 +#define MGA_CARD_TYPE_G400 2 +#define MGA_FRONT 0x1 +#define MGA_BACK 0x2 +#define MGA_DEPTH 0x4 + +/* 3d state excluding texture units: + */ +#define MGA_CTXREG_DSTORG 0 /* validated */ +#define MGA_CTXREG_MACCESS 1 +#define MGA_CTXREG_PLNWT 2 +#define MGA_CTXREG_DWGCTL 3 +#define MGA_CTXREG_ALPHACTRL 4 +#define MGA_CTXREG_FOGCOLOR 5 +#define MGA_CTXREG_WFLAG 6 +#define MGA_CTXREG_TDUAL0 7 +#define MGA_CTXREG_TDUAL1 8 +#define MGA_CTXREG_FCOL 9 +#define MGA_CTX_SETUP_SIZE 10 + +/* 2d state + */ +#define MGA_2DREG_PITCH 0 +#define MGA_2D_SETUP_SIZE 1 + +/* Each texture unit has a state: + */ +#define MGA_TEXREG_CTL 0 +#define MGA_TEXREG_CTL2 1 +#define MGA_TEXREG_FILTER 2 +#define MGA_TEXREG_BORDERCOL 3 +#define MGA_TEXREG_ORG 4 /* validated */ +#define MGA_TEXREG_ORG1 5 +#define MGA_TEXREG_ORG2 6 +#define MGA_TEXREG_ORG3 7 +#define MGA_TEXREG_ORG4 8 +#define MGA_TEXREG_WIDTH 9 +#define MGA_TEXREG_HEIGHT 10 +#define MGA_TEX_SETUP_SIZE 11 + +/* What needs to be changed for the current vertex dma buffer? + */ +#define MGA_UPLOAD_CTX 0x1 +#define MGA_UPLOAD_TEX0 0x2 +#define MGA_UPLOAD_TEX1 0x4 +#define MGA_UPLOAD_PIPE 0x8 +#define MGA_UPLOAD_TEX0IMAGE 0x10 +#define MGA_UPLOAD_TEX1IMAGE 0x20 +#define MGA_UPLOAD_2D 0x40 +#define MGA_WAIT_AGE 0x80 /* handled client-side */ +#define MGA_UPLOAD_CLIPRECTS 0x100 /* handled client-side */ +#define MGA_DMA_FLUSH 0x200 /* set when someone gets the lock + quiescent */ + +/* 64 buffers of 16k each, total 1 meg. + */ +#define MGA_DMA_BUF_ORDER 14 +#define MGA_DMA_BUF_SZ (1< diff --git a/bsd/tdfx_context.c b/bsd/tdfx/tdfx_context.c similarity index 100% rename from bsd/tdfx_context.c rename to bsd/tdfx/tdfx_context.c diff --git a/bsd-core/tdfx_drv.c b/bsd/tdfx/tdfx_drv.c similarity index 90% rename from bsd-core/tdfx_drv.c rename to bsd/tdfx/tdfx_drv.c index 3f396185..e043cdc4 100644 --- a/bsd-core/tdfx_drv.c +++ b/bsd/tdfx/tdfx_drv.c @@ -32,6 +32,8 @@ #include "drmP.h" #include "tdfx_drv.h" +#include + #define TDFX_NAME "tdfx" #define TDFX_DESC "tdfx" #define TDFX_DATE "19991009" @@ -39,10 +41,67 @@ #define TDFX_MINOR 0 #define TDFX_PATCHLEVEL 1 -static drm_device_t tdfx_device; +static int tdfx_init(device_t nbdev); +static void tdfx_cleanup(device_t nbdev); + drm_ctx_t tdfx_res_ctx; -#define CDEV_MAJOR 201 +static int tdfx_probe(device_t dev) +{ + const char *s = 0; + + switch (pci_get_devid(dev)) { + case 0x0003121a: + s = "3Dfx Voodoo Banshee graphics accelerator"; + break; + + case 0x0005121a: + s = "3Dfx Voodoo 3 graphics accelerator"; + break; + } + + if (s) { + device_set_desc(dev, s); + return 0; + } + + return ENXIO; +} + +static int tdfx_attach(device_t dev) +{ + tdfx_init(dev); + return 0; +} + +static int tdfx_detach(device_t dev) +{ + tdfx_cleanup(dev); + return 0; +} + +static device_method_t tdfx_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, tdfx_probe), + DEVMETHOD(device_attach, tdfx_attach), + DEVMETHOD(device_detach, tdfx_detach), + + { 0, 0 } +}; + +static driver_t tdfx_driver = { + "drm", + tdfx_methods, + sizeof(drm_device_t), +}; + +static devclass_t tdfx_devclass; +#define TDFX_SOFTC(unit) \ + ((drm_device_t *) devclass_get_softc(tdfx_devclass, unit)) + +DRIVER_MODULE(if_tdfx, pci, tdfx_driver, tdfx_devclass, 0, 0); + +#define CDEV_MAJOR 145 /* tdfx_drv.c */ static d_open_t tdfx_open; static d_close_t tdfx_close; @@ -243,21 +302,19 @@ tdfx_takedown(drm_device_t *dev) if (dev->lock.hw_lock) { dev->lock.hw_lock = NULL; /* SHM removed */ dev->lock.pid = 0; -#if 0 - wake_up_interruptible(&dev->lock.lock_queue); -#endif + wakeup(&dev->lock.lock_queue); } lockmgr(&dev->dev_lock, LK_RELEASE, 0, curproc); return 0; } -/* tdfx_init is called via SYSINIT at module load time, */ +/* tdfx_init is called via tdfx_attach at module load time, */ static int -tdfx_init(void *arg) +tdfx_init(device_t nbdev) { - drm_device_t *dev = &tdfx_device; + drm_device_t *dev = device_get_softc(nbdev); DRM_DEBUG("\n"); @@ -269,12 +326,13 @@ tdfx_init(void *arg) drm_parse_options(tdfx); #endif - dev->device = make_dev(&tdfx_cdevsw, - /* gamma_misc.minor */ 0, - DRM_DEV_UID, - DRM_DEV_GID, - DRM_DEV_MODE, - TDFX_NAME); + dev->device = nbdev; + dev->devnode = make_dev(&tdfx_cdevsw, + device_get_unit(nbdev), + DRM_DEV_UID, + DRM_DEV_GID, + DRM_DEV_MODE, + TDFX_NAME); dev->name = TDFX_NAME; drm_mem_init(); @@ -287,32 +345,28 @@ tdfx_init(void *arg) TDFX_MINOR, TDFX_PATCHLEVEL, TDFX_DATE, - 0 /* tdfx_misc.minor */); + device_get_unit(nbdev)); return 0; } -SYSINIT(tdfx_init, SI_SUB_DRIVERS, SI_ORDER_ANY, tdfx_init, 0); - -/* tdfx_cleanup is called via SYSUNINIT at module unload time. */ +/* tdfx_cleanup is called via tdfx_detach at module unload time. */ static void -tdfx_cleanup(void *arg) +tdfx_cleanup(device_t nbdev) { - drm_device_t *dev = &tdfx_device; + drm_device_t *dev = device_get_softc(nbdev); DRM_DEBUG("\n"); drm_sysctl_cleanup(dev); - destroy_dev(dev->device); + destroy_dev(dev->devnode); DRM_INFO("Module unloaded\n"); tdfx_takedown(dev); } -SYSUNINIT(tdfx_init, SI_SUB_DRIVERS, SI_ORDER_ANY, tdfx_cleanup, 0); - static int tdfx_version(dev_t kdev, u_long cmd, caddr_t data, int flags, struct proc *p) { @@ -345,19 +399,24 @@ tdfx_version(dev_t kdev, u_long cmd, caddr_t data, int flags, struct proc *p) static int tdfx_open(dev_t kdev, int flags, int fmt, struct proc *p) { - drm_device_t *dev = &tdfx_device; + drm_device_t *dev = TDFX_SOFTC(minor(kdev)); int retcode = 0; DRM_DEBUG("open_count = %d\n", dev->open_count); + + device_busy(dev->device); if (!(retcode = drm_open_helper(kdev, flags, fmt, p, dev))) { atomic_inc(&dev->total_open); simple_lock(&dev->count_lock); if (!dev->open_count++) { simple_unlock(&dev->count_lock); - return tdfx_setup(dev); + retcode = tdfx_setup(dev); } simple_unlock(&dev->count_lock); } + if (retcode) + device_unbusy(dev->device); + return retcode; } @@ -380,6 +439,7 @@ tdfx_close(dev_t kdev, int flags, int fmt, struct proc *p) return EBUSY; } simple_unlock(&dev->count_lock); + device_unbusy(dev->device); return tdfx_takedown(dev); } simple_unlock(&dev->count_lock); diff --git a/bsd/tdfx_drv.h b/bsd/tdfx/tdfx_drv.h similarity index 100% rename from bsd/tdfx_drv.h rename to bsd/tdfx/tdfx_drv.h diff --git a/bsd/tdfx_drv.c b/bsd/tdfx_drv.c deleted file mode 100644 index 3f396185..00000000 --- a/bsd/tdfx_drv.c +++ /dev/null @@ -1,624 +0,0 @@ -/* tdfx.c -- tdfx driver -*- c -*- - * Created: Thu Oct 7 10:38:32 1999 by faith@precisioninsight.com - * Revised: Tue Oct 12 08:51:35 1999 by faith@precisioninsight.com - * - * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. - * 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. - * - * $PI$ - * $XFree86$ - * - */ - -#include "drmP.h" -#include "tdfx_drv.h" - -#define TDFX_NAME "tdfx" -#define TDFX_DESC "tdfx" -#define TDFX_DATE "19991009" -#define TDFX_MAJOR 0 -#define TDFX_MINOR 0 -#define TDFX_PATCHLEVEL 1 - -static drm_device_t tdfx_device; -drm_ctx_t tdfx_res_ctx; - -#define CDEV_MAJOR 201 - /* tdfx_drv.c */ -static d_open_t tdfx_open; -static d_close_t tdfx_close; -static d_ioctl_t tdfx_version; -static d_ioctl_t tdfx_ioctl; -static d_ioctl_t tdfx_lock; -static d_ioctl_t tdfx_unlock; - -static struct cdevsw tdfx_cdevsw = { - /* open */ tdfx_open, - /* close */ tdfx_close, - /* read */ drm_read, - /* write */ drm_write, - /* ioctl */ tdfx_ioctl, - /* poll */ drm_poll, - /* mmap */ drm_mmap, - /* strategy */ nostrategy, - /* name */ "tdfx", - /* maj */ CDEV_MAJOR, - /* dump */ nodump, - /* psize */ nopsize, - /* flags */ D_TTY | D_TRACKCLOSE, - /* bmaj */ -1 -}; - -static drm_ioctl_desc_t tdfx_ioctls[] = { - [DRM_IOCTL_NR(DRM_IOCTL_VERSION)] = { tdfx_version, 0, 0 }, - [DRM_IOCTL_NR(DRM_IOCTL_GET_UNIQUE)] = { drm_getunique, 0, 0 }, - [DRM_IOCTL_NR(DRM_IOCTL_GET_MAGIC)] = { drm_getmagic, 0, 0 }, - [DRM_IOCTL_NR(DRM_IOCTL_IRQ_BUSID)] = { drm_irq_busid, 0, 1 }, - - [DRM_IOCTL_NR(DRM_IOCTL_SET_UNIQUE)] = { drm_setunique, 1, 1 }, - [DRM_IOCTL_NR(DRM_IOCTL_BLOCK)] = { drm_block, 1, 1 }, - [DRM_IOCTL_NR(DRM_IOCTL_UNBLOCK)] = { drm_unblock, 1, 1 }, - [DRM_IOCTL_NR(DRM_IOCTL_AUTH_MAGIC)] = { drm_authmagic, 1, 1 }, - [DRM_IOCTL_NR(DRM_IOCTL_ADD_MAP)] = { drm_addmap, 1, 1 }, - - [DRM_IOCTL_NR(DRM_IOCTL_ADD_CTX)] = { tdfx_addctx, 1, 1 }, - [DRM_IOCTL_NR(DRM_IOCTL_RM_CTX)] = { tdfx_rmctx, 1, 1 }, - [DRM_IOCTL_NR(DRM_IOCTL_MOD_CTX)] = { tdfx_modctx, 1, 1 }, - [DRM_IOCTL_NR(DRM_IOCTL_GET_CTX)] = { tdfx_getctx, 1, 0 }, - [DRM_IOCTL_NR(DRM_IOCTL_SWITCH_CTX)] = { tdfx_switchctx, 1, 1 }, - [DRM_IOCTL_NR(DRM_IOCTL_NEW_CTX)] = { tdfx_newctx, 1, 1 }, - [DRM_IOCTL_NR(DRM_IOCTL_RES_CTX)] = { tdfx_resctx, 1, 0 }, - [DRM_IOCTL_NR(DRM_IOCTL_ADD_DRAW)] = { drm_adddraw, 1, 1 }, - [DRM_IOCTL_NR(DRM_IOCTL_RM_DRAW)] = { drm_rmdraw, 1, 1 }, - [DRM_IOCTL_NR(DRM_IOCTL_LOCK)] = { tdfx_lock, 1, 0 }, - [DRM_IOCTL_NR(DRM_IOCTL_UNLOCK)] = { tdfx_unlock, 1, 0 }, - [DRM_IOCTL_NR(DRM_IOCTL_FINISH)] = { drm_finish, 1, 0 }, -}; -#define TDFX_IOCTL_COUNT DRM_ARRAY_SIZE(tdfx_ioctls) - -static int -tdfx_setup(drm_device_t *dev) -{ - int i; - - atomic_set(&dev->ioctl_count, 0); - atomic_set(&dev->vma_count, 0); - dev->buf_use = 0; - atomic_set(&dev->buf_alloc, 0); - - atomic_set(&dev->total_open, 0); - atomic_set(&dev->total_close, 0); - atomic_set(&dev->total_ioctl, 0); - atomic_set(&dev->total_irq, 0); - atomic_set(&dev->total_ctx, 0); - atomic_set(&dev->total_locks, 0); - atomic_set(&dev->total_unlocks, 0); - atomic_set(&dev->total_contends, 0); - atomic_set(&dev->total_sleeps, 0); - - for (i = 0; i < DRM_HASH_SIZE; i++) { - dev->magiclist[i].head = NULL; - dev->magiclist[i].tail = NULL; - } - dev->maplist = NULL; - dev->map_count = 0; - dev->vmalist = NULL; - dev->lock.hw_lock = NULL; - dev->lock.lock_queue = 0; - dev->queue_count = 0; - dev->queue_reserved = 0; - dev->queue_slots = 0; - dev->queuelist = NULL; - dev->irq = 0; - dev->context_flag = 0; - dev->interrupt_flag = 0; - dev->dma = 0; - dev->dma_flag = 0; - dev->last_context = 0; - dev->last_switch = 0; - dev->last_checked = 0; - callout_init(&dev->timer); - dev->context_wait = 0; - - timespecclear(&dev->ctx_start); - timespecclear(&dev->lck_start); - - dev->buf_rp = dev->buf; - dev->buf_wp = dev->buf; - dev->buf_end = dev->buf + DRM_BSZ; - bzero(&dev->buf_sel, sizeof dev->buf_sel); - dev->buf_sigio = NULL; - dev->buf_readers = 0; - dev->buf_writers = 0; - dev->buf_selecting = 0; - - tdfx_res_ctx.handle=-1; - - DRM_DEBUG("\n"); - - /* The kernel's context could be created here, but is now created - in drm_dma_enqueue. This is more resource-efficient for - hardware that does not do DMA, but may mean that - drm_select_queue fails between the time the interrupt is - initialized and the time the queues are initialized. */ - - return 0; -} - - -static int -tdfx_takedown(drm_device_t *dev) -{ - int i; - drm_magic_entry_t *pt, *next; - drm_map_t *map; - drm_vma_entry_t *vma, *vma_next; - - DRM_DEBUG("\n"); - - lockmgr(&dev->dev_lock, LK_EXCLUSIVE, 0, curproc); - callout_stop(&dev->timer); - - if (dev->devname) { - drm_free(dev->devname, strlen(dev->devname)+1, DRM_MEM_DRIVER); - dev->devname = NULL; - } - - if (dev->unique) { - drm_free(dev->unique, strlen(dev->unique)+1, DRM_MEM_DRIVER); - dev->unique = NULL; - dev->unique_len = 0; - } - /* Clear pid list */ - for (i = 0; i < DRM_HASH_SIZE; i++) { - for (pt = dev->magiclist[i].head; pt; pt = next) { - next = pt->next; - drm_free(pt, sizeof(*pt), DRM_MEM_MAGIC); - } - dev->magiclist[i].head = dev->magiclist[i].tail = NULL; - } - - /* Clear vma list (only built for debugging) */ - if (dev->vmalist) { - for (vma = dev->vmalist; vma; vma = vma_next) { - vma_next = vma->next; - drm_free(vma, sizeof(*vma), DRM_MEM_VMAS); - } - dev->vmalist = NULL; - } - - /* Clear map area and mtrr information */ - if (dev->maplist) { - for (i = 0; i < dev->map_count; i++) { - map = dev->maplist[i]; - switch (map->type) { - case _DRM_REGISTERS: - case _DRM_FRAME_BUFFER: -#ifdef CONFIG_MTRR - if (map->mtrr >= 0) { - int retcode; - retcode = mtrr_del(map->mtrr, - map->offset, - map->size); - DRM_DEBUG("mtrr_del = %d\n", retcode); - } -#endif - drm_ioremapfree(map->handle, map->size); - break; - case _DRM_SHM: - drm_free_pages((unsigned long)map->handle, - drm_order(map->size) - - PAGE_SHIFT, - DRM_MEM_SAREA); - break; - } - drm_free(map, sizeof(*map), DRM_MEM_MAPS); - } - drm_free(dev->maplist, - dev->map_count * sizeof(*dev->maplist), - DRM_MEM_MAPS); - dev->maplist = NULL; - dev->map_count = 0; - } - - if (dev->lock.hw_lock) { - dev->lock.hw_lock = NULL; /* SHM removed */ - dev->lock.pid = 0; -#if 0 - wake_up_interruptible(&dev->lock.lock_queue); -#endif - } - lockmgr(&dev->dev_lock, LK_RELEASE, 0, curproc); - - return 0; -} - -/* tdfx_init is called via SYSINIT at module load time, */ - -static int -tdfx_init(void *arg) -{ - drm_device_t *dev = &tdfx_device; - - DRM_DEBUG("\n"); - - memset((void *)dev, 0, sizeof(*dev)); - simple_lock_init(&dev->count_lock); - lockinit(&dev->dev_lock, PZERO, "drmlk", 0, 0); - -#if 0 - drm_parse_options(tdfx); -#endif - - dev->device = make_dev(&tdfx_cdevsw, - /* gamma_misc.minor */ 0, - DRM_DEV_UID, - DRM_DEV_GID, - DRM_DEV_MODE, - TDFX_NAME); - dev->name = TDFX_NAME; - - drm_mem_init(); - drm_sysctl_init(dev); - TAILQ_INIT(&dev->files); - - DRM_INFO("Initialized %s %d.%d.%d %s on minor %d\n", - TDFX_NAME, - TDFX_MAJOR, - TDFX_MINOR, - TDFX_PATCHLEVEL, - TDFX_DATE, - 0 /* tdfx_misc.minor */); - - return 0; -} - -SYSINIT(tdfx_init, SI_SUB_DRIVERS, SI_ORDER_ANY, tdfx_init, 0); - -/* tdfx_cleanup is called via SYSUNINIT at module unload time. */ - -static void -tdfx_cleanup(void *arg) -{ - drm_device_t *dev = &tdfx_device; - - DRM_DEBUG("\n"); - - drm_sysctl_cleanup(dev); - destroy_dev(dev->device); - - DRM_INFO("Module unloaded\n"); - - tdfx_takedown(dev); -} - -SYSUNINIT(tdfx_init, SI_SUB_DRIVERS, SI_ORDER_ANY, tdfx_cleanup, 0); - -static int -tdfx_version(dev_t kdev, u_long cmd, caddr_t data, int flags, struct proc *p) -{ - drm_version_t version; - int len; - - version = *(drm_version_t *) data; - -#define DRM_COPY(name,value) \ - len = strlen(value); \ - if (len > name##_len) len = name##_len; \ - name##_len = strlen(value); \ - if (len && name) { \ - int error = copyout(value, name, len); \ - if (error) return error; \ - } - - version.version_major = TDFX_MAJOR; - version.version_minor = TDFX_MINOR; - version.version_patchlevel = TDFX_PATCHLEVEL; - - DRM_COPY(version.name, TDFX_NAME); - DRM_COPY(version.date, TDFX_DATE); - DRM_COPY(version.desc, TDFX_DESC); - - *(drm_version_t *) data = version; - return 0; -} - -static int -tdfx_open(dev_t kdev, int flags, int fmt, struct proc *p) -{ - drm_device_t *dev = &tdfx_device; - int retcode = 0; - - DRM_DEBUG("open_count = %d\n", dev->open_count); - if (!(retcode = drm_open_helper(kdev, flags, fmt, p, dev))) { - atomic_inc(&dev->total_open); - simple_lock(&dev->count_lock); - if (!dev->open_count++) { - simple_unlock(&dev->count_lock); - return tdfx_setup(dev); - } - simple_unlock(&dev->count_lock); - } - return retcode; -} - -static int -tdfx_close(dev_t kdev, int flags, int fmt, struct proc *p) -{ - drm_device_t *dev = kdev->si_drv1; - int retcode = 0; - - DRM_DEBUG("open_count = %d\n", dev->open_count); - if (!(retcode = drm_close(kdev, flags, fmt, p))) { - atomic_inc(&dev->total_close); - simple_lock(&dev->count_lock); - if (!--dev->open_count) { - if (atomic_read(&dev->ioctl_count) || dev->blocked) { - DRM_ERROR("Device busy: %d %d\n", - atomic_read(&dev->ioctl_count), - dev->blocked); - simple_unlock(&dev->count_lock); - return EBUSY; - } - simple_unlock(&dev->count_lock); - return tdfx_takedown(dev); - } - simple_unlock(&dev->count_lock); - } - return retcode; -} - -/* tdfx_ioctl is called whenever a process performs an ioctl on /dev/drm. */ - -static int -tdfx_ioctl(dev_t kdev, u_long cmd, caddr_t data, int flags, struct proc *p) -{ - int nr = DRM_IOCTL_NR(cmd); - drm_device_t *dev = kdev->si_drv1; - drm_file_t *priv; - int retcode = 0; - drm_ioctl_desc_t *ioctl; - d_ioctl_t *func; - - DRM_DEBUG("dev=%p\n", dev); - priv = drm_find_file_by_proc(dev, p); - if (!priv) { - DRM_DEBUG("can't find authenticator\n"); - return EINVAL; - } - - atomic_inc(&dev->ioctl_count); - atomic_inc(&dev->total_ioctl); - ++priv->ioctl_count; - - DRM_DEBUG("pid = %d, cmd = 0x%02lx, nr = 0x%02x, auth = %d\n", - p->p_pid, cmd, nr, priv->authenticated); - - switch (cmd) { - case FIONBIO: - atomic_dec(&dev->ioctl_count); - return 0; - - case FIOASYNC: - atomic_dec(&dev->ioctl_count); - dev->flags |= FASYNC; - return 0; - - case FIOSETOWN: - atomic_dec(&dev->ioctl_count); - return fsetown(*(int *)data, &dev->buf_sigio); - - case FIOGETOWN: - atomic_dec(&dev->ioctl_count); - *(int *) data = fgetown(dev->buf_sigio); - return 0; - } - - if (nr >= TDFX_IOCTL_COUNT) { - retcode = EINVAL; - } else { - ioctl = &tdfx_ioctls[nr]; - func = ioctl->func; - - if (!func) { - DRM_DEBUG("no function\n"); - retcode = EINVAL; - } else if ((ioctl->root_only && suser(p)) - || (ioctl->auth_needed && !priv->authenticated)) { - retcode = EACCES; - } else { - retcode = (func)(kdev, cmd, data, flags, p); - } - } - - atomic_dec(&dev->ioctl_count); - return retcode; -} - -static int -tdfx_lock(dev_t kdev, u_long cmd, caddr_t data, int flags, struct proc *p) -{ - drm_device_t *dev = kdev->si_drv1; - int ret = 0; - drm_lock_t lock; -#if DRM_DMA_HISTOGRAM - - getnanotime(&dev->lck_start); -#endif - - lock = *(drm_lock_t *) data; - - if (lock.context == DRM_KERNEL_CONTEXT) { - DRM_ERROR("Process %d using kernel context %d\n", - p->p_pid, lock.context); - return EINVAL; - } - - DRM_DEBUG("%d (pid %d) requests lock (0x%08x), flags = 0x%08x\n", - lock.context, p->p_pid, dev->lock.hw_lock->lock, - lock.flags); - -#if 0 - /* dev->queue_count == 0 right now for - tdfx. FIXME? */ - if (lock.context < 0 || lock.context >= dev->queue_count) - return EINVAL; -#endif - - if (!ret) { -#if 0 - if (_DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock) - != lock.context) { - long j = ticks - dev->lock.lock_time; - - if (lock.context == tdfx_res_ctx.handle && - j >= 0 && j < DRM_LOCK_SLICE) { - /* Can't take lock if we just had it and - there is contention. */ - DRM_DEBUG("%d (pid %d) delayed j=%d dev=%d ticks=%d\n", - lock.context, p->p_pid, j, - dev->lock.lock_time, ticks); - ret = tsleep(&never, PZERO|PCATCH, "drmlk1", - DRM_LOCK_SLICE - j); - if (ret) - return ret; - DRM_DEBUG("ticks=%d\n", ticks); - } - } -#endif - for (;;) { - if (!dev->lock.hw_lock) { - /* Device has been unregistered */ - ret = EINTR; - break; - } - if (drm_lock_take(&dev->lock.hw_lock->lock, - lock.context)) { - dev->lock.pid = p->p_pid; - dev->lock.lock_time = ticks; - atomic_inc(&dev->total_locks); - break; /* Got lock */ - } - - /* Contention */ - atomic_inc(&dev->total_sleeps); - ret = tsleep(&dev->lock.lock_queue, - PZERO|PCATCH, - "drmlk2", - 0); - } - } - -#if 0 - if (!ret && dev->last_context != lock.context && - lock.context != tdfx_res_ctx.handle && - dev->last_context != tdfx_res_ctx.handle) { - add_wait_queue(&dev->context_wait, &entry); - current->state = TASK_INTERRUPTIBLE; - /* PRE: dev->last_context != lock.context */ - tdfx_context_switch(dev, dev->last_context, lock.context); - /* POST: we will wait for the context - switch and will dispatch on a later call - when dev->last_context == lock.context - NOTE WE HOLD THE LOCK THROUGHOUT THIS - TIME! */ - current->policy |= SCHED_YIELD; - schedule(); - current->state = TASK_RUNNING; - remove_wait_queue(&dev->context_wait, &entry); - if (signal_pending(current)) { - ret = EINTR; - } else if (dev->last_context != lock.context) { - DRM_ERROR("Context mismatch: %d %d\n", - dev->last_context, lock.context); - } - } -#endif - - if (!ret) { - if (lock.flags & _DRM_LOCK_READY) { - /* Wait for space in DMA/FIFO */ - } - if (lock.flags & _DRM_LOCK_QUIESCENT) { - /* Make hardware quiescent */ -#if 0 - tdfx_quiescent(dev); -#endif - } - } - -#if 0 - DRM_ERROR("pid = %5d, old counter = %5ld\n", - p->p_pid, current->counter); -#endif -#if 0 - while (current->counter > 25) - current->counter >>= 1; /* decrease time slice */ - DRM_ERROR("pid = %5d, new counter = %5ld\n", - p->p_pid, current->counter); -#endif - DRM_DEBUG("%d %s\n", lock.context, ret ? "interrupted" : "has lock"); - -#if DRM_DMA_HISTOGRAM - { - struct timespec ts; - getnanotime(&ts); - timespecsub(&ts, &dev->lck_start); - atomic_inc(&dev->histo.lhld[drm_histogram_slot(&ts)]); - } -#endif - - return ret; -} - - -static int -tdfx_unlock(dev_t kdev, u_long cmd, caddr_t data, int flags, struct proc *p) -{ - drm_device_t *dev = kdev->si_drv1; - drm_lock_t lock; - - lock = *(drm_lock_t *) data; - - if (lock.context == DRM_KERNEL_CONTEXT) { - DRM_ERROR("Process %d using kernel context %d\n", - p->p_pid, lock.context); - return EINVAL; - } - - DRM_DEBUG("%d frees lock (%d holds)\n", - lock.context, - _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock)); - atomic_inc(&dev->total_unlocks); - if (_DRM_LOCK_IS_CONT(dev->lock.hw_lock->lock)) - atomic_inc(&dev->total_contends); - drm_lock_transfer(dev, &dev->lock.hw_lock->lock, DRM_KERNEL_CONTEXT); - /* FIXME: Try to send data to card here */ - if (!dev->context_flag) { - if (drm_lock_free(dev, &dev->lock.hw_lock->lock, - DRM_KERNEL_CONTEXT)) { - DRM_ERROR("\n"); - } - } - - return 0; -}