1 /* $NetBSD: darwin_ioframebuffer.c,v 1.41 2008/04/28 20:23:41 martin Exp $ */
2
3 /*-
4 * Copyright (c) 2003 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Emmanuel Dreyfus.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 */
31
32 #include <sys/cdefs.h>
33 __KERNEL_RCSID(0, "$NetBSD: darwin_ioframebuffer.c,v 1.41 2008/04/28 20:23:41 martin Exp $");
34
35 #include <sys/types.h>
36 #include <sys/param.h>
37 #include <sys/systm.h>
38 #include <sys/queue.h>
39 #include <sys/malloc.h>
40 #include <sys/conf.h>
41 #include <sys/signal.h>
42 #include <sys/mount.h>
43 #include <sys/proc.h>
44 #include <sys/mman.h>
45 #include <sys/vnode.h>
46 #include <sys/resourcevar.h>
47 #include <sys/device.h>
48
49 #include <uvm/uvm_extern.h>
50 #include <uvm/uvm_object.h>
51 #include <uvm/uvm_device.h>
52 #include <uvm/uvm_map.h>
53 #include <uvm/uvm.h>
54
55 #include <dev/wscons/wsconsio.h>
56 #include <dev/wscons/wsdisplayvar.h>
57
58 #include <compat/sys/signal.h>
59
60 #include <compat/common/compat_util.h>
61
62 #include <compat/mach/mach_types.h>
63 #include <compat/mach/mach_exec.h>
64 #include <compat/mach/mach_message.h>
65 #include <compat/mach/mach_port.h>
66 #include <compat/mach/mach_errno.h>
67 #include <compat/mach/mach_iokit.h>
68
69 #include <compat/darwin/darwin_exec.h>
70 #include <compat/darwin/darwin_iokit.h>
71 #include <compat/darwin/darwin_sysctl.h>
72 #include <compat/darwin/darwin_ioframebuffer.h>
73
74 #include "ioconf.h"
75
76 /* Redefined from sys/dev/wscons/wsdisplay.c */
77 extern const struct cdevsw wsdisplay_cdevsw;
78
79 #define WSDISPLAYMINOR(unit, screen) (((unit) << 8) | (screen))
80
81 static int darwin_findscreen(dev_t *, int, int);
82
83 static struct uvm_object *darwin_ioframebuffer_shmem = NULL;
84 static void darwin_ioframebuffer_shmeminit(vaddr_t);
85
86 /* This is ugly, but we hope to see it going away quickly */
87
88 static char darwin_iofbconfig[] = "<dict ID=\"\"><key>IOFBModes</key><array ID=\"1\"><dict ID=\"2\"><key>AID</key><integer size=\"32\" ID=\"3\">0xee</integer><key>DM</key><data ID=\"4\">AAACAAAAAYAAMgAAAAAAAgAQAAAAAAAAAAAAAAAAAAAAAAAA</data><key>ID</key><integer size=\"32\" ID=\"5\">0x3e</integer></dict><dict ID=\"6\"><key>AID</key><integer size=\"32\" ID=\"7\">0x82</integer><key>DM</key><data ID=\"8\">AAACAAAAAYAAPAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAA</data><key>ID</key><integer size=\"32\" ID=\"9\">0x3</integer></dict><dict ID=\"10\"><key>AID</key><integer size=\"32\" ID=\"11\">0xe8</integer><key>DM</key><data ID=\"12\">AAACAAAAAYAAPAAAAAAAAgAQAAAAAAAAAAAAAAAAAAAAAAAA</data><key>ID</key><integer size=\"32\" ID=\"13\">0x37</integer></dict><dict ID=\"14\"><key>DM</key><data ID=\"15\">AAACAAAAAYAARgAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAA</data><key>ID</key><integer size=\"32\" ID=\"16\">0x5</integer></dict><dict ID=\"17\"><key>AID</key><reference IDREF=\"11\"/><key>DM</key><data ID=\"18\">AAACgAAAAeAAPAAAAAAAAgAQAAAAAAAAAAAAAAAAAAAAAAAA</data><key>ID</key><integer size=\"32\" ID=\"19\">0x38</integer></dict><dict ID=\"20\"><key>AID</key><reference IDREF=\"3\"/><key>DM</key><data ID=\"21\">AAACgAAAAeAAMgAAAAAAAgAQAAAAAAAAAAAAAAAAAAAAAAAA</data><key>ID</key><integer size=\"32\" ID=\"22\">0x3f</integer></dict><dict ID=\"23\"><key>AID</key><integer size=\"32\" ID=\"24\">0x96</integer><key>DM</key><data ID=\"25\">AAACgAAAAeAAPAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAA</data><key>ID</key><integer size=\"32\" ID=\"26\">0x6</integer></dict><dict ID=\"27\"><key>AID</key><integer size=\"32\" ID=\"28\">0x8c</integer><key>DM</key><data ID=\"29\">AAACgAAAAeAAQwAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAA</data><key>ID</key><integer size=\"32\" ID=\"30\">0x7</integer></dict><dict ID=\"31\"><key>AID</key><integer size=\"32\" ID=\"32\">0x98</integer><key>DM</key><data ID=\"33\">AAACgAAAAeAASAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAA</data><key>ID</key><integer size=\"32\" ID=\"34\">0x8</integer></dict><dict ID=\"35\"><key>AID</key><integer size=\"32\" ID=\"36\">0x9a</integer><key>DM</key><data ID=\"37\">AAACgAAAAeAASwAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAA</data><key>ID</key><integer size=\"32\" ID=\"38\">0x9</integer></dict><dict ID=\"39\"><key>AID</key><integer size=\"32\" ID=\"40\">0x9e</integer><key>DM</key><data ID=\"41\">AAACgAAAAeAAVQAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAA</data><key>ID</key><integer size=\"32\" ID=\"42\">0xa</integer></dict><dict ID=\"43\"><key>AID</key><integer size=\"32\" ID=\"44\">0xa0</integer><key>DM</key><data ID=\"45\">AAACgAAAA2YASwAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAA</data><key>ID</key><integer size=\"32\" ID=\"46\">0xe</integer></dict><dict ID=\"47\"><key>AID</key><reference IDREF=\"3\"/><key>DM</key><data ID=\"48\">AAAC0AAAAeAAMgAAAAAAAgAQAAAAAAAAAAAAAAAAAAAAAAAA</data><key>ID</key><integer size=\"32\" ID=\"49\">0x4b</integer></dict><dict ID=\"50\"><key>AID</key><reference IDREF=\"11\"/><key>DM</key><data ID=\"51\">AAAC0AAAAeAAPAAAAAAAAgAQAAAAAAAAAAAAAAAAAAAAAAAA</data><key>ID</key><integer size=\"32\" ID=\"52\">0x4d</integer></dict><dict ID=\"53\"><key>AID</key><reference IDREF=\"3\"/><key>DM</key><data ID=\"54\">AAAC0AAAAkAAMgAAAAAAAgAQAAAAAAAAAAAAAAAAAAAAAAAA</data><key>ID</key><integer size=\"32\" ID=\"55\">0x4c</integer></dict><dict ID=\"56\"><key>AID</key><reference IDREF=\"11\"/><key>DM</key><data ID=\"57\">AAAC0AAAAkAAPAAAAAAAAgAQAAAAAAAAAAAAAAAAAAAAAAAA</data><key>ID</key><integer size=\"32\" ID=\"58\">0x4e</integer></dict><dict ID=\"59\"><key>AID</key><reference IDREF=\"3\"/><key>DM</key><data ID=\"60\">AAADIAAAAlgAMgAAAAAAAgAQAAAAAAAAAAAAAAAAAAAAAAAA</data><key>ID</key><integer size=\"32\" ID=\"61\">0x40</integer></dict><dict ID=\"62\"><key>AID</key><integer size=\"32\" ID=\"63\">0xb4</integer><key>DM</key><data ID=\"64\">AAADIAAAAlgAOAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAA</data><key>ID</key><integer size=\"32\" ID=\"65\">0xf</integer></dict><dict ID=\"66\"><key>AID</key><integer size=\"32\" ID=\"67\">0xb6</integer><key>DM</key><data ID=\"68\">AAADIAAAAlgAPAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAA</data><key>ID</key><integer size=\"32\" ID=\"69\">0x10</integer></dict><dict ID=\"70\"><key>AID</key><reference IDREF=\"11\"/><key>DM</key><data ID=\"71\">AAADIAAAAlgAPAAAAAAAAgAQAAAAAAAAAAAAAAAAAAAAAAAA</data><key>ID</key><integer size=\"32\" ID=\"72\">0x39</integer></dict><dict ID=\"73\"><key>AID</key><integer size=\"32\" ID=\"74\">0x2a</integer><key>ID</key><integer size=\"32\" ID=\"75\">0x2d</integer><key>DF</key><integer size=\"32\" ID=\"76\">0x400</integer><key>DM</key><data ID=\"77\">AAADIAAAAlgAAAAAAAAAAgAABAAAAAAAAAAAAAAAAAAAAAAA</data></dict><dict ID=\"78\"><key>DF</key><integer size=\"32\" ID=\"79\">0x100</integer><key>DM</key><data ID=\"80\">AAADIAAAAlgAPAAAAAAAAgAAAQAAAAAAAAAAAAAAAAAAAAAA</data><key>ID</key><integer size=\"32\" ID=\"81\">0x32</integer></dict><dict ID=\"82\"><key>AID</key><integer size=\"32\" ID=\"83\">0xb8</integer><key>DM</key><data ID=\"84\">AAADIAAAAlgASAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAA</data><key>ID</key><integer size=\"32\" ID=\"85\">0x11</integer></dict><dict ID=\"86\"><key>AID</key><integer size=\"32\" ID=\"87\">0xba</integer><key>DM</key><data ID=\"88\">AAADIAAAAlgASwAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAA</data><key>ID</key><integer size=\"32\" ID=\"89\">0x12</integer></dict><dict ID=\"90\"><key>AID</key><reference IDREF=\"74\"/><key>ID</key><integer size=\"32\" ID=\"91\">0x46</integer><key>DF</key><reference IDREF=\"76\"/><key>DM</key><reference IDREF=\"77\"/></dict><dict ID=\"92\"><key>AID</key><integer size=\"32\" ID=\"93\">0xbc</integer><key>DM</key><data ID=\"94\">AAADIAAAAlgAVQAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAA</data><key>ID</key><integer size=\"32\" ID=\"95\">0x13</integer></dict><dict ID=\"96\"><key>AID</key><reference IDREF=\"3\"/><key>DM</key><data ID=\"97\">AAADQAAAAnAAMgAAAAAAAgAQAAAAAAAAAAAAAAAAAAAAAAAA</data><key>ID</key><integer size=\"32\" ID=\"98\">0x41</integer></dict><dict ID=\"99\"><key>AID</key><reference IDREF=\"11\"/><key>DM</key><data ID=\"100\">AAADQAAAAnAAPAAAAAAAAgAQAAAAAAAAAAAAAAAAAAAAAAAA</data><key>ID</key><integer size=\"32\" ID=\"101\">0x3a</integer></dict><dict ID=\"102\"><key>AID</key><integer size=\"32\" ID=\"103\">0xaa</integer><key>DM</key><data ID=\"104\">AAADQAAAAnAASwAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAA</data><key>ID</key><integer size=\"32\" ID=\"105\">0x17</integer></dict><dict ID=\"106\"><key>DM</key><data ID=\"107\">AAADVAAAAoAAPAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAA</data><key>ID</key><integer size=\"32\" ID=\"108\">0x18</integer></dict><dict ID=\"109\"><key>AID</key><integer size=\"32\" ID=\"110\">0xbe</integer><key>DM</key><data ID=\"111\">AAAEAAAAAwAAPAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAA</data><key>ID</key><integer size=\"32\" ID=\"112\">0x19</integer></dict><dict ID=\"113\"><key>AID</key><reference IDREF=\"74\"/><key>ID</key><integer size=\"32\" ID=\"114\">0x2e</integer><key>DF</key><integer size=\"32\" ID=\"115\">0x407</integer><key>DM</key><data ID=\"116\">AAAEAAAAAwAAAAAAAAAAAgAABAcAAAAAAAAAAAAAAAAAAAAA</data></dict><dict ID=\"117\"><key>AID</key><reference IDREF=\"110\"/><key>ID</key><integer size=\"32\" ID=\"118\">0x33</integer><key>DF</key><reference IDREF=\"79\"/><key>DM</key><data ID=\"119\">AAAEAAAAAwAAPAAAAAAAAgAAAQAAAAAAAAAAAAAAAAAAAAAA</data></dict><dict ID=\"120\"><key>AID</key><integer size=\"32\" ID=\"121\">0xc8</integer><key>DM</key><data ID=\"122\">AAAEAAAAAwAARgAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAA</data><key>ID</key><integer size=\"32\" ID=\"123\">0x1a</integer></dict><dict ID=\"124\"><key>AID</key><integer size=\"32\" ID=\"125\">0xcc</integer><key>DM</key><data ID=\"126\">AAAEAAAAAwAASwAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAA</data><key>ID</key><integer size=\"32\" ID=\"127\">0x1b</integer></dict><dict ID=\"128\"><key>AID</key><integer size=\"32\" ID=\"129\">0xd2</integer><key>DM</key><reference IDREF=\"126\"/><key>ID</key><integer size=\"32\" ID=\"130\">0x1c</integer></dict><dict ID=\"131\"><key>AID</key><integer size=\"32\" ID=\"132\">0xd0</integer><key>DM</key><data ID=\"133\">AAAEAAAAAwAAVQAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAA</data><key>ID</key><integer size=\"32\" ID=\"134\">0x1d</integer></dict><dict ID=\"135\"><key>AID</key><integer size=\"32\" ID=\"136\">0xdc</integer><key>DM</key><data ID=\"137\">AAAEgAAAA2YASwAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAA</data><key>ID</key><integer size=\"32\" ID=\"138\">0x21</integer></dict><dict ID=\"139\"><key>AID</key><integer size=\"32\" ID=\"140\">0xfa</integer><key>DM</key><data ID=\"141\">AAAFAAAAA8AASwAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAA</data><key>ID</key><integer size=\"32\" ID=\"142\">0x22</integer></dict><dict ID=\"143\"><key>AID</key><integer size=\"32\" ID=\"144\">0x104</integer><key>DM</key><data ID=\"145\">AAAFAAAABAAAPAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAA</data><key>ID</key><integer size=\"32\" ID=\"146\">0x23</integer></dict><dict ID=\"147\"><key>AID</key><integer size=\"32\" ID=\"148\">0x106</integer><key>DM</key><data ID=\"149\">AAAFAAAABAAASwAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAA</data><key>ID</key><integer size=\"32\" ID=\"150\">0x24</integer></dict></array><key>IODisplayConnectFlags</key><integer size=\"32\" ID=\"151\">0x0</integer></dict>";
89
90 static char darwin_ioframebuffer_properties[] = "<dict ID=\"\"><key>IOClass</key><string ID=\"1\">AppleBacklightDisplay</string><key>IOProbeScore</key><integer size=\"32\" ID=\"2\">0xbb8</integer><key>IOProviderClass</key><string ID=\"3\">IODisplayConnect</string><key>CFBundleIdentifier</key><string ID=\"4\">com.apple.iokit.IOGraphicsFamily</string><key>IOMatchCategory</key><string ID=\"5\">IODefaultMatchCategory</string><key>IODisplayConnectFlags</key><data ID=\"6\">AAAIxA==</data><key>AppleDisplayType</key><integer size=\"32\" ID=\"7\">0x2</integer><key>AppleSense</key><integer size=\"32\" ID=\"8\">0x400</integer><key>DisplayVendorID</key><integer size=\"32\" ID=\"9\">0x756e6b6e</integer><key>DisplayProductID</key><integer size=\"32\" ID=\"10\">0x20000</integer><key>IODisplayParameters</key><dict ID=\"11\"><key>brightness</key><dict ID=\"12\"><key>max</key><integer size=\"32\" ID=\"13\">0x73</integer><key>min</key><integer size=\"32\" ID=\"14\">0x3a</integer><key>value</key><integer size=\"32\" ID=\"15\">0x7f</integer></dict><key>commit</key><dict ID=\"16\"><key>reg</key><integer size=\"32\" ID=\"17\">0x0</integer></dict></dict><key>IODisplayGUID</key><integer size=\"64\" ID=\"18\">0x610000000000000</integer><key>Power Management protected data</key><string ID=\"19\">{ theNumberOfPowerStates = 4, version 1, power state 0 = { capabilityFlags 00000000, outputPowerCharacter 00000000, inputPowerRequirement 00000000, staticPower 0, unbudgetedPower 0, powerToAttain 0, timeToAttain 0, settleUpTime 0, timeToLower 0, settleDownTime 0, powerDomainBudget 0 }, power state 1 = { capabilityFlags 00000000, outputPowerCharacter 00000000, inputPowerRequirement 00000000, staticPower 0, unbudgetedPower 0, powerToAttain 0, timeToAttain 0, settleUpTime 0, timeToLower 0, settleDownTime 0, powerDomainBudget 0 }, power state 2 = { capabilityFlags 00008000, outputPowerCharacter 00000000, inputPowerRequirement 00000002, staticPower 0, unbudgetedPower 0, powerToAttain 0, timeToAttain 0, settleUpTime 0, timeToLower 0, settleDownTime 0, powerDomainBudget 0 }, power state 3 = { capabilityFlags 0000c000, outputPowerCharacter 00000000, inputPowerRequirement 00000002, staticPower 0, unbudgetedPower 0, powerToAttain 0, timeToAttain 0, settleUpTime 0, timeToLower 0, settleDownTime 0, powerDomainBudget 0 }, aggressiveness = 0, myCurrentState = 0, parentsCurrentPowerFlags = 00000002, maxCapability = 3 }</string><key>Power Management private data</key><string ID=\"20\">{ this object = 0114c800, interested driver = 0114c800, driverDesire = 0, deviceDesire = 0, ourDesiredPowerState = 0, previousReqest = 0 }</string></dict>";
91
92 struct mach_iokit_property darwin_ioframebuffer_properties_array[] = {
93 { "IOFBDependentID", NULL },
94 { "IOFBDependentIndex", NULL },
95 { "graphic-options", "<integer size=\"32\" ID=\"\">0x0</integer>"},
96 { "IOFBConfig", darwin_iofbconfig },
97 { "IOFBMemorySize",
98 "<integer size=\"32\" ID=\"\">0x1000000</integer>"},
99 { "AAPL,boot-display", ""},
100 { NULL, 0}
101 };
102
103 struct mach_iokit_devclass darwin_ioframebuffer_devclass = {
104 "<dict ID=\"\"><key>IOProviderClass</key>"
105 "<string ID=\"1\">IOFramebuffer</string></dict>",
106 { &mach_ioroot_devclass, NULL },
107 darwin_ioframebuffer_properties,
108 darwin_ioframebuffer_properties_array,
109 darwin_ioframebuffer_connect_method_scalari_scalaro,
110 darwin_ioframebuffer_connect_method_scalari_structo,
111 darwin_ioframebuffer_connect_method_structi_structo,
112 darwin_ioframebuffer_connect_method_scalari_structi,
113 darwin_ioframebuffer_connect_map_memory,
114 "IOFramebuffer",
115 NULL,
116 };
117
118 int
119 darwin_ioframebuffer_connect_method_scalari_scalaro(struct mach_trap_args *args)
120 {
121 mach_io_connect_method_scalari_scalaro_request_t *req = args->smsg;
122 mach_io_connect_method_scalari_scalaro_reply_t *rep = args->rmsg;
123 size_t *msglen = args->rsize;
124 struct lwp *l = args->l;
125 int maxoutcount;
126 int error;
127
128 #ifdef DEBUG_DARWIN
129 printf("darwin_ioframebuffer_connect_method_scalari_scalaro()\n");
130 #endif
131 rep->rep_outcount = 0;
132 maxoutcount = req->req_in[req->req_incount];
133
134 switch (req->req_selector) {
135 case DARWIN_IOFBCREATESHAREDCURSOR: {
136 /* Create the shared memory containing cursor information */
137 int shmemvers;
138 int maxwidth;
139 int maxheight;
140 size_t memsize;
141 vaddr_t kvaddr;
142
143 shmemvers = req->req_in[0]; /* 0x2 */
144 maxwidth = req->req_in[1]; /* 0x20 */
145 maxheight = req->req_in[2]; /* 0x20 */
146 #ifdef DEBUG_DARWIN
147 printf("DARWIN_IOFBCREATESHAREDCURSOR: shmemvers = %d, "
148 "maxwidth = %d, maxheight = %d\n", shmemvers,
149 maxwidth, maxheight);
150 #endif
151 if (darwin_ioframebuffer_shmem == NULL) {
152 memsize =
153 round_page(sizeof(*darwin_ioframebuffer_shmem));
154
155 darwin_ioframebuffer_shmem = uao_create(memsize, 0);
156
157 error = uvm_map(kernel_map, &kvaddr, memsize,
158 darwin_ioframebuffer_shmem, 0, PAGE_SIZE,
159 UVM_MAPFLAG(UVM_PROT_RW, UVM_PROT_RW,
160 UVM_INH_SHARE, UVM_ADV_RANDOM, 0));
161 if (error != 0) {
162 uao_detach(darwin_ioframebuffer_shmem);
163 darwin_ioframebuffer_shmem = NULL;
164 return mach_msg_error(args, error);
165 }
166
167 if ((error = uvm_map_pageable(kernel_map, kvaddr,
168 kvaddr + memsize, FALSE, 0)) != 0) {
169 uao_detach(darwin_ioframebuffer_shmem);
170 darwin_ioframebuffer_shmem = NULL;
171 return mach_msg_error(args, error);
172 }
173
174 darwin_ioframebuffer_shmeminit(kvaddr);
175 }
176
177 /* No output, the zone is mapped during another call */
178 rep->rep_outcount = 0;
179 break;
180 }
181
182 case DARWIN_IOFBSETSTARTUPDISPLAYMODE: {
183 darwin_iodisplaymodeid mode;
184 darwin_ioindex depth;
185
186 mode = req->req_in[0];
187 depth = req->req_in[1];
188 #ifdef DEBUG_DARWIN
189 printf("DARWIN_IOFBSETSTARTUPDISPLAYMODE: mode = %d, "
190 "depth = %d\n", mode, depth);
191 #endif
192 /* Nothing for now */
193 break;
194 }
195
196 case DARWIN_IOFBSETDISPLAYMODE: {
197 darwin_iodisplaymodeid mode;
198 darwin_ioindex depth;
199
200 mode = req->req_in[0];
201 depth = req->req_in[1];
202 #ifdef DEBUG_DARWIN
203 printf("DARWIN_IOFBSETDISPLAYMODE: mode = %d, "
204 "depth = %d\n", mode, depth);
205 #endif
206 /* Nothing for now */
207 break;
208 }
209
210 case DARWIN_IOFBGETCURRENTDISPLAYMODE: {
211 /* Get current display mode and depth. No input args */
212
213 #ifdef DEBUG_DARWIN
214 printf("DARWIN_IOFBGETCURRENTDISPLAYMODE\n");
215 #endif
216 if (maxoutcount < 2)
217 return mach_msg_error(args, EINVAL);
218
219 rep->rep_outcount = 2;
220 rep->rep_out[0] = 0x2e; /* mode XXX */
221 rep->rep_out[1] = 0; /* depth (0=>8b 1=>15b 2=>24b) */
222 break;
223 }
224
225 case DARWIN_IOFBSETCURSORVISIBLE: {
226 mach_boolean_t visible;
227
228 visible = req->req_in[0];
229 #ifdef DEBUG_DARWIN
230 printf("DARWIN_IOFBSETCURSORVISIBLE: visible = %d\n", visible);
231 #endif
232 /* Nothing for now */
233 break;
234 }
235
236 case DARWIN_IOFBGETATTRIBUTE: {
237 /* Get attribute value */
238 char *name;
239
240 name = (char *)&req->req_in[0];
241 #ifdef DEBUG_DARWIN
242 printf("DARWIN_IOFBGETATTRIBUTE: name = %s\n", name);
243 #endif
244
245 /* We only heard about the mrdf attribute. What is it? */
246 if (memcmp(name, "mrdf", 4) == 0) {
247 if (maxoutcount < 1)
248 return mach_msg_error(args, EINVAL);
249
250 rep->rep_outcount = 1;
251 rep->rep_out[0] = 0; /* XXX */
252 } else {
253 #ifdef DEBUG_DARWIN
254 printf("Unknown attribute %c%c%c%c\n",
255 req->req_in[0], req->req_in[1],
256 req->req_in[2], req->req_in[3]);
257 #endif
258 return mach_msg_error(args, EINVAL);
259 }
260 break;
261 }
262
263 case DARWIN_IOFBGETVRAMMAPOFFSET: {
264 darwin_iopixelaperture aperture; /* 0 XXX Current aperture? */
265 struct darwin_emuldata *ded = l->l_proc->p_emuldata;
266
267 aperture = req->req_in[0];
268 #ifdef DEBUG_DARWIN
269 printf("DARWIN_IOFBGETVRAMMAPOFFSET: aperture = %d\n",
270 aperture);
271 #endif
272 if (maxoutcount < 1)
273 return mach_msg_error(args, EINVAL);
274
275 rep->rep_outcount = 1;
276 rep->rep_out[0] = (int)ded->ded_vramoffset;
277 break;
278 }
279
280 default:
281 #ifdef DEBUG_DARWIN
282 printf("Unknown selector %d\n", req->req_selector);
283 #endif
284 return mach_msg_error(args, EINVAL);
285 break;
286 }
287
288 *msglen = sizeof(*rep) - ((16 - rep->rep_outcount) * sizeof(int));
289 mach_set_header(rep, req, *msglen);
290 mach_set_trailer(rep, *msglen);
291
292 return 0;
293 }
294
295 int
296 darwin_ioframebuffer_connect_method_scalari_structo(struct mach_trap_args *args)
297 {
298 mach_io_connect_method_scalari_structo_request_t *req = args->smsg;
299 mach_io_connect_method_scalari_structo_reply_t *rep = args->rmsg;
300 size_t *msglen = args->rsize;
301 int maxoutcount;
302
303 #ifdef DEBUG_DARWIN
304 printf("darwin_ioframebuffer_connect_method_scalari_structo()\n");
305 #endif
306 rep->rep_outcount = 0;
307 maxoutcount = req->req_in[req->req_incount];
308
309 switch(req->req_selector) {
310 case DARWIN_IOFBGETPIXELINFORMATION: {
311 /* Get bit per pixel, etc... */
312 darwin_iodisplaymodeid displaymode;
313 darwin_ioindex depth;
314 darwin_iopixelaperture aperture;
315 darwin_iopixelinformation *pixelinfo;
316
317 displaymode = req->req_in[0]; /* 0x2e */
318 depth = req->req_in[1]; /* 0 or 1 */
319 aperture = req->req_in[2]; /* 0 */
320 #ifdef DEBUG_DARWIN
321 printf("DARWIN_IOFBGETPIXELINFORMATION: displaymode = %d, "
322 "depth = %d, aperture = %d\n", displaymode, depth,
323 aperture);
324 #endif
325 pixelinfo = (darwin_iopixelinformation *)&rep->rep_out[0];
326
327 if (maxoutcount < sizeof(*pixelinfo))
328 return mach_msg_error(args, EINVAL);
329
330 /*
331 * darwin_iopixelinformation is shorter than the buffer
332 * usually supplied, but Darwin still returns the whole buffer
333 */
334 rep->rep_outcount = maxoutcount;
335 memset(pixelinfo, 0, maxoutcount * sizeof(int));
336
337 switch (depth) {
338 case 0: /* 8 bpp */
339 pixelinfo->bytesperrow = 0x400;
340 pixelinfo->bytesperplane = 0;
341 pixelinfo->bitsperpixel = 0x8;
342 pixelinfo->pixeltype = DARWIN_IOFB_CLUTPIXELS;
343 pixelinfo->componentcount = 1;
344 pixelinfo->bitspercomponent = 8;
345 pixelinfo->componentmasks[0] = 0x000000ff;
346 memcpy(&pixelinfo->pixelformat, "PPPPPPPP", 8);
347 pixelinfo->flags = 0;
348 pixelinfo->activewidth = 0;
349 pixelinfo->activeheight = 0;
350 break;
351
352 case 1: /* 15 bpp */
353 pixelinfo->bytesperrow = 0x800;
354 pixelinfo->bytesperplane = 0;
355 pixelinfo->bitsperpixel = 0x10;
356 pixelinfo->pixeltype = DARWIN_IOFB_RGBDIRECTPIXELS;
357 pixelinfo->componentcount = 3;
358 pixelinfo->bitspercomponent = 5;
359 pixelinfo->componentmasks[0] = 0x00007c00; /* Red */
360 pixelinfo->componentmasks[1] = 0x000003e0; /* Green */
361 pixelinfo->componentmasks[2] = 0x0000001f; /* Blue */
362 memcpy(&pixelinfo->pixelformat, "-RRRRRGGGGGBBBBB", 16);
363 pixelinfo->flags = 0;
364 pixelinfo->activewidth = 0;
365 pixelinfo->activeheight = 0;
366 break;
367
368 case 2: /* 24 bpp */
369 pixelinfo->bytesperrow = 0x1000;
370 pixelinfo->bytesperplane = 0;
371 pixelinfo->bitsperpixel = 0x20;
372 pixelinfo->pixeltype = DARWIN_IOFB_RGBDIRECTPIXELS;
373 pixelinfo->componentcount = 3;
374 pixelinfo->bitspercomponent = 8;
375 pixelinfo->componentmasks[0] = 0x00ff0000; /* Red */
376 pixelinfo->componentmasks[1] = 0x0000ff00; /* Green */
377 pixelinfo->componentmasks[2] = 0x000000ff; /* Blue */
378 memcpy(&pixelinfo->pixelformat,
379 "--------RRRRRRRRGGGGGGGGBBBBBBBB", 32);
380 pixelinfo->flags = 0;
381 pixelinfo->activewidth = 0;
382 pixelinfo->activeheight = 0;
383 break;
384
385 default:
386 printf("unknown depth %d\n", depth);
387 break;
388 }
389
390 /* Probably useless */
391 rep->rep_out[158] = 0x4;
392 rep->rep_out[162] = 0x3;
393
394 break;
395 }
396
397 default:
398 #ifdef DEBUG_DARWIN
399 printf("Unknown selector %d\n", req->req_selector);
400 #endif
401 return mach_msg_error(args, EINVAL);
402 break;
403 }
404
405 *msglen = sizeof(*rep) - (4096 - rep->rep_outcount);
406 mach_set_header(rep, req, *msglen);
407 mach_set_trailer(rep, *msglen);
408
409 return 0;
410 }
411
412 int
413 darwin_ioframebuffer_connect_method_structi_structo(struct mach_trap_args *args)
414 {
415 mach_io_connect_method_structi_structo_request_t *req = args->smsg;
416 mach_io_connect_method_structi_structo_reply_t *rep = args->rmsg;
417 size_t *msglen = args->rsize;
418 int maxoutcount;
419
420 #ifdef DEBUG_DARWIN
421 printf("darwin_ioframebuffer_connect_method_structi_structo()\n");
422 #endif
423
424 rep->rep_outcount = 0;
425 /* maxoutcount is word aligned */
426 maxoutcount = req->req_in[(req->req_incount & ~0x3UL) + 4];
427
428 switch(req->req_selector) {
429 case DARWIN_IOFBSETBOUNDS: {
430 darwin_iogbounds *bounds;
431
432 bounds = (darwin_iogbounds *)&req->req_in[0];
433
434 #ifdef DEBUG_DARWIN
435 printf("DARWIN_IOFBSETBOUNDS: bounds (%d, %d) - (%d, %d)\n",
436 bounds->minx, bounds->miny, bounds->maxx, bounds->maxy);
437 #endif
438 /* Nothing yet */
439 break;
440 }
441
442 default:
443 #ifdef DEBUG_DARWIN
444 printf("Unknown selector %d\n", req->req_selector);
445 #endif
446 return mach_msg_error(args, EINVAL);
447 break;
448 }
449
450 *msglen = sizeof(*rep) - (4096 - rep->rep_outcount);
451 mach_set_header(rep, req, *msglen);
452 mach_set_trailer(rep, *msglen);
453
454 return 0;
455 }
456
457 int
458 darwin_ioframebuffer_connect_map_memory(struct mach_trap_args *args)
459 {
460 mach_io_connect_map_memory_request_t *req = args->smsg;
461 mach_io_connect_map_memory_reply_t *rep = args->rmsg;
462 size_t *msglen = args->rsize;
463 struct lwp *l = args->l;
464 struct proc *p = args->l->l_proc;
465 int error = 0;
466 size_t memsize;
467 size_t len;
468 vaddr_t pvaddr;
469
470 #ifdef DEBUG_DARWIN
471 printf("darwin_ioframebuffer_connect_map_memory()\n");
472 #endif
473 switch (req->req_memtype) {
474 case DARWIN_IOFRAMEBUFFER_CURSOR_MEMORY:
475 if (darwin_ioframebuffer_shmem == NULL)
476 return mach_msg_error(args, error);
477
478 len = sizeof(struct darwin_ioframebuffer_shmem);
479 memsize = round_page(len);
480
481 uao_reference(darwin_ioframebuffer_shmem);
482 pvaddr = VM_DEFAULT_ADDRESS(p->p_vmspace->vm_daddr, memsize);
483
484 if ((error = uvm_map(&p->p_vmspace->vm_map, &pvaddr,
485 memsize, darwin_ioframebuffer_shmem, 0, PAGE_SIZE,
486 UVM_MAPFLAG(UVM_PROT_RW, UVM_PROT_RW,
487 UVM_INH_SHARE, UVM_ADV_RANDOM, 0))) != 0)
488 return mach_msg_error(args, error);
489
490 #ifdef DEBUG_DARWIN
491 printf("pvaddr = 0x%08lx\n", (long)pvaddr);
492 #endif
493 break;
494
495 case DARWIN_IOFRAMEBUFFER_VRAM_MEMORY:
496 case DARWIN_IOFRAMEBUFFER_SYSTEM_APERTURE: {
497 dev_t device;
498 const struct cdevsw *wsdisplay;
499 int unit;
500 int mode, screen;
501 struct wsdisplay_fbinfo fbi;
502 struct darwin_emuldata *ded;
503 struct vnode *vp;
504
505 /*
506 * Use unit given by sysctl emul.darwin.ioframebuffer.unit
507 * and emul.darwin.ioframebuffer.screen
508 */
509 unit = darwin_ioframebuffer_unit;
510 screen = darwin_ioframebuffer_screen;
511 if ((error = darwin_findscreen(&device, unit, screen)) != 0)
512 return mach_msg_error(args, error);
513
514 if ((wsdisplay = cdevsw_lookup(device)) == NULL)
515 return mach_msg_error(args, ENXIO);
516
517 /* Find the framebuffer's size */
518 if ((error = (wsdisplay->d_ioctl)(device,
519 WSDISPLAYIO_GINFO, (void *)&fbi, 0, l)) != 0) {
520 #ifdef DEBUG_DARWIN
521 printf("*** Cannot get screen params ***\n");
522 #endif
523 return mach_msg_error(args, error);
524 }
525 #ifdef DEBUG_DARWIN
526 printf("framebuffer: %d x %d x %d\n",
527 fbi.width, fbi.height, fbi.depth);
528 #endif
529 len = round_page(fbi.height * fbi.width * fbi.depth / 8);
530
531 /*
532 * The framebuffer cannot be mapped if the console is
533 * not in graphic mode. We will do the switch, but it
534 * screws the console. Therefore we attempt to restore
535 * its original state on process exit. ded->ded_wsdev
536 * is used to remember the console device. If it is not
537 * NODEV on process exit, we use it to restore text mode.
538 */
539 ded = (struct darwin_emuldata *)p->p_emuldata;
540 if ((error = (wsdisplay->d_ioctl)(device,
541 WSDISPLAYIO_GMODE, (void *)&mode, 0, l)) != 0) {
542 #ifdef DEBUG_DARWIN
543 printf("*** Cannot get console state ***\n");
544 #endif
545 return mach_msg_error(args, ENODEV);
546 }
547 if (mode == WSDISPLAYIO_MODE_EMUL)
548 ded->ded_wsdev = device;
549
550 /* Switch to graphic mode */
551 mode = WSDISPLAYIO_MODE_MAPPED;
552 if ((error = (wsdisplay->d_ioctl)(device,
553 WSDISPLAYIO_SMODE, (void *)&mode, 0, l)) != 0) {
554 #ifdef DEBUG_DARWIN
555 printf("*** Cannot switch to graphic mode ***\n");
556 #endif
557 return mach_msg_error(args, ENODEV);
558 }
559
560 if ((error = cdevvp(device, &vp)) != 0) {
561 #ifdef DEBUG_DARWIN
562 printf("*** cdevvp failed ***\n");
563 #endif
564 return mach_msg_error(args, error);
565 }
566
567 pvaddr = 0;
568 if ((error = uvm_mmap(&p->p_vmspace->vm_map, &pvaddr,
569 len, UVM_PROT_RW, UVM_PROT_RW, MAP_SHARED, vp, 0,
570 p->p_rlimit[RLIMIT_MEMLOCK].rlim_cur)) != 0) {
571 #ifdef DEBUG_DARWIN
572 printf("*** uvm_mmap failed ***\n");
573 #endif
574 return mach_msg_error(args, error);
575 }
576
577 #ifdef DEBUG_DARWIN
578 printf("mapped framebuffer at %p\n", (void *)pvaddr);
579 #endif
580 break;
581 }
582
583 default:
584 #ifdef DEBUG_DARWIN
585 printf("unimplemented memtype %d\n", req->req_memtype);
586 #endif
587 return mach_msg_error(args, EINVAL);
588 break;
589 }
590
591 *msglen = sizeof(*rep);
592 mach_set_header(rep, req, *msglen);
593
594 rep->rep_retval = 0;
595 rep->rep_addr = pvaddr;
596 rep->rep_len = len;
597
598 mach_set_trailer(rep, *msglen);
599
600 /* Track VRAM offset for connect_method IOFBGETVRAMMAPOFFSET */
601 if (req->req_memtype == DARWIN_IOFRAMEBUFFER_VRAM_MEMORY) {
602 struct darwin_emuldata *ded;
603
604 ded = p->p_emuldata;
605 /*
606 * This seems to be the offset of the framebuffer
607 * within the VRAM. For now 0, as we are only
608 * able to map the framebuffer.
609 */
610 ded->ded_vramoffset = (void *)(pvaddr - pvaddr);
611 }
612
613 return 0;
614 }
615
616 void
617 darwin_ioframebuffer_shmeminit(vaddr_t kvaddr)
618 {
619 struct darwin_ioframebuffer_shmem *shmem;
620
621 shmem = (struct darwin_ioframebuffer_shmem *)kvaddr;
622
623 return;
624 }
625
626 int
627 darwin_ioframebuffer_connect_method_scalari_structi(struct mach_trap_args *args)
628 {
629 mach_io_connect_method_scalari_structi_request_t *req = args->smsg;
630 mach_io_connect_method_scalari_structi_reply_t *rep = args->rmsg;
631 size_t *msglen = args->rsize;
632 int scalar_len;
633 int struct_len;
634 char *struct_data;
635
636 #ifdef DEBUG_DARWIN
637 printf("darwin_ioframebuffer_connect_method_scalari_structi()\n");
638 #endif
639 scalar_len = req->req_incount;
640 struct_len = req->req_in[scalar_len];
641 struct_data = (char *)&req->req_in[scalar_len + 1];
642
643 switch (req->req_selector) {
644 case DARWIN_IOFBSETCOLORCONVERTTABLE: {
645 int select;
646 int *data;
647 size_t tablelen;
648
649 select = req->req_in[0];
650 tablelen = struct_len / sizeof(*data);
651 #ifdef DEBUG_DARWIN
652 printf("DARWIN_IOFBSETCOLORCONVERTTABLE: select = %d, "
653 "tablelen = %d\n", select, tablelen);
654 #endif
655 if (tablelen == 0)
656 break;
657
658 data = (int *)struct_data;
659 break;
660 }
661
662 case DARWIN_IOFBSETGAMMATABLE: {
663 int entries;
664 int count;
665 int width;
666 int *data;
667
668 entries = req->req_in[0];
669 count = req->req_in[1];
670 width = req->req_in[2];
671
672 #ifdef DEBUG_DARWIN
673 printf("DARWIN_IOFBSETGAMMATABLE: entries = %d, "
674 "count = %d, width = %d\n", entries, count, width);
675 #endif
676
677 data = &req->req_in[3];
678 break;
679 }
680
681 #if 0 /* comment out stackgap using code - needs to be done another way */
682 case DARWIN_IOFBSETCLUTWITHENTRIES: {
683 struct lwp *l = args->l;
684 struct proc *p = args->l->l_proc;
685 int index;
686 int option;
687 struct darwin_iocolorentry *clut;
688 size_t clutlen;
689 size_t tablen;
690 size_t kcolorsz;
691 void *sg = stackgap_init(p, 0);
692 int error;
693 struct wsdisplay_cmap cmap;
694 u_char *red;
695 u_char *green;
696 u_char *blue;
697 u_char kred[256];
698 u_char kgreen[256];
699 u_char kblue[256];
700 int unit, screen;
701 dev_t dev;
702 const struct cdevsw *wsdisplay;
703 int i;
704
705 index = req->req_in[0];
706 option = req->req_in[1];
707 clutlen = struct_len / sizeof(*clut);
708 clut = (struct darwin_iocolorentry *)struct_data;
709
710 if ((clutlen == 0) || (index >= 256))
711 break;
712
713 #ifdef DEBUG_DARWIN
714 printf("DARWIN_IOFBSETCLUTWITHENTRIES: index = %d, "
715 "option = %d, clutlen = %d\n", index, option, clutlen);
716 #endif
717
718 /*
719 * Find wsdisplay. Use the screen given by sysctl
720 * emul.darwin.ioframebuffer.screen
721 */
722 unit = darwin_ioframebuffer_unit;
723 screen = darwin_ioframebuffer_screen;
724 if ((error = darwin_findscreen(&dev, unit, screen)) != 0)
725 return mach_msg_error(args, error);
726
727 if ((wsdisplay = cdevsw_lookup(dev)) == NULL)
728 return mach_msg_error(args, ENXIO);
729
730 /*
731 * We only support 256 entries
732 */
733 if (index + clutlen > 256)
734 clutlen = 256 - index;
735
736 /*
737 * Big tables will not fit in the stackgap.
738 * We have to split the data.
739 */
740 if (clutlen <= 128)
741 tablen = clutlen;
742 else
743 tablen = 128;
744
745 kcolorsz = sizeof(u_char) * tablen;
746 red = stackgap_alloc(p, &sg, kcolorsz);
747 green = stackgap_alloc(p, &sg, kcolorsz);
748 blue = stackgap_alloc(p, &sg, kcolorsz);
749
750 do {
751 for (i = 0; i < tablen; i++) {
752 kred[i] = (u_char)(clut->red >> 8);
753 kgreen[i] = (u_char)(clut->green >> 8);
754 kblue[i] = (u_char)(clut->blue >> 8);
755 clut++;
756 }
757
758 cmap.index = index;
759 cmap.count = tablen;
760 cmap.red = red;
761 cmap.green = green;
762 cmap.blue = blue;
763
764 if (((error = copyout(kred, red, kcolorsz)) != 0) ||
765 ((error = copyout(kgreen, green, kcolorsz)) != 0) ||
766 ((error = copyout(kblue, blue, kcolorsz)) != 0))
767 return mach_msg_error(args, error);
768
769 if ((error = (wsdisplay->d_ioctl)(dev,
770 WSDISPLAYIO_PUTCMAP, (void *)&cmap, 0, l)) != 0)
771 return mach_msg_error(args, error);
772
773 index += tablen;
774 clutlen -= tablen;
775 if (clutlen <= 128)
776 tablen = clutlen;
777 } while (clutlen > 0);
778
779 break;
780 }
781 #endif
782
783 default:
784 #ifdef DEBUG_DARWIN
785 printf("Unknown selector %d\n", req->req_selector);
786 #endif
787 return mach_msg_error(args, EINVAL);
788 break;
789 }
790
791 *msglen = sizeof(*rep);
792 mach_set_header(rep, req, *msglen);
793
794 rep->rep_retval = 0;
795
796 mach_set_trailer(rep, *msglen);
797
798 return 0;
799 }
800
801
802 /* Find a wsdisplay from unit and screen */
803 static int
804 darwin_findscreen(dev, unit, screen)
805 dev_t *dev;
806 int unit, screen;
807 {
808 struct device *dv;
809 struct wsdisplay_softc *sc;
810 int major, minor;
811
812 /* Find a wsdisplay */
813 if ((dv = device_find_by_driver_unit("wsdisplay", unit)) == NULL)
814 return ENODEV;
815
816 sc = device_private(dv);
817
818 /* Derive the device number */
819 major = cdevsw_lookup_major(&wsdisplay_cdevsw);
820 minor = WSDISPLAYMINOR(device_unit(dv), screen);
821 *dev = makedev(major, minor);
822
823 #ifdef DEBUG_DARWIN
824 printf("ioframebuffer uses major = %d, minor = %d\n", major, minor);
825 #endif
826 return 0;
827 }
Cache object: 1a686928ab47538a560bda5dd33a3132
|