Annotation of src/sys/external/bsd/drm2/vmwgfx/vmwgfxfb.c, Revision 1.2
1.2 ! riastrad 1: /* $NetBSD: vmwgfxfb.c,v 1.1 2022/02/17 01:21:03 riastradh Exp $ */
1.1 riastrad 2:
3: /*-
4: * Copyright (c) 2022 The NetBSD Foundation, Inc.
5: * All rights reserved.
6: *
7: * Redistribution and use in source and binary forms, with or without
8: * modification, are permitted provided that the following conditions
9: * are met:
10: * 1. Redistributions of source code must retain the above copyright
11: * notice, this list of conditions and the following disclaimer.
12: * 2. Redistributions in binary form must reproduce the above copyright
13: * notice, this list of conditions and the following disclaimer in the
14: * documentation and/or other materials provided with the distribution.
15: *
16: * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
17: * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
18: * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
20: * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26: * POSSIBILITY OF SUCH DAMAGE.
27: */
28:
29:
30: #include <sys/cdefs.h>
1.2 ! riastrad 31: __KERNEL_RCSID(0, "$NetBSD: vmwgfxfb.c,v 1.1 2022/02/17 01:21:03 riastradh Exp $");
1.1 riastrad 32:
33: #include <sys/types.h>
34: #include <sys/device.h>
35:
36: #include <drm/drm_fb_helper.h>
37: #include <drm/drmfb.h>
38: #include <drm/drmfb_pci.h>
39:
40: #include "vmwgfx_drv.h"
41: #include "vmwgfx_task.h"
42: #include "vmwgfxfb.h"
43:
44: struct vmwgfxfb_softc {
45: struct drmfb_softc sc_drmfb; /* XXX Must be first. */
46: device_t sc_dev;
47: struct vmwgfxfb_attach_args sc_vfa;
48: struct vmwgfx_task sc_attach_task;
49: bool sc_attached:1;
50: };
51:
52: static int vmwgfxfb_match(device_t, cfdata_t, void *);
53: static void vmwgfxfb_attach(device_t, device_t, void *);
54: static int vmwgfxfb_detach(device_t, int);
55:
56: static void vmwgfxfb_attach_task(struct vmwgfx_task *);
57:
58: static paddr_t vmwgfxfb_drmfb_mmapfb(struct drmfb_softc *, off_t, int);
59: static bool vmwgfxfb_shutdown(device_t, int);
60:
61: CFATTACH_DECL_NEW(vmwgfxfb, sizeof(struct vmwgfxfb_softc),
62: vmwgfxfb_match, vmwgfxfb_attach, vmwgfxfb_detach, NULL);
63:
64: static const struct drmfb_params vmwgfxfb_drmfb_params = {
65: .dp_mmapfb = vmwgfxfb_drmfb_mmapfb,
66: .dp_mmap = drmfb_pci_mmap,
67: .dp_ioctl = drmfb_pci_ioctl,
68: .dp_is_vga_console = drmfb_pci_is_vga_console,
69: };
70:
71: static int
72: vmwgfxfb_match(device_t parent, cfdata_t match, void *aux)
73: {
74:
75: return 1;
76: }
77:
78: static void
79: vmwgfxfb_attach(device_t parent, device_t self, void *aux)
80: {
81: struct vmwgfxfb_softc *const sc = device_private(self);
82: const struct vmwgfxfb_attach_args *const vfa = aux;
83: int error;
84:
85: sc->sc_dev = self;
86: sc->sc_vfa = *vfa;
87: sc->sc_attached = false;
88:
89: aprint_naive("\n");
90: aprint_normal("\n");
91:
92: vmwgfx_task_init(&sc->sc_attach_task, &vmwgfxfb_attach_task);
93: error = vmwgfx_task_schedule(parent, &sc->sc_attach_task);
94: if (error) {
95: aprint_error_dev(self, "failed to schedule mode set: %d\n",
96: error);
1.2 ! riastrad 97: return;
1.1 riastrad 98: }
1.2 ! riastrad 99: config_pending_incr(self);
1.1 riastrad 100: }
101:
102: static int
103: vmwgfxfb_detach(device_t self, int flags)
104: {
105: struct vmwgfxfb_softc *const sc = device_private(self);
106: int error;
107:
108: if (sc->sc_attached) {
109: pmf_device_deregister(self);
110: error = drmfb_detach(&sc->sc_drmfb, flags);
111: if (error) {
112: /* XXX Ugh. */
113: (void)pmf_device_register1(self, NULL, NULL,
114: &vmwgfxfb_shutdown);
115: return error;
116: }
117: sc->sc_attached = false;
118: }
119:
120: return 0;
121: }
122:
123: static void
124: vmwgfxfb_attach_task(struct vmwgfx_task *task)
125: {
126: struct vmwgfxfb_softc *const sc = container_of(task,
127: struct vmwgfxfb_softc, sc_attach_task);
128: const struct vmwgfxfb_attach_args *const vfa = &sc->sc_vfa;
129: const struct drmfb_attach_args da = {
130: .da_dev = sc->sc_dev,
131: .da_fb_helper = vfa->vfa_fb_helper,
132: .da_fb_sizes = &vfa->vfa_fb_sizes,
133: .da_fb_vaddr = __UNVOLATILE(vfa->vfa_fb_ptr),
134: .da_fb_linebytes = vfa->vfa_fb_linebytes,
135: .da_params = &vmwgfxfb_drmfb_params,
136: };
137: device_t parent = device_parent(sc->sc_dev);
138: bool is_console;
139: int error;
140:
141: /*
142: * MD device enumeration logic may choose the vmwgfxN PCI
143: * device as the console. If so, propagate that down to the
144: * vmwgfxfbN device for genfb.
145: */
146: if (prop_dictionary_get_bool(device_properties(parent),
147: "is_console", &is_console) &&
148: !prop_dictionary_set_bool(device_properties(sc->sc_dev),
149: "is_console", is_console)) {
150: aprint_error_dev(sc->sc_dev, "failed to set is_console\n");
151: }
152:
153: error = drmfb_attach(&sc->sc_drmfb, &da);
154: if (error) {
155: aprint_error_dev(sc->sc_dev, "failed to attach drmfb: %d\n",
156: error);
1.2 ! riastrad 157: goto out;
1.1 riastrad 158: }
159: if (!pmf_device_register1(sc->sc_dev, NULL, NULL, &vmwgfxfb_shutdown))
160: aprint_error_dev(sc->sc_dev,
161: "failed to register shutdown handler\n");
162:
163: sc->sc_attached = true;
1.2 ! riastrad 164: out:
! 165: config_pending_decr(sc->sc_dev);
1.1 riastrad 166: }
167:
168: static bool
169: vmwgfxfb_shutdown(device_t self, int flags)
170: {
171: struct vmwgfxfb_softc *const sc = device_private(self);
172:
173: return drmfb_shutdown(&sc->sc_drmfb, flags);
174: }
175:
176: static paddr_t
177: vmwgfxfb_drmfb_mmapfb(struct drmfb_softc *drmfb, off_t offset, int prot)
178: {
179: struct vmwgfxfb_softc *const sc = container_of(drmfb,
180: struct vmwgfxfb_softc, sc_drmfb);
181: struct drm_fb_helper *const helper = sc->sc_vfa.vfa_fb_helper;
182: struct drm_framebuffer *const fb = helper->fb;
183: struct vmw_buffer_object *const vbo = /*XXX MAGIC HERE*/;
184: int flags = 0;
185:
186: if (offset < 0)
187: return -1;
188:
189: const unsigned num_pages __diagused = vbo->base.num_pages;
190:
191: KASSERT(offset < (num_pages << PAGE_SHIFT));
192: KASSERT(vbo->base.mem.bus.is_iomem);
193:
194: if (ISSET(vbo->base.mem.placement, TTM_PL_FLAG_WC))
195: flags |= BUS_SPACE_MAP_PREFETCHABLE;
196:
197: return bus_space_mmap(vbo->base.bdev->memt,
198: vbo->base.mem.bus.base, vbo->base.mem.bus.offset + offset,
199: prot, flags);
200: }
CVSweb <webmaster@jp.NetBSD.org>