diff options
Diffstat (limited to 'drivers/char')
32 files changed, 1694 insertions, 590 deletions
diff --git a/drivers/char/drm/Kconfig b/drivers/char/drm/Kconfig index 123417e43040..d6c50312aec6 100644 --- a/drivers/char/drm/Kconfig +++ b/drivers/char/drm/Kconfig | |||
@@ -82,7 +82,7 @@ endchoice | |||
82 | 82 | ||
83 | config DRM_MGA | 83 | config DRM_MGA |
84 | tristate "Matrox g200/g400" | 84 | tristate "Matrox g200/g400" |
85 | depends on DRM && AGP | 85 | depends on DRM |
86 | help | 86 | help |
87 | Choose this option if you have a Matrox G200, G400 or G450 graphics | 87 | Choose this option if you have a Matrox G200, G400 or G450 graphics |
88 | card. If M is selected, the module will be called mga. AGP | 88 | card. If M is selected, the module will be called mga. AGP |
diff --git a/drivers/char/drm/drm.h b/drivers/char/drm/drm.h index e8371dd87fbc..3a4745f76cf0 100644 --- a/drivers/char/drm/drm.h +++ b/drivers/char/drm/drm.h | |||
@@ -209,7 +209,8 @@ typedef enum drm_map_type { | |||
209 | _DRM_REGISTERS = 1, /**< no caching, no core dump */ | 209 | _DRM_REGISTERS = 1, /**< no caching, no core dump */ |
210 | _DRM_SHM = 2, /**< shared, cached */ | 210 | _DRM_SHM = 2, /**< shared, cached */ |
211 | _DRM_AGP = 3, /**< AGP/GART */ | 211 | _DRM_AGP = 3, /**< AGP/GART */ |
212 | _DRM_SCATTER_GATHER = 4 /**< Scatter/gather memory for PCI DMA */ | 212 | _DRM_SCATTER_GATHER = 4, /**< Scatter/gather memory for PCI DMA */ |
213 | _DRM_CONSISTENT = 5, /**< Consistent memory for PCI DMA */ | ||
213 | } drm_map_type_t; | 214 | } drm_map_type_t; |
214 | 215 | ||
215 | 216 | ||
@@ -368,7 +369,8 @@ typedef struct drm_buf_desc { | |||
368 | enum { | 369 | enum { |
369 | _DRM_PAGE_ALIGN = 0x01, /**< Align on page boundaries for DMA */ | 370 | _DRM_PAGE_ALIGN = 0x01, /**< Align on page boundaries for DMA */ |
370 | _DRM_AGP_BUFFER = 0x02, /**< Buffer is in AGP space */ | 371 | _DRM_AGP_BUFFER = 0x02, /**< Buffer is in AGP space */ |
371 | _DRM_SG_BUFFER = 0x04 /**< Scatter/gather memory buffer */ | 372 | _DRM_SG_BUFFER = 0x04, /**< Scatter/gather memory buffer */ |
373 | _DRM_FB_BUFFER = 0x08 /**< Buffer is in frame buffer */ | ||
372 | } flags; | 374 | } flags; |
373 | unsigned long agp_start; /**< | 375 | unsigned long agp_start; /**< |
374 | * Start address of where the AGP buffers are | 376 | * Start address of where the AGP buffers are |
diff --git a/drivers/char/drm/drmP.h b/drivers/char/drm/drmP.h index 5df09cc8c6db..fb2af9279148 100644 --- a/drivers/char/drm/drmP.h +++ b/drivers/char/drm/drmP.h | |||
@@ -96,6 +96,7 @@ | |||
96 | #define DRIVER_IRQ_SHARED 0x80 | 96 | #define DRIVER_IRQ_SHARED 0x80 |
97 | #define DRIVER_IRQ_VBL 0x100 | 97 | #define DRIVER_IRQ_VBL 0x100 |
98 | #define DRIVER_DMA_QUEUE 0x200 | 98 | #define DRIVER_DMA_QUEUE 0x200 |
99 | #define DRIVER_FB_DMA 0x400 | ||
99 | 100 | ||
100 | /***********************************************************************/ | 101 | /***********************************************************************/ |
101 | /** \name Begin the DRM... */ | 102 | /** \name Begin the DRM... */ |
@@ -474,7 +475,8 @@ typedef struct drm_device_dma { | |||
474 | unsigned long byte_count; | 475 | unsigned long byte_count; |
475 | enum { | 476 | enum { |
476 | _DRM_DMA_USE_AGP = 0x01, | 477 | _DRM_DMA_USE_AGP = 0x01, |
477 | _DRM_DMA_USE_SG = 0x02 | 478 | _DRM_DMA_USE_SG = 0x02, |
479 | _DRM_DMA_USE_FB = 0x04 | ||
478 | } flags; | 480 | } flags; |
479 | 481 | ||
480 | } drm_device_dma_t; | 482 | } drm_device_dma_t; |
@@ -525,6 +527,12 @@ typedef struct drm_sigdata { | |||
525 | drm_hw_lock_t *lock; | 527 | drm_hw_lock_t *lock; |
526 | } drm_sigdata_t; | 528 | } drm_sigdata_t; |
527 | 529 | ||
530 | typedef struct drm_dma_handle { | ||
531 | dma_addr_t busaddr; | ||
532 | void *vaddr; | ||
533 | size_t size; | ||
534 | } drm_dma_handle_t; | ||
535 | |||
528 | /** | 536 | /** |
529 | * Mappings list | 537 | * Mappings list |
530 | */ | 538 | */ |
@@ -578,7 +586,22 @@ struct drm_driver { | |||
578 | int (*kernel_context_switch)(struct drm_device *dev, int old, int new); | 586 | int (*kernel_context_switch)(struct drm_device *dev, int old, int new); |
579 | void (*kernel_context_switch_unlock)(struct drm_device *dev, drm_lock_t *lock); | 587 | void (*kernel_context_switch_unlock)(struct drm_device *dev, drm_lock_t *lock); |
580 | int (*vblank_wait)(struct drm_device *dev, unsigned int *sequence); | 588 | int (*vblank_wait)(struct drm_device *dev, unsigned int *sequence); |
589 | |||
590 | /** | ||
591 | * Called by \c drm_device_is_agp. Typically used to determine if a | ||
592 | * card is really attached to AGP or not. | ||
593 | * | ||
594 | * \param dev DRM device handle | ||
595 | * | ||
596 | * \returns | ||
597 | * One of three values is returned depending on whether or not the | ||
598 | * card is absolutely \b not AGP (return of 0), absolutely \b is AGP | ||
599 | * (return of 1), or may or may not be AGP (return of 2). | ||
600 | */ | ||
601 | int (*device_is_agp) (struct drm_device * dev); | ||
602 | |||
581 | /* these have to be filled in */ | 603 | /* these have to be filled in */ |
604 | |||
582 | int (*postinit)(struct drm_device *, unsigned long flags); | 605 | int (*postinit)(struct drm_device *, unsigned long flags); |
583 | irqreturn_t (*irq_handler)( DRM_IRQ_ARGS ); | 606 | irqreturn_t (*irq_handler)( DRM_IRQ_ARGS ); |
584 | void (*irq_preinstall)(struct drm_device *dev); | 607 | void (*irq_preinstall)(struct drm_device *dev); |
@@ -806,7 +829,7 @@ extern void *drm_ioremap_nocache(unsigned long offset, unsigned long size, | |||
806 | drm_device_t *dev); | 829 | drm_device_t *dev); |
807 | extern void drm_ioremapfree(void *pt, unsigned long size, drm_device_t *dev); | 830 | extern void drm_ioremapfree(void *pt, unsigned long size, drm_device_t *dev); |
808 | 831 | ||
809 | extern DRM_AGP_MEM *drm_alloc_agp(struct agp_bridge_data *bridge, int pages, u32 type); | 832 | extern DRM_AGP_MEM *drm_alloc_agp(drm_device_t *dev, int pages, u32 type); |
810 | extern int drm_free_agp(DRM_AGP_MEM *handle, int pages); | 833 | extern int drm_free_agp(DRM_AGP_MEM *handle, int pages); |
811 | extern int drm_bind_agp(DRM_AGP_MEM *handle, unsigned int start); | 834 | extern int drm_bind_agp(DRM_AGP_MEM *handle, unsigned int start); |
812 | extern int drm_unbind_agp(DRM_AGP_MEM *handle); | 835 | extern int drm_unbind_agp(DRM_AGP_MEM *handle); |
@@ -881,11 +904,19 @@ extern int drm_lock_free(drm_device_t *dev, | |||
881 | unsigned int context); | 904 | unsigned int context); |
882 | 905 | ||
883 | /* Buffer management support (drm_bufs.h) */ | 906 | /* Buffer management support (drm_bufs.h) */ |
907 | extern int drm_addbufs_agp(drm_device_t *dev, drm_buf_desc_t *request); | ||
908 | extern int drm_addbufs_pci(drm_device_t *dev, drm_buf_desc_t *request); | ||
909 | extern int drm_addmap(drm_device_t *dev, unsigned int offset, | ||
910 | unsigned int size, drm_map_type_t type, | ||
911 | drm_map_flags_t flags, drm_local_map_t **map_ptr); | ||
912 | extern int drm_addmap_ioctl(struct inode *inode, struct file *filp, | ||
913 | unsigned int cmd, unsigned long arg); | ||
914 | extern int drm_rmmap(drm_device_t *dev, drm_local_map_t *map); | ||
915 | extern int drm_rmmap_locked(drm_device_t *dev, drm_local_map_t *map); | ||
916 | extern int drm_rmmap_ioctl(struct inode *inode, struct file *filp, | ||
917 | unsigned int cmd, unsigned long arg); | ||
918 | |||
884 | extern int drm_order( unsigned long size ); | 919 | extern int drm_order( unsigned long size ); |
885 | extern int drm_addmap( struct inode *inode, struct file *filp, | ||
886 | unsigned int cmd, unsigned long arg ); | ||
887 | extern int drm_rmmap( struct inode *inode, struct file *filp, | ||
888 | unsigned int cmd, unsigned long arg ); | ||
889 | extern int drm_addbufs( struct inode *inode, struct file *filp, | 920 | extern int drm_addbufs( struct inode *inode, struct file *filp, |
890 | unsigned int cmd, unsigned long arg ); | 921 | unsigned int cmd, unsigned long arg ); |
891 | extern int drm_infobufs( struct inode *inode, struct file *filp, | 922 | extern int drm_infobufs( struct inode *inode, struct file *filp, |
@@ -896,6 +927,10 @@ extern int drm_freebufs( struct inode *inode, struct file *filp, | |||
896 | unsigned int cmd, unsigned long arg ); | 927 | unsigned int cmd, unsigned long arg ); |
897 | extern int drm_mapbufs( struct inode *inode, struct file *filp, | 928 | extern int drm_mapbufs( struct inode *inode, struct file *filp, |
898 | unsigned int cmd, unsigned long arg ); | 929 | unsigned int cmd, unsigned long arg ); |
930 | extern unsigned long drm_get_resource_start(drm_device_t *dev, | ||
931 | unsigned int resource); | ||
932 | extern unsigned long drm_get_resource_len(drm_device_t *dev, | ||
933 | unsigned int resource); | ||
899 | 934 | ||
900 | /* DMA support (drm_dma.h) */ | 935 | /* DMA support (drm_dma.h) */ |
901 | extern int drm_dma_setup(drm_device_t *dev); | 936 | extern int drm_dma_setup(drm_device_t *dev); |
@@ -919,15 +954,18 @@ extern void drm_vbl_send_signals( drm_device_t *dev ); | |||
919 | 954 | ||
920 | /* AGP/GART support (drm_agpsupport.h) */ | 955 | /* AGP/GART support (drm_agpsupport.h) */ |
921 | extern drm_agp_head_t *drm_agp_init(drm_device_t *dev); | 956 | extern drm_agp_head_t *drm_agp_init(drm_device_t *dev); |
922 | extern int drm_agp_acquire(struct inode *inode, struct file *filp, | 957 | extern int drm_agp_acquire(drm_device_t * dev); |
923 | unsigned int cmd, unsigned long arg); | 958 | extern int drm_agp_acquire_ioctl(struct inode *inode, struct file *filp, |
924 | extern void drm_agp_do_release(drm_device_t *dev); | 959 | unsigned int cmd, unsigned long arg); |
925 | extern int drm_agp_release(struct inode *inode, struct file *filp, | 960 | extern int drm_agp_release(drm_device_t *dev); |
926 | unsigned int cmd, unsigned long arg); | 961 | extern int drm_agp_release_ioctl(struct inode *inode, struct file *filp, |
927 | extern int drm_agp_enable(struct inode *inode, struct file *filp, | 962 | unsigned int cmd, unsigned long arg); |
928 | unsigned int cmd, unsigned long arg); | 963 | extern int drm_agp_enable(drm_device_t *dev, drm_agp_mode_t mode); |
929 | extern int drm_agp_info(struct inode *inode, struct file *filp, | 964 | extern int drm_agp_enable_ioctl(struct inode *inode, struct file *filp, |
930 | unsigned int cmd, unsigned long arg); | 965 | unsigned int cmd, unsigned long arg); |
966 | extern int drm_agp_info(drm_device_t * dev, drm_agp_info_t *info); | ||
967 | extern int drm_agp_info_ioctl(struct inode *inode, struct file *filp, | ||
968 | unsigned int cmd, unsigned long arg); | ||
931 | extern int drm_agp_alloc(struct inode *inode, struct file *filp, | 969 | extern int drm_agp_alloc(struct inode *inode, struct file *filp, |
932 | unsigned int cmd, unsigned long arg); | 970 | unsigned int cmd, unsigned long arg); |
933 | extern int drm_agp_free(struct inode *inode, struct file *filp, | 971 | extern int drm_agp_free(struct inode *inode, struct file *filp, |
@@ -976,12 +1014,10 @@ extern int drm_ati_pcigart_cleanup(drm_device_t *dev, | |||
976 | unsigned long addr, | 1014 | unsigned long addr, |
977 | dma_addr_t bus_addr); | 1015 | dma_addr_t bus_addr); |
978 | 1016 | ||
979 | extern void *drm_pci_alloc(drm_device_t * dev, size_t size, | 1017 | extern drm_dma_handle_t *drm_pci_alloc(drm_device_t *dev, size_t size, |
980 | size_t align, dma_addr_t maxaddr, | 1018 | size_t align, dma_addr_t maxaddr); |
981 | dma_addr_t * busaddr); | 1019 | extern void __drm_pci_free(drm_device_t *dev, drm_dma_handle_t *dmah); |
982 | 1020 | extern void drm_pci_free(drm_device_t *dev, drm_dma_handle_t *dmah); | |
983 | extern void drm_pci_free(drm_device_t * dev, size_t size, | ||
984 | void *vaddr, dma_addr_t busaddr); | ||
985 | 1021 | ||
986 | /* sysfs support (drm_sysfs.c) */ | 1022 | /* sysfs support (drm_sysfs.c) */ |
987 | struct drm_sysfs_class; | 1023 | struct drm_sysfs_class; |
@@ -1025,6 +1061,19 @@ static __inline__ struct drm_map *drm_core_findmap(struct drm_device *dev, unsig | |||
1025 | return NULL; | 1061 | return NULL; |
1026 | } | 1062 | } |
1027 | 1063 | ||
1064 | static __inline__ int drm_device_is_agp(drm_device_t *dev) | ||
1065 | { | ||
1066 | if ( dev->driver->device_is_agp != NULL ) { | ||
1067 | int err = (*dev->driver->device_is_agp)( dev ); | ||
1068 | |||
1069 | if (err != 2) { | ||
1070 | return err; | ||
1071 | } | ||
1072 | } | ||
1073 | |||
1074 | return pci_find_capability(dev->pdev, PCI_CAP_ID_AGP); | ||
1075 | } | ||
1076 | |||
1028 | static __inline__ void drm_core_dropmap(struct drm_map *map) | 1077 | static __inline__ void drm_core_dropmap(struct drm_map *map) |
1029 | { | 1078 | { |
1030 | } | 1079 | } |
diff --git a/drivers/char/drm/drm_agpsupport.c b/drivers/char/drm/drm_agpsupport.c index 8d94c0b5fa44..ffb4acaefe84 100644 --- a/drivers/char/drm/drm_agpsupport.c +++ b/drivers/char/drm/drm_agpsupport.c | |||
@@ -37,7 +37,7 @@ | |||
37 | #if __OS_HAS_AGP | 37 | #if __OS_HAS_AGP |
38 | 38 | ||
39 | /** | 39 | /** |
40 | * AGP information ioctl. | 40 | * Get AGP information. |
41 | * | 41 | * |
42 | * \param inode device inode. | 42 | * \param inode device inode. |
43 | * \param filp file pointer. | 43 | * \param filp file pointer. |
@@ -48,51 +48,56 @@ | |||
48 | * Verifies the AGP device has been initialized and acquired and fills in the | 48 | * Verifies the AGP device has been initialized and acquired and fills in the |
49 | * drm_agp_info structure with the information in drm_agp_head::agp_info. | 49 | * drm_agp_info structure with the information in drm_agp_head::agp_info. |
50 | */ | 50 | */ |
51 | int drm_agp_info(struct inode *inode, struct file *filp, | 51 | int drm_agp_info(drm_device_t *dev, drm_agp_info_t *info) |
52 | unsigned int cmd, unsigned long arg) | ||
53 | { | 52 | { |
54 | drm_file_t *priv = filp->private_data; | ||
55 | drm_device_t *dev = priv->head->dev; | ||
56 | DRM_AGP_KERN *kern; | 53 | DRM_AGP_KERN *kern; |
57 | drm_agp_info_t info; | ||
58 | 54 | ||
59 | if (!dev->agp || !dev->agp->acquired) | 55 | if (!dev->agp || !dev->agp->acquired) |
60 | return -EINVAL; | 56 | return -EINVAL; |
61 | 57 | ||
62 | kern = &dev->agp->agp_info; | 58 | kern = &dev->agp->agp_info; |
63 | info.agp_version_major = kern->version.major; | 59 | info->agp_version_major = kern->version.major; |
64 | info.agp_version_minor = kern->version.minor; | 60 | info->agp_version_minor = kern->version.minor; |
65 | info.mode = kern->mode; | 61 | info->mode = kern->mode; |
66 | info.aperture_base = kern->aper_base; | 62 | info->aperture_base = kern->aper_base; |
67 | info.aperture_size = kern->aper_size * 1024 * 1024; | 63 | info->aperture_size = kern->aper_size * 1024 * 1024; |
68 | info.memory_allowed = kern->max_memory << PAGE_SHIFT; | 64 | info->memory_allowed = kern->max_memory << PAGE_SHIFT; |
69 | info.memory_used = kern->current_memory << PAGE_SHIFT; | 65 | info->memory_used = kern->current_memory << PAGE_SHIFT; |
70 | info.id_vendor = kern->device->vendor; | 66 | info->id_vendor = kern->device->vendor; |
71 | info.id_device = kern->device->device; | 67 | info->id_device = kern->device->device; |
72 | 68 | ||
73 | if (copy_to_user((drm_agp_info_t __user *)arg, &info, sizeof(info))) | 69 | return 0; |
70 | } | ||
71 | EXPORT_SYMBOL(drm_agp_info); | ||
72 | |||
73 | int drm_agp_info_ioctl(struct inode *inode, struct file *filp, | ||
74 | unsigned int cmd, unsigned long arg) | ||
75 | { | ||
76 | drm_file_t *priv = filp->private_data; | ||
77 | drm_device_t *dev = priv->head->dev; | ||
78 | drm_agp_info_t info; | ||
79 | int err; | ||
80 | |||
81 | err = drm_agp_info(dev, &info); | ||
82 | if (err) | ||
83 | return err; | ||
84 | |||
85 | if (copy_to_user((drm_agp_info_t __user *) arg, &info, sizeof(info))) | ||
74 | return -EFAULT; | 86 | return -EFAULT; |
75 | return 0; | 87 | return 0; |
76 | } | 88 | } |
77 | 89 | ||
78 | /** | 90 | /** |
79 | * Acquire the AGP device (ioctl). | 91 | * Acquire the AGP device. |
80 | * | 92 | * |
81 | * \param inode device inode. | 93 | * \param dev DRM device that is to acquire AGP |
82 | * \param filp file pointer. | ||
83 | * \param cmd command. | ||
84 | * \param arg user argument. | ||
85 | * \return zero on success or a negative number on failure. | 94 | * \return zero on success or a negative number on failure. |
86 | * | 95 | * |
87 | * Verifies the AGP device hasn't been acquired before and calls | 96 | * Verifies the AGP device hasn't been acquired before and calls |
88 | * agp_acquire(). | 97 | * \c agp_backend_acquire. |
89 | */ | 98 | */ |
90 | int drm_agp_acquire(struct inode *inode, struct file *filp, | 99 | int drm_agp_acquire(drm_device_t *dev) |
91 | unsigned int cmd, unsigned long arg) | ||
92 | { | 100 | { |
93 | drm_file_t *priv = filp->private_data; | ||
94 | drm_device_t *dev = priv->head->dev; | ||
95 | |||
96 | if (!dev->agp) | 101 | if (!dev->agp) |
97 | return -ENODEV; | 102 | return -ENODEV; |
98 | if (dev->agp->acquired) | 103 | if (dev->agp->acquired) |
@@ -102,9 +107,10 @@ int drm_agp_acquire(struct inode *inode, struct file *filp, | |||
102 | dev->agp->acquired = 1; | 107 | dev->agp->acquired = 1; |
103 | return 0; | 108 | return 0; |
104 | } | 109 | } |
110 | EXPORT_SYMBOL(drm_agp_acquire); | ||
105 | 111 | ||
106 | /** | 112 | /** |
107 | * Release the AGP device (ioctl). | 113 | * Acquire the AGP device (ioctl). |
108 | * | 114 | * |
109 | * \param inode device inode. | 115 | * \param inode device inode. |
110 | * \param filp file pointer. | 116 | * \param filp file pointer. |
@@ -112,63 +118,80 @@ int drm_agp_acquire(struct inode *inode, struct file *filp, | |||
112 | * \param arg user argument. | 118 | * \param arg user argument. |
113 | * \return zero on success or a negative number on failure. | 119 | * \return zero on success or a negative number on failure. |
114 | * | 120 | * |
115 | * Verifies the AGP device has been acquired and calls agp_backend_release(). | 121 | * Verifies the AGP device hasn't been acquired before and calls |
122 | * \c agp_backend_acquire. | ||
116 | */ | 123 | */ |
117 | int drm_agp_release(struct inode *inode, struct file *filp, | 124 | int drm_agp_acquire_ioctl(struct inode *inode, struct file *filp, |
118 | unsigned int cmd, unsigned long arg) | 125 | unsigned int cmd, unsigned long arg) |
119 | { | 126 | { |
120 | drm_file_t *priv = filp->private_data; | 127 | drm_file_t *priv = filp->private_data; |
121 | drm_device_t *dev = priv->head->dev; | 128 | |
129 | return drm_agp_acquire( (drm_device_t *) priv->head->dev ); | ||
130 | } | ||
122 | 131 | ||
132 | /** | ||
133 | * Release the AGP device. | ||
134 | * | ||
135 | * \param dev DRM device that is to release AGP | ||
136 | * \return zero on success or a negative number on failure. | ||
137 | * | ||
138 | * Verifies the AGP device has been acquired and calls \c agp_backend_release. | ||
139 | */ | ||
140 | int drm_agp_release(drm_device_t *dev) | ||
141 | { | ||
123 | if (!dev->agp || !dev->agp->acquired) | 142 | if (!dev->agp || !dev->agp->acquired) |
124 | return -EINVAL; | 143 | return -EINVAL; |
125 | agp_backend_release(dev->agp->bridge); | 144 | agp_backend_release(dev->agp->bridge); |
126 | dev->agp->acquired = 0; | 145 | dev->agp->acquired = 0; |
127 | return 0; | 146 | return 0; |
128 | |||
129 | } | 147 | } |
148 | EXPORT_SYMBOL(drm_agp_release); | ||
130 | 149 | ||
131 | /** | 150 | int drm_agp_release_ioctl(struct inode *inode, struct file *filp, |
132 | * Release the AGP device. | 151 | unsigned int cmd, unsigned long arg) |
133 | * | ||
134 | * Calls agp_backend_release(). | ||
135 | */ | ||
136 | void drm_agp_do_release(drm_device_t *dev) | ||
137 | { | 152 | { |
138 | agp_backend_release(dev->agp->bridge); | 153 | drm_file_t *priv = filp->private_data; |
154 | drm_device_t *dev = priv->head->dev; | ||
155 | |||
156 | return drm_agp_release(dev); | ||
139 | } | 157 | } |
140 | 158 | ||
141 | /** | 159 | /** |
142 | * Enable the AGP bus. | 160 | * Enable the AGP bus. |
143 | * | 161 | * |
144 | * \param inode device inode. | 162 | * \param dev DRM device that has previously acquired AGP. |
145 | * \param filp file pointer. | 163 | * \param mode Requested AGP mode. |
146 | * \param cmd command. | ||
147 | * \param arg pointer to a drm_agp_mode structure. | ||
148 | * \return zero on success or a negative number on failure. | 164 | * \return zero on success or a negative number on failure. |
149 | * | 165 | * |
150 | * Verifies the AGP device has been acquired but not enabled, and calls | 166 | * Verifies the AGP device has been acquired but not enabled, and calls |
151 | * agp_enable(). | 167 | * \c agp_enable. |
152 | */ | 168 | */ |
153 | int drm_agp_enable(struct inode *inode, struct file *filp, | 169 | int drm_agp_enable(drm_device_t *dev, drm_agp_mode_t mode) |
154 | unsigned int cmd, unsigned long arg) | ||
155 | { | 170 | { |
156 | drm_file_t *priv = filp->private_data; | ||
157 | drm_device_t *dev = priv->head->dev; | ||
158 | drm_agp_mode_t mode; | ||
159 | |||
160 | if (!dev->agp || !dev->agp->acquired) | 171 | if (!dev->agp || !dev->agp->acquired) |
161 | return -EINVAL; | 172 | return -EINVAL; |
162 | 173 | ||
163 | if (copy_from_user(&mode, (drm_agp_mode_t __user *)arg, sizeof(mode))) | ||
164 | return -EFAULT; | ||
165 | |||
166 | dev->agp->mode = mode.mode; | 174 | dev->agp->mode = mode.mode; |
167 | agp_enable(dev->agp->bridge, mode.mode); | 175 | agp_enable(dev->agp->bridge, mode.mode); |
168 | dev->agp->base = dev->agp->agp_info.aper_base; | 176 | dev->agp->base = dev->agp->agp_info.aper_base; |
169 | dev->agp->enabled = 1; | 177 | dev->agp->enabled = 1; |
170 | return 0; | 178 | return 0; |
171 | } | 179 | } |
180 | EXPORT_SYMBOL(drm_agp_enable); | ||
181 | |||
182 | int drm_agp_enable_ioctl(struct inode *inode, struct file *filp, | ||
183 | unsigned int cmd, unsigned long arg) | ||
184 | { | ||
185 | drm_file_t *priv = filp->private_data; | ||
186 | drm_device_t *dev = priv->head->dev; | ||
187 | drm_agp_mode_t mode; | ||
188 | |||
189 | |||
190 | if (copy_from_user(&mode, (drm_agp_mode_t __user *) arg, sizeof(mode))) | ||
191 | return -EFAULT; | ||
192 | |||
193 | return drm_agp_enable(dev, mode); | ||
194 | } | ||
172 | 195 | ||
173 | /** | 196 | /** |
174 | * Allocate AGP memory. | 197 | * Allocate AGP memory. |
@@ -206,7 +229,7 @@ int drm_agp_alloc(struct inode *inode, struct file *filp, | |||
206 | pages = (request.size + PAGE_SIZE - 1) / PAGE_SIZE; | 229 | pages = (request.size + PAGE_SIZE - 1) / PAGE_SIZE; |
207 | type = (u32) request.type; | 230 | type = (u32) request.type; |
208 | 231 | ||
209 | if (!(memory = drm_alloc_agp(dev->agp->bridge, pages, type))) { | 232 | if (!(memory = drm_alloc_agp(dev, pages, type))) { |
210 | drm_free(entry, sizeof(*entry), DRM_MEM_AGPLISTS); | 233 | drm_free(entry, sizeof(*entry), DRM_MEM_AGPLISTS); |
211 | return -ENOMEM; | 234 | return -ENOMEM; |
212 | } | 235 | } |
@@ -436,6 +459,7 @@ int drm_agp_bind_memory(DRM_AGP_MEM *handle, off_t start) | |||
436 | return -EINVAL; | 459 | return -EINVAL; |
437 | return agp_bind_memory(handle, start); | 460 | return agp_bind_memory(handle, start); |
438 | } | 461 | } |
462 | EXPORT_SYMBOL(drm_agp_bind_memory); | ||
439 | 463 | ||
440 | /** Calls agp_unbind_memory() */ | 464 | /** Calls agp_unbind_memory() */ |
441 | int drm_agp_unbind_memory(DRM_AGP_MEM *handle) | 465 | int drm_agp_unbind_memory(DRM_AGP_MEM *handle) |
diff --git a/drivers/char/drm/drm_bufs.c b/drivers/char/drm/drm_bufs.c index 4c6191d231b8..fcc8d244f46f 100644 --- a/drivers/char/drm/drm_bufs.c +++ b/drivers/char/drm/drm_bufs.c | |||
@@ -36,29 +36,33 @@ | |||
36 | #include <linux/vmalloc.h> | 36 | #include <linux/vmalloc.h> |
37 | #include "drmP.h" | 37 | #include "drmP.h" |
38 | 38 | ||
39 | /** | 39 | unsigned long drm_get_resource_start(drm_device_t *dev, unsigned int resource) |
40 | * Compute size order. Returns the exponent of the smaller power of two which | ||
41 | * is greater or equal to given number. | ||
42 | * | ||
43 | * \param size size. | ||
44 | * \return order. | ||
45 | * | ||
46 | * \todo Can be made faster. | ||
47 | */ | ||
48 | int drm_order( unsigned long size ) | ||
49 | { | 40 | { |
50 | int order; | 41 | return pci_resource_start(dev->pdev, resource); |
51 | unsigned long tmp; | 42 | } |
43 | EXPORT_SYMBOL(drm_get_resource_start); | ||
52 | 44 | ||
53 | for (order = 0, tmp = size >> 1; tmp; tmp >>= 1, order++) | 45 | unsigned long drm_get_resource_len(drm_device_t *dev, unsigned int resource) |
54 | ; | 46 | { |
47 | return pci_resource_len(dev->pdev, resource); | ||
48 | } | ||
49 | EXPORT_SYMBOL(drm_get_resource_len); | ||
55 | 50 | ||
56 | if (size & (size - 1)) | 51 | static drm_local_map_t *drm_find_matching_map(drm_device_t *dev, |
57 | ++order; | 52 | drm_local_map_t *map) |
53 | { | ||
54 | struct list_head *list; | ||
58 | 55 | ||
59 | return order; | 56 | list_for_each(list, &dev->maplist->head) { |
57 | drm_map_list_t *entry = list_entry(list, drm_map_list_t, head); | ||
58 | if (entry->map && map->type == entry->map->type && | ||
59 | entry->map->offset == map->offset) { | ||
60 | return entry->map; | ||
61 | } | ||
62 | } | ||
63 | |||
64 | return NULL; | ||
60 | } | 65 | } |
61 | EXPORT_SYMBOL(drm_order); | ||
62 | 66 | ||
63 | #ifdef CONFIG_COMPAT | 67 | #ifdef CONFIG_COMPAT |
64 | /* | 68 | /* |
@@ -82,25 +86,23 @@ static unsigned int map32_handle = 0x10000000; | |||
82 | * type. Adds the map to the map list drm_device::maplist. Adds MTRR's where | 86 | * type. Adds the map to the map list drm_device::maplist. Adds MTRR's where |
83 | * applicable and if supported by the kernel. | 87 | * applicable and if supported by the kernel. |
84 | */ | 88 | */ |
85 | int drm_addmap( struct inode *inode, struct file *filp, | 89 | int drm_addmap(drm_device_t * dev, unsigned int offset, |
86 | unsigned int cmd, unsigned long arg ) | 90 | unsigned int size, drm_map_type_t type, |
91 | drm_map_flags_t flags, drm_local_map_t ** map_ptr) | ||
87 | { | 92 | { |
88 | drm_file_t *priv = filp->private_data; | ||
89 | drm_device_t *dev = priv->head->dev; | ||
90 | drm_map_t *map; | 93 | drm_map_t *map; |
91 | drm_map_t __user *argp = (void __user *)arg; | ||
92 | drm_map_list_t *list; | 94 | drm_map_list_t *list; |
93 | 95 | drm_dma_handle_t *dmah; | |
94 | if ( !(filp->f_mode & 3) ) return -EACCES; /* Require read/write */ | 96 | drm_local_map_t *found_map; |
95 | 97 | ||
96 | map = drm_alloc( sizeof(*map), DRM_MEM_MAPS ); | 98 | map = drm_alloc( sizeof(*map), DRM_MEM_MAPS ); |
97 | if ( !map ) | 99 | if ( !map ) |
98 | return -ENOMEM; | 100 | return -ENOMEM; |
99 | 101 | ||
100 | if ( copy_from_user( map, argp, sizeof(*map) ) ) { | 102 | map->offset = offset; |
101 | drm_free( map, sizeof(*map), DRM_MEM_MAPS ); | 103 | map->size = size; |
102 | return -EFAULT; | 104 | map->flags = flags; |
103 | } | 105 | map->type = type; |
104 | 106 | ||
105 | /* Only allow shared memory to be removable since we only keep enough | 107 | /* Only allow shared memory to be removable since we only keep enough |
106 | * book keeping information about shared memory to allow for removal | 108 | * book keeping information about shared memory to allow for removal |
@@ -132,6 +134,24 @@ int drm_addmap( struct inode *inode, struct file *filp, | |||
132 | #ifdef __alpha__ | 134 | #ifdef __alpha__ |
133 | map->offset += dev->hose->mem_space->start; | 135 | map->offset += dev->hose->mem_space->start; |
134 | #endif | 136 | #endif |
137 | /* Some drivers preinitialize some maps, without the X Server | ||
138 | * needing to be aware of it. Therefore, we just return success | ||
139 | * when the server tries to create a duplicate map. | ||
140 | */ | ||
141 | found_map = drm_find_matching_map(dev, map); | ||
142 | if (found_map != NULL) { | ||
143 | if (found_map->size != map->size) { | ||
144 | DRM_DEBUG("Matching maps of type %d with " | ||
145 | "mismatched sizes, (%ld vs %ld)\n", | ||
146 | map->type, map->size, found_map->size); | ||
147 | found_map->size = map->size; | ||
148 | } | ||
149 | |||
150 | drm_free(map, sizeof(*map), DRM_MEM_MAPS); | ||
151 | *map_ptr = found_map; | ||
152 | return 0; | ||
153 | } | ||
154 | |||
135 | if (drm_core_has_MTRR(dev)) { | 155 | if (drm_core_has_MTRR(dev)) { |
136 | if ( map->type == _DRM_FRAME_BUFFER || | 156 | if ( map->type == _DRM_FRAME_BUFFER || |
137 | (map->flags & _DRM_WRITE_COMBINING) ) { | 157 | (map->flags & _DRM_WRITE_COMBINING) ) { |
@@ -180,7 +200,20 @@ int drm_addmap( struct inode *inode, struct file *filp, | |||
180 | } | 200 | } |
181 | map->offset += dev->sg->handle; | 201 | map->offset += dev->sg->handle; |
182 | break; | 202 | break; |
183 | 203 | case _DRM_CONSISTENT: | |
204 | /* dma_addr_t is 64bit on i386 with CONFIG_HIGHMEM64G, | ||
205 | * As we're limiting the address to 2^32-1 (or less), | ||
206 | * casting it down to 32 bits is no problem, but we | ||
207 | * need to point to a 64bit variable first. */ | ||
208 | dmah = drm_pci_alloc(dev, map->size, map->size, 0xffffffffUL); | ||
209 | if (!dmah) { | ||
210 | drm_free(map, sizeof(*map), DRM_MEM_MAPS); | ||
211 | return -ENOMEM; | ||
212 | } | ||
213 | map->handle = dmah->vaddr; | ||
214 | map->offset = (unsigned long)dmah->busaddr; | ||
215 | kfree(dmah); | ||
216 | break; | ||
184 | default: | 217 | default: |
185 | drm_free( map, sizeof(*map), DRM_MEM_MAPS ); | 218 | drm_free( map, sizeof(*map), DRM_MEM_MAPS ); |
186 | return -EINVAL; | 219 | return -EINVAL; |
@@ -204,10 +237,42 @@ int drm_addmap( struct inode *inode, struct file *filp, | |||
204 | #endif | 237 | #endif |
205 | up(&dev->struct_sem); | 238 | up(&dev->struct_sem); |
206 | 239 | ||
207 | if ( copy_to_user( argp, map, sizeof(*map) ) ) | 240 | *map_ptr = map; |
241 | return 0; | ||
242 | } | ||
243 | EXPORT_SYMBOL(drm_addmap); | ||
244 | |||
245 | int drm_addmap_ioctl(struct inode *inode, struct file *filp, | ||
246 | unsigned int cmd, unsigned long arg) | ||
247 | { | ||
248 | drm_file_t *priv = filp->private_data; | ||
249 | drm_device_t *dev = priv->head->dev; | ||
250 | drm_map_t map; | ||
251 | drm_map_t *map_ptr; | ||
252 | drm_map_t __user *argp = (void __user *)arg; | ||
253 | int err; | ||
254 | |||
255 | if (!(filp->f_mode & 3)) | ||
256 | return -EACCES; /* Require read/write */ | ||
257 | |||
258 | if (copy_from_user(& map, argp, sizeof(map))) { | ||
208 | return -EFAULT; | 259 | return -EFAULT; |
209 | if (copy_to_user(&argp->handle, &map->offset, sizeof(map->offset))) | 260 | } |
261 | |||
262 | err = drm_addmap( dev, map.offset, map.size, map.type, map.flags, | ||
263 | &map_ptr ); | ||
264 | |||
265 | if (err) { | ||
266 | return err; | ||
267 | } | ||
268 | |||
269 | if (copy_to_user(argp, map_ptr, sizeof(*map_ptr))) | ||
210 | return -EFAULT; | 270 | return -EFAULT; |
271 | if (map_ptr->type != _DRM_SHM) { | ||
272 | if (copy_to_user(&argp->handle, &map_ptr->offset, | ||
273 | sizeof(map_ptr->offset))) | ||
274 | return -EFAULT; | ||
275 | } | ||
211 | return 0; | 276 | return 0; |
212 | } | 277 | } |
213 | 278 | ||
@@ -226,81 +291,138 @@ int drm_addmap( struct inode *inode, struct file *filp, | |||
226 | * its being used, and free any associate resource (such as MTRR's) if it's not | 291 | * its being used, and free any associate resource (such as MTRR's) if it's not |
227 | * being on use. | 292 | * being on use. |
228 | * | 293 | * |
229 | * \sa addmap(). | 294 | * \sa drm_addmap |
230 | */ | 295 | */ |
231 | int drm_rmmap(struct inode *inode, struct file *filp, | 296 | int drm_rmmap_locked(drm_device_t *dev, drm_local_map_t *map) |
232 | unsigned int cmd, unsigned long arg) | ||
233 | { | 297 | { |
234 | drm_file_t *priv = filp->private_data; | ||
235 | drm_device_t *dev = priv->head->dev; | ||
236 | struct list_head *list; | 298 | struct list_head *list; |
237 | drm_map_list_t *r_list = NULL; | 299 | drm_map_list_t *r_list = NULL; |
238 | drm_vma_entry_t *pt, *prev; | 300 | drm_dma_handle_t dmah; |
239 | drm_map_t *map; | 301 | |
302 | /* Find the list entry for the map and remove it */ | ||
303 | list_for_each(list, &dev->maplist->head) { | ||
304 | r_list = list_entry(list, drm_map_list_t, head); | ||
305 | |||
306 | if (r_list->map == map) { | ||
307 | list_del(list); | ||
308 | drm_free(list, sizeof(*list), DRM_MEM_MAPS); | ||
309 | break; | ||
310 | } | ||
311 | } | ||
312 | |||
313 | /* List has wrapped around to the head pointer, or it's empty and we | ||
314 | * didn't find anything. | ||
315 | */ | ||
316 | if (list == (&dev->maplist->head)) { | ||
317 | return -EINVAL; | ||
318 | } | ||
319 | |||
320 | switch (map->type) { | ||
321 | case _DRM_REGISTERS: | ||
322 | drm_ioremapfree(map->handle, map->size, dev); | ||
323 | /* FALLTHROUGH */ | ||
324 | case _DRM_FRAME_BUFFER: | ||
325 | if (drm_core_has_MTRR(dev) && map->mtrr >= 0) { | ||
326 | int retcode; | ||
327 | retcode = mtrr_del(map->mtrr, map->offset, | ||
328 | map->size); | ||
329 | DRM_DEBUG ("mtrr_del=%d\n", retcode); | ||
330 | } | ||
331 | break; | ||
332 | case _DRM_SHM: | ||
333 | vfree(map->handle); | ||
334 | break; | ||
335 | case _DRM_AGP: | ||
336 | case _DRM_SCATTER_GATHER: | ||
337 | break; | ||
338 | case _DRM_CONSISTENT: | ||
339 | dmah.vaddr = map->handle; | ||
340 | dmah.busaddr = map->offset; | ||
341 | dmah.size = map->size; | ||
342 | __drm_pci_free(dev, &dmah); | ||
343 | break; | ||
344 | } | ||
345 | drm_free(map, sizeof(*map), DRM_MEM_MAPS); | ||
346 | |||
347 | return 0; | ||
348 | } | ||
349 | EXPORT_SYMBOL(drm_rmmap_locked); | ||
350 | |||
351 | int drm_rmmap(drm_device_t *dev, drm_local_map_t *map) | ||
352 | { | ||
353 | int ret; | ||
354 | |||
355 | down(&dev->struct_sem); | ||
356 | ret = drm_rmmap_locked(dev, map); | ||
357 | up(&dev->struct_sem); | ||
358 | |||
359 | return ret; | ||
360 | } | ||
361 | EXPORT_SYMBOL(drm_rmmap); | ||
362 | |||
363 | /* The rmmap ioctl appears to be unnecessary. All mappings are torn down on | ||
364 | * the last close of the device, and this is necessary for cleanup when things | ||
365 | * exit uncleanly. Therefore, having userland manually remove mappings seems | ||
366 | * like a pointless exercise since they're going away anyway. | ||
367 | * | ||
368 | * One use case might be after addmap is allowed for normal users for SHM and | ||
369 | * gets used by drivers that the server doesn't need to care about. This seems | ||
370 | * unlikely. | ||
371 | */ | ||
372 | int drm_rmmap_ioctl(struct inode *inode, struct file *filp, | ||
373 | unsigned int cmd, unsigned long arg) | ||
374 | { | ||
375 | drm_file_t *priv = filp->private_data; | ||
376 | drm_device_t *dev = priv->head->dev; | ||
240 | drm_map_t request; | 377 | drm_map_t request; |
241 | int found_maps = 0; | 378 | drm_local_map_t *map = NULL; |
379 | struct list_head *list; | ||
380 | int ret; | ||
242 | 381 | ||
243 | if (copy_from_user(&request, (drm_map_t __user *)arg, | 382 | if (copy_from_user(&request, (drm_map_t __user *)arg, sizeof(request))) { |
244 | sizeof(request))) { | ||
245 | return -EFAULT; | 383 | return -EFAULT; |
246 | } | 384 | } |
247 | 385 | ||
248 | down(&dev->struct_sem); | 386 | down(&dev->struct_sem); |
249 | list = &dev->maplist->head; | ||
250 | list_for_each(list, &dev->maplist->head) { | 387 | list_for_each(list, &dev->maplist->head) { |
251 | r_list = list_entry(list, drm_map_list_t, head); | 388 | drm_map_list_t *r_list = list_entry(list, drm_map_list_t, head); |
252 | 389 | ||
253 | if(r_list->map && | 390 | if (r_list->map && |
254 | r_list->map->offset == (unsigned long) request.handle && | 391 | r_list->map->handle == request.handle && |
255 | r_list->map->flags & _DRM_REMOVABLE) break; | 392 | r_list->map->flags & _DRM_REMOVABLE) { |
393 | map = r_list->map; | ||
394 | break; | ||
395 | } | ||
256 | } | 396 | } |
257 | 397 | ||
258 | /* List has wrapped around to the head pointer, or its empty we didn't | 398 | /* List has wrapped around to the head pointer, or its empty we didn't |
259 | * find anything. | 399 | * find anything. |
260 | */ | 400 | */ |
261 | if(list == (&dev->maplist->head)) { | 401 | if (list == (&dev->maplist->head)) { |
262 | up(&dev->struct_sem); | 402 | up(&dev->struct_sem); |
263 | return -EINVAL; | 403 | return -EINVAL; |
264 | } | 404 | } |
265 | map = r_list->map; | ||
266 | list_del(list); | ||
267 | drm_free(list, sizeof(*list), DRM_MEM_MAPS); | ||
268 | 405 | ||
269 | for (pt = dev->vmalist, prev = NULL; pt; prev = pt, pt = pt->next) { | 406 | if (!map) |
270 | if (pt->vma->vm_private_data == map) found_maps++; | 407 | return -EINVAL; |
271 | } | ||
272 | 408 | ||
273 | if(!found_maps) { | 409 | /* Register and framebuffer maps are permanent */ |
274 | switch (map->type) { | 410 | if ((map->type == _DRM_REGISTERS) || (map->type == _DRM_FRAME_BUFFER)) { |
275 | case _DRM_REGISTERS: | 411 | up(&dev->struct_sem); |
276 | case _DRM_FRAME_BUFFER: | 412 | return 0; |
277 | if (drm_core_has_MTRR(dev)) { | ||
278 | if (map->mtrr >= 0) { | ||
279 | int retcode; | ||
280 | retcode = mtrr_del(map->mtrr, | ||
281 | map->offset, | ||
282 | map->size); | ||
283 | DRM_DEBUG("mtrr_del = %d\n", retcode); | ||
284 | } | ||
285 | } | ||
286 | drm_ioremapfree(map->handle, map->size, dev); | ||
287 | break; | ||
288 | case _DRM_SHM: | ||
289 | vfree(map->handle); | ||
290 | break; | ||
291 | case _DRM_AGP: | ||
292 | case _DRM_SCATTER_GATHER: | ||
293 | break; | ||
294 | } | ||
295 | drm_free(map, sizeof(*map), DRM_MEM_MAPS); | ||
296 | } | 413 | } |
414 | |||
415 | ret = drm_rmmap_locked(dev, map); | ||
416 | |||
297 | up(&dev->struct_sem); | 417 | up(&dev->struct_sem); |
298 | return 0; | 418 | |
419 | return ret; | ||
299 | } | 420 | } |
300 | 421 | ||
301 | /** | 422 | /** |
302 | * Cleanup after an error on one of the addbufs() functions. | 423 | * Cleanup after an error on one of the addbufs() functions. |
303 | * | 424 | * |
425 | * \param dev DRM device. | ||
304 | * \param entry buffer entry where the error occurred. | 426 | * \param entry buffer entry where the error occurred. |
305 | * | 427 | * |
306 | * Frees any pages and buffers associated with the given entry. | 428 | * Frees any pages and buffers associated with the given entry. |
@@ -344,25 +466,19 @@ static void drm_cleanup_buf_error(drm_device_t *dev, drm_buf_entry_t *entry) | |||
344 | 466 | ||
345 | #if __OS_HAS_AGP | 467 | #if __OS_HAS_AGP |
346 | /** | 468 | /** |
347 | * Add AGP buffers for DMA transfers (ioctl). | 469 | * Add AGP buffers for DMA transfers. |
348 | * | 470 | * |
349 | * \param inode device inode. | 471 | * \param dev drm_device_t to which the buffers are to be added. |
350 | * \param filp file pointer. | 472 | * \param request pointer to a drm_buf_desc_t describing the request. |
351 | * \param cmd command. | ||
352 | * \param arg pointer to a drm_buf_desc_t request. | ||
353 | * \return zero on success or a negative number on failure. | 473 | * \return zero on success or a negative number on failure. |
354 | * | 474 | * |
355 | * After some sanity checks creates a drm_buf structure for each buffer and | 475 | * After some sanity checks creates a drm_buf structure for each buffer and |
356 | * reallocates the buffer list of the same size order to accommodate the new | 476 | * reallocates the buffer list of the same size order to accommodate the new |
357 | * buffers. | 477 | * buffers. |
358 | */ | 478 | */ |
359 | static int drm_addbufs_agp( struct inode *inode, struct file *filp, | 479 | int drm_addbufs_agp(drm_device_t *dev, drm_buf_desc_t *request) |
360 | unsigned int cmd, unsigned long arg ) | ||
361 | { | 480 | { |
362 | drm_file_t *priv = filp->private_data; | ||
363 | drm_device_t *dev = priv->head->dev; | ||
364 | drm_device_dma_t *dma = dev->dma; | 481 | drm_device_dma_t *dma = dev->dma; |
365 | drm_buf_desc_t request; | ||
366 | drm_buf_entry_t *entry; | 482 | drm_buf_entry_t *entry; |
367 | drm_buf_t *buf; | 483 | drm_buf_t *buf; |
368 | unsigned long offset; | 484 | unsigned long offset; |
@@ -376,25 +492,20 @@ static int drm_addbufs_agp( struct inode *inode, struct file *filp, | |||
376 | int byte_count; | 492 | int byte_count; |
377 | int i; | 493 | int i; |
378 | drm_buf_t **temp_buflist; | 494 | drm_buf_t **temp_buflist; |
379 | drm_buf_desc_t __user *argp = (void __user *)arg; | ||
380 | 495 | ||
381 | if ( !dma ) return -EINVAL; | 496 | if ( !dma ) return -EINVAL; |
382 | 497 | ||
383 | if ( copy_from_user( &request, argp, | 498 | count = request->count; |
384 | sizeof(request) ) ) | 499 | order = drm_order(request->size); |
385 | return -EFAULT; | ||
386 | |||
387 | count = request.count; | ||
388 | order = drm_order( request.size ); | ||
389 | size = 1 << order; | 500 | size = 1 << order; |
390 | 501 | ||
391 | alignment = (request.flags & _DRM_PAGE_ALIGN) | 502 | alignment = (request->flags & _DRM_PAGE_ALIGN) |
392 | ? PAGE_ALIGN(size) : size; | 503 | ? PAGE_ALIGN(size) : size; |
393 | page_order = order - PAGE_SHIFT > 0 ? order - PAGE_SHIFT : 0; | 504 | page_order = order - PAGE_SHIFT > 0 ? order - PAGE_SHIFT : 0; |
394 | total = PAGE_SIZE << page_order; | 505 | total = PAGE_SIZE << page_order; |
395 | 506 | ||
396 | byte_count = 0; | 507 | byte_count = 0; |
397 | agp_offset = dev->agp->base + request.agp_start; | 508 | agp_offset = dev->agp->base + request->agp_start; |
398 | 509 | ||
399 | DRM_DEBUG( "count: %d\n", count ); | 510 | DRM_DEBUG( "count: %d\n", count ); |
400 | DRM_DEBUG( "order: %d\n", order ); | 511 | DRM_DEBUG( "order: %d\n", order ); |
@@ -508,26 +619,20 @@ static int drm_addbufs_agp( struct inode *inode, struct file *filp, | |||
508 | 619 | ||
509 | up( &dev->struct_sem ); | 620 | up( &dev->struct_sem ); |
510 | 621 | ||
511 | request.count = entry->buf_count; | 622 | request->count = entry->buf_count; |
512 | request.size = size; | 623 | request->size = size; |
513 | |||
514 | if ( copy_to_user( argp, &request, sizeof(request) ) ) | ||
515 | return -EFAULT; | ||
516 | 624 | ||
517 | dma->flags = _DRM_DMA_USE_AGP; | 625 | dma->flags = _DRM_DMA_USE_AGP; |
518 | 626 | ||
519 | atomic_dec( &dev->buf_alloc ); | 627 | atomic_dec( &dev->buf_alloc ); |
520 | return 0; | 628 | return 0; |
521 | } | 629 | } |
630 | EXPORT_SYMBOL(drm_addbufs_agp); | ||
522 | #endif /* __OS_HAS_AGP */ | 631 | #endif /* __OS_HAS_AGP */ |
523 | 632 | ||
524 | static int drm_addbufs_pci( struct inode *inode, struct file *filp, | 633 | int drm_addbufs_pci(drm_device_t *dev, drm_buf_desc_t *request) |
525 | unsigned int cmd, unsigned long arg ) | ||
526 | { | 634 | { |
527 | drm_file_t *priv = filp->private_data; | ||
528 | drm_device_t *dev = priv->head->dev; | ||
529 | drm_device_dma_t *dma = dev->dma; | 635 | drm_device_dma_t *dma = dev->dma; |
530 | drm_buf_desc_t request; | ||
531 | int count; | 636 | int count; |
532 | int order; | 637 | int order; |
533 | int size; | 638 | int size; |
@@ -543,26 +648,22 @@ static int drm_addbufs_pci( struct inode *inode, struct file *filp, | |||
543 | int page_count; | 648 | int page_count; |
544 | unsigned long *temp_pagelist; | 649 | unsigned long *temp_pagelist; |
545 | drm_buf_t **temp_buflist; | 650 | drm_buf_t **temp_buflist; |
546 | drm_buf_desc_t __user *argp = (void __user *)arg; | ||
547 | 651 | ||
548 | if (!drm_core_check_feature(dev, DRIVER_PCI_DMA)) return -EINVAL; | 652 | if (!drm_core_check_feature(dev, DRIVER_PCI_DMA)) return -EINVAL; |
549 | if ( !dma ) return -EINVAL; | 653 | if ( !dma ) return -EINVAL; |
550 | 654 | ||
551 | if ( copy_from_user( &request, argp, sizeof(request) ) ) | 655 | count = request->count; |
552 | return -EFAULT; | 656 | order = drm_order(request->size); |
553 | |||
554 | count = request.count; | ||
555 | order = drm_order( request.size ); | ||
556 | size = 1 << order; | 657 | size = 1 << order; |
557 | 658 | ||
558 | DRM_DEBUG( "count=%d, size=%d (%d), order=%d, queue_count=%d\n", | 659 | DRM_DEBUG( "count=%d, size=%d (%d), order=%d, queue_count=%d\n", |
559 | request.count, request.size, size, | 660 | request->count, request->size, size, |
560 | order, dev->queue_count ); | 661 | order, dev->queue_count ); |
561 | 662 | ||
562 | if ( order < DRM_MIN_ORDER || order > DRM_MAX_ORDER ) return -EINVAL; | 663 | if ( order < DRM_MIN_ORDER || order > DRM_MAX_ORDER ) return -EINVAL; |
563 | if ( dev->queue_count ) return -EBUSY; /* Not while in use */ | 664 | if ( dev->queue_count ) return -EBUSY; /* Not while in use */ |
564 | 665 | ||
565 | alignment = (request.flags & _DRM_PAGE_ALIGN) | 666 | alignment = (request->flags & _DRM_PAGE_ALIGN) |
566 | ? PAGE_ALIGN(size) : size; | 667 | ? PAGE_ALIGN(size) : size; |
567 | page_order = order - PAGE_SHIFT > 0 ? order - PAGE_SHIFT : 0; | 668 | page_order = order - PAGE_SHIFT > 0 ? order - PAGE_SHIFT : 0; |
568 | total = PAGE_SIZE << page_order; | 669 | total = PAGE_SIZE << page_order; |
@@ -740,25 +841,18 @@ static int drm_addbufs_pci( struct inode *inode, struct file *filp, | |||
740 | 841 | ||
741 | up( &dev->struct_sem ); | 842 | up( &dev->struct_sem ); |
742 | 843 | ||
743 | request.count = entry->buf_count; | 844 | request->count = entry->buf_count; |
744 | request.size = size; | 845 | request->size = size; |
745 | |||
746 | if ( copy_to_user( argp, &request, sizeof(request) ) ) | ||
747 | return -EFAULT; | ||
748 | 846 | ||
749 | atomic_dec( &dev->buf_alloc ); | 847 | atomic_dec( &dev->buf_alloc ); |
750 | return 0; | 848 | return 0; |
751 | 849 | ||
752 | } | 850 | } |
851 | EXPORT_SYMBOL(drm_addbufs_pci); | ||
753 | 852 | ||
754 | static int drm_addbufs_sg( struct inode *inode, struct file *filp, | 853 | static int drm_addbufs_sg(drm_device_t *dev, drm_buf_desc_t *request) |
755 | unsigned int cmd, unsigned long arg ) | ||
756 | { | 854 | { |
757 | drm_file_t *priv = filp->private_data; | ||
758 | drm_device_t *dev = priv->head->dev; | ||
759 | drm_device_dma_t *dma = dev->dma; | 855 | drm_device_dma_t *dma = dev->dma; |
760 | drm_buf_desc_t __user *argp = (void __user *)arg; | ||
761 | drm_buf_desc_t request; | ||
762 | drm_buf_entry_t *entry; | 856 | drm_buf_entry_t *entry; |
763 | drm_buf_t *buf; | 857 | drm_buf_t *buf; |
764 | unsigned long offset; | 858 | unsigned long offset; |
@@ -777,20 +871,17 @@ static int drm_addbufs_sg( struct inode *inode, struct file *filp, | |||
777 | 871 | ||
778 | if ( !dma ) return -EINVAL; | 872 | if ( !dma ) return -EINVAL; |
779 | 873 | ||
780 | if ( copy_from_user( &request, argp, sizeof(request) ) ) | 874 | count = request->count; |
781 | return -EFAULT; | 875 | order = drm_order(request->size); |
782 | |||
783 | count = request.count; | ||
784 | order = drm_order( request.size ); | ||
785 | size = 1 << order; | 876 | size = 1 << order; |
786 | 877 | ||
787 | alignment = (request.flags & _DRM_PAGE_ALIGN) | 878 | alignment = (request->flags & _DRM_PAGE_ALIGN) |
788 | ? PAGE_ALIGN(size) : size; | 879 | ? PAGE_ALIGN(size) : size; |
789 | page_order = order - PAGE_SHIFT > 0 ? order - PAGE_SHIFT : 0; | 880 | page_order = order - PAGE_SHIFT > 0 ? order - PAGE_SHIFT : 0; |
790 | total = PAGE_SIZE << page_order; | 881 | total = PAGE_SIZE << page_order; |
791 | 882 | ||
792 | byte_count = 0; | 883 | byte_count = 0; |
793 | agp_offset = request.agp_start; | 884 | agp_offset = request->agp_start; |
794 | 885 | ||
795 | DRM_DEBUG( "count: %d\n", count ); | 886 | DRM_DEBUG( "count: %d\n", count ); |
796 | DRM_DEBUG( "order: %d\n", order ); | 887 | DRM_DEBUG( "order: %d\n", order ); |
@@ -905,11 +996,8 @@ static int drm_addbufs_sg( struct inode *inode, struct file *filp, | |||
905 | 996 | ||
906 | up( &dev->struct_sem ); | 997 | up( &dev->struct_sem ); |
907 | 998 | ||
908 | request.count = entry->buf_count; | 999 | request->count = entry->buf_count; |
909 | request.size = size; | 1000 | request->size = size; |
910 | |||
911 | if ( copy_to_user( argp, &request, sizeof(request) ) ) | ||
912 | return -EFAULT; | ||
913 | 1001 | ||
914 | dma->flags = _DRM_DMA_USE_SG; | 1002 | dma->flags = _DRM_DMA_USE_SG; |
915 | 1003 | ||
@@ -917,6 +1005,161 @@ static int drm_addbufs_sg( struct inode *inode, struct file *filp, | |||
917 | return 0; | 1005 | return 0; |
918 | } | 1006 | } |
919 | 1007 | ||
1008 | int drm_addbufs_fb(drm_device_t *dev, drm_buf_desc_t *request) | ||
1009 | { | ||
1010 | drm_device_dma_t *dma = dev->dma; | ||
1011 | drm_buf_entry_t *entry; | ||
1012 | drm_buf_t *buf; | ||
1013 | unsigned long offset; | ||
1014 | unsigned long agp_offset; | ||
1015 | int count; | ||
1016 | int order; | ||
1017 | int size; | ||
1018 | int alignment; | ||
1019 | int page_order; | ||
1020 | int total; | ||
1021 | int byte_count; | ||
1022 | int i; | ||
1023 | drm_buf_t **temp_buflist; | ||
1024 | |||
1025 | if (!drm_core_check_feature(dev, DRIVER_FB_DMA)) | ||
1026 | return -EINVAL; | ||
1027 | |||
1028 | if (!dma) | ||
1029 | return -EINVAL; | ||
1030 | |||
1031 | count = request->count; | ||
1032 | order = drm_order(request->size); | ||
1033 | size = 1 << order; | ||
1034 | |||
1035 | alignment = (request->flags & _DRM_PAGE_ALIGN) | ||
1036 | ? PAGE_ALIGN(size) : size; | ||
1037 | page_order = order - PAGE_SHIFT > 0 ? order - PAGE_SHIFT : 0; | ||
1038 | total = PAGE_SIZE << page_order; | ||
1039 | |||
1040 | byte_count = 0; | ||
1041 | agp_offset = request->agp_start; | ||
1042 | |||
1043 | DRM_DEBUG("count: %d\n", count); | ||
1044 | DRM_DEBUG("order: %d\n", order); | ||
1045 | DRM_DEBUG("size: %d\n", size); | ||
1046 | DRM_DEBUG("agp_offset: %lu\n", agp_offset); | ||
1047 | DRM_DEBUG("alignment: %d\n", alignment); | ||
1048 | DRM_DEBUG("page_order: %d\n", page_order); | ||
1049 | DRM_DEBUG("total: %d\n", total); | ||
1050 | |||
1051 | if (order < DRM_MIN_ORDER || order > DRM_MAX_ORDER) | ||
1052 | return -EINVAL; | ||
1053 | if (dev->queue_count) | ||
1054 | return -EBUSY; /* Not while in use */ | ||
1055 | |||
1056 | spin_lock(&dev->count_lock); | ||
1057 | if (dev->buf_use) { | ||
1058 | spin_unlock(&dev->count_lock); | ||
1059 | return -EBUSY; | ||
1060 | } | ||
1061 | atomic_inc(&dev->buf_alloc); | ||
1062 | spin_unlock(&dev->count_lock); | ||
1063 | |||
1064 | down(&dev->struct_sem); | ||
1065 | entry = &dma->bufs[order]; | ||
1066 | if (entry->buf_count) { | ||
1067 | up(&dev->struct_sem); | ||
1068 | atomic_dec(&dev->buf_alloc); | ||
1069 | return -ENOMEM; /* May only call once for each order */ | ||
1070 | } | ||
1071 | |||
1072 | if (count < 0 || count > 4096) { | ||
1073 | up(&dev->struct_sem); | ||
1074 | atomic_dec(&dev->buf_alloc); | ||
1075 | return -EINVAL; | ||
1076 | } | ||
1077 | |||
1078 | entry->buflist = drm_alloc(count * sizeof(*entry->buflist), | ||
1079 | DRM_MEM_BUFS); | ||
1080 | if (!entry->buflist) { | ||
1081 | up(&dev->struct_sem); | ||
1082 | atomic_dec(&dev->buf_alloc); | ||
1083 | return -ENOMEM; | ||
1084 | } | ||
1085 | memset(entry->buflist, 0, count * sizeof(*entry->buflist)); | ||
1086 | |||
1087 | entry->buf_size = size; | ||
1088 | entry->page_order = page_order; | ||
1089 | |||
1090 | offset = 0; | ||
1091 | |||
1092 | while (entry->buf_count < count) { | ||
1093 | buf = &entry->buflist[entry->buf_count]; | ||
1094 | buf->idx = dma->buf_count + entry->buf_count; | ||
1095 | buf->total = alignment; | ||
1096 | buf->order = order; | ||
1097 | buf->used = 0; | ||
1098 | |||
1099 | buf->offset = (dma->byte_count + offset); | ||
1100 | buf->bus_address = agp_offset + offset; | ||
1101 | buf->address = (void *)(agp_offset + offset); | ||
1102 | buf->next = NULL; | ||
1103 | buf->waiting = 0; | ||
1104 | buf->pending = 0; | ||
1105 | init_waitqueue_head(&buf->dma_wait); | ||
1106 | buf->filp = NULL; | ||
1107 | |||
1108 | buf->dev_priv_size = dev->driver->dev_priv_size; | ||
1109 | buf->dev_private = drm_alloc(buf->dev_priv_size, DRM_MEM_BUFS); | ||
1110 | if (!buf->dev_private) { | ||
1111 | /* Set count correctly so we free the proper amount. */ | ||
1112 | entry->buf_count = count; | ||
1113 | drm_cleanup_buf_error(dev, entry); | ||
1114 | up(&dev->struct_sem); | ||
1115 | atomic_dec(&dev->buf_alloc); | ||
1116 | return -ENOMEM; | ||
1117 | } | ||
1118 | memset(buf->dev_private, 0, buf->dev_priv_size); | ||
1119 | |||
1120 | DRM_DEBUG("buffer %d @ %p\n", entry->buf_count, buf->address); | ||
1121 | |||
1122 | offset += alignment; | ||
1123 | entry->buf_count++; | ||
1124 | byte_count += PAGE_SIZE << page_order; | ||
1125 | } | ||
1126 | |||
1127 | DRM_DEBUG("byte_count: %d\n", byte_count); | ||
1128 | |||
1129 | temp_buflist = drm_realloc(dma->buflist, | ||
1130 | dma->buf_count * sizeof(*dma->buflist), | ||
1131 | (dma->buf_count + entry->buf_count) | ||
1132 | * sizeof(*dma->buflist), DRM_MEM_BUFS); | ||
1133 | if (!temp_buflist) { | ||
1134 | /* Free the entry because it isn't valid */ | ||
1135 | drm_cleanup_buf_error(dev, entry); | ||
1136 | up(&dev->struct_sem); | ||
1137 | atomic_dec(&dev->buf_alloc); | ||
1138 | return -ENOMEM; | ||
1139 | } | ||
1140 | dma->buflist = temp_buflist; | ||
1141 | |||
1142 | for (i = 0; i < entry->buf_count; i++) { | ||
1143 | dma->buflist[i + dma->buf_count] = &entry->buflist[i]; | ||
1144 | } | ||
1145 | |||
1146 | dma->buf_count += entry->buf_count; | ||
1147 | dma->byte_count += byte_count; | ||
1148 | |||
1149 | DRM_DEBUG("dma->buf_count : %d\n", dma->buf_count); | ||
1150 | DRM_DEBUG("entry->buf_count : %d\n", entry->buf_count); | ||
1151 | |||
1152 | up(&dev->struct_sem); | ||
1153 | |||
1154 | request->count = entry->buf_count; | ||
1155 | request->size = size; | ||
1156 | |||
1157 | dma->flags = _DRM_DMA_USE_FB; | ||
1158 | |||
1159 | atomic_dec(&dev->buf_alloc); | ||
1160 | return 0; | ||
1161 | } | ||
1162 | |||
920 | /** | 1163 | /** |
921 | * Add buffers for DMA transfers (ioctl). | 1164 | * Add buffers for DMA transfers (ioctl). |
922 | * | 1165 | * |
@@ -937,6 +1180,7 @@ int drm_addbufs( struct inode *inode, struct file *filp, | |||
937 | drm_buf_desc_t request; | 1180 | drm_buf_desc_t request; |
938 | drm_file_t *priv = filp->private_data; | 1181 | drm_file_t *priv = filp->private_data; |
939 | drm_device_t *dev = priv->head->dev; | 1182 | drm_device_t *dev = priv->head->dev; |
1183 | int ret; | ||
940 | 1184 | ||
941 | if (!drm_core_check_feature(dev, DRIVER_HAVE_DMA)) | 1185 | if (!drm_core_check_feature(dev, DRIVER_HAVE_DMA)) |
942 | return -EINVAL; | 1186 | return -EINVAL; |
@@ -947,13 +1191,23 @@ int drm_addbufs( struct inode *inode, struct file *filp, | |||
947 | 1191 | ||
948 | #if __OS_HAS_AGP | 1192 | #if __OS_HAS_AGP |
949 | if ( request.flags & _DRM_AGP_BUFFER ) | 1193 | if ( request.flags & _DRM_AGP_BUFFER ) |
950 | return drm_addbufs_agp( inode, filp, cmd, arg ); | 1194 | ret=drm_addbufs_agp(dev, &request); |
951 | else | 1195 | else |
952 | #endif | 1196 | #endif |
953 | if ( request.flags & _DRM_SG_BUFFER ) | 1197 | if ( request.flags & _DRM_SG_BUFFER ) |
954 | return drm_addbufs_sg( inode, filp, cmd, arg ); | 1198 | ret=drm_addbufs_sg(dev, &request); |
1199 | else if ( request.flags & _DRM_FB_BUFFER) | ||
1200 | ret=drm_addbufs_fb(dev, &request); | ||
955 | else | 1201 | else |
956 | return drm_addbufs_pci( inode, filp, cmd, arg ); | 1202 | ret=drm_addbufs_pci(dev, &request); |
1203 | |||
1204 | if (ret==0) { | ||
1205 | if (copy_to_user((void __user *)arg, &request, | ||
1206 | sizeof(request))) { | ||
1207 | ret = -EFAULT; | ||
1208 | } | ||
1209 | } | ||
1210 | return ret; | ||
957 | } | 1211 | } |
958 | 1212 | ||
959 | 1213 | ||
@@ -1196,8 +1450,11 @@ int drm_mapbufs( struct inode *inode, struct file *filp, | |||
1196 | return -EFAULT; | 1450 | return -EFAULT; |
1197 | 1451 | ||
1198 | if ( request.count >= dma->buf_count ) { | 1452 | if ( request.count >= dma->buf_count ) { |
1199 | if ((drm_core_has_AGP(dev) && (dma->flags & _DRM_DMA_USE_AGP)) || | 1453 | if ((drm_core_has_AGP(dev) && (dma->flags & _DRM_DMA_USE_AGP)) |
1200 | (drm_core_check_feature(dev, DRIVER_SG) && (dma->flags & _DRM_DMA_USE_SG)) ) { | 1454 | || (drm_core_check_feature(dev, DRIVER_SG) |
1455 | && (dma->flags & _DRM_DMA_USE_SG)) | ||
1456 | || (drm_core_check_feature(dev, DRIVER_FB_DMA) | ||
1457 | && (dma->flags & _DRM_DMA_USE_FB))) { | ||
1201 | drm_map_t *map = dev->agp_buffer_map; | 1458 | drm_map_t *map = dev->agp_buffer_map; |
1202 | 1459 | ||
1203 | if ( !map ) { | 1460 | if ( !map ) { |
@@ -1279,3 +1536,26 @@ int drm_mapbufs( struct inode *inode, struct file *filp, | |||
1279 | return retcode; | 1536 | return retcode; |
1280 | } | 1537 | } |
1281 | 1538 | ||
1539 | /** | ||
1540 | * Compute size order. Returns the exponent of the smaller power of two which | ||
1541 | * is greater or equal to given number. | ||
1542 | * | ||
1543 | * \param size size. | ||
1544 | * \return order. | ||
1545 | * | ||
1546 | * \todo Can be made faster. | ||
1547 | */ | ||
1548 | int drm_order( unsigned long size ) | ||
1549 | { | ||
1550 | int order; | ||
1551 | unsigned long tmp; | ||
1552 | |||
1553 | for (order = 0, tmp = size >> 1; tmp; tmp >>= 1, order++) | ||
1554 | ; | ||
1555 | |||
1556 | if (size & (size - 1)) | ||
1557 | ++order; | ||
1558 | |||
1559 | return order; | ||
1560 | } | ||
1561 | EXPORT_SYMBOL(drm_order); | ||
diff --git a/drivers/char/drm/drm_drv.c b/drivers/char/drm/drm_drv.c index 3333c250c4d9..6ba48f346fcf 100644 --- a/drivers/char/drm/drm_drv.c +++ b/drivers/char/drm/drm_drv.c | |||
@@ -70,8 +70,8 @@ static drm_ioctl_desc_t drm_ioctls[] = { | |||
70 | [DRM_IOCTL_NR(DRM_IOCTL_UNBLOCK)] = { drm_noop, 1, 1 }, | 70 | [DRM_IOCTL_NR(DRM_IOCTL_UNBLOCK)] = { drm_noop, 1, 1 }, |
71 | [DRM_IOCTL_NR(DRM_IOCTL_AUTH_MAGIC)] = { drm_authmagic, 1, 1 }, | 71 | [DRM_IOCTL_NR(DRM_IOCTL_AUTH_MAGIC)] = { drm_authmagic, 1, 1 }, |
72 | 72 | ||
73 | [DRM_IOCTL_NR(DRM_IOCTL_ADD_MAP)] = { drm_addmap, 1, 1 }, | 73 | [DRM_IOCTL_NR(DRM_IOCTL_ADD_MAP)] = { drm_addmap_ioctl,1, 1 }, |
74 | [DRM_IOCTL_NR(DRM_IOCTL_RM_MAP)] = { drm_rmmap, 1, 0 }, | 74 | [DRM_IOCTL_NR(DRM_IOCTL_RM_MAP)] = { drm_rmmap_ioctl, 1, 0 }, |
75 | 75 | ||
76 | [DRM_IOCTL_NR(DRM_IOCTL_SET_SAREA_CTX)] = { drm_setsareactx, 1, 1 }, | 76 | [DRM_IOCTL_NR(DRM_IOCTL_SET_SAREA_CTX)] = { drm_setsareactx, 1, 1 }, |
77 | [DRM_IOCTL_NR(DRM_IOCTL_GET_SAREA_CTX)] = { drm_getsareactx, 1, 0 }, | 77 | [DRM_IOCTL_NR(DRM_IOCTL_GET_SAREA_CTX)] = { drm_getsareactx, 1, 0 }, |
@@ -102,10 +102,10 @@ static drm_ioctl_desc_t drm_ioctls[] = { | |||
102 | [DRM_IOCTL_NR(DRM_IOCTL_CONTROL)] = { drm_control, 1, 1 }, | 102 | [DRM_IOCTL_NR(DRM_IOCTL_CONTROL)] = { drm_control, 1, 1 }, |
103 | 103 | ||
104 | #if __OS_HAS_AGP | 104 | #if __OS_HAS_AGP |
105 | [DRM_IOCTL_NR(DRM_IOCTL_AGP_ACQUIRE)] = { drm_agp_acquire, 1, 1 }, | 105 | [DRM_IOCTL_NR(DRM_IOCTL_AGP_ACQUIRE)] = { drm_agp_acquire_ioctl, 1, 1 }, |
106 | [DRM_IOCTL_NR(DRM_IOCTL_AGP_RELEASE)] = { drm_agp_release, 1, 1 }, | 106 | [DRM_IOCTL_NR(DRM_IOCTL_AGP_RELEASE)] = { drm_agp_release_ioctl, 1, 1 }, |
107 | [DRM_IOCTL_NR(DRM_IOCTL_AGP_ENABLE)] = { drm_agp_enable, 1, 1 }, | 107 | [DRM_IOCTL_NR(DRM_IOCTL_AGP_ENABLE)] = { drm_agp_enable_ioctl, 1, 1 }, |
108 | [DRM_IOCTL_NR(DRM_IOCTL_AGP_INFO)] = { drm_agp_info, 1, 0 }, | 108 | [DRM_IOCTL_NR(DRM_IOCTL_AGP_INFO)] = { drm_agp_info_ioctl, 1, 0 }, |
109 | [DRM_IOCTL_NR(DRM_IOCTL_AGP_ALLOC)] = { drm_agp_alloc, 1, 1 }, | 109 | [DRM_IOCTL_NR(DRM_IOCTL_AGP_ALLOC)] = { drm_agp_alloc, 1, 1 }, |
110 | [DRM_IOCTL_NR(DRM_IOCTL_AGP_FREE)] = { drm_agp_free, 1, 1 }, | 110 | [DRM_IOCTL_NR(DRM_IOCTL_AGP_FREE)] = { drm_agp_free, 1, 1 }, |
111 | [DRM_IOCTL_NR(DRM_IOCTL_AGP_BIND)] = { drm_agp_bind, 1, 1 }, | 111 | [DRM_IOCTL_NR(DRM_IOCTL_AGP_BIND)] = { drm_agp_bind, 1, 1 }, |
@@ -127,14 +127,12 @@ static drm_ioctl_desc_t drm_ioctls[] = { | |||
127 | * | 127 | * |
128 | * Frees every resource in \p dev. | 128 | * Frees every resource in \p dev. |
129 | * | 129 | * |
130 | * \sa drm_device and setup(). | 130 | * \sa drm_device |
131 | */ | 131 | */ |
132 | int drm_takedown( drm_device_t *dev ) | 132 | int drm_takedown( drm_device_t *dev ) |
133 | { | 133 | { |
134 | drm_magic_entry_t *pt, *next; | 134 | drm_magic_entry_t *pt, *next; |
135 | drm_map_t *map; | ||
136 | drm_map_list_t *r_list; | 135 | drm_map_list_t *r_list; |
137 | struct list_head *list, *list_next; | ||
138 | drm_vma_entry_t *vma, *vma_next; | 136 | drm_vma_entry_t *vma, *vma_next; |
139 | int i; | 137 | int i; |
140 | 138 | ||
@@ -142,6 +140,7 @@ int drm_takedown( drm_device_t *dev ) | |||
142 | 140 | ||
143 | if (dev->driver->pretakedown) | 141 | if (dev->driver->pretakedown) |
144 | dev->driver->pretakedown(dev); | 142 | dev->driver->pretakedown(dev); |
143 | DRM_DEBUG("driver pretakedown completed\n"); | ||
145 | 144 | ||
146 | if (dev->unique) { | 145 | if (dev->unique) { |
147 | drm_free(dev->unique, strlen(dev->unique) + 1, DRM_MEM_DRIVER); | 146 | drm_free(dev->unique, strlen(dev->unique) + 1, DRM_MEM_DRIVER); |
@@ -178,11 +177,16 @@ int drm_takedown( drm_device_t *dev ) | |||
178 | } | 177 | } |
179 | dev->agp->memory = NULL; | 178 | dev->agp->memory = NULL; |
180 | 179 | ||
181 | if ( dev->agp->acquired ) drm_agp_do_release(dev); | 180 | if (dev->agp->acquired) |
181 | drm_agp_release(dev); | ||
182 | 182 | ||
183 | dev->agp->acquired = 0; | 183 | dev->agp->acquired = 0; |
184 | dev->agp->enabled = 0; | 184 | dev->agp->enabled = 0; |
185 | } | 185 | } |
186 | if (drm_core_check_feature(dev, DRIVER_SG) && dev->sg) { | ||
187 | drm_sg_cleanup(dev->sg); | ||
188 | dev->sg = NULL; | ||
189 | } | ||
186 | 190 | ||
187 | /* Clear vma list (only built for debugging) */ | 191 | /* Clear vma list (only built for debugging) */ |
188 | if ( dev->vmalist ) { | 192 | if ( dev->vmalist ) { |
@@ -194,48 +198,11 @@ int drm_takedown( drm_device_t *dev ) | |||
194 | } | 198 | } |
195 | 199 | ||
196 | if( dev->maplist ) { | 200 | if( dev->maplist ) { |
197 | list_for_each_safe( list, list_next, &dev->maplist->head ) { | 201 | while (!list_empty(&dev->maplist->head)) { |
198 | r_list = (drm_map_list_t *)list; | 202 | struct list_head *list = dev->maplist->head.next; |
199 | 203 | r_list = list_entry(list, drm_map_list_t, head); | |
200 | if ( ( map = r_list->map ) ) { | 204 | drm_rmmap_locked(dev, r_list->map); |
201 | switch ( map->type ) { | 205 | } |
202 | case _DRM_REGISTERS: | ||
203 | case _DRM_FRAME_BUFFER: | ||
204 | if (drm_core_has_MTRR(dev)) { | ||
205 | if ( map->mtrr >= 0 ) { | ||
206 | int retcode; | ||
207 | retcode = mtrr_del( map->mtrr, | ||
208 | map->offset, | ||
209 | map->size ); | ||
210 | DRM_DEBUG( "mtrr_del=%d\n", retcode ); | ||
211 | } | ||
212 | } | ||
213 | drm_ioremapfree( map->handle, map->size, dev ); | ||
214 | break; | ||
215 | case _DRM_SHM: | ||
216 | vfree(map->handle); | ||
217 | break; | ||
218 | |||
219 | case _DRM_AGP: | ||
220 | /* Do nothing here, because this is all | ||
221 | * handled in the AGP/GART driver. | ||
222 | */ | ||
223 | break; | ||
224 | case _DRM_SCATTER_GATHER: | ||
225 | /* Handle it */ | ||
226 | if (drm_core_check_feature(dev, DRIVER_SG) && dev->sg) { | ||
227 | drm_sg_cleanup(dev->sg); | ||
228 | dev->sg = NULL; | ||
229 | } | ||
230 | break; | ||
231 | } | ||
232 | drm_free(map, sizeof(*map), DRM_MEM_MAPS); | ||
233 | } | ||
234 | list_del( list ); | ||
235 | drm_free(r_list, sizeof(*r_list), DRM_MEM_MAPS); | ||
236 | } | ||
237 | drm_free(dev->maplist, sizeof(*dev->maplist), DRM_MEM_MAPS); | ||
238 | dev->maplist = NULL; | ||
239 | } | 206 | } |
240 | 207 | ||
241 | if (drm_core_check_feature(dev, DRIVER_DMA_QUEUE) && dev->queuelist ) { | 208 | if (drm_core_check_feature(dev, DRIVER_DMA_QUEUE) && dev->queuelist ) { |
@@ -264,6 +231,7 @@ int drm_takedown( drm_device_t *dev ) | |||
264 | } | 231 | } |
265 | up( &dev->struct_sem ); | 232 | up( &dev->struct_sem ); |
266 | 233 | ||
234 | DRM_DEBUG("takedown completed\n"); | ||
267 | return 0; | 235 | return 0; |
268 | } | 236 | } |
269 | 237 | ||
@@ -312,7 +280,7 @@ EXPORT_SYMBOL(drm_init); | |||
312 | * | 280 | * |
313 | * Cleans up all DRM device, calling takedown(). | 281 | * Cleans up all DRM device, calling takedown(). |
314 | * | 282 | * |
315 | * \sa drm_init(). | 283 | * \sa drm_init |
316 | */ | 284 | */ |
317 | static void drm_cleanup( drm_device_t *dev ) | 285 | static void drm_cleanup( drm_device_t *dev ) |
318 | { | 286 | { |
@@ -325,6 +293,11 @@ static void drm_cleanup( drm_device_t *dev ) | |||
325 | 293 | ||
326 | drm_takedown( dev ); | 294 | drm_takedown( dev ); |
327 | 295 | ||
296 | if (dev->maplist) { | ||
297 | drm_free(dev->maplist, sizeof(*dev->maplist), DRM_MEM_MAPS); | ||
298 | dev->maplist = NULL; | ||
299 | } | ||
300 | |||
328 | drm_ctxbitmap_cleanup( dev ); | 301 | drm_ctxbitmap_cleanup( dev ); |
329 | 302 | ||
330 | if (drm_core_has_MTRR(dev) && drm_core_has_AGP(dev) && | 303 | if (drm_core_has_MTRR(dev) && drm_core_has_AGP(dev) && |
diff --git a/drivers/char/drm/drm_fops.c b/drivers/char/drm/drm_fops.c index 10e64fde8d78..a1f4e9cd64ed 100644 --- a/drivers/char/drm/drm_fops.c +++ b/drivers/char/drm/drm_fops.c | |||
@@ -71,12 +71,6 @@ static int drm_setup( drm_device_t *dev ) | |||
71 | dev->magiclist[i].tail = NULL; | 71 | dev->magiclist[i].tail = NULL; |
72 | } | 72 | } |
73 | 73 | ||
74 | dev->maplist = drm_alloc(sizeof(*dev->maplist), | ||
75 | DRM_MEM_MAPS); | ||
76 | if(dev->maplist == NULL) return -ENOMEM; | ||
77 | memset(dev->maplist, 0, sizeof(*dev->maplist)); | ||
78 | INIT_LIST_HEAD(&dev->maplist->head); | ||
79 | |||
80 | dev->ctxlist = drm_alloc(sizeof(*dev->ctxlist), | 74 | dev->ctxlist = drm_alloc(sizeof(*dev->ctxlist), |
81 | DRM_MEM_CTXLIST); | 75 | DRM_MEM_CTXLIST); |
82 | if(dev->ctxlist == NULL) return -ENOMEM; | 76 | if(dev->ctxlist == NULL) return -ENOMEM; |
diff --git a/drivers/char/drm/drm_memory.c b/drivers/char/drm/drm_memory.c index ace3d42f4407..ff483fb418aa 100644 --- a/drivers/char/drm/drm_memory.c +++ b/drivers/char/drm/drm_memory.c | |||
@@ -142,27 +142,31 @@ void drm_free_pages(unsigned long address, int order, int area) | |||
142 | 142 | ||
143 | #if __OS_HAS_AGP | 143 | #if __OS_HAS_AGP |
144 | /** Wrapper around agp_allocate_memory() */ | 144 | /** Wrapper around agp_allocate_memory() */ |
145 | DRM_AGP_MEM *drm_alloc_agp(struct agp_bridge_data *bridge, int pages, u32 type) | 145 | DRM_AGP_MEM *drm_alloc_agp(drm_device_t *dev, int pages, u32 type) |
146 | { | 146 | { |
147 | return drm_agp_allocate_memory(bridge, pages, type); | 147 | return drm_agp_allocate_memory(dev->agp->bridge, pages, type); |
148 | } | 148 | } |
149 | EXPORT_SYMBOL(drm_alloc_agp); | ||
149 | 150 | ||
150 | /** Wrapper around agp_free_memory() */ | 151 | /** Wrapper around agp_free_memory() */ |
151 | int drm_free_agp(DRM_AGP_MEM *handle, int pages) | 152 | int drm_free_agp(DRM_AGP_MEM *handle, int pages) |
152 | { | 153 | { |
153 | return drm_agp_free_memory(handle) ? 0 : -EINVAL; | 154 | return drm_agp_free_memory(handle) ? 0 : -EINVAL; |
154 | } | 155 | } |
156 | EXPORT_SYMBOL(drm_free_agp); | ||
155 | 157 | ||
156 | /** Wrapper around agp_bind_memory() */ | 158 | /** Wrapper around agp_bind_memory() */ |
157 | int drm_bind_agp(DRM_AGP_MEM *handle, unsigned int start) | 159 | int drm_bind_agp(DRM_AGP_MEM *handle, unsigned int start) |
158 | { | 160 | { |
159 | return drm_agp_bind_memory(handle, start); | 161 | return drm_agp_bind_memory(handle, start); |
160 | } | 162 | } |
163 | EXPORT_SYMBOL(drm_bind_agp); | ||
161 | 164 | ||
162 | /** Wrapper around agp_unbind_memory() */ | 165 | /** Wrapper around agp_unbind_memory() */ |
163 | int drm_unbind_agp(DRM_AGP_MEM *handle) | 166 | int drm_unbind_agp(DRM_AGP_MEM *handle) |
164 | { | 167 | { |
165 | return drm_agp_unbind_memory(handle); | 168 | return drm_agp_unbind_memory(handle); |
166 | } | 169 | } |
170 | EXPORT_SYMBOL(drm_unbind_agp); | ||
167 | #endif /* agp */ | 171 | #endif /* agp */ |
168 | #endif /* debug_memory */ | 172 | #endif /* debug_memory */ |
diff --git a/drivers/char/drm/drm_pci.c b/drivers/char/drm/drm_pci.c index 192e8762571c..3e452e8967fa 100644 --- a/drivers/char/drm/drm_pci.c +++ b/drivers/char/drm/drm_pci.c | |||
@@ -46,10 +46,10 @@ | |||
46 | /** | 46 | /** |
47 | * \brief Allocate a PCI consistent memory block, for DMA. | 47 | * \brief Allocate a PCI consistent memory block, for DMA. |
48 | */ | 48 | */ |
49 | void *drm_pci_alloc(drm_device_t * dev, size_t size, size_t align, | 49 | drm_dma_handle_t *drm_pci_alloc(drm_device_t * dev, size_t size, size_t align, |
50 | dma_addr_t maxaddr, dma_addr_t * busaddr) | 50 | dma_addr_t maxaddr) |
51 | { | 51 | { |
52 | void *address; | 52 | drm_dma_handle_t *dmah; |
53 | #if DRM_DEBUG_MEMORY | 53 | #if DRM_DEBUG_MEMORY |
54 | int area = DRM_MEM_DMA; | 54 | int area = DRM_MEM_DMA; |
55 | 55 | ||
@@ -74,13 +74,19 @@ void *drm_pci_alloc(drm_device_t * dev, size_t size, size_t align, | |||
74 | return NULL; | 74 | return NULL; |
75 | } | 75 | } |
76 | 76 | ||
77 | address = pci_alloc_consistent(dev->pdev, size, busaddr); | 77 | dmah = kmalloc(sizeof(drm_dma_handle_t), GFP_KERNEL); |
78 | if (!dmah) | ||
79 | return NULL; | ||
80 | |||
81 | dmah->size = size; | ||
82 | dmah->vaddr = pci_alloc_consistent(dev->pdev, size, &dmah->busaddr); | ||
78 | 83 | ||
79 | #if DRM_DEBUG_MEMORY | 84 | #if DRM_DEBUG_MEMORY |
80 | if (address == NULL) { | 85 | if (dmah->vaddr == NULL) { |
81 | spin_lock(&drm_mem_lock); | 86 | spin_lock(&drm_mem_lock); |
82 | ++drm_mem_stats[area].fail_count; | 87 | ++drm_mem_stats[area].fail_count; |
83 | spin_unlock(&drm_mem_lock); | 88 | spin_unlock(&drm_mem_lock); |
89 | kfree(dmah); | ||
84 | return NULL; | 90 | return NULL; |
85 | } | 91 | } |
86 | 92 | ||
@@ -90,21 +96,25 @@ void *drm_pci_alloc(drm_device_t * dev, size_t size, size_t align, | |||
90 | drm_ram_used += size; | 96 | drm_ram_used += size; |
91 | spin_unlock(&drm_mem_lock); | 97 | spin_unlock(&drm_mem_lock); |
92 | #else | 98 | #else |
93 | if (address == NULL) | 99 | if (dmah->vaddr == NULL) { |
100 | kfree(dmah); | ||
94 | return NULL; | 101 | return NULL; |
102 | } | ||
95 | #endif | 103 | #endif |
96 | 104 | ||
97 | memset(address, 0, size); | 105 | memset(dmah->vaddr, 0, size); |
98 | 106 | ||
99 | return address; | 107 | return dmah; |
100 | } | 108 | } |
101 | EXPORT_SYMBOL(drm_pci_alloc); | 109 | EXPORT_SYMBOL(drm_pci_alloc); |
102 | 110 | ||
103 | /** | 111 | /** |
104 | * \brief Free a PCI consistent memory block. | 112 | * \brief Free a PCI consistent memory block with freeing its descriptor. |
113 | * | ||
114 | * This function is for internal use in the Linux-specific DRM core code. | ||
105 | */ | 115 | */ |
106 | void | 116 | void |
107 | drm_pci_free(drm_device_t * dev, size_t size, void *vaddr, dma_addr_t busaddr) | 117 | __drm_pci_free(drm_device_t * dev, drm_dma_handle_t *dmah) |
108 | { | 118 | { |
109 | #if DRM_DEBUG_MEMORY | 119 | #if DRM_DEBUG_MEMORY |
110 | int area = DRM_MEM_DMA; | 120 | int area = DRM_MEM_DMA; |
@@ -112,12 +122,13 @@ drm_pci_free(drm_device_t * dev, size_t size, void *vaddr, dma_addr_t busaddr) | |||
112 | int free_count; | 122 | int free_count; |
113 | #endif | 123 | #endif |
114 | 124 | ||
115 | if (!vaddr) { | 125 | if (!dmah->vaddr) { |
116 | #if DRM_DEBUG_MEMORY | 126 | #if DRM_DEBUG_MEMORY |
117 | DRM_MEM_ERROR(area, "Attempt to free address 0\n"); | 127 | DRM_MEM_ERROR(area, "Attempt to free address 0\n"); |
118 | #endif | 128 | #endif |
119 | } else { | 129 | } else { |
120 | pci_free_consistent(dev->pdev, size, vaddr, busaddr); | 130 | pci_free_consistent(dev->pdev, dmah->size, dmah->vaddr, |
131 | dmah->busaddr); | ||
121 | } | 132 | } |
122 | 133 | ||
123 | #if DRM_DEBUG_MEMORY | 134 | #if DRM_DEBUG_MEMORY |
@@ -135,6 +146,16 @@ drm_pci_free(drm_device_t * dev, size_t size, void *vaddr, dma_addr_t busaddr) | |||
135 | #endif | 146 | #endif |
136 | 147 | ||
137 | } | 148 | } |
149 | |||
150 | /** | ||
151 | * \brief Free a PCI consistent memory block | ||
152 | */ | ||
153 | void | ||
154 | drm_pci_free(drm_device_t *dev, drm_dma_handle_t *dmah) | ||
155 | { | ||
156 | __drm_pci_free(dev, dmah); | ||
157 | kfree(dmah); | ||
158 | } | ||
138 | EXPORT_SYMBOL(drm_pci_free); | 159 | EXPORT_SYMBOL(drm_pci_free); |
139 | 160 | ||
140 | /*@}*/ | 161 | /*@}*/ |
diff --git a/drivers/char/drm/drm_pciids.h b/drivers/char/drm/drm_pciids.h index 70ca4fa55c9d..4f317ec092ee 100644 --- a/drivers/char/drm/drm_pciids.h +++ b/drivers/char/drm/drm_pciids.h | |||
@@ -116,9 +116,10 @@ | |||
116 | {0, 0, 0} | 116 | {0, 0, 0} |
117 | 117 | ||
118 | #define mga_PCI_IDS \ | 118 | #define mga_PCI_IDS \ |
119 | {0x102b, 0x0521, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ | 119 | {0x102b, 0x0520, PCI_ANY_ID, PCI_ANY_ID, 0, 0, MGA_CARD_TYPE_G200}, \ |
120 | {0x102b, 0x0525, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ | 120 | {0x102b, 0x0521, PCI_ANY_ID, PCI_ANY_ID, 0, 0, MGA_CARD_TYPE_G200}, \ |
121 | {0x102b, 0x2527, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ | 121 | {0x102b, 0x0525, PCI_ANY_ID, PCI_ANY_ID, 0, 0, MGA_CARD_TYPE_G400}, \ |
122 | {0x102b, 0x2527, PCI_ANY_ID, PCI_ANY_ID, 0, 0, MGA_CARD_TYPE_G550}, \ | ||
122 | {0, 0, 0} | 123 | {0, 0, 0} |
123 | 124 | ||
124 | #define mach64_PCI_IDS \ | 125 | #define mach64_PCI_IDS \ |
diff --git a/drivers/char/drm/drm_proc.c b/drivers/char/drm/drm_proc.c index 4774087d2e9e..f4154cc71abb 100644 --- a/drivers/char/drm/drm_proc.c +++ b/drivers/char/drm/drm_proc.c | |||
@@ -210,8 +210,8 @@ static int drm__vm_info(char *buf, char **start, off_t offset, int request, | |||
210 | 210 | ||
211 | /* Hardcoded from _DRM_FRAME_BUFFER, | 211 | /* Hardcoded from _DRM_FRAME_BUFFER, |
212 | _DRM_REGISTERS, _DRM_SHM, _DRM_AGP, and | 212 | _DRM_REGISTERS, _DRM_SHM, _DRM_AGP, and |
213 | _DRM_SCATTER_GATHER. */ | 213 | _DRM_SCATTER_GATHER and _DRM_CONSISTENT */ |
214 | const char *types[] = { "FB", "REG", "SHM", "AGP", "SG" }; | 214 | const char *types[] = { "FB", "REG", "SHM", "AGP", "SG", "PCI" }; |
215 | const char *type; | 215 | const char *type; |
216 | int i; | 216 | int i; |
217 | 217 | ||
@@ -229,9 +229,12 @@ static int drm__vm_info(char *buf, char **start, off_t offset, int request, | |||
229 | if (dev->maplist != NULL) list_for_each(list, &dev->maplist->head) { | 229 | if (dev->maplist != NULL) list_for_each(list, &dev->maplist->head) { |
230 | r_list = list_entry(list, drm_map_list_t, head); | 230 | r_list = list_entry(list, drm_map_list_t, head); |
231 | map = r_list->map; | 231 | map = r_list->map; |
232 | if(!map) continue; | 232 | if(!map) |
233 | if (map->type < 0 || map->type > 4) type = "??"; | 233 | continue; |
234 | else type = types[map->type]; | 234 | if (map->type < 0 || map->type > 5) |
235 | type = "??"; | ||
236 | else | ||
237 | type = types[map->type]; | ||
235 | DRM_PROC_PRINT("%4d 0x%08lx 0x%08lx %4.4s 0x%02x 0x%08lx ", | 238 | DRM_PROC_PRINT("%4d 0x%08lx 0x%08lx %4.4s 0x%02x 0x%08lx ", |
236 | i, | 239 | i, |
237 | map->offset, | 240 | map->offset, |
diff --git a/drivers/char/drm/drm_stub.c b/drivers/char/drm/drm_stub.c index 48829a1a086a..95a976c96eb8 100644 --- a/drivers/char/drm/drm_stub.c +++ b/drivers/char/drm/drm_stub.c | |||
@@ -75,6 +75,11 @@ static int drm_fill_in_dev(drm_device_t *dev, struct pci_dev *pdev, const struct | |||
75 | dev->pci_func = PCI_FUNC(pdev->devfn); | 75 | dev->pci_func = PCI_FUNC(pdev->devfn); |
76 | dev->irq = pdev->irq; | 76 | dev->irq = pdev->irq; |
77 | 77 | ||
78 | dev->maplist = drm_calloc(1, sizeof(*dev->maplist), DRM_MEM_MAPS); | ||
79 | if (dev->maplist == NULL) | ||
80 | return -ENOMEM; | ||
81 | INIT_LIST_HEAD(&dev->maplist->head); | ||
82 | |||
78 | /* the DRM has 6 basic counters */ | 83 | /* the DRM has 6 basic counters */ |
79 | dev->counters = 6; | 84 | dev->counters = 6; |
80 | dev->types[0] = _DRM_STAT_LOCK; | 85 | dev->types[0] = _DRM_STAT_LOCK; |
@@ -91,7 +96,8 @@ static int drm_fill_in_dev(drm_device_t *dev, struct pci_dev *pdev, const struct | |||
91 | goto error_out_unreg; | 96 | goto error_out_unreg; |
92 | 97 | ||
93 | if (drm_core_has_AGP(dev)) { | 98 | if (drm_core_has_AGP(dev)) { |
94 | dev->agp = drm_agp_init(dev); | 99 | if (drm_device_is_agp(dev)) |
100 | dev->agp = drm_agp_init(dev); | ||
95 | if (drm_core_check_feature(dev, DRIVER_REQUIRE_AGP) && (dev->agp == NULL)) { | 101 | if (drm_core_check_feature(dev, DRIVER_REQUIRE_AGP) && (dev->agp == NULL)) { |
96 | DRM_ERROR( "Cannot initialize the agpgart module.\n" ); | 102 | DRM_ERROR( "Cannot initialize the agpgart module.\n" ); |
97 | retcode = -EINVAL; | 103 | retcode = -EINVAL; |
diff --git a/drivers/char/drm/drm_vm.c b/drivers/char/drm/drm_vm.c index 621220f3f372..675d2397def9 100644 --- a/drivers/char/drm/drm_vm.c +++ b/drivers/char/drm/drm_vm.c | |||
@@ -210,6 +210,8 @@ static void drm_vm_shm_close(struct vm_area_struct *vma) | |||
210 | } | 210 | } |
211 | 211 | ||
212 | if(!found_maps) { | 212 | if(!found_maps) { |
213 | drm_dma_handle_t dmah; | ||
214 | |||
213 | switch (map->type) { | 215 | switch (map->type) { |
214 | case _DRM_REGISTERS: | 216 | case _DRM_REGISTERS: |
215 | case _DRM_FRAME_BUFFER: | 217 | case _DRM_FRAME_BUFFER: |
@@ -228,6 +230,12 @@ static void drm_vm_shm_close(struct vm_area_struct *vma) | |||
228 | case _DRM_AGP: | 230 | case _DRM_AGP: |
229 | case _DRM_SCATTER_GATHER: | 231 | case _DRM_SCATTER_GATHER: |
230 | break; | 232 | break; |
233 | case _DRM_CONSISTENT: | ||
234 | dmah.vaddr = map->handle; | ||
235 | dmah.busaddr = map->offset; | ||
236 | dmah.size = map->size; | ||
237 | __drm_pci_free(dev, &dmah); | ||
238 | break; | ||
231 | } | 239 | } |
232 | drm_free(map, sizeof(*map), DRM_MEM_MAPS); | 240 | drm_free(map, sizeof(*map), DRM_MEM_MAPS); |
233 | } | 241 | } |
@@ -645,6 +653,9 @@ int drm_mmap(struct file *filp, struct vm_area_struct *vma) | |||
645 | vma->vm_ops = &drm_vm_ops; | 653 | vma->vm_ops = &drm_vm_ops; |
646 | break; | 654 | break; |
647 | case _DRM_SHM: | 655 | case _DRM_SHM: |
656 | case _DRM_CONSISTENT: | ||
657 | /* Consistent memory is really like shared memory. It's only | ||
658 | * allocate in a different way */ | ||
648 | vma->vm_ops = &drm_vm_shm_ops; | 659 | vma->vm_ops = &drm_vm_shm_ops; |
649 | vma->vm_private_data = (void *)map; | 660 | vma->vm_private_data = (void *)map; |
650 | /* Don't let this area swap. Change when | 661 | /* Don't let this area swap. Change when |
diff --git a/drivers/char/drm/i810_dma.c b/drivers/char/drm/i810_dma.c index 18e0b7622893..0a9ac1f2e215 100644 --- a/drivers/char/drm/i810_dma.c +++ b/drivers/char/drm/i810_dma.c | |||
@@ -1383,3 +1383,19 @@ drm_ioctl_desc_t i810_ioctls[] = { | |||
1383 | }; | 1383 | }; |
1384 | 1384 | ||
1385 | int i810_max_ioctl = DRM_ARRAY_SIZE(i810_ioctls); | 1385 | int i810_max_ioctl = DRM_ARRAY_SIZE(i810_ioctls); |
1386 | |||
1387 | /** | ||
1388 | * Determine if the device really is AGP or not. | ||
1389 | * | ||
1390 | * All Intel graphics chipsets are treated as AGP, even if they are really | ||
1391 | * PCI-e. | ||
1392 | * | ||
1393 | * \param dev The device to be tested. | ||
1394 | * | ||
1395 | * \returns | ||
1396 | * A value of 1 is always retured to indictate every i810 is AGP. | ||
1397 | */ | ||
1398 | int i810_driver_device_is_agp(drm_device_t * dev) | ||
1399 | { | ||
1400 | return 1; | ||
1401 | } | ||
diff --git a/drivers/char/drm/i810_drv.c b/drivers/char/drm/i810_drv.c index ff51b3259af9..00609329d578 100644 --- a/drivers/char/drm/i810_drv.c +++ b/drivers/char/drm/i810_drv.c | |||
@@ -84,6 +84,7 @@ static struct drm_driver driver = { | |||
84 | .dev_priv_size = sizeof(drm_i810_buf_priv_t), | 84 | .dev_priv_size = sizeof(drm_i810_buf_priv_t), |
85 | .pretakedown = i810_driver_pretakedown, | 85 | .pretakedown = i810_driver_pretakedown, |
86 | .prerelease = i810_driver_prerelease, | 86 | .prerelease = i810_driver_prerelease, |
87 | .device_is_agp = i810_driver_device_is_agp, | ||
87 | .release = i810_driver_release, | 88 | .release = i810_driver_release, |
88 | .dma_quiescent = i810_driver_dma_quiescent, | 89 | .dma_quiescent = i810_driver_dma_quiescent, |
89 | .reclaim_buffers = i810_reclaim_buffers, | 90 | .reclaim_buffers = i810_reclaim_buffers, |
diff --git a/drivers/char/drm/i810_drv.h b/drivers/char/drm/i810_drv.h index 1b40538d1725..62ee4f58c59a 100644 --- a/drivers/char/drm/i810_drv.h +++ b/drivers/char/drm/i810_drv.h | |||
@@ -120,6 +120,7 @@ extern int i810_driver_dma_quiescent(drm_device_t *dev); | |||
120 | extern void i810_driver_release(drm_device_t *dev, struct file *filp); | 120 | extern void i810_driver_release(drm_device_t *dev, struct file *filp); |
121 | extern void i810_driver_pretakedown(drm_device_t *dev); | 121 | extern void i810_driver_pretakedown(drm_device_t *dev); |
122 | extern void i810_driver_prerelease(drm_device_t *dev, DRMFILE filp); | 122 | extern void i810_driver_prerelease(drm_device_t *dev, DRMFILE filp); |
123 | extern int i810_driver_device_is_agp(drm_device_t * dev); | ||
123 | 124 | ||
124 | #define I810_BASE(reg) ((unsigned long) \ | 125 | #define I810_BASE(reg) ((unsigned long) \ |
125 | dev_priv->mmio_map->handle) | 126 | dev_priv->mmio_map->handle) |
diff --git a/drivers/char/drm/i830_dma.c b/drivers/char/drm/i830_dma.c index dc7733035864..80d8966397c1 100644 --- a/drivers/char/drm/i830_dma.c +++ b/drivers/char/drm/i830_dma.c | |||
@@ -1586,3 +1586,19 @@ drm_ioctl_desc_t i830_ioctls[] = { | |||
1586 | }; | 1586 | }; |
1587 | 1587 | ||
1588 | int i830_max_ioctl = DRM_ARRAY_SIZE(i830_ioctls); | 1588 | int i830_max_ioctl = DRM_ARRAY_SIZE(i830_ioctls); |
1589 | |||
1590 | /** | ||
1591 | * Determine if the device really is AGP or not. | ||
1592 | * | ||
1593 | * All Intel graphics chipsets are treated as AGP, even if they are really | ||
1594 | * PCI-e. | ||
1595 | * | ||
1596 | * \param dev The device to be tested. | ||
1597 | * | ||
1598 | * \returns | ||
1599 | * A value of 1 is always retured to indictate every i8xx is AGP. | ||
1600 | */ | ||
1601 | int i830_driver_device_is_agp(drm_device_t * dev) | ||
1602 | { | ||
1603 | return 1; | ||
1604 | } | ||
diff --git a/drivers/char/drm/i830_drv.c b/drivers/char/drm/i830_drv.c index bc36be76b8b2..0da9cd19919e 100644 --- a/drivers/char/drm/i830_drv.c +++ b/drivers/char/drm/i830_drv.c | |||
@@ -88,6 +88,7 @@ static struct drm_driver driver = { | |||
88 | .dev_priv_size = sizeof(drm_i830_buf_priv_t), | 88 | .dev_priv_size = sizeof(drm_i830_buf_priv_t), |
89 | .pretakedown = i830_driver_pretakedown, | 89 | .pretakedown = i830_driver_pretakedown, |
90 | .prerelease = i830_driver_prerelease, | 90 | .prerelease = i830_driver_prerelease, |
91 | .device_is_agp = i830_driver_device_is_agp, | ||
91 | .release = i830_driver_release, | 92 | .release = i830_driver_release, |
92 | .dma_quiescent = i830_driver_dma_quiescent, | 93 | .dma_quiescent = i830_driver_dma_quiescent, |
93 | .reclaim_buffers = i830_reclaim_buffers, | 94 | .reclaim_buffers = i830_reclaim_buffers, |
diff --git a/drivers/char/drm/i830_drv.h b/drivers/char/drm/i830_drv.h index df7746131dea..63f96a8b6a4a 100644 --- a/drivers/char/drm/i830_drv.h +++ b/drivers/char/drm/i830_drv.h | |||
@@ -137,6 +137,7 @@ extern void i830_driver_pretakedown(drm_device_t *dev); | |||
137 | extern void i830_driver_release(drm_device_t *dev, struct file *filp); | 137 | extern void i830_driver_release(drm_device_t *dev, struct file *filp); |
138 | extern int i830_driver_dma_quiescent(drm_device_t *dev); | 138 | extern int i830_driver_dma_quiescent(drm_device_t *dev); |
139 | extern void i830_driver_prerelease(drm_device_t *dev, DRMFILE filp); | 139 | extern void i830_driver_prerelease(drm_device_t *dev, DRMFILE filp); |
140 | extern int i830_driver_device_is_agp(drm_device_t * dev); | ||
140 | 141 | ||
141 | #define I830_BASE(reg) ((unsigned long) \ | 142 | #define I830_BASE(reg) ((unsigned long) \ |
142 | dev_priv->mmio_map->handle) | 143 | dev_priv->mmio_map->handle) |
diff --git a/drivers/char/drm/i915_dma.c b/drivers/char/drm/i915_dma.c index acf9e52a9507..34f552f90c4a 100644 --- a/drivers/char/drm/i915_dma.c +++ b/drivers/char/drm/i915_dma.c | |||
@@ -95,9 +95,8 @@ static int i915_dma_cleanup(drm_device_t * dev) | |||
95 | drm_core_ioremapfree( &dev_priv->ring.map, dev); | 95 | drm_core_ioremapfree( &dev_priv->ring.map, dev); |
96 | } | 96 | } |
97 | 97 | ||
98 | if (dev_priv->hw_status_page) { | 98 | if (dev_priv->status_page_dmah) { |
99 | drm_pci_free(dev, PAGE_SIZE, dev_priv->hw_status_page, | 99 | drm_pci_free(dev, dev_priv->status_page_dmah); |
100 | dev_priv->dma_status_page); | ||
101 | /* Need to rewrite hardware status page */ | 100 | /* Need to rewrite hardware status page */ |
102 | I915_WRITE(0x02080, 0x1ffff000); | 101 | I915_WRITE(0x02080, 0x1ffff000); |
103 | } | 102 | } |
@@ -174,16 +173,18 @@ static int i915_initialize(drm_device_t * dev, | |||
174 | dev_priv->allow_batchbuffer = 1; | 173 | dev_priv->allow_batchbuffer = 1; |
175 | 174 | ||
176 | /* Program Hardware Status Page */ | 175 | /* Program Hardware Status Page */ |
177 | dev_priv->hw_status_page = drm_pci_alloc(dev, PAGE_SIZE, PAGE_SIZE, | 176 | dev_priv->status_page_dmah = drm_pci_alloc(dev, PAGE_SIZE, PAGE_SIZE, |
178 | 0xffffffff, | 177 | 0xffffffff); |
179 | &dev_priv->dma_status_page); | ||
180 | 178 | ||
181 | if (!dev_priv->hw_status_page) { | 179 | if (!dev_priv->status_page_dmah) { |
182 | dev->dev_private = (void *)dev_priv; | 180 | dev->dev_private = (void *)dev_priv; |
183 | i915_dma_cleanup(dev); | 181 | i915_dma_cleanup(dev); |
184 | DRM_ERROR("Can not allocate hardware status page\n"); | 182 | DRM_ERROR("Can not allocate hardware status page\n"); |
185 | return DRM_ERR(ENOMEM); | 183 | return DRM_ERR(ENOMEM); |
186 | } | 184 | } |
185 | dev_priv->hw_status_page = dev_priv->status_page_dmah->vaddr; | ||
186 | dev_priv->dma_status_page = dev_priv->status_page_dmah->busaddr; | ||
187 | |||
187 | memset(dev_priv->hw_status_page, 0, PAGE_SIZE); | 188 | memset(dev_priv->hw_status_page, 0, PAGE_SIZE); |
188 | DRM_DEBUG("hw status page @ %p\n", dev_priv->hw_status_page); | 189 | DRM_DEBUG("hw status page @ %p\n", dev_priv->hw_status_page); |
189 | 190 | ||
@@ -731,3 +732,19 @@ drm_ioctl_desc_t i915_ioctls[] = { | |||
731 | }; | 732 | }; |
732 | 733 | ||
733 | int i915_max_ioctl = DRM_ARRAY_SIZE(i915_ioctls); | 734 | int i915_max_ioctl = DRM_ARRAY_SIZE(i915_ioctls); |
735 | |||
736 | /** | ||
737 | * Determine if the device really is AGP or not. | ||
738 | * | ||
739 | * All Intel graphics chipsets are treated as AGP, even if they are really | ||
740 | * PCI-e. | ||
741 | * | ||
742 | * \param dev The device to be tested. | ||
743 | * | ||
744 | * \returns | ||
745 | * A value of 1 is always retured to indictate every i9x5 is AGP. | ||
746 | */ | ||
747 | int i915_driver_device_is_agp(drm_device_t * dev) | ||
748 | { | ||
749 | return 1; | ||
750 | } | ||
diff --git a/drivers/char/drm/i915_drv.c b/drivers/char/drm/i915_drv.c index 1f59d3fc79bc..106b9ec02213 100644 --- a/drivers/char/drm/i915_drv.c +++ b/drivers/char/drm/i915_drv.c | |||
@@ -79,6 +79,7 @@ static struct drm_driver driver = { | |||
79 | DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED, | 79 | DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED, |
80 | .pretakedown = i915_driver_pretakedown, | 80 | .pretakedown = i915_driver_pretakedown, |
81 | .prerelease = i915_driver_prerelease, | 81 | .prerelease = i915_driver_prerelease, |
82 | .device_is_agp = i915_driver_device_is_agp, | ||
82 | .irq_preinstall = i915_driver_irq_preinstall, | 83 | .irq_preinstall = i915_driver_irq_preinstall, |
83 | .irq_postinstall = i915_driver_irq_postinstall, | 84 | .irq_postinstall = i915_driver_irq_postinstall, |
84 | .irq_uninstall = i915_driver_irq_uninstall, | 85 | .irq_uninstall = i915_driver_irq_uninstall, |
diff --git a/drivers/char/drm/i915_drv.h b/drivers/char/drm/i915_drv.h index 9c37d2367dd5..70ed4e68eac8 100644 --- a/drivers/char/drm/i915_drv.h +++ b/drivers/char/drm/i915_drv.h | |||
@@ -79,9 +79,10 @@ typedef struct drm_i915_private { | |||
79 | drm_i915_sarea_t *sarea_priv; | 79 | drm_i915_sarea_t *sarea_priv; |
80 | drm_i915_ring_buffer_t ring; | 80 | drm_i915_ring_buffer_t ring; |
81 | 81 | ||
82 | drm_dma_handle_t *status_page_dmah; | ||
82 | void *hw_status_page; | 83 | void *hw_status_page; |
83 | unsigned long counter; | ||
84 | dma_addr_t dma_status_page; | 84 | dma_addr_t dma_status_page; |
85 | unsigned long counter; | ||
85 | 86 | ||
86 | int back_offset; | 87 | int back_offset; |
87 | int front_offset; | 88 | int front_offset; |
@@ -102,6 +103,7 @@ typedef struct drm_i915_private { | |||
102 | extern void i915_kernel_lost_context(drm_device_t * dev); | 103 | extern void i915_kernel_lost_context(drm_device_t * dev); |
103 | extern void i915_driver_pretakedown(drm_device_t *dev); | 104 | extern void i915_driver_pretakedown(drm_device_t *dev); |
104 | extern void i915_driver_prerelease(drm_device_t *dev, DRMFILE filp); | 105 | extern void i915_driver_prerelease(drm_device_t *dev, DRMFILE filp); |
106 | extern int i915_driver_device_is_agp(drm_device_t *dev); | ||
105 | 107 | ||
106 | /* i915_irq.c */ | 108 | /* i915_irq.c */ |
107 | extern int i915_irq_emit(DRM_IOCTL_ARGS); | 109 | extern int i915_irq_emit(DRM_IOCTL_ARGS); |
diff --git a/drivers/char/drm/mga_dma.c b/drivers/char/drm/mga_dma.c index 832eaf8a5068..7899e281d062 100644 --- a/drivers/char/drm/mga_dma.c +++ b/drivers/char/drm/mga_dma.c | |||
@@ -23,18 +23,21 @@ | |||
23 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | 23 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, |
24 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | 24 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
25 | * DEALINGS IN THE SOFTWARE. | 25 | * DEALINGS IN THE SOFTWARE. |
26 | * | 26 | */ |
27 | * Authors: | 27 | |
28 | * Rickard E. (Rik) Faith <faith@valinux.com> | 28 | /** |
29 | * Jeff Hartmann <jhartmann@valinux.com> | 29 | * \file mga_dma.c |
30 | * Keith Whitwell <keith@tungstengraphics.com> | 30 | * DMA support for MGA G200 / G400. |
31 | * | 31 | * |
32 | * Rewritten by: | 32 | * \author Rickard E. (Rik) Faith <faith@valinux.com> |
33 | * Gareth Hughes <gareth@valinux.com> | 33 | * \author Jeff Hartmann <jhartmann@valinux.com> |
34 | * \author Keith Whitwell <keith@tungstengraphics.com> | ||
35 | * \author Gareth Hughes <gareth@valinux.com> | ||
34 | */ | 36 | */ |
35 | 37 | ||
36 | #include "drmP.h" | 38 | #include "drmP.h" |
37 | #include "drm.h" | 39 | #include "drm.h" |
40 | #include "drm_sarea.h" | ||
38 | #include "mga_drm.h" | 41 | #include "mga_drm.h" |
39 | #include "mga_drv.h" | 42 | #include "mga_drv.h" |
40 | 43 | ||
@@ -148,7 +151,7 @@ void mga_do_dma_flush( drm_mga_private_t *dev_priv ) | |||
148 | DRM_DEBUG( " space = 0x%06x\n", primary->space ); | 151 | DRM_DEBUG( " space = 0x%06x\n", primary->space ); |
149 | 152 | ||
150 | mga_flush_write_combine(); | 153 | mga_flush_write_combine(); |
151 | MGA_WRITE( MGA_PRIMEND, tail | MGA_PAGPXFER ); | 154 | MGA_WRITE(MGA_PRIMEND, tail | dev_priv->dma_access); |
152 | 155 | ||
153 | DRM_DEBUG( "done.\n" ); | 156 | DRM_DEBUG( "done.\n" ); |
154 | } | 157 | } |
@@ -190,7 +193,7 @@ void mga_do_dma_wrap_start( drm_mga_private_t *dev_priv ) | |||
190 | DRM_DEBUG( " space = 0x%06x\n", primary->space ); | 193 | DRM_DEBUG( " space = 0x%06x\n", primary->space ); |
191 | 194 | ||
192 | mga_flush_write_combine(); | 195 | mga_flush_write_combine(); |
193 | MGA_WRITE( MGA_PRIMEND, tail | MGA_PAGPXFER ); | 196 | MGA_WRITE(MGA_PRIMEND, tail | dev_priv->dma_access); |
194 | 197 | ||
195 | set_bit( 0, &primary->wrapped ); | 198 | set_bit( 0, &primary->wrapped ); |
196 | DRM_DEBUG( "done.\n" ); | 199 | DRM_DEBUG( "done.\n" ); |
@@ -396,23 +399,383 @@ int mga_freelist_put( drm_device_t *dev, drm_buf_t *buf ) | |||
396 | * DMA initialization, cleanup | 399 | * DMA initialization, cleanup |
397 | */ | 400 | */ |
398 | 401 | ||
402 | |||
403 | int mga_driver_preinit(drm_device_t *dev, unsigned long flags) | ||
404 | { | ||
405 | drm_mga_private_t * dev_priv; | ||
406 | |||
407 | dev_priv = drm_alloc(sizeof(drm_mga_private_t), DRM_MEM_DRIVER); | ||
408 | if (!dev_priv) | ||
409 | return DRM_ERR(ENOMEM); | ||
410 | |||
411 | dev->dev_private = (void *)dev_priv; | ||
412 | memset(dev_priv, 0, sizeof(drm_mga_private_t)); | ||
413 | |||
414 | dev_priv->usec_timeout = MGA_DEFAULT_USEC_TIMEOUT; | ||
415 | dev_priv->chipset = flags; | ||
416 | |||
417 | return 0; | ||
418 | } | ||
419 | |||
420 | /** | ||
421 | * Bootstrap the driver for AGP DMA. | ||
422 | * | ||
423 | * \todo | ||
424 | * Investigate whether there is any benifit to storing the WARP microcode in | ||
425 | * AGP memory. If not, the microcode may as well always be put in PCI | ||
426 | * memory. | ||
427 | * | ||
428 | * \todo | ||
429 | * This routine needs to set dma_bs->agp_mode to the mode actually configured | ||
430 | * in the hardware. Looking just at the Linux AGP driver code, I don't see | ||
431 | * an easy way to determine this. | ||
432 | * | ||
433 | * \sa mga_do_dma_bootstrap, mga_do_pci_dma_bootstrap | ||
434 | */ | ||
435 | static int mga_do_agp_dma_bootstrap(drm_device_t * dev, | ||
436 | drm_mga_dma_bootstrap_t * dma_bs) | ||
437 | { | ||
438 | drm_mga_private_t * const dev_priv = (drm_mga_private_t *) dev->dev_private; | ||
439 | const unsigned int warp_size = mga_warp_microcode_size(dev_priv); | ||
440 | int err; | ||
441 | unsigned offset; | ||
442 | const unsigned secondary_size = dma_bs->secondary_bin_count | ||
443 | * dma_bs->secondary_bin_size; | ||
444 | const unsigned agp_size = (dma_bs->agp_size << 20); | ||
445 | drm_buf_desc_t req; | ||
446 | drm_agp_mode_t mode; | ||
447 | drm_agp_info_t info; | ||
448 | |||
449 | |||
450 | /* Acquire AGP. */ | ||
451 | err = drm_agp_acquire(dev); | ||
452 | if (err) { | ||
453 | DRM_ERROR("Unable to acquire AGP\n"); | ||
454 | return err; | ||
455 | } | ||
456 | |||
457 | err = drm_agp_info(dev, &info); | ||
458 | if (err) { | ||
459 | DRM_ERROR("Unable to get AGP info\n"); | ||
460 | return err; | ||
461 | } | ||
462 | |||
463 | mode.mode = (info.mode & ~0x07) | dma_bs->agp_mode; | ||
464 | err = drm_agp_enable(dev, mode); | ||
465 | if (err) { | ||
466 | DRM_ERROR("Unable to enable AGP (mode = 0x%lx)\n", mode.mode); | ||
467 | return err; | ||
468 | } | ||
469 | |||
470 | |||
471 | /* In addition to the usual AGP mode configuration, the G200 AGP cards | ||
472 | * need to have the AGP mode "manually" set. | ||
473 | */ | ||
474 | |||
475 | if (dev_priv->chipset == MGA_CARD_TYPE_G200) { | ||
476 | if (mode.mode & 0x02) { | ||
477 | MGA_WRITE(MGA_AGP_PLL, MGA_AGP2XPLL_ENABLE); | ||
478 | } | ||
479 | else { | ||
480 | MGA_WRITE(MGA_AGP_PLL, MGA_AGP2XPLL_DISABLE); | ||
481 | } | ||
482 | } | ||
483 | |||
484 | |||
485 | /* Allocate and bind AGP memory. */ | ||
486 | dev_priv->agp_pages = agp_size / PAGE_SIZE; | ||
487 | dev_priv->agp_mem = drm_alloc_agp( dev, dev_priv->agp_pages, 0 ); | ||
488 | if (dev_priv->agp_mem == NULL) { | ||
489 | dev_priv->agp_pages = 0; | ||
490 | DRM_ERROR("Unable to allocate %uMB AGP memory\n", | ||
491 | dma_bs->agp_size); | ||
492 | return DRM_ERR(ENOMEM); | ||
493 | } | ||
494 | |||
495 | err = drm_bind_agp( dev_priv->agp_mem, 0 ); | ||
496 | if (err) { | ||
497 | DRM_ERROR("Unable to bind AGP memory\n"); | ||
498 | return err; | ||
499 | } | ||
500 | |||
501 | offset = 0; | ||
502 | err = drm_addmap( dev, offset, warp_size, | ||
503 | _DRM_AGP, _DRM_READ_ONLY, & dev_priv->warp ); | ||
504 | if (err) { | ||
505 | DRM_ERROR("Unable to map WARP microcode\n"); | ||
506 | return err; | ||
507 | } | ||
508 | |||
509 | offset += warp_size; | ||
510 | err = drm_addmap( dev, offset, dma_bs->primary_size, | ||
511 | _DRM_AGP, _DRM_READ_ONLY, & dev_priv->primary ); | ||
512 | if (err) { | ||
513 | DRM_ERROR("Unable to map primary DMA region\n"); | ||
514 | return err; | ||
515 | } | ||
516 | |||
517 | offset += dma_bs->primary_size; | ||
518 | err = drm_addmap( dev, offset, secondary_size, | ||
519 | _DRM_AGP, 0, & dev->agp_buffer_map ); | ||
520 | if (err) { | ||
521 | DRM_ERROR("Unable to map secondary DMA region\n"); | ||
522 | return err; | ||
523 | } | ||
524 | |||
525 | (void) memset( &req, 0, sizeof(req) ); | ||
526 | req.count = dma_bs->secondary_bin_count; | ||
527 | req.size = dma_bs->secondary_bin_size; | ||
528 | req.flags = _DRM_AGP_BUFFER; | ||
529 | req.agp_start = offset; | ||
530 | |||
531 | err = drm_addbufs_agp( dev, & req ); | ||
532 | if (err) { | ||
533 | DRM_ERROR("Unable to add secondary DMA buffers\n"); | ||
534 | return err; | ||
535 | } | ||
536 | |||
537 | offset += secondary_size; | ||
538 | err = drm_addmap( dev, offset, agp_size - offset, | ||
539 | _DRM_AGP, 0, & dev_priv->agp_textures ); | ||
540 | if (err) { | ||
541 | DRM_ERROR("Unable to map AGP texture region\n"); | ||
542 | return err; | ||
543 | } | ||
544 | |||
545 | drm_core_ioremap(dev_priv->warp, dev); | ||
546 | drm_core_ioremap(dev_priv->primary, dev); | ||
547 | drm_core_ioremap(dev->agp_buffer_map, dev); | ||
548 | |||
549 | if (!dev_priv->warp->handle || | ||
550 | !dev_priv->primary->handle || !dev->agp_buffer_map->handle) { | ||
551 | DRM_ERROR("failed to ioremap agp regions! (%p, %p, %p)\n", | ||
552 | dev_priv->warp->handle, dev_priv->primary->handle, | ||
553 | dev->agp_buffer_map->handle); | ||
554 | return DRM_ERR(ENOMEM); | ||
555 | } | ||
556 | |||
557 | dev_priv->dma_access = MGA_PAGPXFER; | ||
558 | dev_priv->wagp_enable = MGA_WAGP_ENABLE; | ||
559 | |||
560 | DRM_INFO("Initialized card for AGP DMA.\n"); | ||
561 | return 0; | ||
562 | } | ||
563 | |||
564 | /** | ||
565 | * Bootstrap the driver for PCI DMA. | ||
566 | * | ||
567 | * \todo | ||
568 | * The algorithm for decreasing the size of the primary DMA buffer could be | ||
569 | * better. The size should be rounded up to the nearest page size, then | ||
570 | * decrease the request size by a single page each pass through the loop. | ||
571 | * | ||
572 | * \todo | ||
573 | * Determine whether the maximum address passed to drm_pci_alloc is correct. | ||
574 | * The same goes for drm_addbufs_pci. | ||
575 | * | ||
576 | * \sa mga_do_dma_bootstrap, mga_do_agp_dma_bootstrap | ||
577 | */ | ||
578 | static int mga_do_pci_dma_bootstrap(drm_device_t * dev, | ||
579 | drm_mga_dma_bootstrap_t * dma_bs) | ||
580 | { | ||
581 | drm_mga_private_t * const dev_priv = (drm_mga_private_t *) dev->dev_private; | ||
582 | const unsigned int warp_size = mga_warp_microcode_size(dev_priv); | ||
583 | unsigned int primary_size; | ||
584 | unsigned int bin_count; | ||
585 | int err; | ||
586 | drm_buf_desc_t req; | ||
587 | |||
588 | |||
589 | if (dev->dma == NULL) { | ||
590 | DRM_ERROR("dev->dma is NULL\n"); | ||
591 | return DRM_ERR(EFAULT); | ||
592 | } | ||
593 | |||
594 | /* The proper alignment is 0x100 for this mapping */ | ||
595 | err = drm_addmap(dev, 0, warp_size, _DRM_CONSISTENT, | ||
596 | _DRM_READ_ONLY, &dev_priv->warp); | ||
597 | if (err != 0) { | ||
598 | DRM_ERROR("Unable to create mapping for WARP microcode\n"); | ||
599 | return err; | ||
600 | } | ||
601 | |||
602 | /* Other than the bottom two bits being used to encode other | ||
603 | * information, there don't appear to be any restrictions on the | ||
604 | * alignment of the primary or secondary DMA buffers. | ||
605 | */ | ||
606 | |||
607 | for ( primary_size = dma_bs->primary_size | ||
608 | ; primary_size != 0 | ||
609 | ; primary_size >>= 1 ) { | ||
610 | /* The proper alignment for this mapping is 0x04 */ | ||
611 | err = drm_addmap(dev, 0, primary_size, _DRM_CONSISTENT, | ||
612 | _DRM_READ_ONLY, &dev_priv->primary); | ||
613 | if (!err) | ||
614 | break; | ||
615 | } | ||
616 | |||
617 | if (err != 0) { | ||
618 | DRM_ERROR("Unable to allocate primary DMA region\n"); | ||
619 | return DRM_ERR(ENOMEM); | ||
620 | } | ||
621 | |||
622 | if (dev_priv->primary->size != dma_bs->primary_size) { | ||
623 | DRM_INFO("Primary DMA buffer size reduced from %u to %u.\n", | ||
624 | dma_bs->primary_size, | ||
625 | (unsigned) dev_priv->primary->size); | ||
626 | dma_bs->primary_size = dev_priv->primary->size; | ||
627 | } | ||
628 | |||
629 | for ( bin_count = dma_bs->secondary_bin_count | ||
630 | ; bin_count > 0 | ||
631 | ; bin_count-- ) { | ||
632 | (void) memset( &req, 0, sizeof(req) ); | ||
633 | req.count = bin_count; | ||
634 | req.size = dma_bs->secondary_bin_size; | ||
635 | |||
636 | err = drm_addbufs_pci( dev, & req ); | ||
637 | if (!err) { | ||
638 | break; | ||
639 | } | ||
640 | } | ||
641 | |||
642 | if (bin_count == 0) { | ||
643 | DRM_ERROR("Unable to add secondary DMA buffers\n"); | ||
644 | return err; | ||
645 | } | ||
646 | |||
647 | if (bin_count != dma_bs->secondary_bin_count) { | ||
648 | DRM_INFO("Secondary PCI DMA buffer bin count reduced from %u " | ||
649 | "to %u.\n", dma_bs->secondary_bin_count, bin_count); | ||
650 | |||
651 | dma_bs->secondary_bin_count = bin_count; | ||
652 | } | ||
653 | |||
654 | dev_priv->dma_access = 0; | ||
655 | dev_priv->wagp_enable = 0; | ||
656 | |||
657 | dma_bs->agp_mode = 0; | ||
658 | |||
659 | DRM_INFO("Initialized card for PCI DMA.\n"); | ||
660 | return 0; | ||
661 | } | ||
662 | |||
663 | |||
664 | static int mga_do_dma_bootstrap(drm_device_t * dev, | ||
665 | drm_mga_dma_bootstrap_t * dma_bs) | ||
666 | { | ||
667 | const int is_agp = (dma_bs->agp_mode != 0) && drm_device_is_agp(dev); | ||
668 | int err; | ||
669 | drm_mga_private_t * const dev_priv = | ||
670 | (drm_mga_private_t *) dev->dev_private; | ||
671 | |||
672 | |||
673 | dev_priv->used_new_dma_init = 1; | ||
674 | |||
675 | /* The first steps are the same for both PCI and AGP based DMA. Map | ||
676 | * the cards MMIO registers and map a status page. | ||
677 | */ | ||
678 | err = drm_addmap( dev, dev_priv->mmio_base, dev_priv->mmio_size, | ||
679 | _DRM_REGISTERS, _DRM_READ_ONLY, & dev_priv->mmio ); | ||
680 | if (err) { | ||
681 | DRM_ERROR("Unable to map MMIO region\n"); | ||
682 | return err; | ||
683 | } | ||
684 | |||
685 | |||
686 | err = drm_addmap( dev, 0, SAREA_MAX, _DRM_SHM, | ||
687 | _DRM_READ_ONLY | _DRM_LOCKED | _DRM_KERNEL, | ||
688 | & dev_priv->status ); | ||
689 | if (err) { | ||
690 | DRM_ERROR("Unable to map status region\n"); | ||
691 | return err; | ||
692 | } | ||
693 | |||
694 | |||
695 | /* The DMA initialization procedure is slightly different for PCI and | ||
696 | * AGP cards. AGP cards just allocate a large block of AGP memory and | ||
697 | * carve off portions of it for internal uses. The remaining memory | ||
698 | * is returned to user-mode to be used for AGP textures. | ||
699 | */ | ||
700 | |||
701 | if (is_agp) { | ||
702 | err = mga_do_agp_dma_bootstrap(dev, dma_bs); | ||
703 | } | ||
704 | |||
705 | /* If we attempted to initialize the card for AGP DMA but failed, | ||
706 | * clean-up any mess that may have been created. | ||
707 | */ | ||
708 | |||
709 | if (err) { | ||
710 | mga_do_cleanup_dma(dev); | ||
711 | } | ||
712 | |||
713 | |||
714 | /* Not only do we want to try and initialized PCI cards for PCI DMA, | ||
715 | * but we also try to initialized AGP cards that could not be | ||
716 | * initialized for AGP DMA. This covers the case where we have an AGP | ||
717 | * card in a system with an unsupported AGP chipset. In that case the | ||
718 | * card will be detected as AGP, but we won't be able to allocate any | ||
719 | * AGP memory, etc. | ||
720 | */ | ||
721 | |||
722 | if (!is_agp || err) { | ||
723 | err = mga_do_pci_dma_bootstrap(dev, dma_bs); | ||
724 | } | ||
725 | |||
726 | |||
727 | return err; | ||
728 | } | ||
729 | |||
730 | int mga_dma_bootstrap(DRM_IOCTL_ARGS) | ||
731 | { | ||
732 | DRM_DEVICE; | ||
733 | drm_mga_dma_bootstrap_t bootstrap; | ||
734 | int err; | ||
735 | |||
736 | |||
737 | DRM_COPY_FROM_USER_IOCTL(bootstrap, | ||
738 | (drm_mga_dma_bootstrap_t __user *) data, | ||
739 | sizeof(bootstrap)); | ||
740 | |||
741 | err = mga_do_dma_bootstrap(dev, & bootstrap); | ||
742 | if (! err) { | ||
743 | static const int modes[] = { 0, 1, 2, 2, 4, 4, 4, 4 }; | ||
744 | const drm_mga_private_t * const dev_priv = | ||
745 | (drm_mga_private_t *) dev->dev_private; | ||
746 | |||
747 | if (dev_priv->agp_textures != NULL) { | ||
748 | bootstrap.texture_handle = dev_priv->agp_textures->offset; | ||
749 | bootstrap.texture_size = dev_priv->agp_textures->size; | ||
750 | } | ||
751 | else { | ||
752 | bootstrap.texture_handle = 0; | ||
753 | bootstrap.texture_size = 0; | ||
754 | } | ||
755 | |||
756 | bootstrap.agp_mode = modes[ bootstrap.agp_mode & 0x07 ]; | ||
757 | if (DRM_COPY_TO_USER( (void __user *) data, & bootstrap, | ||
758 | sizeof(bootstrap))) { | ||
759 | err = DRM_ERR(EFAULT); | ||
760 | } | ||
761 | } | ||
762 | else { | ||
763 | mga_do_cleanup_dma(dev); | ||
764 | } | ||
765 | |||
766 | return err; | ||
767 | } | ||
768 | |||
399 | static int mga_do_init_dma( drm_device_t *dev, drm_mga_init_t *init ) | 769 | static int mga_do_init_dma( drm_device_t *dev, drm_mga_init_t *init ) |
400 | { | 770 | { |
401 | drm_mga_private_t *dev_priv; | 771 | drm_mga_private_t *dev_priv; |
402 | int ret; | 772 | int ret; |
403 | DRM_DEBUG( "\n" ); | 773 | DRM_DEBUG( "\n" ); |
404 | 774 | ||
405 | dev_priv = drm_alloc( sizeof(drm_mga_private_t), DRM_MEM_DRIVER ); | ||
406 | if ( !dev_priv ) | ||
407 | return DRM_ERR(ENOMEM); | ||
408 | |||
409 | memset( dev_priv, 0, sizeof(drm_mga_private_t) ); | ||
410 | 775 | ||
411 | dev_priv->chipset = init->chipset; | 776 | dev_priv = dev->dev_private; |
412 | 777 | ||
413 | dev_priv->usec_timeout = MGA_DEFAULT_USEC_TIMEOUT; | 778 | if (init->sgram) { |
414 | |||
415 | if ( init->sgram ) { | ||
416 | dev_priv->clear_cmd = MGA_DWGCTL_CLEAR | MGA_ATYPE_BLK; | 779 | dev_priv->clear_cmd = MGA_DWGCTL_CLEAR | MGA_ATYPE_BLK; |
417 | } else { | 780 | } else { |
418 | dev_priv->clear_cmd = MGA_DWGCTL_CLEAR | MGA_ATYPE_RSTR; | 781 | dev_priv->clear_cmd = MGA_DWGCTL_CLEAR | MGA_ATYPE_RSTR; |
@@ -436,88 +799,65 @@ static int mga_do_init_dma( drm_device_t *dev, drm_mga_init_t *init ) | |||
436 | 799 | ||
437 | DRM_GETSAREA(); | 800 | DRM_GETSAREA(); |
438 | 801 | ||
439 | if(!dev_priv->sarea) { | 802 | if (!dev_priv->sarea) { |
440 | DRM_ERROR( "failed to find sarea!\n" ); | 803 | DRM_ERROR("failed to find sarea!\n"); |
441 | /* Assign dev_private so we can do cleanup. */ | ||
442 | dev->dev_private = (void *)dev_priv; | ||
443 | mga_do_cleanup_dma( dev ); | ||
444 | return DRM_ERR(EINVAL); | 804 | return DRM_ERR(EINVAL); |
445 | } | 805 | } |
446 | 806 | ||
447 | dev_priv->mmio = drm_core_findmap(dev, init->mmio_offset); | 807 | if (! dev_priv->used_new_dma_init) { |
448 | if(!dev_priv->mmio) { | 808 | dev_priv->status = drm_core_findmap(dev, init->status_offset); |
449 | DRM_ERROR( "failed to find mmio region!\n" ); | 809 | if (!dev_priv->status) { |
450 | /* Assign dev_private so we can do cleanup. */ | 810 | DRM_ERROR("failed to find status page!\n"); |
451 | dev->dev_private = (void *)dev_priv; | 811 | return DRM_ERR(EINVAL); |
452 | mga_do_cleanup_dma( dev ); | 812 | } |
453 | return DRM_ERR(EINVAL); | 813 | dev_priv->mmio = drm_core_findmap(dev, init->mmio_offset); |
454 | } | 814 | if (!dev_priv->mmio) { |
455 | dev_priv->status = drm_core_findmap(dev, init->status_offset); | 815 | DRM_ERROR("failed to find mmio region!\n"); |
456 | if(!dev_priv->status) { | 816 | return DRM_ERR(EINVAL); |
457 | DRM_ERROR( "failed to find status page!\n" ); | 817 | } |
458 | /* Assign dev_private so we can do cleanup. */ | 818 | dev_priv->warp = drm_core_findmap(dev, init->warp_offset); |
459 | dev->dev_private = (void *)dev_priv; | 819 | if (!dev_priv->warp) { |
460 | mga_do_cleanup_dma( dev ); | 820 | DRM_ERROR("failed to find warp microcode region!\n"); |
461 | return DRM_ERR(EINVAL); | 821 | return DRM_ERR(EINVAL); |
462 | } | 822 | } |
463 | dev_priv->warp = drm_core_findmap(dev, init->warp_offset); | 823 | dev_priv->primary = drm_core_findmap(dev, init->primary_offset); |
464 | if(!dev_priv->warp) { | 824 | if (!dev_priv->primary) { |
465 | DRM_ERROR( "failed to find warp microcode region!\n" ); | 825 | DRM_ERROR("failed to find primary dma region!\n"); |
466 | /* Assign dev_private so we can do cleanup. */ | 826 | return DRM_ERR(EINVAL); |
467 | dev->dev_private = (void *)dev_priv; | 827 | } |
468 | mga_do_cleanup_dma( dev ); | 828 | dev->agp_buffer_map = drm_core_findmap(dev, init->buffers_offset); |
469 | return DRM_ERR(EINVAL); | 829 | if (!dev->agp_buffer_map) { |
470 | } | 830 | DRM_ERROR("failed to find dma buffer region!\n"); |
471 | dev_priv->primary = drm_core_findmap(dev, init->primary_offset); | 831 | return DRM_ERR(EINVAL); |
472 | if(!dev_priv->primary) { | 832 | } |
473 | DRM_ERROR( "failed to find primary dma region!\n" ); | 833 | |
474 | /* Assign dev_private so we can do cleanup. */ | 834 | drm_core_ioremap(dev_priv->warp, dev); |
475 | dev->dev_private = (void *)dev_priv; | 835 | drm_core_ioremap(dev_priv->primary, dev); |
476 | mga_do_cleanup_dma( dev ); | 836 | drm_core_ioremap(dev->agp_buffer_map, dev); |
477 | return DRM_ERR(EINVAL); | ||
478 | } | ||
479 | dev->agp_buffer_map = drm_core_findmap(dev, init->buffers_offset); | ||
480 | if(!dev->agp_buffer_map) { | ||
481 | DRM_ERROR( "failed to find dma buffer region!\n" ); | ||
482 | /* Assign dev_private so we can do cleanup. */ | ||
483 | dev->dev_private = (void *)dev_priv; | ||
484 | mga_do_cleanup_dma( dev ); | ||
485 | return DRM_ERR(EINVAL); | ||
486 | } | 837 | } |
487 | 838 | ||
488 | dev_priv->sarea_priv = | 839 | dev_priv->sarea_priv = |
489 | (drm_mga_sarea_t *)((u8 *)dev_priv->sarea->handle + | 840 | (drm_mga_sarea_t *)((u8 *)dev_priv->sarea->handle + |
490 | init->sarea_priv_offset); | 841 | init->sarea_priv_offset); |
491 | 842 | ||
492 | drm_core_ioremap( dev_priv->warp, dev ); | 843 | if (!dev_priv->warp->handle || |
493 | drm_core_ioremap( dev_priv->primary, dev ); | 844 | !dev_priv->primary->handle || |
494 | drm_core_ioremap( dev->agp_buffer_map, dev ); | 845 | ((dev_priv->dma_access != 0) && |
495 | 846 | ((dev->agp_buffer_map == NULL) || | |
496 | if(!dev_priv->warp->handle || | 847 | (dev->agp_buffer_map->handle == NULL)))) { |
497 | !dev_priv->primary->handle || | 848 | DRM_ERROR("failed to ioremap agp regions!\n"); |
498 | !dev->agp_buffer_map->handle ) { | ||
499 | DRM_ERROR( "failed to ioremap agp regions!\n" ); | ||
500 | /* Assign dev_private so we can do cleanup. */ | ||
501 | dev->dev_private = (void *)dev_priv; | ||
502 | mga_do_cleanup_dma( dev ); | ||
503 | return DRM_ERR(ENOMEM); | 849 | return DRM_ERR(ENOMEM); |
504 | } | 850 | } |
505 | 851 | ||
506 | ret = mga_warp_install_microcode( dev_priv ); | 852 | ret = mga_warp_install_microcode(dev_priv); |
507 | if ( ret < 0 ) { | 853 | if (ret < 0) { |
508 | DRM_ERROR( "failed to install WARP ucode!\n" ); | 854 | DRM_ERROR("failed to install WARP ucode!\n"); |
509 | /* Assign dev_private so we can do cleanup. */ | ||
510 | dev->dev_private = (void *)dev_priv; | ||
511 | mga_do_cleanup_dma( dev ); | ||
512 | return ret; | 855 | return ret; |
513 | } | 856 | } |
514 | 857 | ||
515 | ret = mga_warp_init( dev_priv ); | 858 | ret = mga_warp_init(dev_priv); |
516 | if ( ret < 0 ) { | 859 | if (ret < 0) { |
517 | DRM_ERROR( "failed to init WARP engine!\n" ); | 860 | DRM_ERROR("failed to init WARP engine!\n"); |
518 | /* Assign dev_private so we can do cleanup. */ | ||
519 | dev->dev_private = (void *)dev_priv; | ||
520 | mga_do_cleanup_dma( dev ); | ||
521 | return ret; | 861 | return ret; |
522 | } | 862 | } |
523 | 863 | ||
@@ -557,22 +897,18 @@ static int mga_do_init_dma( drm_device_t *dev, drm_mga_init_t *init ) | |||
557 | dev_priv->sarea_priv->last_frame.head = 0; | 897 | dev_priv->sarea_priv->last_frame.head = 0; |
558 | dev_priv->sarea_priv->last_frame.wrap = 0; | 898 | dev_priv->sarea_priv->last_frame.wrap = 0; |
559 | 899 | ||
560 | if ( mga_freelist_init( dev, dev_priv ) < 0 ) { | 900 | if (mga_freelist_init(dev, dev_priv) < 0) { |
561 | DRM_ERROR( "could not initialize freelist\n" ); | 901 | DRM_ERROR("could not initialize freelist\n"); |
562 | /* Assign dev_private so we can do cleanup. */ | ||
563 | dev->dev_private = (void *)dev_priv; | ||
564 | mga_do_cleanup_dma( dev ); | ||
565 | return DRM_ERR(ENOMEM); | 902 | return DRM_ERR(ENOMEM); |
566 | } | 903 | } |
567 | 904 | ||
568 | /* Make dev_private visable to others. */ | ||
569 | dev->dev_private = (void *)dev_priv; | ||
570 | return 0; | 905 | return 0; |
571 | } | 906 | } |
572 | 907 | ||
573 | static int mga_do_cleanup_dma( drm_device_t *dev ) | 908 | static int mga_do_cleanup_dma( drm_device_t *dev ) |
574 | { | 909 | { |
575 | DRM_DEBUG( "\n" ); | 910 | int err = 0; |
911 | DRM_DEBUG("\n"); | ||
576 | 912 | ||
577 | /* Make sure interrupts are disabled here because the uninstall ioctl | 913 | /* Make sure interrupts are disabled here because the uninstall ioctl |
578 | * may not have been called from userspace and after dev_private | 914 | * may not have been called from userspace and after dev_private |
@@ -583,20 +919,49 @@ static int mga_do_cleanup_dma( drm_device_t *dev ) | |||
583 | if ( dev->dev_private ) { | 919 | if ( dev->dev_private ) { |
584 | drm_mga_private_t *dev_priv = dev->dev_private; | 920 | drm_mga_private_t *dev_priv = dev->dev_private; |
585 | 921 | ||
586 | if ( dev_priv->warp != NULL ) | 922 | if ((dev_priv->warp != NULL) |
587 | drm_core_ioremapfree( dev_priv->warp, dev ); | 923 | && (dev_priv->mmio->type != _DRM_CONSISTENT)) |
588 | if ( dev_priv->primary != NULL ) | 924 | drm_core_ioremapfree(dev_priv->warp, dev); |
589 | drm_core_ioremapfree( dev_priv->primary, dev ); | 925 | |
590 | if ( dev->agp_buffer_map != NULL ) | 926 | if ((dev_priv->primary != NULL) |
591 | drm_core_ioremapfree( dev->agp_buffer_map, dev ); | 927 | && (dev_priv->primary->type != _DRM_CONSISTENT)) |
928 | drm_core_ioremapfree(dev_priv->primary, dev); | ||
592 | 929 | ||
593 | if ( dev_priv->head != NULL ) { | 930 | if (dev->agp_buffer_map != NULL) |
594 | mga_freelist_cleanup( dev ); | 931 | drm_core_ioremapfree(dev->agp_buffer_map, dev); |
932 | |||
933 | if (dev_priv->used_new_dma_init) { | ||
934 | if (dev_priv->agp_mem != NULL) { | ||
935 | dev_priv->agp_textures = NULL; | ||
936 | drm_unbind_agp(dev_priv->agp_mem); | ||
937 | |||
938 | drm_free_agp(dev_priv->agp_mem, dev_priv->agp_pages); | ||
939 | dev_priv->agp_pages = 0; | ||
940 | dev_priv->agp_mem = NULL; | ||
941 | } | ||
942 | |||
943 | if ((dev->agp != NULL) && dev->agp->acquired) { | ||
944 | err = drm_agp_release(dev); | ||
945 | } | ||
946 | |||
947 | dev_priv->used_new_dma_init = 0; | ||
595 | } | 948 | } |
596 | 949 | ||
597 | drm_free( dev->dev_private, sizeof(drm_mga_private_t), | 950 | dev_priv->warp = NULL; |
598 | DRM_MEM_DRIVER ); | 951 | dev_priv->primary = NULL; |
599 | dev->dev_private = NULL; | 952 | dev_priv->mmio = NULL; |
953 | dev_priv->status = NULL; | ||
954 | dev_priv->sarea = NULL; | ||
955 | dev_priv->sarea_priv = NULL; | ||
956 | dev->agp_buffer_map = NULL; | ||
957 | |||
958 | memset(&dev_priv->prim, 0, sizeof(dev_priv->prim)); | ||
959 | dev_priv->warp_pipe = 0; | ||
960 | memset(dev_priv->warp_pipe_phys, 0, sizeof(dev_priv->warp_pipe_phys)); | ||
961 | |||
962 | if (dev_priv->head != NULL) { | ||
963 | mga_freelist_cleanup(dev); | ||
964 | } | ||
600 | } | 965 | } |
601 | 966 | ||
602 | return 0; | 967 | return 0; |
@@ -606,14 +971,20 @@ int mga_dma_init( DRM_IOCTL_ARGS ) | |||
606 | { | 971 | { |
607 | DRM_DEVICE; | 972 | DRM_DEVICE; |
608 | drm_mga_init_t init; | 973 | drm_mga_init_t init; |
974 | int err; | ||
609 | 975 | ||
610 | LOCK_TEST_WITH_RETURN( dev, filp ); | 976 | LOCK_TEST_WITH_RETURN( dev, filp ); |
611 | 977 | ||
612 | DRM_COPY_FROM_USER_IOCTL( init, (drm_mga_init_t __user *)data, sizeof(init) ); | 978 | DRM_COPY_FROM_USER_IOCTL(init, (drm_mga_init_t __user *) data, |
979 | sizeof(init)); | ||
613 | 980 | ||
614 | switch ( init.func ) { | 981 | switch ( init.func ) { |
615 | case MGA_INIT_DMA: | 982 | case MGA_INIT_DMA: |
616 | return mga_do_init_dma( dev, &init ); | 983 | err = mga_do_init_dma(dev, &init); |
984 | if (err) { | ||
985 | (void) mga_do_cleanup_dma(dev); | ||
986 | } | ||
987 | return err; | ||
617 | case MGA_CLEANUP_DMA: | 988 | case MGA_CLEANUP_DMA: |
618 | return mga_do_cleanup_dma( dev ); | 989 | return mga_do_cleanup_dma( dev ); |
619 | } | 990 | } |
@@ -742,7 +1113,21 @@ int mga_dma_buffers( DRM_IOCTL_ARGS ) | |||
742 | return ret; | 1113 | return ret; |
743 | } | 1114 | } |
744 | 1115 | ||
745 | void mga_driver_pretakedown(drm_device_t *dev) | 1116 | /** |
1117 | * Called just before the module is unloaded. | ||
1118 | */ | ||
1119 | int mga_driver_postcleanup(drm_device_t * dev) | ||
1120 | { | ||
1121 | drm_free(dev->dev_private, sizeof(drm_mga_private_t), DRM_MEM_DRIVER); | ||
1122 | dev->dev_private = NULL; | ||
1123 | |||
1124 | return 0; | ||
1125 | } | ||
1126 | |||
1127 | /** | ||
1128 | * Called when the last opener of the device is closed. | ||
1129 | */ | ||
1130 | void mga_driver_pretakedown(drm_device_t * dev) | ||
746 | { | 1131 | { |
747 | mga_do_cleanup_dma( dev ); | 1132 | mga_do_cleanup_dma( dev ); |
748 | } | 1133 | } |
diff --git a/drivers/char/drm/mga_drm.h b/drivers/char/drm/mga_drm.h index 521d4451d012..2d8aa790379e 100644 --- a/drivers/char/drm/mga_drm.h +++ b/drivers/char/drm/mga_drm.h | |||
@@ -73,7 +73,8 @@ | |||
73 | 73 | ||
74 | #define MGA_CARD_TYPE_G200 1 | 74 | #define MGA_CARD_TYPE_G200 1 |
75 | #define MGA_CARD_TYPE_G400 2 | 75 | #define MGA_CARD_TYPE_G400 2 |
76 | 76 | #define MGA_CARD_TYPE_G450 3 /* not currently used */ | |
77 | #define MGA_CARD_TYPE_G550 4 | ||
77 | 78 | ||
78 | #define MGA_FRONT 0x1 | 79 | #define MGA_FRONT 0x1 |
79 | #define MGA_BACK 0x2 | 80 | #define MGA_BACK 0x2 |
@@ -225,10 +226,6 @@ typedef struct _drm_mga_sarea { | |||
225 | } drm_mga_sarea_t; | 226 | } drm_mga_sarea_t; |
226 | 227 | ||
227 | 228 | ||
228 | /* WARNING: If you change any of these defines, make sure to change the | ||
229 | * defines in the Xserver file (xf86drmMga.h) | ||
230 | */ | ||
231 | |||
232 | /* MGA specific ioctls | 229 | /* MGA specific ioctls |
233 | * The device specific ioctl range is 0x40 to 0x79. | 230 | * The device specific ioctl range is 0x40 to 0x79. |
234 | */ | 231 | */ |
@@ -243,6 +240,14 @@ typedef struct _drm_mga_sarea { | |||
243 | #define DRM_MGA_BLIT 0x08 | 240 | #define DRM_MGA_BLIT 0x08 |
244 | #define DRM_MGA_GETPARAM 0x09 | 241 | #define DRM_MGA_GETPARAM 0x09 |
245 | 242 | ||
243 | /* 3.2: | ||
244 | * ioctls for operating on fences. | ||
245 | */ | ||
246 | #define DRM_MGA_SET_FENCE 0x0a | ||
247 | #define DRM_MGA_WAIT_FENCE 0x0b | ||
248 | #define DRM_MGA_DMA_BOOTSTRAP 0x0c | ||
249 | |||
250 | |||
246 | #define DRM_IOCTL_MGA_INIT DRM_IOW( DRM_COMMAND_BASE + DRM_MGA_INIT, drm_mga_init_t) | 251 | #define DRM_IOCTL_MGA_INIT DRM_IOW( DRM_COMMAND_BASE + DRM_MGA_INIT, drm_mga_init_t) |
247 | #define DRM_IOCTL_MGA_FLUSH DRM_IOW( DRM_COMMAND_BASE + DRM_MGA_FLUSH, drm_lock_t) | 252 | #define DRM_IOCTL_MGA_FLUSH DRM_IOW( DRM_COMMAND_BASE + DRM_MGA_FLUSH, drm_lock_t) |
248 | #define DRM_IOCTL_MGA_RESET DRM_IO( DRM_COMMAND_BASE + DRM_MGA_RESET) | 253 | #define DRM_IOCTL_MGA_RESET DRM_IO( DRM_COMMAND_BASE + DRM_MGA_RESET) |
@@ -253,6 +258,9 @@ typedef struct _drm_mga_sarea { | |||
253 | #define DRM_IOCTL_MGA_ILOAD DRM_IOW( DRM_COMMAND_BASE + DRM_MGA_ILOAD, drm_mga_iload_t) | 258 | #define DRM_IOCTL_MGA_ILOAD DRM_IOW( DRM_COMMAND_BASE + DRM_MGA_ILOAD, drm_mga_iload_t) |
254 | #define DRM_IOCTL_MGA_BLIT DRM_IOW( DRM_COMMAND_BASE + DRM_MGA_BLIT, drm_mga_blit_t) | 259 | #define DRM_IOCTL_MGA_BLIT DRM_IOW( DRM_COMMAND_BASE + DRM_MGA_BLIT, drm_mga_blit_t) |
255 | #define DRM_IOCTL_MGA_GETPARAM DRM_IOWR(DRM_COMMAND_BASE + DRM_MGA_GETPARAM, drm_mga_getparam_t) | 260 | #define DRM_IOCTL_MGA_GETPARAM DRM_IOWR(DRM_COMMAND_BASE + DRM_MGA_GETPARAM, drm_mga_getparam_t) |
261 | #define DRM_IOCTL_MGA_SET_FENCE DRM_IOW( DRM_COMMAND_BASE + DRM_MGA_SET_FENCE, uint32_t) | ||
262 | #define DRM_IOCTL_MGA_WAIT_FENCE DRM_IOWR(DRM_COMMAND_BASE + DRM_MGA_WAIT_FENCE, uint32_t) | ||
263 | #define DRM_IOCTL_MGA_DMA_BOOTSTRAP DRM_IOWR(DRM_COMMAND_BASE + DRM_MGA_DMA_BOOTSTRAP, drm_mga_dma_bootstrap_t) | ||
256 | 264 | ||
257 | typedef struct _drm_mga_warp_index { | 265 | typedef struct _drm_mga_warp_index { |
258 | int installed; | 266 | int installed; |
@@ -291,12 +299,72 @@ typedef struct drm_mga_init { | |||
291 | unsigned long buffers_offset; | 299 | unsigned long buffers_offset; |
292 | } drm_mga_init_t; | 300 | } drm_mga_init_t; |
293 | 301 | ||
294 | typedef struct drm_mga_fullscreen { | 302 | typedef struct drm_mga_dma_bootstrap { |
295 | enum { | 303 | /** |
296 | MGA_INIT_FULLSCREEN = 0x01, | 304 | * \name AGP texture region |
297 | MGA_CLEANUP_FULLSCREEN = 0x02 | 305 | * |
298 | } func; | 306 | * On return from the DRM_MGA_DMA_BOOTSTRAP ioctl, these fields will |
299 | } drm_mga_fullscreen_t; | 307 | * be filled in with the actual AGP texture settings. |
308 | * | ||
309 | * \warning | ||
310 | * If these fields are non-zero, but dma_mga_dma_bootstrap::agp_mode | ||
311 | * is zero, it means that PCI memory (most likely through the use of | ||
312 | * an IOMMU) is being used for "AGP" textures. | ||
313 | */ | ||
314 | /*@{*/ | ||
315 | drm_handle_t texture_handle; /**< Handle used to map AGP textures. */ | ||
316 | uint32_t texture_size; /**< Size of the AGP texture region. */ | ||
317 | /*@}*/ | ||
318 | |||
319 | |||
320 | /** | ||
321 | * Requested size of the primary DMA region. | ||
322 | * | ||
323 | * On return from the DRM_MGA_DMA_BOOTSTRAP ioctl, this field will be | ||
324 | * filled in with the actual AGP mode. If AGP was not available | ||
325 | */ | ||
326 | uint32_t primary_size; | ||
327 | |||
328 | |||
329 | /** | ||
330 | * Requested number of secondary DMA buffers. | ||
331 | * | ||
332 | * On return from the DRM_MGA_DMA_BOOTSTRAP ioctl, this field will be | ||
333 | * filled in with the actual number of secondary DMA buffers | ||
334 | * allocated. Particularly when PCI DMA is used, this may be | ||
335 | * (subtantially) less than the number requested. | ||
336 | */ | ||
337 | uint32_t secondary_bin_count; | ||
338 | |||
339 | |||
340 | /** | ||
341 | * Requested size of each secondary DMA buffer. | ||
342 | * | ||
343 | * While the kernel \b is free to reduce | ||
344 | * dma_mga_dma_bootstrap::secondary_bin_count, it is \b not allowed | ||
345 | * to reduce dma_mga_dma_bootstrap::secondary_bin_size. | ||
346 | */ | ||
347 | uint32_t secondary_bin_size; | ||
348 | |||
349 | |||
350 | /** | ||
351 | * Bit-wise mask of AGPSTAT2_* values. Currently only \c AGPSTAT2_1X, | ||
352 | * \c AGPSTAT2_2X, and \c AGPSTAT2_4X are supported. If this value is | ||
353 | * zero, it means that PCI DMA should be used, even if AGP is | ||
354 | * possible. | ||
355 | * | ||
356 | * On return from the DRM_MGA_DMA_BOOTSTRAP ioctl, this field will be | ||
357 | * filled in with the actual AGP mode. If AGP was not available | ||
358 | * (i.e., PCI DMA was used), this value will be zero. | ||
359 | */ | ||
360 | uint32_t agp_mode; | ||
361 | |||
362 | |||
363 | /** | ||
364 | * Desired AGP GART size, measured in megabytes. | ||
365 | */ | ||
366 | uint8_t agp_size; | ||
367 | } drm_mga_dma_bootstrap_t; | ||
300 | 368 | ||
301 | typedef struct drm_mga_clear { | 369 | typedef struct drm_mga_clear { |
302 | unsigned int flags; | 370 | unsigned int flags; |
@@ -341,6 +409,14 @@ typedef struct _drm_mga_blit { | |||
341 | */ | 409 | */ |
342 | #define MGA_PARAM_IRQ_NR 1 | 410 | #define MGA_PARAM_IRQ_NR 1 |
343 | 411 | ||
412 | /* 3.2: Query the actual card type. The DDX only distinguishes between | ||
413 | * G200 chips and non-G200 chips, which it calls G400. It turns out that | ||
414 | * there are some very sublte differences between the G4x0 chips and the G550 | ||
415 | * chips. Using this parameter query, a client-side driver can detect the | ||
416 | * difference between a G4x0 and a G550. | ||
417 | */ | ||
418 | #define MGA_PARAM_CARD_TYPE 2 | ||
419 | |||
344 | typedef struct drm_mga_getparam { | 420 | typedef struct drm_mga_getparam { |
345 | int param; | 421 | int param; |
346 | void __user *value; | 422 | void __user *value; |
diff --git a/drivers/char/drm/mga_drv.c b/drivers/char/drm/mga_drv.c index 844cca9cb29d..daabbba3b297 100644 --- a/drivers/char/drm/mga_drv.c +++ b/drivers/char/drm/mga_drv.c | |||
@@ -38,8 +38,15 @@ | |||
38 | 38 | ||
39 | #include "drm_pciids.h" | 39 | #include "drm_pciids.h" |
40 | 40 | ||
41 | static int mga_driver_device_is_agp(drm_device_t * dev); | ||
41 | static int postinit( struct drm_device *dev, unsigned long flags ) | 42 | static int postinit( struct drm_device *dev, unsigned long flags ) |
42 | { | 43 | { |
44 | drm_mga_private_t * const dev_priv = | ||
45 | (drm_mga_private_t *) dev->dev_private; | ||
46 | |||
47 | dev_priv->mmio_base = pci_resource_start(dev->pdev, 1); | ||
48 | dev_priv->mmio_size = pci_resource_len(dev->pdev, 1); | ||
49 | |||
43 | dev->counters += 3; | 50 | dev->counters += 3; |
44 | dev->types[6] = _DRM_STAT_IRQ; | 51 | dev->types[6] = _DRM_STAT_IRQ; |
45 | dev->types[7] = _DRM_STAT_PRIMARY; | 52 | dev->types[7] = _DRM_STAT_PRIMARY; |
@@ -79,8 +86,11 @@ extern int mga_max_ioctl; | |||
79 | 86 | ||
80 | static struct drm_driver driver = { | 87 | static struct drm_driver driver = { |
81 | .driver_features = DRIVER_USE_AGP | DRIVER_REQUIRE_AGP | DRIVER_USE_MTRR | DRIVER_HAVE_DMA | DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED | DRIVER_IRQ_VBL, | 88 | .driver_features = DRIVER_USE_AGP | DRIVER_REQUIRE_AGP | DRIVER_USE_MTRR | DRIVER_HAVE_DMA | DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED | DRIVER_IRQ_VBL, |
89 | .preinit = mga_driver_preinit, | ||
90 | .postcleanup = mga_driver_postcleanup, | ||
82 | .pretakedown = mga_driver_pretakedown, | 91 | .pretakedown = mga_driver_pretakedown, |
83 | .dma_quiescent = mga_driver_dma_quiescent, | 92 | .dma_quiescent = mga_driver_dma_quiescent, |
93 | .device_is_agp = mga_driver_device_is_agp, | ||
84 | .vblank_wait = mga_driver_vblank_wait, | 94 | .vblank_wait = mga_driver_vblank_wait, |
85 | .irq_preinstall = mga_driver_irq_preinstall, | 95 | .irq_preinstall = mga_driver_irq_preinstall, |
86 | .irq_postinstall = mga_driver_irq_postinstall, | 96 | .irq_postinstall = mga_driver_irq_postinstall, |
@@ -128,3 +138,38 @@ module_exit(mga_exit); | |||
128 | MODULE_AUTHOR( DRIVER_AUTHOR ); | 138 | MODULE_AUTHOR( DRIVER_AUTHOR ); |
129 | MODULE_DESCRIPTION( DRIVER_DESC ); | 139 | MODULE_DESCRIPTION( DRIVER_DESC ); |
130 | MODULE_LICENSE("GPL and additional rights"); | 140 | MODULE_LICENSE("GPL and additional rights"); |
141 | |||
142 | /** | ||
143 | * Determine if the device really is AGP or not. | ||
144 | * | ||
145 | * In addition to the usual tests performed by \c drm_device_is_agp, this | ||
146 | * function detects PCI G450 cards that appear to the system exactly like | ||
147 | * AGP G450 cards. | ||
148 | * | ||
149 | * \param dev The device to be tested. | ||
150 | * | ||
151 | * \returns | ||
152 | * If the device is a PCI G450, zero is returned. Otherwise 2 is returned. | ||
153 | */ | ||
154 | int mga_driver_device_is_agp(drm_device_t * dev) | ||
155 | { | ||
156 | const struct pci_dev * const pdev = dev->pdev; | ||
157 | |||
158 | |||
159 | /* There are PCI versions of the G450. These cards have the | ||
160 | * same PCI ID as the AGP G450, but have an additional PCI-to-PCI | ||
161 | * bridge chip. We detect these cards, which are not currently | ||
162 | * supported by this driver, by looking at the device ID of the | ||
163 | * bus the "card" is on. If vendor is 0x3388 (Hint Corp) and the | ||
164 | * device is 0x0021 (HB6 Universal PCI-PCI bridge), we reject the | ||
165 | * device. | ||
166 | */ | ||
167 | |||
168 | if ( (pdev->device == 0x0525) | ||
169 | && (pdev->bus->self->vendor == 0x3388) | ||
170 | && (pdev->bus->self->device == 0x0021) ) { | ||
171 | return 0; | ||
172 | } | ||
173 | |||
174 | return 2; | ||
175 | } | ||
diff --git a/drivers/char/drm/mga_drv.h b/drivers/char/drm/mga_drv.h index 9412e2816eb7..b22fdbd4f830 100644 --- a/drivers/char/drm/mga_drv.h +++ b/drivers/char/drm/mga_drv.h | |||
@@ -38,10 +38,10 @@ | |||
38 | 38 | ||
39 | #define DRIVER_NAME "mga" | 39 | #define DRIVER_NAME "mga" |
40 | #define DRIVER_DESC "Matrox G200/G400" | 40 | #define DRIVER_DESC "Matrox G200/G400" |
41 | #define DRIVER_DATE "20021029" | 41 | #define DRIVER_DATE "20050607" |
42 | 42 | ||
43 | #define DRIVER_MAJOR 3 | 43 | #define DRIVER_MAJOR 3 |
44 | #define DRIVER_MINOR 1 | 44 | #define DRIVER_MINOR 2 |
45 | #define DRIVER_PATCHLEVEL 0 | 45 | #define DRIVER_PATCHLEVEL 0 |
46 | 46 | ||
47 | typedef struct drm_mga_primary_buffer { | 47 | typedef struct drm_mga_primary_buffer { |
@@ -87,9 +87,43 @@ typedef struct drm_mga_private { | |||
87 | int chipset; | 87 | int chipset; |
88 | int usec_timeout; | 88 | int usec_timeout; |
89 | 89 | ||
90 | /** | ||
91 | * If set, the new DMA initialization sequence was used. This is | ||
92 | * primarilly used to select how the driver should uninitialized its | ||
93 | * internal DMA structures. | ||
94 | */ | ||
95 | int used_new_dma_init; | ||
96 | |||
97 | /** | ||
98 | * If AGP memory is used for DMA buffers, this will be the value | ||
99 | * \c MGA_PAGPXFER. Otherwise, it will be zero (for a PCI transfer). | ||
100 | */ | ||
101 | u32 dma_access; | ||
102 | |||
103 | /** | ||
104 | * If AGP memory is used for DMA buffers, this will be the value | ||
105 | * \c MGA_WAGP_ENABLE. Otherwise, it will be zero (for a PCI | ||
106 | * transfer). | ||
107 | */ | ||
108 | u32 wagp_enable; | ||
109 | |||
110 | /** | ||
111 | * \name MMIO region parameters. | ||
112 | * | ||
113 | * \sa drm_mga_private_t::mmio | ||
114 | */ | ||
115 | /*@{*/ | ||
116 | u32 mmio_base; /**< Bus address of base of MMIO. */ | ||
117 | u32 mmio_size; /**< Size of the MMIO region. */ | ||
118 | /*@}*/ | ||
119 | |||
90 | u32 clear_cmd; | 120 | u32 clear_cmd; |
91 | u32 maccess; | 121 | u32 maccess; |
92 | 122 | ||
123 | wait_queue_head_t fence_queue; | ||
124 | atomic_t last_fence_retired; | ||
125 | u32 next_fence_to_post; | ||
126 | |||
93 | unsigned int fb_cpp; | 127 | unsigned int fb_cpp; |
94 | unsigned int front_offset; | 128 | unsigned int front_offset; |
95 | unsigned int front_pitch; | 129 | unsigned int front_pitch; |
@@ -108,35 +142,43 @@ typedef struct drm_mga_private { | |||
108 | drm_local_map_t *status; | 142 | drm_local_map_t *status; |
109 | drm_local_map_t *warp; | 143 | drm_local_map_t *warp; |
110 | drm_local_map_t *primary; | 144 | drm_local_map_t *primary; |
111 | drm_local_map_t *buffers; | ||
112 | drm_local_map_t *agp_textures; | 145 | drm_local_map_t *agp_textures; |
146 | |||
147 | DRM_AGP_MEM *agp_mem; | ||
148 | unsigned int agp_pages; | ||
113 | } drm_mga_private_t; | 149 | } drm_mga_private_t; |
114 | 150 | ||
115 | /* mga_dma.c */ | 151 | /* mga_dma.c */ |
116 | extern int mga_dma_init( DRM_IOCTL_ARGS ); | 152 | extern int mga_driver_preinit(drm_device_t * dev, unsigned long flags); |
117 | extern int mga_dma_flush( DRM_IOCTL_ARGS ); | 153 | extern int mga_dma_bootstrap(DRM_IOCTL_ARGS); |
118 | extern int mga_dma_reset( DRM_IOCTL_ARGS ); | 154 | extern int mga_dma_init(DRM_IOCTL_ARGS); |
119 | extern int mga_dma_buffers( DRM_IOCTL_ARGS ); | 155 | extern int mga_dma_flush(DRM_IOCTL_ARGS); |
120 | extern void mga_driver_pretakedown(drm_device_t *dev); | 156 | extern int mga_dma_reset(DRM_IOCTL_ARGS); |
121 | extern int mga_driver_dma_quiescent(drm_device_t *dev); | 157 | extern int mga_dma_buffers(DRM_IOCTL_ARGS); |
122 | 158 | extern int mga_driver_postcleanup(drm_device_t * dev); | |
123 | extern int mga_do_wait_for_idle( drm_mga_private_t *dev_priv ); | 159 | extern void mga_driver_pretakedown(drm_device_t * dev); |
124 | 160 | extern int mga_driver_dma_quiescent(drm_device_t * dev); | |
125 | extern void mga_do_dma_flush( drm_mga_private_t *dev_priv ); | 161 | |
126 | extern void mga_do_dma_wrap_start( drm_mga_private_t *dev_priv ); | 162 | extern int mga_do_wait_for_idle(drm_mga_private_t * dev_priv); |
127 | extern void mga_do_dma_wrap_end( drm_mga_private_t *dev_priv ); | 163 | |
164 | extern void mga_do_dma_flush(drm_mga_private_t * dev_priv); | ||
165 | extern void mga_do_dma_wrap_start(drm_mga_private_t * dev_priv); | ||
166 | extern void mga_do_dma_wrap_end(drm_mga_private_t * dev_priv); | ||
128 | 167 | ||
129 | extern int mga_freelist_put( drm_device_t *dev, drm_buf_t *buf ); | 168 | extern int mga_freelist_put( drm_device_t *dev, drm_buf_t *buf ); |
130 | 169 | ||
131 | /* mga_warp.c */ | 170 | /* mga_warp.c */ |
132 | extern int mga_warp_install_microcode( drm_mga_private_t *dev_priv ); | 171 | extern unsigned int mga_warp_microcode_size(const drm_mga_private_t * dev_priv); |
133 | extern int mga_warp_init( drm_mga_private_t *dev_priv ); | 172 | extern int mga_warp_install_microcode(drm_mga_private_t * dev_priv); |
134 | 173 | extern int mga_warp_init(drm_mga_private_t * dev_priv); | |
135 | extern int mga_driver_vblank_wait(drm_device_t *dev, unsigned int *sequence); | 174 | |
136 | extern irqreturn_t mga_driver_irq_handler( DRM_IRQ_ARGS ); | 175 | /* mga_irq.c */ |
137 | extern void mga_driver_irq_preinstall( drm_device_t *dev ); | 176 | extern int mga_driver_fence_wait(drm_device_t * dev, unsigned int *sequence); |
138 | extern void mga_driver_irq_postinstall( drm_device_t *dev ); | 177 | extern int mga_driver_vblank_wait(drm_device_t * dev, unsigned int *sequence); |
139 | extern void mga_driver_irq_uninstall( drm_device_t *dev ); | 178 | extern irqreturn_t mga_driver_irq_handler(DRM_IRQ_ARGS); |
179 | extern void mga_driver_irq_preinstall(drm_device_t * dev); | ||
180 | extern void mga_driver_irq_postinstall(drm_device_t * dev); | ||
181 | extern void mga_driver_irq_uninstall(drm_device_t * dev); | ||
140 | extern long mga_compat_ioctl(struct file *filp, unsigned int cmd, | 182 | extern long mga_compat_ioctl(struct file *filp, unsigned int cmd, |
141 | unsigned long arg); | 183 | unsigned long arg); |
142 | 184 | ||
@@ -527,6 +569,12 @@ do { \ | |||
527 | */ | 569 | */ |
528 | #define MGA_EXEC 0x0100 | 570 | #define MGA_EXEC 0x0100 |
529 | 571 | ||
572 | /* AGP PLL encoding (for G200 only). | ||
573 | */ | ||
574 | #define MGA_AGP_PLL 0x1e4c | ||
575 | # define MGA_AGP2XPLL_DISABLE (0 << 0) | ||
576 | # define MGA_AGP2XPLL_ENABLE (1 << 0) | ||
577 | |||
530 | /* Warp registers | 578 | /* Warp registers |
531 | */ | 579 | */ |
532 | #define MGA_WR0 0x2d00 | 580 | #define MGA_WR0 0x2d00 |
diff --git a/drivers/char/drm/mga_irq.c b/drivers/char/drm/mga_irq.c index bc0b6b5d43a6..52eaa4e788f9 100644 --- a/drivers/char/drm/mga_irq.c +++ b/drivers/char/drm/mga_irq.c | |||
@@ -41,15 +41,40 @@ irqreturn_t mga_driver_irq_handler( DRM_IRQ_ARGS ) | |||
41 | drm_mga_private_t *dev_priv = | 41 | drm_mga_private_t *dev_priv = |
42 | (drm_mga_private_t *)dev->dev_private; | 42 | (drm_mga_private_t *)dev->dev_private; |
43 | int status; | 43 | int status; |
44 | int handled = 0; | ||
45 | |||
46 | status = MGA_READ(MGA_STATUS); | ||
44 | 47 | ||
45 | status = MGA_READ( MGA_STATUS ); | ||
46 | |||
47 | /* VBLANK interrupt */ | 48 | /* VBLANK interrupt */ |
48 | if ( status & MGA_VLINEPEN ) { | 49 | if ( status & MGA_VLINEPEN ) { |
49 | MGA_WRITE( MGA_ICLEAR, MGA_VLINEICLR ); | 50 | MGA_WRITE( MGA_ICLEAR, MGA_VLINEICLR ); |
50 | atomic_inc(&dev->vbl_received); | 51 | atomic_inc(&dev->vbl_received); |
51 | DRM_WAKEUP(&dev->vbl_queue); | 52 | DRM_WAKEUP(&dev->vbl_queue); |
52 | drm_vbl_send_signals( dev ); | 53 | drm_vbl_send_signals(dev); |
54 | handled = 1; | ||
55 | } | ||
56 | |||
57 | /* SOFTRAP interrupt */ | ||
58 | if (status & MGA_SOFTRAPEN) { | ||
59 | const u32 prim_start = MGA_READ(MGA_PRIMADDRESS); | ||
60 | const u32 prim_end = MGA_READ(MGA_PRIMEND); | ||
61 | |||
62 | |||
63 | MGA_WRITE(MGA_ICLEAR, MGA_SOFTRAPICLR); | ||
64 | |||
65 | /* In addition to clearing the interrupt-pending bit, we | ||
66 | * have to write to MGA_PRIMEND to re-start the DMA operation. | ||
67 | */ | ||
68 | if ( (prim_start & ~0x03) != (prim_end & ~0x03) ) { | ||
69 | MGA_WRITE(MGA_PRIMEND, prim_end); | ||
70 | } | ||
71 | |||
72 | atomic_inc(&dev_priv->last_fence_retired); | ||
73 | DRM_WAKEUP(&dev_priv->fence_queue); | ||
74 | handled = 1; | ||
75 | } | ||
76 | |||
77 | if ( handled ) { | ||
53 | return IRQ_HANDLED; | 78 | return IRQ_HANDLED; |
54 | } | 79 | } |
55 | return IRQ_NONE; | 80 | return IRQ_NONE; |
@@ -73,9 +98,28 @@ int mga_driver_vblank_wait(drm_device_t *dev, unsigned int *sequence) | |||
73 | return ret; | 98 | return ret; |
74 | } | 99 | } |
75 | 100 | ||
76 | void mga_driver_irq_preinstall( drm_device_t *dev ) { | 101 | int mga_driver_fence_wait(drm_device_t * dev, unsigned int *sequence) |
77 | drm_mga_private_t *dev_priv = | 102 | { |
78 | (drm_mga_private_t *)dev->dev_private; | 103 | drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private; |
104 | unsigned int cur_fence; | ||
105 | int ret = 0; | ||
106 | |||
107 | /* Assume that the user has missed the current sequence number | ||
108 | * by about a day rather than she wants to wait for years | ||
109 | * using fences. | ||
110 | */ | ||
111 | DRM_WAIT_ON(ret, dev_priv->fence_queue, 3 * DRM_HZ, | ||
112 | (((cur_fence = atomic_read(&dev_priv->last_fence_retired)) | ||
113 | - *sequence) <= (1 << 23))); | ||
114 | |||
115 | *sequence = cur_fence; | ||
116 | |||
117 | return ret; | ||
118 | } | ||
119 | |||
120 | void mga_driver_irq_preinstall(drm_device_t * dev) | ||
121 | { | ||
122 | drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private; | ||
79 | 123 | ||
80 | /* Disable *all* interrupts */ | 124 | /* Disable *all* interrupts */ |
81 | MGA_WRITE( MGA_IEN, 0 ); | 125 | MGA_WRITE( MGA_IEN, 0 ); |
@@ -83,12 +127,14 @@ void mga_driver_irq_preinstall( drm_device_t *dev ) { | |||
83 | MGA_WRITE( MGA_ICLEAR, ~0 ); | 127 | MGA_WRITE( MGA_ICLEAR, ~0 ); |
84 | } | 128 | } |
85 | 129 | ||
86 | void mga_driver_irq_postinstall( drm_device_t *dev ) { | 130 | void mga_driver_irq_postinstall(drm_device_t * dev) |
87 | drm_mga_private_t *dev_priv = | 131 | { |
88 | (drm_mga_private_t *)dev->dev_private; | 132 | drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private; |
133 | |||
134 | DRM_INIT_WAITQUEUE( &dev_priv->fence_queue ); | ||
89 | 135 | ||
90 | /* Turn on VBL interrupt */ | 136 | /* Turn on vertical blank interrupt and soft trap interrupt. */ |
91 | MGA_WRITE( MGA_IEN, MGA_VLINEIEN ); | 137 | MGA_WRITE(MGA_IEN, MGA_VLINEIEN | MGA_SOFTRAPEN); |
92 | } | 138 | } |
93 | 139 | ||
94 | void mga_driver_irq_uninstall( drm_device_t *dev ) { | 140 | void mga_driver_irq_uninstall( drm_device_t *dev ) { |
@@ -98,5 +144,7 @@ void mga_driver_irq_uninstall( drm_device_t *dev ) { | |||
98 | return; | 144 | return; |
99 | 145 | ||
100 | /* Disable *all* interrupts */ | 146 | /* Disable *all* interrupts */ |
101 | MGA_WRITE( MGA_IEN, 0 ); | 147 | MGA_WRITE(MGA_IEN, 0); |
148 | |||
149 | dev->irq_enabled = 0; | ||
102 | } | 150 | } |
diff --git a/drivers/char/drm/mga_state.c b/drivers/char/drm/mga_state.c index 3c7a8f5ba501..05bbb4719376 100644 --- a/drivers/char/drm/mga_state.c +++ b/drivers/char/drm/mga_state.c | |||
@@ -53,16 +53,16 @@ static void mga_emit_clip_rect( drm_mga_private_t *dev_priv, | |||
53 | 53 | ||
54 | /* Force reset of DWGCTL on G400 (eliminates clip disable bit). | 54 | /* Force reset of DWGCTL on G400 (eliminates clip disable bit). |
55 | */ | 55 | */ |
56 | if ( dev_priv->chipset == MGA_CARD_TYPE_G400 ) { | 56 | if (dev_priv->chipset == MGA_CARD_TYPE_G400) { |
57 | DMA_BLOCK( MGA_DWGCTL, ctx->dwgctl, | 57 | DMA_BLOCK(MGA_DWGCTL, ctx->dwgctl, |
58 | MGA_LEN + MGA_EXEC, 0x80000000, | 58 | MGA_LEN + MGA_EXEC, 0x80000000, |
59 | MGA_DWGCTL, ctx->dwgctl, | 59 | MGA_DWGCTL, ctx->dwgctl, |
60 | MGA_LEN + MGA_EXEC, 0x80000000 ); | 60 | MGA_LEN + MGA_EXEC, 0x80000000); |
61 | } | 61 | } |
62 | DMA_BLOCK( MGA_DMAPAD, 0x00000000, | 62 | DMA_BLOCK(MGA_DMAPAD, 0x00000000, |
63 | MGA_CXBNDRY, (box->x2 << 16) | box->x1, | 63 | MGA_CXBNDRY, ((box->x2 - 1) << 16) | box->x1, |
64 | MGA_YTOP, box->y1 * pitch, | 64 | MGA_YTOP, box->y1 * pitch, |
65 | MGA_YBOT, box->y2 * pitch ); | 65 | MGA_YBOT, (box->y2 - 1) * pitch); |
66 | 66 | ||
67 | ADVANCE_DMA(); | 67 | ADVANCE_DMA(); |
68 | } | 68 | } |
@@ -260,12 +260,11 @@ static __inline__ void mga_g200_emit_pipe( drm_mga_private_t *dev_priv ) | |||
260 | 260 | ||
261 | /* Padding required to to hardware bug. | 261 | /* Padding required to to hardware bug. |
262 | */ | 262 | */ |
263 | DMA_BLOCK( MGA_DMAPAD, 0xffffffff, | 263 | DMA_BLOCK(MGA_DMAPAD, 0xffffffff, |
264 | MGA_DMAPAD, 0xffffffff, | 264 | MGA_DMAPAD, 0xffffffff, |
265 | MGA_DMAPAD, 0xffffffff, | 265 | MGA_DMAPAD, 0xffffffff, |
266 | MGA_WIADDR, (dev_priv->warp_pipe_phys[pipe] | | 266 | MGA_WIADDR, (dev_priv->warp_pipe_phys[pipe] | |
267 | MGA_WMODE_START | | 267 | MGA_WMODE_START | dev_priv->wagp_enable)); |
268 | MGA_WAGP_ENABLE) ); | ||
269 | 268 | ||
270 | ADVANCE_DMA(); | 269 | ADVANCE_DMA(); |
271 | } | 270 | } |
@@ -342,12 +341,11 @@ static __inline__ void mga_g400_emit_pipe( drm_mga_private_t *dev_priv ) | |||
342 | MGA_WR60, MGA_G400_WR_MAGIC ); /* tex1 height */ | 341 | MGA_WR60, MGA_G400_WR_MAGIC ); /* tex1 height */ |
343 | 342 | ||
344 | /* Padding required to to hardware bug */ | 343 | /* Padding required to to hardware bug */ |
345 | DMA_BLOCK( MGA_DMAPAD, 0xffffffff, | 344 | DMA_BLOCK(MGA_DMAPAD, 0xffffffff, |
346 | MGA_DMAPAD, 0xffffffff, | 345 | MGA_DMAPAD, 0xffffffff, |
347 | MGA_DMAPAD, 0xffffffff, | 346 | MGA_DMAPAD, 0xffffffff, |
348 | MGA_WIADDR2, (dev_priv->warp_pipe_phys[pipe] | | 347 | MGA_WIADDR2, (dev_priv->warp_pipe_phys[pipe] | |
349 | MGA_WMODE_START | | 348 | MGA_WMODE_START | dev_priv->wagp_enable)); |
350 | MGA_WAGP_ENABLE) ); | ||
351 | 349 | ||
352 | ADVANCE_DMA(); | 350 | ADVANCE_DMA(); |
353 | } | 351 | } |
@@ -459,9 +457,9 @@ static int mga_verify_state( drm_mga_private_t *dev_priv ) | |||
459 | if ( dirty & MGA_UPLOAD_TEX0 ) | 457 | if ( dirty & MGA_UPLOAD_TEX0 ) |
460 | ret |= mga_verify_tex( dev_priv, 0 ); | 458 | ret |= mga_verify_tex( dev_priv, 0 ); |
461 | 459 | ||
462 | if ( dev_priv->chipset == MGA_CARD_TYPE_G400 ) { | 460 | if (dev_priv->chipset >= MGA_CARD_TYPE_G400) { |
463 | if ( dirty & MGA_UPLOAD_TEX1 ) | 461 | if (dirty & MGA_UPLOAD_TEX1) |
464 | ret |= mga_verify_tex( dev_priv, 1 ); | 462 | ret |= mga_verify_tex(dev_priv, 1); |
465 | 463 | ||
466 | if ( dirty & MGA_UPLOAD_PIPE ) | 464 | if ( dirty & MGA_UPLOAD_PIPE ) |
467 | ret |= ( sarea_priv->warp_pipe > MGA_MAX_G400_PIPES ); | 465 | ret |= ( sarea_priv->warp_pipe > MGA_MAX_G400_PIPES ); |
@@ -686,12 +684,12 @@ static void mga_dma_dispatch_vertex( drm_device_t *dev, drm_buf_t *buf ) | |||
686 | 684 | ||
687 | BEGIN_DMA( 1 ); | 685 | BEGIN_DMA( 1 ); |
688 | 686 | ||
689 | DMA_BLOCK( MGA_DMAPAD, 0x00000000, | 687 | DMA_BLOCK(MGA_DMAPAD, 0x00000000, |
690 | MGA_DMAPAD, 0x00000000, | 688 | MGA_DMAPAD, 0x00000000, |
691 | MGA_SECADDRESS, (address | | 689 | MGA_SECADDRESS, (address | |
692 | MGA_DMA_VERTEX), | 690 | MGA_DMA_VERTEX), |
693 | MGA_SECEND, ((address + length) | | 691 | MGA_SECEND, ((address + length) | |
694 | MGA_PAGPXFER) ); | 692 | dev_priv->dma_access)); |
695 | 693 | ||
696 | ADVANCE_DMA(); | 694 | ADVANCE_DMA(); |
697 | } while ( ++i < sarea_priv->nbox ); | 695 | } while ( ++i < sarea_priv->nbox ); |
@@ -733,11 +731,11 @@ static void mga_dma_dispatch_indices( drm_device_t *dev, drm_buf_t *buf, | |||
733 | 731 | ||
734 | BEGIN_DMA( 1 ); | 732 | BEGIN_DMA( 1 ); |
735 | 733 | ||
736 | DMA_BLOCK( MGA_DMAPAD, 0x00000000, | 734 | DMA_BLOCK(MGA_DMAPAD, 0x00000000, |
737 | MGA_DMAPAD, 0x00000000, | 735 | MGA_DMAPAD, 0x00000000, |
738 | MGA_SETUPADDRESS, address + start, | 736 | MGA_SETUPADDRESS, address + start, |
739 | MGA_SETUPEND, ((address + end) | | 737 | MGA_SETUPEND, ((address + end) | |
740 | MGA_PAGPXFER) ); | 738 | dev_priv->dma_access)); |
741 | 739 | ||
742 | ADVANCE_DMA(); | 740 | ADVANCE_DMA(); |
743 | } while ( ++i < sarea_priv->nbox ); | 741 | } while ( ++i < sarea_priv->nbox ); |
@@ -764,7 +762,7 @@ static void mga_dma_dispatch_iload( drm_device_t *dev, drm_buf_t *buf, | |||
764 | drm_mga_private_t *dev_priv = dev->dev_private; | 762 | drm_mga_private_t *dev_priv = dev->dev_private; |
765 | drm_mga_buf_priv_t *buf_priv = buf->dev_private; | 763 | drm_mga_buf_priv_t *buf_priv = buf->dev_private; |
766 | drm_mga_context_regs_t *ctx = &dev_priv->sarea_priv->context_state; | 764 | drm_mga_context_regs_t *ctx = &dev_priv->sarea_priv->context_state; |
767 | u32 srcorg = buf->bus_address | MGA_SRCACC_AGP | MGA_SRCMAP_SYSMEM; | 765 | u32 srcorg = buf->bus_address | dev_priv->dma_access | MGA_SRCMAP_SYSMEM; |
768 | u32 y2; | 766 | u32 y2; |
769 | DMA_LOCALS; | 767 | DMA_LOCALS; |
770 | DRM_DEBUG( "buf=%d used=%d\n", buf->idx, buf->used ); | 768 | DRM_DEBUG( "buf=%d used=%d\n", buf->idx, buf->used ); |
@@ -1095,6 +1093,9 @@ static int mga_getparam( DRM_IOCTL_ARGS ) | |||
1095 | case MGA_PARAM_IRQ_NR: | 1093 | case MGA_PARAM_IRQ_NR: |
1096 | value = dev->irq; | 1094 | value = dev->irq; |
1097 | break; | 1095 | break; |
1096 | case MGA_PARAM_CARD_TYPE: | ||
1097 | value = dev_priv->chipset; | ||
1098 | break; | ||
1098 | default: | 1099 | default: |
1099 | return DRM_ERR(EINVAL); | 1100 | return DRM_ERR(EINVAL); |
1100 | } | 1101 | } |
@@ -1107,17 +1108,82 @@ static int mga_getparam( DRM_IOCTL_ARGS ) | |||
1107 | return 0; | 1108 | return 0; |
1108 | } | 1109 | } |
1109 | 1110 | ||
1111 | static int mga_set_fence(DRM_IOCTL_ARGS) | ||
1112 | { | ||
1113 | DRM_DEVICE; | ||
1114 | drm_mga_private_t *dev_priv = dev->dev_private; | ||
1115 | u32 temp; | ||
1116 | DMA_LOCALS; | ||
1117 | |||
1118 | if (!dev_priv) { | ||
1119 | DRM_ERROR("%s called with no initialization\n", __FUNCTION__); | ||
1120 | return DRM_ERR(EINVAL); | ||
1121 | } | ||
1122 | |||
1123 | DRM_DEBUG("pid=%d\n", DRM_CURRENTPID); | ||
1124 | |||
1125 | /* I would normal do this assignment in the declaration of temp, | ||
1126 | * but dev_priv may be NULL. | ||
1127 | */ | ||
1128 | |||
1129 | temp = dev_priv->next_fence_to_post; | ||
1130 | dev_priv->next_fence_to_post++; | ||
1131 | |||
1132 | BEGIN_DMA(1); | ||
1133 | DMA_BLOCK(MGA_DMAPAD, 0x00000000, | ||
1134 | MGA_DMAPAD, 0x00000000, | ||
1135 | MGA_DMAPAD, 0x00000000, | ||
1136 | MGA_SOFTRAP, 0x00000000); | ||
1137 | ADVANCE_DMA(); | ||
1138 | |||
1139 | if (DRM_COPY_TO_USER( (u32 __user *) data, & temp, sizeof(u32))) { | ||
1140 | DRM_ERROR("copy_to_user\n"); | ||
1141 | return DRM_ERR(EFAULT); | ||
1142 | } | ||
1143 | |||
1144 | return 0; | ||
1145 | } | ||
1146 | |||
1147 | static int mga_wait_fence(DRM_IOCTL_ARGS) | ||
1148 | { | ||
1149 | DRM_DEVICE; | ||
1150 | drm_mga_private_t *dev_priv = dev->dev_private; | ||
1151 | u32 fence; | ||
1152 | |||
1153 | if (!dev_priv) { | ||
1154 | DRM_ERROR("%s called with no initialization\n", __FUNCTION__); | ||
1155 | return DRM_ERR(EINVAL); | ||
1156 | } | ||
1157 | |||
1158 | DRM_COPY_FROM_USER_IOCTL(fence, (u32 __user *) data, sizeof(u32)); | ||
1159 | |||
1160 | DRM_DEBUG("pid=%d\n", DRM_CURRENTPID); | ||
1161 | |||
1162 | mga_driver_fence_wait(dev, & fence); | ||
1163 | |||
1164 | if (DRM_COPY_TO_USER( (u32 __user *) data, & fence, sizeof(u32))) { | ||
1165 | DRM_ERROR("copy_to_user\n"); | ||
1166 | return DRM_ERR(EFAULT); | ||
1167 | } | ||
1168 | |||
1169 | return 0; | ||
1170 | } | ||
1171 | |||
1110 | drm_ioctl_desc_t mga_ioctls[] = { | 1172 | drm_ioctl_desc_t mga_ioctls[] = { |
1111 | [DRM_IOCTL_NR(DRM_MGA_INIT)] = { mga_dma_init, 1, 1 }, | 1173 | [DRM_IOCTL_NR(DRM_MGA_INIT)] = {mga_dma_init, 1, 1}, |
1112 | [DRM_IOCTL_NR(DRM_MGA_FLUSH)] = { mga_dma_flush, 1, 0 }, | 1174 | [DRM_IOCTL_NR(DRM_MGA_FLUSH)] = {mga_dma_flush, 1, 0}, |
1113 | [DRM_IOCTL_NR(DRM_MGA_RESET)] = { mga_dma_reset, 1, 0 }, | 1175 | [DRM_IOCTL_NR(DRM_MGA_RESET)] = {mga_dma_reset, 1, 0}, |
1114 | [DRM_IOCTL_NR(DRM_MGA_SWAP)] = { mga_dma_swap, 1, 0 }, | 1176 | [DRM_IOCTL_NR(DRM_MGA_SWAP)] = {mga_dma_swap, 1, 0}, |
1115 | [DRM_IOCTL_NR(DRM_MGA_CLEAR)] = { mga_dma_clear, 1, 0 }, | 1177 | [DRM_IOCTL_NR(DRM_MGA_CLEAR)] = {mga_dma_clear, 1, 0}, |
1116 | [DRM_IOCTL_NR(DRM_MGA_VERTEX)] = { mga_dma_vertex, 1, 0 }, | 1178 | [DRM_IOCTL_NR(DRM_MGA_VERTEX)] = {mga_dma_vertex, 1, 0}, |
1117 | [DRM_IOCTL_NR(DRM_MGA_INDICES)] = { mga_dma_indices, 1, 0 }, | 1179 | [DRM_IOCTL_NR(DRM_MGA_INDICES)] = {mga_dma_indices, 1, 0}, |
1118 | [DRM_IOCTL_NR(DRM_MGA_ILOAD)] = { mga_dma_iload, 1, 0 }, | 1180 | [DRM_IOCTL_NR(DRM_MGA_ILOAD)] = {mga_dma_iload, 1, 0}, |
1119 | [DRM_IOCTL_NR(DRM_MGA_BLIT)] = { mga_dma_blit, 1, 0 }, | 1181 | [DRM_IOCTL_NR(DRM_MGA_BLIT)] = {mga_dma_blit, 1, 0}, |
1120 | [DRM_IOCTL_NR(DRM_MGA_GETPARAM)]= { mga_getparam, 1, 0 }, | 1182 | [DRM_IOCTL_NR(DRM_MGA_GETPARAM)] = {mga_getparam, 1, 0}, |
1183 | [DRM_IOCTL_NR(DRM_MGA_SET_FENCE)] = {mga_set_fence, 1, 0}, | ||
1184 | [DRM_IOCTL_NR(DRM_MGA_WAIT_FENCE)] = {mga_wait_fence, 1, 0}, | ||
1185 | [DRM_IOCTL_NR(DRM_MGA_DMA_BOOTSTRAP)] = {mga_dma_bootstrap, 1, 1}, | ||
1186 | |||
1121 | }; | 1187 | }; |
1122 | 1188 | ||
1123 | int mga_max_ioctl = DRM_ARRAY_SIZE(mga_ioctls); | 1189 | int mga_max_ioctl = DRM_ARRAY_SIZE(mga_ioctls); |
diff --git a/drivers/char/drm/mga_warp.c b/drivers/char/drm/mga_warp.c index 0a3a0cc700dc..55ccc8a0ac29 100644 --- a/drivers/char/drm/mga_warp.c +++ b/drivers/char/drm/mga_warp.c | |||
@@ -48,65 +48,52 @@ do { \ | |||
48 | vcbase += WARP_UCODE_SIZE( which ); \ | 48 | vcbase += WARP_UCODE_SIZE( which ); \ |
49 | } while (0) | 49 | } while (0) |
50 | 50 | ||
51 | 51 | static const unsigned int mga_warp_g400_microcode_size = | |
52 | static unsigned int mga_warp_g400_microcode_size( drm_mga_private_t *dev_priv ) | 52 | (WARP_UCODE_SIZE(warp_g400_tgz) + |
53 | { | 53 | WARP_UCODE_SIZE(warp_g400_tgza) + |
54 | unsigned int size; | 54 | WARP_UCODE_SIZE(warp_g400_tgzaf) + |
55 | 55 | WARP_UCODE_SIZE(warp_g400_tgzf) + | |
56 | size = ( WARP_UCODE_SIZE( warp_g400_tgz ) + | 56 | WARP_UCODE_SIZE(warp_g400_tgzs) + |
57 | WARP_UCODE_SIZE( warp_g400_tgza ) + | 57 | WARP_UCODE_SIZE(warp_g400_tgzsa) + |
58 | WARP_UCODE_SIZE( warp_g400_tgzaf ) + | 58 | WARP_UCODE_SIZE(warp_g400_tgzsaf) + |
59 | WARP_UCODE_SIZE( warp_g400_tgzf ) + | 59 | WARP_UCODE_SIZE(warp_g400_tgzsf) + |
60 | WARP_UCODE_SIZE( warp_g400_tgzs ) + | 60 | WARP_UCODE_SIZE(warp_g400_t2gz) + |
61 | WARP_UCODE_SIZE( warp_g400_tgzsa ) + | 61 | WARP_UCODE_SIZE(warp_g400_t2gza) + |
62 | WARP_UCODE_SIZE( warp_g400_tgzsaf ) + | 62 | WARP_UCODE_SIZE(warp_g400_t2gzaf) + |
63 | WARP_UCODE_SIZE( warp_g400_tgzsf ) + | 63 | WARP_UCODE_SIZE(warp_g400_t2gzf) + |
64 | WARP_UCODE_SIZE( warp_g400_t2gz ) + | 64 | WARP_UCODE_SIZE(warp_g400_t2gzs) + |
65 | WARP_UCODE_SIZE( warp_g400_t2gza ) + | 65 | WARP_UCODE_SIZE(warp_g400_t2gzsa) + |
66 | WARP_UCODE_SIZE( warp_g400_t2gzaf ) + | 66 | WARP_UCODE_SIZE(warp_g400_t2gzsaf) + |
67 | WARP_UCODE_SIZE( warp_g400_t2gzf ) + | 67 | WARP_UCODE_SIZE(warp_g400_t2gzsf)); |
68 | WARP_UCODE_SIZE( warp_g400_t2gzs ) + | 68 | |
69 | WARP_UCODE_SIZE( warp_g400_t2gzsa ) + | 69 | static const unsigned int mga_warp_g200_microcode_size = |
70 | WARP_UCODE_SIZE( warp_g400_t2gzsaf ) + | 70 | (WARP_UCODE_SIZE(warp_g200_tgz) + |
71 | WARP_UCODE_SIZE( warp_g400_t2gzsf ) ); | 71 | WARP_UCODE_SIZE(warp_g200_tgza) + |
72 | 72 | WARP_UCODE_SIZE(warp_g200_tgzaf) + | |
73 | size = PAGE_ALIGN( size ); | 73 | WARP_UCODE_SIZE(warp_g200_tgzf) + |
74 | 74 | WARP_UCODE_SIZE(warp_g200_tgzs) + | |
75 | DRM_DEBUG( "G400 ucode size = %d bytes\n", size ); | 75 | WARP_UCODE_SIZE(warp_g200_tgzsa) + |
76 | return size; | 76 | WARP_UCODE_SIZE(warp_g200_tgzsaf) + |
77 | } | 77 | WARP_UCODE_SIZE(warp_g200_tgzsf)); |
78 | 78 | ||
79 | static unsigned int mga_warp_g200_microcode_size( drm_mga_private_t *dev_priv ) | 79 | |
80 | unsigned int mga_warp_microcode_size(const drm_mga_private_t * dev_priv) | ||
80 | { | 81 | { |
81 | unsigned int size; | 82 | switch (dev_priv->chipset) { |
82 | 83 | case MGA_CARD_TYPE_G400: | |
83 | size = ( WARP_UCODE_SIZE( warp_g200_tgz ) + | 84 | case MGA_CARD_TYPE_G550: |
84 | WARP_UCODE_SIZE( warp_g200_tgza ) + | 85 | return PAGE_ALIGN(mga_warp_g400_microcode_size); |
85 | WARP_UCODE_SIZE( warp_g200_tgzaf ) + | 86 | case MGA_CARD_TYPE_G200: |
86 | WARP_UCODE_SIZE( warp_g200_tgzf ) + | 87 | return PAGE_ALIGN(mga_warp_g200_microcode_size); |
87 | WARP_UCODE_SIZE( warp_g200_tgzs ) + | 88 | default: |
88 | WARP_UCODE_SIZE( warp_g200_tgzsa ) + | 89 | return 0; |
89 | WARP_UCODE_SIZE( warp_g200_tgzsaf ) + | 90 | } |
90 | WARP_UCODE_SIZE( warp_g200_tgzsf ) ); | ||
91 | |||
92 | size = PAGE_ALIGN( size ); | ||
93 | |||
94 | DRM_DEBUG( "G200 ucode size = %d bytes\n", size ); | ||
95 | return size; | ||
96 | } | 91 | } |
97 | 92 | ||
98 | static int mga_warp_install_g400_microcode( drm_mga_private_t *dev_priv ) | 93 | static int mga_warp_install_g400_microcode( drm_mga_private_t *dev_priv ) |
99 | { | 94 | { |
100 | unsigned char *vcbase = dev_priv->warp->handle; | 95 | unsigned char *vcbase = dev_priv->warp->handle; |
101 | unsigned long pcbase = dev_priv->warp->offset; | 96 | unsigned long pcbase = dev_priv->warp->offset; |
102 | unsigned int size; | ||
103 | |||
104 | size = mga_warp_g400_microcode_size( dev_priv ); | ||
105 | if ( size > dev_priv->warp->size ) { | ||
106 | DRM_ERROR( "microcode too large! (%u > %lu)\n", | ||
107 | size, dev_priv->warp->size ); | ||
108 | return DRM_ERR(ENOMEM); | ||
109 | } | ||
110 | 97 | ||
111 | memset( dev_priv->warp_pipe_phys, 0, | 98 | memset( dev_priv->warp_pipe_phys, 0, |
112 | sizeof(dev_priv->warp_pipe_phys) ); | 99 | sizeof(dev_priv->warp_pipe_phys) ); |
@@ -136,35 +123,36 @@ static int mga_warp_install_g200_microcode( drm_mga_private_t *dev_priv ) | |||
136 | { | 123 | { |
137 | unsigned char *vcbase = dev_priv->warp->handle; | 124 | unsigned char *vcbase = dev_priv->warp->handle; |
138 | unsigned long pcbase = dev_priv->warp->offset; | 125 | unsigned long pcbase = dev_priv->warp->offset; |
139 | unsigned int size; | ||
140 | |||
141 | size = mga_warp_g200_microcode_size( dev_priv ); | ||
142 | if ( size > dev_priv->warp->size ) { | ||
143 | DRM_ERROR( "microcode too large! (%u > %lu)\n", | ||
144 | size, dev_priv->warp->size ); | ||
145 | return DRM_ERR(ENOMEM); | ||
146 | } | ||
147 | 126 | ||
148 | memset( dev_priv->warp_pipe_phys, 0, | 127 | memset(dev_priv->warp_pipe_phys, 0, sizeof(dev_priv->warp_pipe_phys)); |
149 | sizeof(dev_priv->warp_pipe_phys) ); | ||
150 | 128 | ||
151 | WARP_UCODE_INSTALL( warp_g200_tgz, MGA_WARP_TGZ ); | 129 | WARP_UCODE_INSTALL(warp_g200_tgz, MGA_WARP_TGZ); |
152 | WARP_UCODE_INSTALL( warp_g200_tgzf, MGA_WARP_TGZF ); | 130 | WARP_UCODE_INSTALL(warp_g200_tgzf, MGA_WARP_TGZF); |
153 | WARP_UCODE_INSTALL( warp_g200_tgza, MGA_WARP_TGZA ); | 131 | WARP_UCODE_INSTALL(warp_g200_tgza, MGA_WARP_TGZA); |
154 | WARP_UCODE_INSTALL( warp_g200_tgzaf, MGA_WARP_TGZAF ); | 132 | WARP_UCODE_INSTALL(warp_g200_tgzaf, MGA_WARP_TGZAF); |
155 | WARP_UCODE_INSTALL( warp_g200_tgzs, MGA_WARP_TGZS ); | 133 | WARP_UCODE_INSTALL(warp_g200_tgzs, MGA_WARP_TGZS); |
156 | WARP_UCODE_INSTALL( warp_g200_tgzsf, MGA_WARP_TGZSF ); | 134 | WARP_UCODE_INSTALL(warp_g200_tgzsf, MGA_WARP_TGZSF); |
157 | WARP_UCODE_INSTALL( warp_g200_tgzsa, MGA_WARP_TGZSA ); | 135 | WARP_UCODE_INSTALL(warp_g200_tgzsa, MGA_WARP_TGZSA); |
158 | WARP_UCODE_INSTALL( warp_g200_tgzsaf, MGA_WARP_TGZSAF ); | 136 | WARP_UCODE_INSTALL(warp_g200_tgzsaf, MGA_WARP_TGZSAF); |
159 | 137 | ||
160 | return 0; | 138 | return 0; |
161 | } | 139 | } |
162 | 140 | ||
163 | int mga_warp_install_microcode( drm_mga_private_t *dev_priv ) | 141 | int mga_warp_install_microcode( drm_mga_private_t *dev_priv ) |
164 | { | 142 | { |
165 | switch ( dev_priv->chipset ) { | 143 | const unsigned int size = mga_warp_microcode_size(dev_priv); |
144 | |||
145 | DRM_DEBUG("MGA ucode size = %d bytes\n", size); | ||
146 | if (size > dev_priv->warp->size) { | ||
147 | DRM_ERROR("microcode too large! (%u > %lu)\n", | ||
148 | size, dev_priv->warp->size); | ||
149 | return DRM_ERR(ENOMEM); | ||
150 | } | ||
151 | |||
152 | switch (dev_priv->chipset) { | ||
166 | case MGA_CARD_TYPE_G400: | 153 | case MGA_CARD_TYPE_G400: |
167 | return mga_warp_install_g400_microcode( dev_priv ); | 154 | case MGA_CARD_TYPE_G550: |
155 | return mga_warp_install_g400_microcode(dev_priv); | ||
168 | case MGA_CARD_TYPE_G200: | 156 | case MGA_CARD_TYPE_G200: |
169 | return mga_warp_install_g200_microcode( dev_priv ); | 157 | return mga_warp_install_g200_microcode( dev_priv ); |
170 | default: | 158 | default: |
@@ -182,10 +170,11 @@ int mga_warp_init( drm_mga_private_t *dev_priv ) | |||
182 | */ | 170 | */ |
183 | switch ( dev_priv->chipset ) { | 171 | switch ( dev_priv->chipset ) { |
184 | case MGA_CARD_TYPE_G400: | 172 | case MGA_CARD_TYPE_G400: |
185 | MGA_WRITE( MGA_WIADDR2, MGA_WMODE_SUSPEND ); | 173 | case MGA_CARD_TYPE_G550: |
186 | MGA_WRITE( MGA_WGETMSB, 0x00000E00 ); | 174 | MGA_WRITE(MGA_WIADDR2, MGA_WMODE_SUSPEND); |
187 | MGA_WRITE( MGA_WVRTXSZ, 0x00001807 ); | 175 | MGA_WRITE(MGA_WGETMSB, 0x00000E00); |
188 | MGA_WRITE( MGA_WACCEPTSEQ, 0x18000000 ); | 176 | MGA_WRITE(MGA_WVRTXSZ, 0x00001807); |
177 | MGA_WRITE(MGA_WACCEPTSEQ, 0x18000000); | ||
189 | break; | 178 | break; |
190 | case MGA_CARD_TYPE_G200: | 179 | case MGA_CARD_TYPE_G200: |
191 | MGA_WRITE( MGA_WIADDR, MGA_WMODE_SUSPEND ); | 180 | MGA_WRITE( MGA_WIADDR, MGA_WMODE_SUSPEND ); |
diff --git a/drivers/char/drm/radeon_cp.c b/drivers/char/drm/radeon_cp.c index 20bcf872b348..8255cc6fdc28 100644 --- a/drivers/char/drm/radeon_cp.c +++ b/drivers/char/drm/radeon_cp.c | |||
@@ -2048,6 +2048,27 @@ int radeon_driver_preinit(struct drm_device *dev, unsigned long flags) | |||
2048 | return ret; | 2048 | return ret; |
2049 | } | 2049 | } |
2050 | 2050 | ||
2051 | int radeon_presetup(struct drm_device *dev) | ||
2052 | { | ||
2053 | int ret; | ||
2054 | drm_local_map_t *map; | ||
2055 | drm_radeon_private_t *dev_priv = dev->dev_private; | ||
2056 | |||
2057 | ret = drm_addmap(dev, drm_get_resource_start(dev, 2), | ||
2058 | drm_get_resource_len(dev, 2), _DRM_REGISTERS, | ||
2059 | _DRM_READ_ONLY, &dev_priv->mmio); | ||
2060 | if (ret != 0) | ||
2061 | return ret; | ||
2062 | |||
2063 | ret = drm_addmap(dev, drm_get_resource_start(dev, 0), | ||
2064 | drm_get_resource_len(dev, 0), _DRM_FRAME_BUFFER, | ||
2065 | _DRM_WRITE_COMBINING, &map); | ||
2066 | if (ret != 0) | ||
2067 | return ret; | ||
2068 | |||
2069 | return 0; | ||
2070 | } | ||
2071 | |||
2051 | int radeon_driver_postcleanup(struct drm_device *dev) | 2072 | int radeon_driver_postcleanup(struct drm_device *dev) |
2052 | { | 2073 | { |
2053 | drm_radeon_private_t *dev_priv = dev->dev_private; | 2074 | drm_radeon_private_t *dev_priv = dev->dev_private; |
diff --git a/drivers/char/drm/radeon_drv.c b/drivers/char/drm/radeon_drv.c index 18e4e5b0952f..e0682f64b400 100644 --- a/drivers/char/drm/radeon_drv.c +++ b/drivers/char/drm/radeon_drv.c | |||
@@ -76,6 +76,7 @@ static struct drm_driver driver = { | |||
76 | .driver_features = DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_PCI_DMA | DRIVER_SG | DRIVER_HAVE_IRQ | DRIVER_HAVE_DMA | DRIVER_IRQ_SHARED | DRIVER_IRQ_VBL, | 76 | .driver_features = DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_PCI_DMA | DRIVER_SG | DRIVER_HAVE_IRQ | DRIVER_HAVE_DMA | DRIVER_IRQ_SHARED | DRIVER_IRQ_VBL, |
77 | .dev_priv_size = sizeof(drm_radeon_buf_priv_t), | 77 | .dev_priv_size = sizeof(drm_radeon_buf_priv_t), |
78 | .preinit = radeon_driver_preinit, | 78 | .preinit = radeon_driver_preinit, |
79 | .presetup = radeon_presetup, | ||
79 | .postcleanup = radeon_driver_postcleanup, | 80 | .postcleanup = radeon_driver_postcleanup, |
80 | .prerelease = radeon_driver_prerelease, | 81 | .prerelease = radeon_driver_prerelease, |
81 | .pretakedown = radeon_driver_pretakedown, | 82 | .pretakedown = radeon_driver_pretakedown, |
diff --git a/drivers/char/drm/radeon_drv.h b/drivers/char/drm/radeon_drv.h index 771aa80a5e8c..e701dffe978d 100644 --- a/drivers/char/drm/radeon_drv.h +++ b/drivers/char/drm/radeon_drv.h | |||
@@ -290,6 +290,7 @@ extern int radeon_wait_ring( drm_radeon_private_t *dev_priv, int n ); | |||
290 | extern int radeon_do_cp_idle( drm_radeon_private_t *dev_priv ); | 290 | extern int radeon_do_cp_idle( drm_radeon_private_t *dev_priv ); |
291 | 291 | ||
292 | extern int radeon_driver_preinit(struct drm_device *dev, unsigned long flags); | 292 | extern int radeon_driver_preinit(struct drm_device *dev, unsigned long flags); |
293 | extern int radeon_presetup(struct drm_device *dev); | ||
293 | extern int radeon_driver_postcleanup(struct drm_device *dev); | 294 | extern int radeon_driver_postcleanup(struct drm_device *dev); |
294 | 295 | ||
295 | extern int radeon_mem_alloc( DRM_IOCTL_ARGS ); | 296 | extern int radeon_mem_alloc( DRM_IOCTL_ARGS ); |