2 * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
12 * The above copyright notice and this permission notice (including the next
13 * paragraph) shall be included in all copies or substantial portions of the
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 * DEALINGS IN THE SOFTWARE.
25 * Gareth Hughes <gareth@valinux.com>
26 * Eric Anholt <anholt@FreeBSD.org>
30 /** @file drm_scatter.c
31 * Allocation of memory for scatter-gather mappings by the graphics chip.
33 * The memory allocated here is then made into an aperture in the card
34 * by drm_ati_pcigart_init().
37 #include "dev/drm/drmP.h"
39 static void drm_sg_alloc_cb(void *arg
, bus_dma_segment_t
*segs
,
40 int nsegs
, int error
);
43 drm_sg_alloc(struct drm_device
*dev
, struct drm_scatter_gather
*request
)
45 struct drm_sg_mem
*entry
;
46 struct drm_dma_handle
*dmah
;
53 entry
= malloc(sizeof(*entry
), DRM_MEM_SGLISTS
, M_WAITOK
| M_ZERO
);
57 pages
= round_page(request
->size
) / PAGE_SIZE
;
58 DRM_DEBUG("sg size=%ld pages=%ld\n", request
->size
, pages
);
62 entry
->busaddr
= malloc(pages
* sizeof(*entry
->busaddr
), DRM_MEM_PAGES
,
64 if (!entry
->busaddr
) {
65 free(entry
, DRM_MEM_SGLISTS
);
69 dmah
= malloc(sizeof(struct drm_dma_handle
), DRM_MEM_DMA
,
72 free(entry
->busaddr
, DRM_MEM_PAGES
);
73 free(entry
, DRM_MEM_SGLISTS
);
77 ret
= bus_dma_tag_create(NULL
, PAGE_SIZE
, 0, /* tag, align, boundary */
78 BUS_SPACE_MAXADDR_32BIT
, BUS_SPACE_MAXADDR
, /* lowaddr, highaddr */
79 NULL
, NULL
, /* filtfunc, filtfuncargs */
80 request
->size
, pages
, /* maxsize, nsegs */
81 PAGE_SIZE
, 0, /* maxsegsize, flags */
84 free(dmah
, DRM_MEM_DMA
);
85 free(entry
->busaddr
, DRM_MEM_PAGES
);
86 free(entry
, DRM_MEM_SGLISTS
);
90 /* XXX BUS_DMA_NOCACHE */
91 ret
= bus_dmamem_alloc(dmah
->tag
, &dmah
->vaddr
,
92 BUS_DMA_WAITOK
| BUS_DMA_ZERO
, &dmah
->map
);
94 bus_dma_tag_destroy(dmah
->tag
);
95 free(dmah
, DRM_MEM_DMA
);
96 free(entry
->busaddr
, DRM_MEM_PAGES
);
97 free(entry
, DRM_MEM_SGLISTS
);
101 ret
= bus_dmamap_load(dmah
->tag
, dmah
->map
, dmah
->vaddr
,
102 request
->size
, drm_sg_alloc_cb
, entry
, BUS_DMA_NOWAIT
);
104 bus_dmamem_free(dmah
->tag
, dmah
->vaddr
, dmah
->map
);
105 bus_dma_tag_destroy(dmah
->tag
);
106 free(dmah
, DRM_MEM_DMA
);
107 free(entry
->busaddr
, DRM_MEM_PAGES
);
108 free(entry
, DRM_MEM_SGLISTS
);
113 entry
->handle
= (unsigned long)dmah
->vaddr
;
115 DRM_DEBUG("sg alloc handle = %08lx\n", entry
->handle
);
117 entry
->virtual = (void *)entry
->handle
;
118 request
->handle
= entry
->handle
;
123 drm_sg_cleanup(entry
);
133 drm_sg_alloc_cb(void *arg
, bus_dma_segment_t
*segs
, int nsegs
, int error
)
135 struct drm_sg_mem
*entry
= arg
;
141 for(i
= 0 ; i
< nsegs
; i
++) {
142 entry
->busaddr
[i
] = segs
[i
].ds_addr
;
147 drm_sg_alloc_ioctl(struct drm_device
*dev
, void *data
,
148 struct drm_file
*file_priv
)
150 struct drm_scatter_gather
*request
= data
;
154 return drm_sg_alloc(dev
, request
);
158 drm_sg_cleanup(struct drm_sg_mem
*entry
)
160 struct drm_dma_handle
*dmah
= entry
->dmah
;
162 bus_dmamap_unload(dmah
->tag
, dmah
->map
);
163 bus_dmamem_free(dmah
->tag
, dmah
->vaddr
, dmah
->map
);
164 bus_dma_tag_destroy(dmah
->tag
);
165 free(dmah
, DRM_MEM_DMA
);
166 free(entry
->busaddr
, DRM_MEM_PAGES
);
167 free(entry
, DRM_MEM_SGLISTS
);
171 drm_sg_free(struct drm_device
*dev
, void *data
, struct drm_file
*file_priv
)
173 struct drm_scatter_gather
*request
= data
;
174 struct drm_sg_mem
*entry
;
181 if (!entry
|| entry
->handle
!= request
->handle
)
184 DRM_DEBUG("sg free virtual = 0x%lx\n", entry
->handle
);
186 drm_sg_cleanup(entry
);