1592ffb21SWarner Losh
2592ffb21SWarner Losh #include <sys/cdefs.h>
3592ffb21SWarner Losh #include <dev/drm2/drmP.h>
4592ffb21SWarner Losh
5592ffb21SWarner Losh #include <dev/agp/agpreg.h>
6592ffb21SWarner Losh #include <dev/pci/pcireg.h>
7592ffb21SWarner Losh
8592ffb21SWarner Losh MALLOC_DEFINE(DRM_MEM_DMA, "drm_dma", "DRM DMA Data Structures");
9592ffb21SWarner Losh MALLOC_DEFINE(DRM_MEM_SAREA, "drm_sarea", "DRM SAREA Data Structures");
10592ffb21SWarner Losh MALLOC_DEFINE(DRM_MEM_DRIVER, "drm_driver", "DRM DRIVER Data Structures");
11592ffb21SWarner Losh MALLOC_DEFINE(DRM_MEM_MAGIC, "drm_magic", "DRM MAGIC Data Structures");
12592ffb21SWarner Losh MALLOC_DEFINE(DRM_MEM_MINOR, "drm_minor", "DRM MINOR Data Structures");
13592ffb21SWarner Losh MALLOC_DEFINE(DRM_MEM_IOCTLS, "drm_ioctls", "DRM IOCTL Data Structures");
14592ffb21SWarner Losh MALLOC_DEFINE(DRM_MEM_MAPS, "drm_maps", "DRM MAP Data Structures");
15592ffb21SWarner Losh MALLOC_DEFINE(DRM_MEM_BUFS, "drm_bufs", "DRM BUFFER Data Structures");
16592ffb21SWarner Losh MALLOC_DEFINE(DRM_MEM_SEGS, "drm_segs", "DRM SEGMENTS Data Structures");
17592ffb21SWarner Losh MALLOC_DEFINE(DRM_MEM_PAGES, "drm_pages", "DRM PAGES Data Structures");
18592ffb21SWarner Losh MALLOC_DEFINE(DRM_MEM_FILES, "drm_files", "DRM FILE Data Structures");
19592ffb21SWarner Losh MALLOC_DEFINE(DRM_MEM_QUEUES, "drm_queues", "DRM QUEUE Data Structures");
20592ffb21SWarner Losh MALLOC_DEFINE(DRM_MEM_CMDS, "drm_cmds", "DRM COMMAND Data Structures");
21592ffb21SWarner Losh MALLOC_DEFINE(DRM_MEM_MAPPINGS, "drm_mapping", "DRM MAPPING Data Structures");
22592ffb21SWarner Losh MALLOC_DEFINE(DRM_MEM_BUFLISTS, "drm_buflists", "DRM BUFLISTS Data Structures");
23592ffb21SWarner Losh MALLOC_DEFINE(DRM_MEM_AGPLISTS, "drm_agplists", "DRM AGPLISTS Data Structures");
24592ffb21SWarner Losh MALLOC_DEFINE(DRM_MEM_CTXBITMAP, "drm_ctxbitmap",
25592ffb21SWarner Losh "DRM CTXBITMAP Data Structures");
26592ffb21SWarner Losh MALLOC_DEFINE(DRM_MEM_SGLISTS, "drm_sglists", "DRM SGLISTS Data Structures");
27592ffb21SWarner Losh MALLOC_DEFINE(DRM_MEM_MM, "drm_sman", "DRM MEMORY MANAGER Data Structures");
28592ffb21SWarner Losh MALLOC_DEFINE(DRM_MEM_HASHTAB, "drm_hashtab", "DRM HASHTABLE Data Structures");
29592ffb21SWarner Losh MALLOC_DEFINE(DRM_MEM_KMS, "drm_kms", "DRM KMS Data Structures");
30592ffb21SWarner Losh MALLOC_DEFINE(DRM_MEM_VBLANK, "drm_vblank", "DRM VBLANK Handling Data");
31592ffb21SWarner Losh
32592ffb21SWarner Losh const char *fb_mode_option = NULL;
33592ffb21SWarner Losh
34592ffb21SWarner Losh #define NSEC_PER_USEC 1000L
35592ffb21SWarner Losh #define NSEC_PER_SEC 1000000000L
36592ffb21SWarner Losh
37592ffb21SWarner Losh int64_t
timeval_to_ns(const struct timeval * tv)38592ffb21SWarner Losh timeval_to_ns(const struct timeval *tv)
39592ffb21SWarner Losh {
40592ffb21SWarner Losh return ((int64_t)tv->tv_sec * NSEC_PER_SEC) +
41592ffb21SWarner Losh tv->tv_usec * NSEC_PER_USEC;
42592ffb21SWarner Losh }
43592ffb21SWarner Losh
44592ffb21SWarner Losh struct timeval
ns_to_timeval(const int64_t nsec)45592ffb21SWarner Losh ns_to_timeval(const int64_t nsec)
46592ffb21SWarner Losh {
47592ffb21SWarner Losh struct timeval tv;
48592ffb21SWarner Losh long rem;
49592ffb21SWarner Losh
50592ffb21SWarner Losh if (nsec == 0) {
51592ffb21SWarner Losh tv.tv_sec = 0;
52592ffb21SWarner Losh tv.tv_usec = 0;
53592ffb21SWarner Losh return (tv);
54592ffb21SWarner Losh }
55592ffb21SWarner Losh
56592ffb21SWarner Losh tv.tv_sec = nsec / NSEC_PER_SEC;
57592ffb21SWarner Losh rem = nsec % NSEC_PER_SEC;
58592ffb21SWarner Losh if (rem < 0) {
59592ffb21SWarner Losh tv.tv_sec--;
60592ffb21SWarner Losh rem += NSEC_PER_SEC;
61592ffb21SWarner Losh }
62592ffb21SWarner Losh tv.tv_usec = rem / 1000;
63592ffb21SWarner Losh return (tv);
64592ffb21SWarner Losh }
65592ffb21SWarner Losh
66592ffb21SWarner Losh /* Copied from OFED. */
67592ffb21SWarner Losh unsigned long drm_linux_timer_hz_mask;
68592ffb21SWarner Losh
69592ffb21SWarner Losh static void
drm_linux_timer_init(void * arg)70592ffb21SWarner Losh drm_linux_timer_init(void *arg)
71592ffb21SWarner Losh {
72592ffb21SWarner Losh
73592ffb21SWarner Losh /*
74592ffb21SWarner Losh * Compute an internal HZ value which can divide 2**32 to
75592ffb21SWarner Losh * avoid timer rounding problems when the tick value wraps
76592ffb21SWarner Losh * around 2**32:
77592ffb21SWarner Losh */
78592ffb21SWarner Losh drm_linux_timer_hz_mask = 1;
79592ffb21SWarner Losh while (drm_linux_timer_hz_mask < (unsigned long)hz)
80592ffb21SWarner Losh drm_linux_timer_hz_mask *= 2;
81592ffb21SWarner Losh drm_linux_timer_hz_mask--;
82592ffb21SWarner Losh }
83592ffb21SWarner Losh SYSINIT(drm_linux_timer, SI_SUB_DRIVERS, SI_ORDER_FIRST, drm_linux_timer_init, NULL);
84592ffb21SWarner Losh
85592ffb21SWarner Losh static const drm_pci_id_list_t *
drm_find_description(int vendor,int device,const drm_pci_id_list_t * idlist)86592ffb21SWarner Losh drm_find_description(int vendor, int device, const drm_pci_id_list_t *idlist)
87592ffb21SWarner Losh {
88592ffb21SWarner Losh int i = 0;
89592ffb21SWarner Losh
90592ffb21SWarner Losh for (i = 0; idlist[i].vendor != 0; i++) {
91592ffb21SWarner Losh if ((idlist[i].vendor == vendor) &&
92592ffb21SWarner Losh ((idlist[i].device == device) ||
93592ffb21SWarner Losh (idlist[i].device == 0))) {
94592ffb21SWarner Losh return (&idlist[i]);
95592ffb21SWarner Losh }
96592ffb21SWarner Losh }
97592ffb21SWarner Losh return (NULL);
98592ffb21SWarner Losh }
99592ffb21SWarner Losh
100592ffb21SWarner Losh /*
101592ffb21SWarner Losh * drm_probe_helper: called by a driver at the end of its probe
102592ffb21SWarner Losh * method.
103592ffb21SWarner Losh */
104592ffb21SWarner Losh int
drm_probe_helper(device_t kdev,const drm_pci_id_list_t * idlist)105592ffb21SWarner Losh drm_probe_helper(device_t kdev, const drm_pci_id_list_t *idlist)
106592ffb21SWarner Losh {
107592ffb21SWarner Losh const drm_pci_id_list_t *id_entry;
108592ffb21SWarner Losh int vendor, device;
109592ffb21SWarner Losh
110592ffb21SWarner Losh vendor = pci_get_vendor(kdev);
111592ffb21SWarner Losh device = pci_get_device(kdev);
112592ffb21SWarner Losh
113592ffb21SWarner Losh if (pci_get_class(kdev) != PCIC_DISPLAY ||
114592ffb21SWarner Losh (pci_get_subclass(kdev) != PCIS_DISPLAY_VGA &&
115592ffb21SWarner Losh pci_get_subclass(kdev) != PCIS_DISPLAY_OTHER))
116592ffb21SWarner Losh return (-ENXIO);
117592ffb21SWarner Losh
118592ffb21SWarner Losh id_entry = drm_find_description(vendor, device, idlist);
119592ffb21SWarner Losh if (id_entry != NULL) {
120592ffb21SWarner Losh if (device_get_desc(kdev) == NULL) {
121592ffb21SWarner Losh DRM_DEBUG("%s desc: %s\n",
122592ffb21SWarner Losh device_get_nameunit(kdev), id_entry->name);
123592ffb21SWarner Losh device_set_desc(kdev, id_entry->name);
124592ffb21SWarner Losh }
125*1f42dc84SNiclas Zeising #if !defined(__arm__)
126264d4ffdSWarner Losh DRM_OBSOLETE(kdev);
127*1f42dc84SNiclas Zeising #endif
128264d4ffdSWarner Losh return (-BUS_PROBE_GENERIC);
129592ffb21SWarner Losh }
130592ffb21SWarner Losh
131592ffb21SWarner Losh return (-ENXIO);
132592ffb21SWarner Losh }
133592ffb21SWarner Losh
134592ffb21SWarner Losh /*
135592ffb21SWarner Losh * drm_attach_helper: called by a driver at the end of its attach
136592ffb21SWarner Losh * method.
137592ffb21SWarner Losh */
138592ffb21SWarner Losh int
drm_attach_helper(device_t kdev,const drm_pci_id_list_t * idlist,struct drm_driver * driver)139592ffb21SWarner Losh drm_attach_helper(device_t kdev, const drm_pci_id_list_t *idlist,
140592ffb21SWarner Losh struct drm_driver *driver)
141592ffb21SWarner Losh {
142592ffb21SWarner Losh struct drm_device *dev;
143592ffb21SWarner Losh int vendor, device;
144592ffb21SWarner Losh int ret;
145592ffb21SWarner Losh
146592ffb21SWarner Losh dev = device_get_softc(kdev);
147592ffb21SWarner Losh
148592ffb21SWarner Losh vendor = pci_get_vendor(kdev);
149592ffb21SWarner Losh device = pci_get_device(kdev);
150592ffb21SWarner Losh dev->id_entry = drm_find_description(vendor, device, idlist);
151592ffb21SWarner Losh
152592ffb21SWarner Losh ret = drm_get_pci_dev(kdev, dev, driver);
153592ffb21SWarner Losh
154592ffb21SWarner Losh return (ret);
155592ffb21SWarner Losh }
156592ffb21SWarner Losh
157592ffb21SWarner Losh int
drm_generic_suspend(device_t kdev)158592ffb21SWarner Losh drm_generic_suspend(device_t kdev)
159592ffb21SWarner Losh {
160592ffb21SWarner Losh struct drm_device *dev;
161592ffb21SWarner Losh int error;
162592ffb21SWarner Losh
163592ffb21SWarner Losh DRM_DEBUG_KMS("Starting suspend\n");
164592ffb21SWarner Losh
165592ffb21SWarner Losh dev = device_get_softc(kdev);
166592ffb21SWarner Losh if (dev->driver->suspend) {
167592ffb21SWarner Losh pm_message_t state;
168592ffb21SWarner Losh
169592ffb21SWarner Losh state.event = PM_EVENT_SUSPEND;
170592ffb21SWarner Losh error = -dev->driver->suspend(dev, state);
171592ffb21SWarner Losh if (error)
172592ffb21SWarner Losh goto out;
173592ffb21SWarner Losh }
174592ffb21SWarner Losh
175592ffb21SWarner Losh error = bus_generic_suspend(kdev);
176592ffb21SWarner Losh
177592ffb21SWarner Losh out:
178592ffb21SWarner Losh DRM_DEBUG_KMS("Finished suspend: %d\n", error);
179592ffb21SWarner Losh
180592ffb21SWarner Losh return error;
181592ffb21SWarner Losh }
182592ffb21SWarner Losh
183592ffb21SWarner Losh int
drm_generic_resume(device_t kdev)184592ffb21SWarner Losh drm_generic_resume(device_t kdev)
185592ffb21SWarner Losh {
186592ffb21SWarner Losh struct drm_device *dev;
187592ffb21SWarner Losh int error;
188592ffb21SWarner Losh
189592ffb21SWarner Losh DRM_DEBUG_KMS("Starting resume\n");
190592ffb21SWarner Losh
191592ffb21SWarner Losh dev = device_get_softc(kdev);
192592ffb21SWarner Losh if (dev->driver->resume) {
193592ffb21SWarner Losh error = -dev->driver->resume(dev);
194592ffb21SWarner Losh if (error)
195592ffb21SWarner Losh goto out;
196592ffb21SWarner Losh }
197592ffb21SWarner Losh
198592ffb21SWarner Losh error = bus_generic_resume(kdev);
199592ffb21SWarner Losh
200592ffb21SWarner Losh out:
201592ffb21SWarner Losh DRM_DEBUG_KMS("Finished resume: %d\n", error);
202592ffb21SWarner Losh
203592ffb21SWarner Losh return error;
204592ffb21SWarner Losh }
205592ffb21SWarner Losh
206592ffb21SWarner Losh int
drm_generic_detach(device_t kdev)207592ffb21SWarner Losh drm_generic_detach(device_t kdev)
208592ffb21SWarner Losh {
209592ffb21SWarner Losh struct drm_device *dev;
210592ffb21SWarner Losh int i;
211592ffb21SWarner Losh
212592ffb21SWarner Losh dev = device_get_softc(kdev);
213592ffb21SWarner Losh
214592ffb21SWarner Losh drm_put_dev(dev);
215592ffb21SWarner Losh
216592ffb21SWarner Losh /* Clean up PCI resources allocated by drm_bufs.c. We're not really
217592ffb21SWarner Losh * worried about resource consumption while the DRM is inactive (between
218592ffb21SWarner Losh * lastclose and firstopen or unload) because these aren't actually
219592ffb21SWarner Losh * taking up KVA, just keeping the PCI resource allocated.
220592ffb21SWarner Losh */
221592ffb21SWarner Losh for (i = 0; i < DRM_MAX_PCI_RESOURCE; i++) {
222592ffb21SWarner Losh if (dev->pcir[i] == NULL)
223592ffb21SWarner Losh continue;
224592ffb21SWarner Losh bus_release_resource(dev->dev, SYS_RES_MEMORY,
225592ffb21SWarner Losh dev->pcirid[i], dev->pcir[i]);
226592ffb21SWarner Losh dev->pcir[i] = NULL;
227592ffb21SWarner Losh }
228592ffb21SWarner Losh
229592ffb21SWarner Losh if (pci_disable_busmaster(dev->dev))
230592ffb21SWarner Losh DRM_ERROR("Request to disable bus-master failed.\n");
231592ffb21SWarner Losh
232592ffb21SWarner Losh return (0);
233592ffb21SWarner Losh }
234592ffb21SWarner Losh
235592ffb21SWarner Losh int
drm_add_busid_modesetting(struct drm_device * dev,struct sysctl_ctx_list * ctx,struct sysctl_oid * top)236592ffb21SWarner Losh drm_add_busid_modesetting(struct drm_device *dev, struct sysctl_ctx_list *ctx,
237592ffb21SWarner Losh struct sysctl_oid *top)
238592ffb21SWarner Losh {
239592ffb21SWarner Losh struct sysctl_oid *oid;
240592ffb21SWarner Losh
241592ffb21SWarner Losh snprintf(dev->busid_str, sizeof(dev->busid_str),
242592ffb21SWarner Losh "pci:%04x:%02x:%02x.%d", dev->pci_domain, dev->pci_bus,
243592ffb21SWarner Losh dev->pci_slot, dev->pci_func);
244592ffb21SWarner Losh oid = SYSCTL_ADD_STRING(ctx, SYSCTL_CHILDREN(top), OID_AUTO, "busid",
245592ffb21SWarner Losh CTLFLAG_RD, dev->busid_str, 0, NULL);
246592ffb21SWarner Losh if (oid == NULL)
247592ffb21SWarner Losh return (-ENOMEM);
248592ffb21SWarner Losh dev->modesetting = (dev->driver->driver_features & DRIVER_MODESET) != 0;
249592ffb21SWarner Losh oid = SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(top), OID_AUTO,
250592ffb21SWarner Losh "modesetting", CTLFLAG_RD, &dev->modesetting, 0, NULL);
251592ffb21SWarner Losh if (oid == NULL)
252592ffb21SWarner Losh return (-ENOMEM);
253592ffb21SWarner Losh
254592ffb21SWarner Losh return (0);
255592ffb21SWarner Losh }
256592ffb21SWarner Losh
257592ffb21SWarner Losh static int
drm_device_find_capability(struct drm_device * dev,int cap)258592ffb21SWarner Losh drm_device_find_capability(struct drm_device *dev, int cap)
259592ffb21SWarner Losh {
260592ffb21SWarner Losh
261592ffb21SWarner Losh return (pci_find_cap(dev->dev, cap, NULL) == 0);
262592ffb21SWarner Losh }
263592ffb21SWarner Losh
264592ffb21SWarner Losh int
drm_pci_device_is_agp(struct drm_device * dev)265592ffb21SWarner Losh drm_pci_device_is_agp(struct drm_device *dev)
266592ffb21SWarner Losh {
267592ffb21SWarner Losh if (dev->driver->device_is_agp != NULL) {
268592ffb21SWarner Losh int ret;
269592ffb21SWarner Losh
270592ffb21SWarner Losh /* device_is_agp returns a tristate, 0 = not AGP, 1 = definitely
271592ffb21SWarner Losh * AGP, 2 = fall back to PCI capability
272592ffb21SWarner Losh */
273592ffb21SWarner Losh ret = (*dev->driver->device_is_agp)(dev);
274592ffb21SWarner Losh if (ret != DRM_MIGHT_BE_AGP)
275592ffb21SWarner Losh return ret;
276592ffb21SWarner Losh }
277592ffb21SWarner Losh
278592ffb21SWarner Losh return (drm_device_find_capability(dev, PCIY_AGP));
279592ffb21SWarner Losh }
280592ffb21SWarner Losh
281592ffb21SWarner Losh int
drm_pci_device_is_pcie(struct drm_device * dev)282592ffb21SWarner Losh drm_pci_device_is_pcie(struct drm_device *dev)
283592ffb21SWarner Losh {
284592ffb21SWarner Losh
285592ffb21SWarner Losh return (drm_device_find_capability(dev, PCIY_EXPRESS));
286592ffb21SWarner Losh }
287592ffb21SWarner Losh
288592ffb21SWarner Losh static bool
dmi_found(const struct dmi_system_id * dsi)289592ffb21SWarner Losh dmi_found(const struct dmi_system_id *dsi)
290592ffb21SWarner Losh {
291592ffb21SWarner Losh char *hw_vendor, *hw_prod;
292592ffb21SWarner Losh int i, slot;
293592ffb21SWarner Losh bool res;
294592ffb21SWarner Losh
295592ffb21SWarner Losh hw_vendor = kern_getenv("smbios.planar.maker");
296592ffb21SWarner Losh hw_prod = kern_getenv("smbios.planar.product");
297592ffb21SWarner Losh res = true;
298592ffb21SWarner Losh for (i = 0; i < nitems(dsi->matches); i++) {
299592ffb21SWarner Losh slot = dsi->matches[i].slot;
300592ffb21SWarner Losh switch (slot) {
301592ffb21SWarner Losh case DMI_NONE:
302592ffb21SWarner Losh break;
303592ffb21SWarner Losh case DMI_SYS_VENDOR:
304592ffb21SWarner Losh case DMI_BOARD_VENDOR:
305592ffb21SWarner Losh if (hw_vendor != NULL &&
306592ffb21SWarner Losh !strcmp(hw_vendor, dsi->matches[i].substr)) {
307592ffb21SWarner Losh break;
308592ffb21SWarner Losh } else {
309592ffb21SWarner Losh res = false;
310592ffb21SWarner Losh goto out;
311592ffb21SWarner Losh }
312592ffb21SWarner Losh case DMI_PRODUCT_NAME:
313592ffb21SWarner Losh case DMI_BOARD_NAME:
314592ffb21SWarner Losh if (hw_prod != NULL &&
315592ffb21SWarner Losh !strcmp(hw_prod, dsi->matches[i].substr)) {
316592ffb21SWarner Losh break;
317592ffb21SWarner Losh } else {
318592ffb21SWarner Losh res = false;
319592ffb21SWarner Losh goto out;
320592ffb21SWarner Losh }
321592ffb21SWarner Losh default:
322592ffb21SWarner Losh res = false;
323592ffb21SWarner Losh goto out;
324592ffb21SWarner Losh }
325592ffb21SWarner Losh }
326592ffb21SWarner Losh out:
327592ffb21SWarner Losh freeenv(hw_vendor);
328592ffb21SWarner Losh freeenv(hw_prod);
329592ffb21SWarner Losh
330592ffb21SWarner Losh return (res);
331592ffb21SWarner Losh }
332592ffb21SWarner Losh
333592ffb21SWarner Losh bool
dmi_check_system(const struct dmi_system_id * sysid)334592ffb21SWarner Losh dmi_check_system(const struct dmi_system_id *sysid)
335592ffb21SWarner Losh {
336592ffb21SWarner Losh const struct dmi_system_id *dsi;
337592ffb21SWarner Losh bool res;
338592ffb21SWarner Losh
339592ffb21SWarner Losh for (res = false, dsi = sysid; dsi->matches[0].slot != 0 ; dsi++) {
340592ffb21SWarner Losh if (dmi_found(dsi)) {
341592ffb21SWarner Losh res = true;
342592ffb21SWarner Losh if (dsi->callback != NULL && dsi->callback(dsi))
343592ffb21SWarner Losh break;
344592ffb21SWarner Losh }
345592ffb21SWarner Losh }
346592ffb21SWarner Losh return (res);
347592ffb21SWarner Losh }
348592ffb21SWarner Losh
349592ffb21SWarner Losh #if __OS_HAS_MTRR
350592ffb21SWarner Losh int
drm_mtrr_add(unsigned long offset,unsigned long size,unsigned int flags)351592ffb21SWarner Losh drm_mtrr_add(unsigned long offset, unsigned long size, unsigned int flags)
352592ffb21SWarner Losh {
353592ffb21SWarner Losh int act;
354592ffb21SWarner Losh struct mem_range_desc mrdesc;
355592ffb21SWarner Losh
356592ffb21SWarner Losh mrdesc.mr_base = offset;
357592ffb21SWarner Losh mrdesc.mr_len = size;
358592ffb21SWarner Losh mrdesc.mr_flags = flags;
359592ffb21SWarner Losh act = MEMRANGE_SET_UPDATE;
360592ffb21SWarner Losh strlcpy(mrdesc.mr_owner, "drm", sizeof(mrdesc.mr_owner));
361592ffb21SWarner Losh return (-mem_range_attr_set(&mrdesc, &act));
362592ffb21SWarner Losh }
363592ffb21SWarner Losh
364592ffb21SWarner Losh int
drm_mtrr_del(int handle __unused,unsigned long offset,unsigned long size,unsigned int flags)365592ffb21SWarner Losh drm_mtrr_del(int handle __unused, unsigned long offset, unsigned long size,
366592ffb21SWarner Losh unsigned int flags)
367592ffb21SWarner Losh {
368592ffb21SWarner Losh int act;
369592ffb21SWarner Losh struct mem_range_desc mrdesc;
370592ffb21SWarner Losh
371592ffb21SWarner Losh mrdesc.mr_base = offset;
372592ffb21SWarner Losh mrdesc.mr_len = size;
373592ffb21SWarner Losh mrdesc.mr_flags = flags;
374592ffb21SWarner Losh act = MEMRANGE_SET_REMOVE;
375592ffb21SWarner Losh strlcpy(mrdesc.mr_owner, "drm", sizeof(mrdesc.mr_owner));
376592ffb21SWarner Losh return (-mem_range_attr_set(&mrdesc, &act));
377592ffb21SWarner Losh }
378592ffb21SWarner Losh #endif
379592ffb21SWarner Losh
380592ffb21SWarner Losh void
drm_clflush_pages(vm_page_t * pages,unsigned long num_pages)381592ffb21SWarner Losh drm_clflush_pages(vm_page_t *pages, unsigned long num_pages)
382592ffb21SWarner Losh {
383592ffb21SWarner Losh
384592ffb21SWarner Losh #if defined(__i386__) || defined(__amd64__)
385592ffb21SWarner Losh pmap_invalidate_cache_pages(pages, num_pages);
386592ffb21SWarner Losh #else
387592ffb21SWarner Losh DRM_ERROR("drm_clflush_pages not implemented on this architecture");
388592ffb21SWarner Losh #endif
389592ffb21SWarner Losh }
390592ffb21SWarner Losh
391592ffb21SWarner Losh void
drm_clflush_virt_range(char * addr,unsigned long length)392592ffb21SWarner Losh drm_clflush_virt_range(char *addr, unsigned long length)
393592ffb21SWarner Losh {
394592ffb21SWarner Losh
395592ffb21SWarner Losh #if defined(__i386__) || defined(__amd64__)
396d12c4465SKonstantin Belousov pmap_force_invalidate_cache_range((vm_offset_t)addr,
397d12c4465SKonstantin Belousov (vm_offset_t)addr + length);
398592ffb21SWarner Losh #else
399592ffb21SWarner Losh DRM_ERROR("drm_clflush_virt_range not implemented on this architecture");
400592ffb21SWarner Losh #endif
401592ffb21SWarner Losh }
402592ffb21SWarner Losh
403592ffb21SWarner Losh void
hex_dump_to_buffer(const void * buf,size_t len,int rowsize,int groupsize,char * linebuf,size_t linebuflen,bool ascii __unused)404592ffb21SWarner Losh hex_dump_to_buffer(const void *buf, size_t len, int rowsize, int groupsize,
405592ffb21SWarner Losh char *linebuf, size_t linebuflen, bool ascii __unused)
406592ffb21SWarner Losh {
407592ffb21SWarner Losh int i, j, c;
408592ffb21SWarner Losh
409592ffb21SWarner Losh i = j = 0;
410592ffb21SWarner Losh
411592ffb21SWarner Losh while (i < len && j <= linebuflen) {
412592ffb21SWarner Losh c = ((const char *)buf)[i];
413592ffb21SWarner Losh
414592ffb21SWarner Losh if (i != 0) {
415592ffb21SWarner Losh if (i % rowsize == 0) {
416592ffb21SWarner Losh /* Newline required. */
417592ffb21SWarner Losh sprintf(linebuf + j, "\n");
418592ffb21SWarner Losh ++j;
419592ffb21SWarner Losh } else if (i % groupsize == 0) {
420592ffb21SWarner Losh /* Space required. */
421592ffb21SWarner Losh sprintf(linebuf + j, " ");
422592ffb21SWarner Losh ++j;
423592ffb21SWarner Losh }
424592ffb21SWarner Losh }
425592ffb21SWarner Losh
426592ffb21SWarner Losh if (j > linebuflen - 4)
427592ffb21SWarner Losh break;
428592ffb21SWarner Losh
429592ffb21SWarner Losh sprintf(linebuf + j, "%02X", c);
430592ffb21SWarner Losh j += 2;
431592ffb21SWarner Losh
432592ffb21SWarner Losh ++i;
433592ffb21SWarner Losh }
434592ffb21SWarner Losh
435592ffb21SWarner Losh if (j <= linebuflen)
436592ffb21SWarner Losh sprintf(linebuf + j, "\n");
437592ffb21SWarner Losh }
438592ffb21SWarner Losh
439592ffb21SWarner Losh #if DRM_LINUX
440592ffb21SWarner Losh
441592ffb21SWarner Losh #include <sys/sysproto.h>
442592ffb21SWarner Losh
443592ffb21SWarner Losh MODULE_DEPEND(DRIVER_NAME, linux, 1, 1, 1);
444592ffb21SWarner Losh
445592ffb21SWarner Losh #define LINUX_IOCTL_DRM_MIN 0x6400
446592ffb21SWarner Losh #define LINUX_IOCTL_DRM_MAX 0x64ff
447592ffb21SWarner Losh
448592ffb21SWarner Losh static linux_ioctl_function_t drm_linux_ioctl;
449592ffb21SWarner Losh static struct linux_ioctl_handler drm_handler = {drm_linux_ioctl,
450592ffb21SWarner Losh LINUX_IOCTL_DRM_MIN, LINUX_IOCTL_DRM_MAX};
451592ffb21SWarner Losh
452592ffb21SWarner Losh /* The bits for in/out are switched on Linux */
453592ffb21SWarner Losh #define LINUX_IOC_IN IOC_OUT
454592ffb21SWarner Losh #define LINUX_IOC_OUT IOC_IN
455592ffb21SWarner Losh
456592ffb21SWarner Losh static int
drm_linux_ioctl(DRM_STRUCTPROC * p,struct linux_ioctl_args * args)457592ffb21SWarner Losh drm_linux_ioctl(DRM_STRUCTPROC *p, struct linux_ioctl_args* args)
458592ffb21SWarner Losh {
459592ffb21SWarner Losh int error;
460592ffb21SWarner Losh int cmd = args->cmd;
461592ffb21SWarner Losh
462592ffb21SWarner Losh args->cmd &= ~(LINUX_IOC_IN | LINUX_IOC_OUT);
463592ffb21SWarner Losh if (cmd & LINUX_IOC_IN)
464592ffb21SWarner Losh args->cmd |= IOC_IN;
465592ffb21SWarner Losh if (cmd & LINUX_IOC_OUT)
466592ffb21SWarner Losh args->cmd |= IOC_OUT;
467592ffb21SWarner Losh
468592ffb21SWarner Losh error = ioctl(p, (struct ioctl_args *)args);
469592ffb21SWarner Losh
470592ffb21SWarner Losh return error;
471592ffb21SWarner Losh }
472592ffb21SWarner Losh #endif /* DRM_LINUX */
473592ffb21SWarner Losh
474592ffb21SWarner Losh static int
drm_modevent(module_t mod,int type,void * data)475592ffb21SWarner Losh drm_modevent(module_t mod, int type, void *data)
476592ffb21SWarner Losh {
477592ffb21SWarner Losh
478592ffb21SWarner Losh switch (type) {
479592ffb21SWarner Losh case MOD_LOAD:
480592ffb21SWarner Losh TUNABLE_INT_FETCH("drm.debug", &drm_debug);
481592ffb21SWarner Losh TUNABLE_INT_FETCH("drm.notyet", &drm_notyet);
482592ffb21SWarner Losh break;
483592ffb21SWarner Losh }
484592ffb21SWarner Losh return (0);
485592ffb21SWarner Losh }
486592ffb21SWarner Losh
487592ffb21SWarner Losh static moduledata_t drm_mod = {
488592ffb21SWarner Losh "drmn",
489592ffb21SWarner Losh drm_modevent,
490592ffb21SWarner Losh 0
491592ffb21SWarner Losh };
492592ffb21SWarner Losh
493592ffb21SWarner Losh DECLARE_MODULE(drmn, drm_mod, SI_SUB_DRIVERS, SI_ORDER_FIRST);
494592ffb21SWarner Losh MODULE_VERSION(drmn, 1);
495592ffb21SWarner Losh MODULE_DEPEND(drmn, agp, 1, 1, 1);
496592ffb21SWarner Losh MODULE_DEPEND(drmn, pci, 1, 1, 1);
497592ffb21SWarner Losh MODULE_DEPEND(drmn, mem, 1, 1, 1);
498592ffb21SWarner Losh MODULE_DEPEND(drmn, iicbus, 1, 1, 1);
499