1
2#include <sys/cdefs.h>
3__FBSDID("$FreeBSD: stable/11/sys/dev/drm2/drm_os_freebsd.c 317008 2017-04-16 07:58:41Z mmel $");
4
5#include <dev/drm2/drmP.h>
6
7#include <dev/agp/agpreg.h>
8#include <dev/pci/pcireg.h>
9
10devclass_t drm_devclass;
11
12MALLOC_DEFINE(DRM_MEM_DMA, "drm_dma", "DRM DMA Data Structures");
13MALLOC_DEFINE(DRM_MEM_SAREA, "drm_sarea", "DRM SAREA Data Structures");
14MALLOC_DEFINE(DRM_MEM_DRIVER, "drm_driver", "DRM DRIVER Data Structures");
15MALLOC_DEFINE(DRM_MEM_MAGIC, "drm_magic", "DRM MAGIC Data Structures");
16MALLOC_DEFINE(DRM_MEM_MINOR, "drm_minor", "DRM MINOR Data Structures");
17MALLOC_DEFINE(DRM_MEM_IOCTLS, "drm_ioctls", "DRM IOCTL Data Structures");
18MALLOC_DEFINE(DRM_MEM_MAPS, "drm_maps", "DRM MAP Data Structures");
19MALLOC_DEFINE(DRM_MEM_BUFS, "drm_bufs", "DRM BUFFER Data Structures");
20MALLOC_DEFINE(DRM_MEM_SEGS, "drm_segs", "DRM SEGMENTS Data Structures");
21MALLOC_DEFINE(DRM_MEM_PAGES, "drm_pages", "DRM PAGES Data Structures");
22MALLOC_DEFINE(DRM_MEM_FILES, "drm_files", "DRM FILE Data Structures");
23MALLOC_DEFINE(DRM_MEM_QUEUES, "drm_queues", "DRM QUEUE Data Structures");
24MALLOC_DEFINE(DRM_MEM_CMDS, "drm_cmds", "DRM COMMAND Data Structures");
25MALLOC_DEFINE(DRM_MEM_MAPPINGS, "drm_mapping", "DRM MAPPING Data Structures");
26MALLOC_DEFINE(DRM_MEM_BUFLISTS, "drm_buflists", "DRM BUFLISTS Data Structures");
27MALLOC_DEFINE(DRM_MEM_AGPLISTS, "drm_agplists", "DRM AGPLISTS Data Structures");
28MALLOC_DEFINE(DRM_MEM_CTXBITMAP, "drm_ctxbitmap",
29    "DRM CTXBITMAP Data Structures");
30MALLOC_DEFINE(DRM_MEM_SGLISTS, "drm_sglists", "DRM SGLISTS Data Structures");
31MALLOC_DEFINE(DRM_MEM_MM, "drm_sman", "DRM MEMORY MANAGER Data Structures");
32MALLOC_DEFINE(DRM_MEM_HASHTAB, "drm_hashtab", "DRM HASHTABLE Data Structures");
33MALLOC_DEFINE(DRM_MEM_KMS, "drm_kms", "DRM KMS Data Structures");
34MALLOC_DEFINE(DRM_MEM_VBLANK, "drm_vblank", "DRM VBLANK Handling Data");
35
36const char *fb_mode_option = NULL;
37
38#define NSEC_PER_USEC	1000L
39#define NSEC_PER_SEC	1000000000L
40
41int64_t
42timeval_to_ns(const struct timeval *tv)
43{
44	return ((int64_t)tv->tv_sec * NSEC_PER_SEC) +
45		tv->tv_usec * NSEC_PER_USEC;
46}
47
48struct timeval
49ns_to_timeval(const int64_t nsec)
50{
51        struct timeval tv;
52	long rem;
53
54	if (nsec == 0) {
55		tv.tv_sec = 0;
56		tv.tv_usec = 0;
57		return (tv);
58	}
59
60        tv.tv_sec = nsec / NSEC_PER_SEC;
61	rem = nsec % NSEC_PER_SEC;
62        if (rem < 0) {
63                tv.tv_sec--;
64                rem += NSEC_PER_SEC;
65        }
66	tv.tv_usec = rem / 1000;
67        return (tv);
68}
69
70/* Copied from OFED. */
71unsigned long drm_linux_timer_hz_mask;
72
73static void
74drm_linux_timer_init(void *arg)
75{
76
77        /*
78         * Compute an internal HZ value which can divide 2**32 to
79         * avoid timer rounding problems when the tick value wraps
80         * around 2**32:
81         */
82        drm_linux_timer_hz_mask = 1;
83        while (drm_linux_timer_hz_mask < (unsigned long)hz)
84                drm_linux_timer_hz_mask *= 2;
85        drm_linux_timer_hz_mask--;
86}
87SYSINIT(drm_linux_timer, SI_SUB_DRIVERS, SI_ORDER_FIRST, drm_linux_timer_init, NULL);
88
89static const drm_pci_id_list_t *
90drm_find_description(int vendor, int device, const drm_pci_id_list_t *idlist)
91{
92	int i = 0;
93
94	for (i = 0; idlist[i].vendor != 0; i++) {
95		if ((idlist[i].vendor == vendor) &&
96		    ((idlist[i].device == device) ||
97		    (idlist[i].device == 0))) {
98			return (&idlist[i]);
99		}
100	}
101	return (NULL);
102}
103
104/*
105 * drm_probe_helper: called by a driver at the end of its probe
106 * method.
107 */
108int
109drm_probe_helper(device_t kdev, const drm_pci_id_list_t *idlist)
110{
111	const drm_pci_id_list_t *id_entry;
112	int vendor, device;
113
114	vendor = pci_get_vendor(kdev);
115	device = pci_get_device(kdev);
116
117	if (pci_get_class(kdev) != PCIC_DISPLAY ||
118	    (pci_get_subclass(kdev) != PCIS_DISPLAY_VGA &&
119	     pci_get_subclass(kdev) != PCIS_DISPLAY_OTHER))
120		return (-ENXIO);
121
122	id_entry = drm_find_description(vendor, device, idlist);
123	if (id_entry != NULL) {
124		if (device_get_desc(kdev) == NULL) {
125			DRM_DEBUG("%s desc: %s\n",
126			    device_get_nameunit(kdev), id_entry->name);
127			device_set_desc(kdev, id_entry->name);
128		}
129		return (0);
130	}
131
132	return (-ENXIO);
133}
134
135/*
136 * drm_attach_helper: called by a driver at the end of its attach
137 * method.
138 */
139int
140drm_attach_helper(device_t kdev, const drm_pci_id_list_t *idlist,
141    struct drm_driver *driver)
142{
143	struct drm_device *dev;
144	int vendor, device;
145	int ret;
146
147	dev = device_get_softc(kdev);
148
149	vendor = pci_get_vendor(kdev);
150	device = pci_get_device(kdev);
151	dev->id_entry = drm_find_description(vendor, device, idlist);
152
153	ret = drm_get_pci_dev(kdev, dev, driver);
154
155	return (ret);
156}
157
158int
159drm_generic_suspend(device_t kdev)
160{
161	struct drm_device *dev;
162	int error;
163
164	DRM_DEBUG_KMS("Starting suspend\n");
165
166	dev = device_get_softc(kdev);
167	if (dev->driver->suspend) {
168		pm_message_t state;
169
170		state.event = PM_EVENT_SUSPEND;
171		error = -dev->driver->suspend(dev, state);
172		if (error)
173			goto out;
174	}
175
176	error = bus_generic_suspend(kdev);
177
178out:
179	DRM_DEBUG_KMS("Finished suspend: %d\n", error);
180
181	return error;
182}
183
184int
185drm_generic_resume(device_t kdev)
186{
187	struct drm_device *dev;
188	int error;
189
190	DRM_DEBUG_KMS("Starting resume\n");
191
192	dev = device_get_softc(kdev);
193	if (dev->driver->resume) {
194		error = -dev->driver->resume(dev);
195		if (error)
196			goto out;
197	}
198
199	error = bus_generic_resume(kdev);
200
201out:
202	DRM_DEBUG_KMS("Finished resume: %d\n", error);
203
204	return error;
205}
206
207int
208drm_generic_detach(device_t kdev)
209{
210	struct drm_device *dev;
211	int i;
212
213	dev = device_get_softc(kdev);
214
215	drm_put_dev(dev);
216
217	/* Clean up PCI resources allocated by drm_bufs.c.  We're not really
218	 * worried about resource consumption while the DRM is inactive (between
219	 * lastclose and firstopen or unload) because these aren't actually
220	 * taking up KVA, just keeping the PCI resource allocated.
221	 */
222	for (i = 0; i < DRM_MAX_PCI_RESOURCE; i++) {
223		if (dev->pcir[i] == NULL)
224			continue;
225		bus_release_resource(dev->dev, SYS_RES_MEMORY,
226		    dev->pcirid[i], dev->pcir[i]);
227		dev->pcir[i] = NULL;
228	}
229
230	if (pci_disable_busmaster(dev->dev))
231		DRM_ERROR("Request to disable bus-master failed.\n");
232
233	return (0);
234}
235
236int
237drm_add_busid_modesetting(struct drm_device *dev, struct sysctl_ctx_list *ctx,
238    struct sysctl_oid *top)
239{
240	struct sysctl_oid *oid;
241
242	snprintf(dev->busid_str, sizeof(dev->busid_str),
243	     "pci:%04x:%02x:%02x.%d", dev->pci_domain, dev->pci_bus,
244	     dev->pci_slot, dev->pci_func);
245	oid = SYSCTL_ADD_STRING(ctx, SYSCTL_CHILDREN(top), OID_AUTO, "busid",
246	    CTLFLAG_RD, dev->busid_str, 0, NULL);
247	if (oid == NULL)
248		return (-ENOMEM);
249	dev->modesetting = (dev->driver->driver_features & DRIVER_MODESET) != 0;
250	oid = SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(top), OID_AUTO,
251	    "modesetting", CTLFLAG_RD, &dev->modesetting, 0, NULL);
252	if (oid == NULL)
253		return (-ENOMEM);
254
255	return (0);
256}
257
258static int
259drm_device_find_capability(struct drm_device *dev, int cap)
260{
261
262	return (pci_find_cap(dev->dev, cap, NULL) == 0);
263}
264
265int
266drm_pci_device_is_agp(struct drm_device *dev)
267{
268	if (dev->driver->device_is_agp != NULL) {
269		int ret;
270
271		/* device_is_agp returns a tristate, 0 = not AGP, 1 = definitely
272		 * AGP, 2 = fall back to PCI capability
273		 */
274		ret = (*dev->driver->device_is_agp)(dev);
275		if (ret != DRM_MIGHT_BE_AGP)
276			return ret;
277	}
278
279	return (drm_device_find_capability(dev, PCIY_AGP));
280}
281
282int
283drm_pci_device_is_pcie(struct drm_device *dev)
284{
285
286	return (drm_device_find_capability(dev, PCIY_EXPRESS));
287}
288
289static bool
290dmi_found(const struct dmi_system_id *dsi)
291{
292	char *hw_vendor, *hw_prod;
293	int i, slot;
294	bool res;
295
296	hw_vendor = kern_getenv("smbios.planar.maker");
297	hw_prod = kern_getenv("smbios.planar.product");
298	res = true;
299	for (i = 0; i < nitems(dsi->matches); i++) {
300		slot = dsi->matches[i].slot;
301		switch (slot) {
302		case DMI_NONE:
303			break;
304		case DMI_SYS_VENDOR:
305		case DMI_BOARD_VENDOR:
306			if (hw_vendor != NULL &&
307			    !strcmp(hw_vendor, dsi->matches[i].substr)) {
308				break;
309			} else {
310				res = false;
311				goto out;
312			}
313		case DMI_PRODUCT_NAME:
314		case DMI_BOARD_NAME:
315			if (hw_prod != NULL &&
316			    !strcmp(hw_prod, dsi->matches[i].substr)) {
317				break;
318			} else {
319				res = false;
320				goto out;
321			}
322		default:
323			res = false;
324			goto out;
325		}
326	}
327out:
328	freeenv(hw_vendor);
329	freeenv(hw_prod);
330
331	return (res);
332}
333
334bool
335dmi_check_system(const struct dmi_system_id *sysid)
336{
337	const struct dmi_system_id *dsi;
338	bool res;
339
340	for (res = false, dsi = sysid; dsi->matches[0].slot != 0 ; dsi++) {
341		if (dmi_found(dsi)) {
342			res = true;
343			if (dsi->callback != NULL && dsi->callback(dsi))
344				break;
345		}
346	}
347	return (res);
348}
349
350#if __OS_HAS_MTRR
351int
352drm_mtrr_add(unsigned long offset, unsigned long size, unsigned int flags)
353{
354	int act;
355	struct mem_range_desc mrdesc;
356
357	mrdesc.mr_base = offset;
358	mrdesc.mr_len = size;
359	mrdesc.mr_flags = flags;
360	act = MEMRANGE_SET_UPDATE;
361	strlcpy(mrdesc.mr_owner, "drm", sizeof(mrdesc.mr_owner));
362	return (-mem_range_attr_set(&mrdesc, &act));
363}
364
365int
366drm_mtrr_del(int handle __unused, unsigned long offset, unsigned long size,
367    unsigned int flags)
368{
369	int act;
370	struct mem_range_desc mrdesc;
371
372	mrdesc.mr_base = offset;
373	mrdesc.mr_len = size;
374	mrdesc.mr_flags = flags;
375	act = MEMRANGE_SET_REMOVE;
376	strlcpy(mrdesc.mr_owner, "drm", sizeof(mrdesc.mr_owner));
377	return (-mem_range_attr_set(&mrdesc, &act));
378}
379#endif
380
381void
382drm_clflush_pages(vm_page_t *pages, unsigned long num_pages)
383{
384
385#if defined(__i386__) || defined(__amd64__)
386	pmap_invalidate_cache_pages(pages, num_pages);
387#else
388	DRM_ERROR("drm_clflush_pages not implemented on this architecture");
389#endif
390}
391
392void
393drm_clflush_virt_range(char *addr, unsigned long length)
394{
395
396#if defined(__i386__) || defined(__amd64__)
397	pmap_invalidate_cache_range((vm_offset_t)addr,
398	    (vm_offset_t)addr + length, TRUE);
399#else
400	DRM_ERROR("drm_clflush_virt_range not implemented on this architecture");
401#endif
402}
403
404void
405hex_dump_to_buffer(const void *buf, size_t len, int rowsize, int groupsize,
406    char *linebuf, size_t linebuflen, bool ascii __unused)
407{
408	int i, j, c;
409
410	i = j = 0;
411
412	while (i < len && j <= linebuflen) {
413		c = ((const char *)buf)[i];
414
415		if (i != 0) {
416			if (i % rowsize == 0) {
417				/* Newline required. */
418				sprintf(linebuf + j, "\n");
419				++j;
420			} else if (i % groupsize == 0) {
421				/* Space required. */
422				sprintf(linebuf + j, " ");
423				++j;
424			}
425		}
426
427		if (j > linebuflen - 4)
428			break;
429
430		sprintf(linebuf + j, "%02X", c);
431		j += 2;
432
433		++i;
434	}
435
436	if (j <= linebuflen)
437		sprintf(linebuf + j, "\n");
438}
439
440#if DRM_LINUX
441
442#include <sys/sysproto.h>
443
444MODULE_DEPEND(DRIVER_NAME, linux, 1, 1, 1);
445
446#define LINUX_IOCTL_DRM_MIN		0x6400
447#define LINUX_IOCTL_DRM_MAX		0x64ff
448
449static linux_ioctl_function_t drm_linux_ioctl;
450static struct linux_ioctl_handler drm_handler = {drm_linux_ioctl,
451    LINUX_IOCTL_DRM_MIN, LINUX_IOCTL_DRM_MAX};
452
453/* The bits for in/out are switched on Linux */
454#define LINUX_IOC_IN	IOC_OUT
455#define LINUX_IOC_OUT	IOC_IN
456
457static int
458drm_linux_ioctl(DRM_STRUCTPROC *p, struct linux_ioctl_args* args)
459{
460	int error;
461	int cmd = args->cmd;
462
463	args->cmd &= ~(LINUX_IOC_IN | LINUX_IOC_OUT);
464	if (cmd & LINUX_IOC_IN)
465		args->cmd |= IOC_IN;
466	if (cmd & LINUX_IOC_OUT)
467		args->cmd |= IOC_OUT;
468
469	error = ioctl(p, (struct ioctl_args *)args);
470
471	return error;
472}
473#endif /* DRM_LINUX */
474
475static int
476drm_modevent(module_t mod, int type, void *data)
477{
478
479	switch (type) {
480	case MOD_LOAD:
481		TUNABLE_INT_FETCH("drm.debug", &drm_debug);
482		TUNABLE_INT_FETCH("drm.notyet", &drm_notyet);
483		break;
484	}
485	return (0);
486}
487
488static moduledata_t drm_mod = {
489	"drmn",
490	drm_modevent,
491	0
492};
493
494DECLARE_MODULE(drmn, drm_mod, SI_SUB_DRIVERS, SI_ORDER_FIRST);
495MODULE_VERSION(drmn, 1);
496MODULE_DEPEND(drmn, agp, 1, 1, 1);
497MODULE_DEPEND(drmn, pci, 1, 1, 1);
498MODULE_DEPEND(drmn, mem, 1, 1, 1);
499MODULE_DEPEND(drmn, iicbus, 1, 1, 1);
500