1/*
2 * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License").  You may not use this file except in compliance with the
9 * License.  Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
11 *
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
17 * License for the specific language governing rights and limitations
18 * under the License.
19 *
20 * @APPLE_LICENSE_HEADER_END@
21 */
22
23#include <IOKit/pwr_mgt/RootDomain.h>
24#include <IOKit/IOLib.h>
25#include <IOKit/IOMessage.h>
26#include <libkern/c++/OSContainers.h>
27#include <IOKit/IOBufferMemoryDescriptor.h>
28#include <IOKit/IOPlatformExpert.h>
29#include <IOKit/IOHibernatePrivate.h>
30#include <IOKit/assert.h>
31
32#define IOFRAMEBUFFER_PRIVATE
33#include <IOKit/graphics/IOFramebufferShared.h>
34#include <IOKit/graphics/IOGraphicsPrivate.h>
35
36#include "IOFramebufferUserClient.h"
37
38/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
39
40#undef super
41#define super IOUserClient
42
43OSDefineMetaClassAndStructors(IOFramebufferUserClient, IOUserClient)
44
45/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
46
47IOFramebufferUserClient * IOFramebufferUserClient::withTask( task_t owningTask )
48{
49    IOFramebufferUserClient * inst;
50
51    inst = new IOFramebufferUserClient;
52
53    if (inst && !inst->init())
54    {
55        inst->release();
56        inst = 0;
57    }
58
59    return (inst);
60}
61
62bool IOFramebufferUserClient::start( IOService * _owner )
63{
64    if (!super::start(_owner))
65        return (false);
66
67    owner = (IOFramebuffer *) _owner;
68    owner->serverConnect = this;
69
70    return (true);
71}
72
73IOReturn IOFramebufferUserClient::registerNotificationPort(
74    mach_port_t         port,
75    UInt32              type,
76    UInt32              refCon )
77{
78    return (owner->extRegisterNotificationPort(port, type, refCon));
79}
80
81IOReturn IOFramebufferUserClient::getNotificationSemaphore(
82    UInt32 interruptType, semaphore_t * semaphore )
83{
84    return (owner->getNotificationSemaphore(interruptType, semaphore));
85}
86
87// The window server is going away.
88
89IOReturn IOFramebufferUserClient::clientClose( void )
90{
91    owner->close();
92    detach( owner);
93
94    return (kIOReturnSuccess);
95}
96
97IOService * IOFramebufferUserClient::getService( void )
98{
99    return (owner);
100}
101
102IOReturn IOFramebufferUserClient::clientMemoryForType( UInt32 type,
103        IOOptionBits * flags, IOMemoryDescriptor ** memory )
104{
105    static bool          havePublishedResource;
106    IOMemoryDescriptor * mem;
107    IOReturn             err;
108
109    switch (type)
110    {
111        case kIOFBCursorMemory:
112
113            if (!havePublishedResource)
114            {
115                havePublishedResource = true;
116                publishResource("WindowServer");
117            }
118
119            mem = owner->sharedCursor;
120            mem->retain();
121            break;
122
123        case kIOFBVRAMMemory:
124            mem = owner->getVRAMRange();
125            break;
126
127        default:
128            mem = (IOMemoryDescriptor *) owner->userAccessRanges->getObject( type );
129            mem->retain();
130            break;
131    }
132
133    *memory = mem;
134    if (mem)
135        err = kIOReturnSuccess;
136    else
137        err = kIOReturnBadArgument;
138
139    return (err);
140}
141
142IOReturn IOFramebufferUserClient::setProperties( OSObject * properties )
143{
144    OSDictionary *      props;
145    IOReturn            kr = kIOReturnUnsupported;
146
147    if (!(props = OSDynamicCast(OSDictionary, properties)))
148        return (kIOReturnBadArgument);
149
150    kr = owner->extSetProperties( props );
151
152    return (kr);
153}
154
155IOReturn IOFramebufferUserClient::externalMethod( uint32_t selector, IOExternalMethodArguments * args,
156                                        IOExternalMethodDispatch * dispatch, OSObject * target, void * reference )
157{
158    IOReturn ret;
159
160    static const IOExternalMethodDispatch methodTemplate[20] =
161    {
162        /*[0]*/  { (IOExternalMethodAction) &IOFramebuffer::extCreateSharedCursor,
163                    3, 0, 0, 0 },
164        /*[1]*/  { (IOExternalMethodAction) &IOFramebuffer::extGetPixelInformation,
165                    3, 0, 0, sizeof(IOPixelInformation) },
166        /*[2]*/  { (IOExternalMethodAction) &IOFramebuffer::extGetCurrentDisplayMode,
167                    0, 0, 2, 0 },
168        /*[3]*/  { (IOExternalMethodAction) &IOFramebuffer::extSetStartupDisplayMode,
169                    2, 0, 0, 0 },
170        /*[4]*/  { (IOExternalMethodAction) &IOFramebuffer::extSetDisplayMode,
171                    2, 0, 0, 0 },
172        /*[5]*/  { (IOExternalMethodAction) &IOFramebuffer::extGetInformationForDisplayMode,
173                    1, 0, 0, kIOUCVariableStructureSize },
174        /*[6]*/  { (IOExternalMethodAction) &IOFramebuffer::extGetDisplayModeCount,
175                    0, 0, 1, 0 },
176        /*[7]*/  { (IOExternalMethodAction) &IOFramebuffer::extGetDisplayModes,
177                    0, 0, 0, kIOUCVariableStructureSize },
178        /*[8]*/  { (IOExternalMethodAction) &IOFramebuffer::extGetVRAMMapOffset,
179                    1, 0, 1, 0 },
180        /*[9]*/  { (IOExternalMethodAction) &IOFramebuffer::extSetBounds,
181                    0, kIOUCVariableStructureSize, 0, 0 },
182        /*[10]*/ { (IOExternalMethodAction) &IOFramebuffer::extSetNewCursor,
183                    3, 0, 0, 0 },
184        /*[11]*/ { (IOExternalMethodAction) &IOFramebuffer::extSetGammaTable,
185                    3, kIOUCVariableStructureSize, 0, 0 },
186        /*[12]*/ { (IOExternalMethodAction) &IOFramebuffer::extSetCursorVisible,
187                    1, 0, 0, 0 },
188        /*[13]*/ { (IOExternalMethodAction) &IOFramebuffer::extSetCursorPosition,
189                    2, 0, 0, 0 },
190        /*[14]*/ { (IOExternalMethodAction) &IOFramebuffer::extAcknowledgeNotification,
191                    kIOUCVariableStructureSize, 0, 0, 0 },
192        /*[15]*/ { (IOExternalMethodAction) &IOFramebuffer::extSetColorConvertTable,
193                    1, kIOUCVariableStructureSize, 0, 0 },
194        /*[16]*/ { (IOExternalMethodAction) &IOFramebuffer::extSetCLUTWithEntries,
195                    2, kIOUCVariableStructureSize, 0, 0 },
196        /*[17]*/ { (IOExternalMethodAction) &IOFramebuffer::extValidateDetailedTiming,
197                    0, kIOUCVariableStructureSize, 0, kIOUCVariableStructureSize },
198        /*[18]*/ { (IOExternalMethodAction) &IOFramebuffer::extGetAttribute,
199                    1, 0, 1, 0 },
200        /*[19]*/ { (IOExternalMethodAction) &IOFramebuffer::extSetAttribute,
201                    2, 0, 0, 0 },
202    };
203
204    if (selector > (sizeof(methodTemplate) / sizeof(methodTemplate[0])))
205        return (kIOReturnBadArgument);
206
207    ret = super::externalMethod(selector, args,
208                    const_cast<IOExternalMethodDispatch *>(&methodTemplate[selector]),
209                    owner, other);
210
211    return (ret);
212}
213
214IOReturn IOFramebufferUserClient::connectClient( IOUserClient * _other )
215{
216    other = OSDynamicCast(IOFramebuffer, _other->getService());
217
218    if (_other && !other)
219        return (kIOReturnBadArgument);
220    else
221        return (kIOReturnSuccess);
222}
223
224/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
225
226OSDefineMetaClassAndStructors(IOFramebufferSharedUserClient, IOUserClient)
227
228/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
229
230IOFramebufferSharedUserClient * IOFramebufferSharedUserClient::withTask(
231    task_t owningTask )
232{
233    IOFramebufferSharedUserClient * inst;
234
235    inst = new IOFramebufferSharedUserClient;
236
237    if (inst && !inst->init())
238    {
239        inst->release();
240        inst = 0;
241    }
242
243    return (inst);
244}
245
246bool IOFramebufferSharedUserClient::start( IOService * _owner )
247{
248    if (!super::start(_owner))
249        return (false);
250
251    owner = (IOFramebuffer *) _owner;
252    owner->sharedConnect = this;
253    setProperty(kIOUserClientSharedInstanceKey, kOSBooleanTrue);
254
255    return (true);
256}
257
258void IOFramebufferSharedUserClient::free( void )
259{
260    owner->sharedConnect = 0;
261    super::free();
262}
263
264void IOFramebufferSharedUserClient::release() const
265{
266    super::release();
267}
268
269IOReturn IOFramebufferSharedUserClient::clientClose( void )
270{
271    return (kIOReturnSuccess);
272}
273
274IOService * IOFramebufferSharedUserClient::getService( void )
275{
276    return (owner);
277}
278
279IOReturn IOFramebufferSharedUserClient::clientMemoryForType( UInt32 type,
280        IOOptionBits * options, IOMemoryDescriptor ** memory )
281{
282    IOMemoryDescriptor *        mem = 0;
283    IOReturn                    err;
284
285    switch (type)
286    {
287        case kIOFBCursorMemory:
288            mem = owner->sharedCursor;
289            mem->retain();
290            *options = kIOMapReadOnly;
291            break;
292
293        case kIOFBVRAMMemory:
294            if (kIOReturnSuccess == clientHasPrivilege(current_task(), kIOClientPrivilegeLocalUser))
295                mem = owner->getVRAMRange();
296            break;
297    }
298
299    *memory = mem;
300    if (mem)
301        err = kIOReturnSuccess;
302    else
303        err = kIOReturnBadArgument;
304
305    return (err);
306}
307
308IOReturn IOFramebufferSharedUserClient::getNotificationSemaphore(
309    UInt32 interruptType, semaphore_t * semaphore )
310{
311    return (owner->getNotificationSemaphore(interruptType, semaphore));
312}
313
314