Print this page
7127 remove -Wno-missing-braces from Makefile.uts
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/uts/common/io/drm/drm_sunmod.c
+++ new/usr/src/uts/common/io/drm/drm_sunmod.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21
22 22 /*
23 23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
24 24 * Use is subject to license terms.
25 25 */
26 26
27 27 /*
28 28 * Common misc module interfaces of DRM under Solaris
29 29 */
30 30
31 31 /*
32 32 * This module calls into gfx and agpmaster misc modules respectively
33 33 * for generic graphics operations and AGP master device support.
34 34 */
35 35
↓ open down ↓ |
35 lines elided |
↑ open up ↑ |
36 36 #include "drm_sunmod.h"
37 37 #include <sys/modctl.h>
38 38 #include <sys/kmem.h>
39 39 #include <vm/seg_kmem.h>
40 40
41 41 static struct modlmisc modlmisc = {
42 42 &mod_miscops, "DRM common interfaces"
43 43 };
44 44
45 45 static struct modlinkage modlinkage = {
46 - MODREV_1, (void *)&modlmisc, NULL
46 + MODREV_1, { (void *)&modlmisc, NULL }
47 47 };
48 48
49 49 static drm_inst_list_t *drm_inst_head;
50 50 static kmutex_t drm_inst_list_lock;
51 51
52 52 static int drm_sun_open(dev_t *, int, int, cred_t *);
53 53 static int drm_sun_close(dev_t, int, int, cred_t *);
54 54 static int drm_sun_ioctl(dev_t, int, intptr_t, int, cred_t *, int *);
55 55 static int drm_sun_devmap(dev_t, devmap_cookie_t, offset_t, size_t,
56 56 size_t *, uint_t);
57 57
58 58 /*
59 59 * devmap callbacks for AGP and PCI GART
60 60 */
61 61 static int drm_devmap_map(devmap_cookie_t, dev_t,
62 62 uint_t, offset_t, size_t, void **);
63 63 static int drm_devmap_dup(devmap_cookie_t, void *,
64 64 devmap_cookie_t, void **);
65 65 static void drm_devmap_unmap(devmap_cookie_t, void *,
66 66 offset_t, size_t, devmap_cookie_t, void **, devmap_cookie_t, void **);
67 67
68 68 static drm_inst_list_t *drm_supp_alloc_drv_entry(dev_info_t *);
69 69 static drm_inst_state_t *drm_sup_devt_to_state(dev_t);
70 70 static void drm_supp_free_drv_entry(dev_info_t *);
71 71
72 72 static struct devmap_callback_ctl drm_devmap_callbacks = {
73 73 DEVMAP_OPS_REV, /* devmap_rev */
74 74 drm_devmap_map, /* devmap_map */
75 75 NULL, /* devmap_access */
76 76 drm_devmap_dup, /* devmap_dup */
77 77 drm_devmap_unmap /* devmap_unmap */
78 78 };
79 79
80 80 /*
81 81 * Common device operations structure for all DRM drivers
82 82 */
83 83 struct cb_ops drm_cb_ops = {
84 84 drm_sun_open, /* cb_open */
85 85 drm_sun_close, /* cb_close */
86 86 nodev, /* cb_strategy */
87 87 nodev, /* cb_print */
88 88 nodev, /* cb_dump */
89 89 nodev, /* cb_read */
90 90 nodev, /* cb_write */
91 91 drm_sun_ioctl, /* cb_ioctl */
92 92 drm_sun_devmap, /* cb_devmap */
93 93 nodev, /* cb_mmap */
94 94 NULL, /* cb_segmap */
95 95 nochpoll, /* cb_chpoll */
96 96 ddi_prop_op, /* cb_prop_op */
97 97 0, /* cb_stream */
98 98 D_NEW | D_MTSAFE |D_DEVMAP /* cb_flag */
99 99 };
100 100
101 101 int
102 102 _init(void)
103 103 {
104 104 int error;
105 105
106 106 if ((error = mod_install(&modlinkage)) != 0) {
107 107 return (error);
108 108 }
109 109
110 110 /* initialize the instance list lock */
111 111 mutex_init(&drm_inst_list_lock, NULL, MUTEX_DRIVER, NULL);
112 112 return (0);
113 113 }
114 114
115 115 int
116 116 _fini(void)
117 117 {
118 118 int err;
119 119
120 120 if ((err = mod_remove(&modlinkage)) != 0)
121 121 return (err);
122 122
123 123 mutex_destroy(&drm_inst_list_lock);
124 124 return (0);
125 125 }
126 126
127 127 int
128 128 _info(struct modinfo *modinfop)
129 129 {
130 130 return (mod_info(&modlinkage, modinfop));
131 131 }
132 132
133 133 void *
134 134 drm_supp_register(dev_info_t *dip, drm_device_t *dp)
135 135 {
136 136 int error;
137 137 char buf[80];
138 138 int instance = ddi_get_instance(dip);
139 139 ddi_acc_handle_t pci_cfg_handle;
140 140 agp_master_softc_t *agpm;
141 141 drm_inst_state_t *mstate;
142 142 drm_inst_list_t *entry;
143 143 gfxp_vgatext_softc_ptr_t gfxp;
144 144 struct dev_ops *devop;
145 145
146 146 ASSERT(dip != NULL);
147 147
148 148 entry = drm_supp_alloc_drv_entry(dip);
149 149 if (entry == NULL) {
150 150 cmn_err(CE_WARN, "drm_supp_register: failed to get softstate");
151 151 return (NULL);
152 152 }
153 153 mstate = &entry->disl_state;
154 154
155 155 /*
156 156 * DRM drivers are required to use common cb_ops
157 157 */
158 158 devop = ddi_get_driver(dip);
159 159 if (devop->devo_cb_ops != &drm_cb_ops) {
160 160 devop->devo_cb_ops = &drm_cb_ops;
161 161 }
162 162
163 163 /* Generic graphics initialization */
164 164 gfxp = gfxp_vgatext_softc_alloc();
165 165 error = gfxp_vgatext_attach(dip, DDI_ATTACH, gfxp);
166 166 if (error != DDI_SUCCESS) {
167 167 DRM_ERROR("drm_supp_regiter: failed to init gfx");
168 168 goto exit1;
169 169 }
170 170
171 171 /* create a minor node for common graphics ops */
172 172 (void) sprintf(buf, "%s%d", GFX_NAME, instance);
173 173 error = ddi_create_minor_node(dip, buf, S_IFCHR,
174 174 INST2NODE0(instance), DDI_NT_DISPLAY, NULL);
175 175 if (error != DDI_SUCCESS) {
176 176 DRM_ERROR("drm_supp_regiter: "
177 177 "failed to create minor node for gfx");
178 178 goto exit2;
179 179 }
180 180
181 181 /* setup mapping for later PCI config space access */
182 182 error = pci_config_setup(dip, &pci_cfg_handle);
183 183 if (error != DDI_SUCCESS) {
184 184 DRM_ERROR("drm_supp_regiter: "
185 185 "PCI configuration space setup failed");
186 186 goto exit2;
187 187 }
188 188
189 189 /* AGP master attach */
190 190 agpm = NULL;
191 191 if (dp->driver->use_agp) {
192 192 DRM_DEBUG("drm_supp_regiter: driver use AGP\n");
193 193 error = agpmaster_attach(dip, &agpm,
194 194 pci_cfg_handle, INST2NODE1(instance));
195 195 if ((error != DDI_SUCCESS) && (dp->driver->require_agp)) {
196 196 DRM_ERROR("drm_supp_regiter: "
197 197 "AGP master support not available");
198 198 goto exit3;
199 199 }
200 200 }
201 201
202 202 mutex_enter(&mstate->mis_lock);
203 203 mstate->mis_major = ddi_driver_major(dip);
204 204 mstate->mis_dip = dip;
205 205 mstate->mis_gfxp = gfxp;
206 206 mstate->mis_agpm = agpm;
207 207 mstate->mis_cfg_hdl = pci_cfg_handle;
208 208 mstate->mis_devp = dp;
209 209 mutex_exit(&mstate->mis_lock);
210 210
211 211 /* create minor node for DRM access */
212 212 (void) sprintf(buf, "%s%d", DRM_DEVNODE, instance);
213 213 if (ddi_create_minor_node(dip, buf, S_IFCHR,
214 214 INST2NODE2(instance), DDI_NT_DISPLAY_DRM, 0)) {
215 215 DRM_ERROR("supp_regiter: faled to create minor node for drm");
216 216 goto exit4;
217 217 }
218 218
219 219 return ((void *)mstate);
220 220
221 221 exit4:
222 222 if ((dp->driver->use_agp) && agpm)
223 223 agpmaster_detach(&agpm);
224 224 exit3:
225 225 pci_config_teardown(&pci_cfg_handle);
226 226 exit2:
227 227 (void) gfxp_vgatext_detach(dip, DDI_DETACH, gfxp);
228 228 exit1:
229 229 gfxp_vgatext_softc_free(gfxp);
230 230 drm_supp_free_drv_entry(dip);
231 231 ddi_remove_minor_node(dip, NULL);
232 232
233 233 return (NULL);
234 234 }
235 235
236 236
237 237 int
238 238 drm_supp_unregister(void *handle)
239 239 {
240 240 drm_inst_list_t *list;
241 241 drm_inst_state_t *mstate;
242 242
243 243 list = (drm_inst_list_t *)handle;
244 244 mstate = &list->disl_state;
245 245 mutex_enter(&mstate->mis_lock);
246 246
247 247 /* AGP master detach */
248 248 if (mstate->mis_agpm != NULL)
249 249 agpmaster_detach(&mstate->mis_agpm);
250 250
251 251 /* free PCI config access handle */
252 252 if (mstate->mis_cfg_hdl)
253 253 pci_config_teardown(&mstate->mis_cfg_hdl);
254 254
255 255 /* graphics misc module detach */
256 256 if (mstate->mis_gfxp) {
257 257 (void) gfxp_vgatext_detach(mstate->mis_dip, DDI_DETACH,
258 258 mstate->mis_gfxp);
259 259 gfxp_vgatext_softc_free(mstate->mis_gfxp);
260 260 }
261 261
262 262 mstate->mis_devp = NULL;
263 263
264 264 /* remove all minor nodes */
265 265 ddi_remove_minor_node(mstate->mis_dip, NULL);
266 266 mutex_exit(&mstate->mis_lock);
267 267 drm_supp_free_drv_entry(mstate->mis_dip);
268 268
269 269 return (DDI_SUCCESS);
270 270 }
271 271
272 272
273 273 /*ARGSUSED*/
274 274 static int
275 275 drm_sun_open(dev_t *devp, int flag, int otyp, cred_t *credp)
276 276 {
277 277 drm_inst_state_t *mstate;
278 278 drm_cminor_t *mp, *newp;
279 279 drm_device_t *dp;
280 280 minor_t minor;
281 281 int newminor;
282 282 int instance;
283 283 int err;
284 284
285 285 mstate = drm_sup_devt_to_state(*devp);
286 286 /*
287 287 * return ENXIO for deferred attach so that system can
288 288 * attach us again.
289 289 */
290 290 if (mstate == NULL)
291 291 return (ENXIO);
292 292
293 293 /*
294 294 * The lest significant 15 bits are used for minor_number, and
295 295 * the mid 3 bits are used for instance number. All minor numbers
296 296 * are used as follows:
297 297 * 0 -- gfx
298 298 * 1 -- agpmaster
299 299 * 2 -- drm
300 300 * (3, MAX_CLONE_MINOR) -- drm minor node for clone open.
301 301 */
302 302 minor = DEV2MINOR(*devp);
303 303 instance = DEV2INST(*devp);
304 304 ASSERT(minor <= MAX_CLONE_MINOR);
305 305
306 306 /*
307 307 * No operations for VGA & AGP mater devices, always return OK.
308 308 */
309 309 if ((minor == GFX_MINOR) || (minor == AGPMASTER_MINOR))
310 310 return (0);
311 311
312 312 /*
313 313 * From here, we start to process drm
314 314 */
315 315
316 316 dp = mstate->mis_devp;
317 317 if (!dp)
318 318 return (ENXIO);
319 319
320 320 /*
321 321 * Drm driver implements a software lock to serialize access
322 322 * to graphics hardware based on per-process granulation. Before
323 323 * operating graphics hardware, all clients, including kernel
324 324 * and applications, must acquire this lock via DRM_IOCTL_LOCK
325 325 * ioctl, and release it via DRM_IOCTL_UNLOCK after finishing
326 326 * operations. Drm driver will grant r/w permission to the
327 327 * process which acquires this lock (Kernel is assumed to have
328 328 * process ID 0).
329 329 *
330 330 * A process might be terminated without releasing drm lock, in
331 331 * this case, drm driver is responsible for clearing the holding.
332 332 * To be informed of process exiting, drm driver uses clone open
333 333 * to guarantee that each call to open(9e) have one corresponding
334 334 * call to close(9e). In most cases, a process will close drm
335 335 * during process termination, so that drm driver could have a
336 336 * chance to release drm lock.
337 337 *
338 338 * In fact, a driver cannot know exactly when a process exits.
339 339 * Clone open doesn't address this issue completely: Because of
340 340 * inheritance, child processes inherit file descriptors from
341 341 * their parent. As a result, if the parent exits before its
342 342 * children, drm close(9e) entrypoint won't be called until all
343 343 * of its children terminate.
344 344 *
345 345 * Another issue brought up by inhertance is the process PID
346 346 * that calls the drm close() entry point may not be the same
347 347 * as the one who called open(). Per-process struct is allocated
348 348 * when a process first open() drm, and released when the process
349 349 * last close() drm. Since open()/close() may be not the same
350 350 * process, PID cannot be used for key to lookup per-process
351 351 * struct. So, we associate minor number with per-process struct
352 352 * during open()'ing, and find corresponding process struct
353 353 * via minor number when close() is called.
354 354 */
355 355 newp = kmem_zalloc(sizeof (drm_cminor_t), KM_SLEEP);
356 356 mutex_enter(&dp->dev_lock);
357 357 for (newminor = DRM_MIN_CLONEMINOR; newminor < MAX_CLONE_MINOR;
358 358 newminor ++) {
359 359 TAILQ_FOREACH(mp, &dp->minordevs, link) {
360 360 if (mp->minor == newminor)
361 361 break;
362 362 }
363 363 if (mp == NULL)
364 364 goto gotminor;
365 365 }
366 366
367 367 mutex_exit(&dp->dev_lock);
368 368 (void) kmem_free(newp, sizeof (drm_cminor_t));
369 369 return (EMFILE);
370 370
371 371 gotminor:
372 372 TAILQ_INSERT_TAIL(&dp->minordevs, newp, link);
373 373 newp->minor = newminor;
374 374 mutex_exit(&dp->dev_lock);
375 375 err = drm_open(dp, newp, flag, otyp, credp);
376 376 if (err) {
377 377 mutex_enter(&dp->dev_lock);
378 378 TAILQ_REMOVE(&dp->minordevs, newp, link);
379 379 (void) kmem_free(newp, sizeof (drm_cminor_t));
380 380 mutex_exit(&dp->dev_lock);
381 381
382 382 return (err);
383 383 }
384 384
385 385 /* return a clone minor */
386 386 newminor = newminor | (instance << NBITSMNODE);
387 387 *devp = makedevice(getmajor(*devp), newminor);
388 388 return (err);
389 389 }
390 390
391 391 /*ARGSUSED*/
392 392 static int
393 393 drm_sun_close(dev_t dev, int flag, int otyp, cred_t *credp)
394 394 {
395 395 drm_inst_state_t *mstate;
396 396 drm_device_t *dp;
397 397 minor_t minor;
398 398 int ret;
399 399
400 400 mstate = drm_sup_devt_to_state(dev);
401 401 if (mstate == NULL)
402 402 return (EBADF);
403 403
404 404 minor = DEV2MINOR(dev);
405 405 ASSERT(minor <= MAX_CLONE_MINOR);
406 406 if ((minor == GFX_MINOR) || (minor == AGPMASTER_MINOR))
407 407 return (0);
408 408
409 409 dp = mstate->mis_devp;
410 410 if (dp == NULL) {
411 411 DRM_ERROR("drm_sun_close: NULL soft state");
412 412 return (ENXIO);
413 413 }
414 414
415 415 ret = drm_close(dp, minor, flag, otyp, credp);
416 416
417 417 return (ret);
418 418 }
419 419
420 420 /*ARGSUSED*/
421 421 static int
422 422 drm_sun_ioctl(dev_t dev, int cmd, intptr_t arg, int mode,
423 423 cred_t *credp, int *rvalp)
424 424 {
425 425 extern drm_ioctl_desc_t drm_ioctls[];
426 426
427 427 drm_inst_state_t *mstate;
428 428 drm_device_t *dp;
429 429 drm_ioctl_desc_t *ioctl;
430 430 drm_ioctl_t *func;
431 431 drm_file_t *fpriv;
432 432 minor_t minor;
433 433 int retval;
434 434 int nr;
435 435
436 436 if (cmd == VIS_GETIDENTIFIER) {
437 437 if (ddi_copyout(&text_ident, (void *)arg,
438 438 sizeof (struct vis_identifier), mode))
439 439 return (EFAULT);
440 440 }
441 441
442 442 mstate = drm_sup_devt_to_state(dev);
443 443 if (mstate == NULL) {
444 444 return (EIO);
445 445 }
446 446
447 447 minor = DEV2MINOR(dev);
448 448 ASSERT(minor <= MAX_CLONE_MINOR);
449 449 switch (minor) {
450 450 case GFX_MINOR:
451 451 retval = gfxp_vgatext_ioctl(dev, cmd, arg,
452 452 mode, credp, rvalp, mstate->mis_gfxp);
453 453 return (retval);
454 454
455 455 case AGPMASTER_MINOR:
456 456 retval = agpmaster_ioctl(dev, cmd, arg, mode,
457 457 credp, rvalp, mstate->mis_agpm);
458 458 return (retval);
459 459
460 460 case DRM_MINOR:
461 461 default: /* DRM cloning minor nodes */
462 462 break;
463 463 }
464 464
465 465 dp = mstate->mis_devp;
466 466 ASSERT(dp != NULL);
467 467
468 468 nr = DRM_IOCTL_NR(cmd);
469 469 ioctl = &drm_ioctls[nr];
470 470 atomic_inc_32(&dp->counts[_DRM_STAT_IOCTLS]);
471 471
472 472 /* It's not a core DRM ioctl, try driver-specific. */
473 473 if (ioctl->func == NULL && nr >= DRM_COMMAND_BASE) {
474 474 /* The array entries begin at DRM_COMMAND_BASE ioctl nr */
475 475 nr -= DRM_COMMAND_BASE;
476 476 if (nr > dp->driver->max_driver_ioctl) {
477 477 DRM_ERROR("Bad driver ioctl number, 0x%x (of 0x%x)",
478 478 nr, dp->driver->max_driver_ioctl);
479 479 return (EINVAL);
480 480 }
481 481 ioctl = &dp->driver->driver_ioctls[nr];
482 482 }
483 483
484 484 func = ioctl->func;
485 485 if (func == NULL) {
486 486 return (ENOTSUP);
487 487 }
488 488
489 489 mutex_enter(&dp->dev_lock);
490 490 fpriv = drm_find_file_by_proc(dp, credp);
491 491 mutex_exit(&dp->dev_lock);
492 492 if (fpriv == NULL) {
493 493 DRM_ERROR("drm_sun_ioctl : can't find authenticator");
494 494 return (EACCES);
495 495 }
496 496
497 497 if (((ioctl->flags & DRM_ROOT_ONLY) && !DRM_SUSER(credp)) ||
498 498 ((ioctl->flags & DRM_AUTH) && !fpriv->authenticated) ||
499 499 ((ioctl->flags & DRM_MASTER) && !fpriv->master))
500 500 return (EACCES);
501 501
502 502 fpriv->dev = dev;
503 503 fpriv->credp = credp;
504 504
505 505 retval = func(dp, arg, fpriv, mode);
506 506
507 507 return (retval);
508 508 }
509 509
510 510 /*ARGSUSED*/
511 511 static int
512 512 drm_sun_devmap(dev_t dev, devmap_cookie_t dhp, offset_t offset,
513 513 size_t len, size_t *maplen, uint_t model)
514 514 {
515 515 extern int drm_get_pci_index_reg(dev_info_t *, uint_t, uint_t, off_t *);
516 516
517 517 drm_inst_state_t *mstate;
518 518 drm_device_t *dp;
519 519 ddi_umem_cookie_t cookie;
520 520 drm_local_map_t *map = NULL;
521 521 unsigned long aperbase;
522 522 u_offset_t handle;
523 523 offset_t koff;
524 524 caddr_t kva;
525 525 minor_t minor;
526 526 size_t length;
527 527 int ret;
528 528
529 529 static ddi_device_acc_attr_t dev_attr = {
530 530 DDI_DEVICE_ATTR_V0,
531 531 DDI_NEVERSWAP_ACC,
532 532 DDI_STRICTORDER_ACC,
533 533 };
534 534 static ddi_device_acc_attr_t gem_dev_attr = {
535 535 DDI_DEVICE_ATTR_V0,
536 536 DDI_NEVERSWAP_ACC,
537 537 DDI_MERGING_OK_ACC
538 538 };
539 539
540 540 mstate = drm_sup_devt_to_state(dev);
541 541 if (mstate == NULL)
542 542 return (ENXIO);
543 543
544 544 minor = DEV2MINOR(dev);
545 545 switch (minor) {
546 546 case GFX_MINOR:
547 547 ret = gfxp_vgatext_devmap(dev, dhp, offset, len, maplen, model,
548 548 mstate->mis_gfxp);
549 549 return (ret);
550 550
551 551 case AGPMASTER_MINOR:
552 552 return (ENOTSUP);
553 553
554 554 case DRM_MINOR:
555 555 break;
556 556
557 557 default:
558 558 /* DRM cloning nodes */
559 559 if (minor > MAX_CLONE_MINOR)
560 560 return (EBADF);
561 561 break;
562 562 }
563 563
564 564
565 565 dp = mstate->mis_devp;
566 566 if (dp == NULL) {
567 567 DRM_ERROR("drm_sun_devmap: NULL soft state");
568 568 return (EINVAL);
569 569 }
570 570
571 571 mutex_enter(&dp->dev_lock);
572 572
573 573 if (dp->driver->use_gem == 1) {
574 574 struct idr_list *entry;
575 575 drm_cminor_t *mp;
576 576
577 577 mp = drm_find_file_by_minor(dp, minor);
578 578 if (!mp) {
579 579 mutex_exit(&dp->dev_lock);
580 580 DRM_ERROR("drm_sun_devmap: can't find authenticator");
581 581 return (EACCES);
582 582 }
583 583
584 584 spin_lock(&dp->struct_mutex);
585 585 idr_list_for_each(entry, &(mp->fpriv->object_idr)) {
586 586 if ((uintptr_t)entry->obj == (u_offset_t)offset) {
587 587 map = entry->obj->map;
588 588 goto goon;
589 589 }
590 590 }
591 591 goon:
592 592 spin_unlock(&dp->struct_mutex);
593 593 }
594 594
595 595 if (map == NULL) {
596 596 /*
597 597 * We will solve 32-bit application on 64-bit kernel
598 598 * issue later, now, we just use low 32-bit
599 599 */
600 600 handle = (u_offset_t)offset;
601 601 handle &= 0xffffffff;
602 602
603 603 TAILQ_FOREACH(map, &dp->maplist, link) {
604 604 if (handle ==
605 605 ((u_offset_t)((uintptr_t)map->handle) & 0xffffffff))
606 606 break;
607 607 }
608 608
609 609 /*
610 610 * Temporarily, because offset is phys_addr for register
611 611 * and framebuffer, is kernel virtual_addr for others
612 612 * Maybe we will use hash table to solve this issue later.
613 613 */
614 614 if (map == NULL) {
615 615 TAILQ_FOREACH(map, &dp->maplist, link) {
616 616 if (handle == (map->offset & 0xffffffff))
617 617 break;
618 618 }
619 619 }
620 620 }
621 621
622 622 if (map == NULL) {
623 623 u_offset_t tmp;
624 624
625 625 mutex_exit(&dp->dev_lock);
626 626 cmn_err(CE_WARN, "Can't find map, offset=0x%llx, len=%x\n",
627 627 offset, (int)len);
628 628 cmn_err(CE_WARN, "Current mapping:\n");
629 629 TAILQ_FOREACH(map, &dp->maplist, link) {
630 630 tmp = (u_offset_t)((uintptr_t)map->handle) & 0xffffffff;
631 631 cmn_err(CE_WARN, "map(handle=0x%p, size=0x%lx,type=%d,"
632 632 "offset=0x%lx), handle=%llx, tmp=%lld", map->handle,
633 633 map->size, map->type, map->offset, handle, tmp);
634 634 }
635 635 return (-1);
636 636 }
637 637 if (map->flags & _DRM_RESTRICTED) {
638 638 mutex_exit(&dp->dev_lock);
639 639 cmn_err(CE_WARN, "restricted map\n");
640 640 return (-1);
641 641 }
642 642
643 643 mutex_exit(&dp->dev_lock);
644 644 switch (map->type) {
645 645 case _DRM_FRAME_BUFFER:
646 646 case _DRM_REGISTERS:
647 647 {
648 648 int regno;
649 649 off_t regoff;
650 650
651 651 regno = drm_get_pci_index_reg(dp->dip,
652 652 map->offset, (uint_t)len, ®off);
653 653 if (regno < 0) {
654 654 DRM_ERROR("devmap: failed to get register"
655 655 " offset=0x%llx, len=0x%x", handle, len);
656 656 return (EINVAL);
657 657 }
658 658
659 659 ret = devmap_devmem_setup(dhp, dp->dip, NULL,
660 660 regno, (offset_t)regoff, len, PROT_ALL,
661 661 0, &dev_attr);
662 662 if (ret != 0) {
663 663 *maplen = 0;
664 664 DRM_ERROR("devmap: failed, regno=%d,type=%d,"
665 665 " handle=0x%x, offset=0x%llx, len=0x%x",
666 666 regno, map->type, handle, offset, len);
667 667 return (ret);
668 668 }
669 669 *maplen = len;
670 670 return (ret);
671 671 }
672 672
673 673 case _DRM_SHM:
674 674 if (map->drm_umem_cookie == NULL)
675 675 return (EINVAL);
676 676 length = ptob(btopr(map->size));
677 677 ret = devmap_umem_setup(dhp, dp->dip, NULL,
678 678 map->drm_umem_cookie, 0, length,
679 679 PROT_ALL, IOMEM_DATA_CACHED, NULL);
680 680 if (ret != 0) {
681 681 *maplen = 0;
682 682 return (ret);
683 683 }
684 684 *maplen = length;
685 685
686 686 return (DDI_SUCCESS);
687 687
688 688 case _DRM_AGP:
689 689 if (dp->agp == NULL) {
690 690 cmn_err(CE_WARN, "drm_sun_devmap: attempted to mmap AGP"
691 691 "memory before AGP support is enabled");
692 692 return (DDI_FAILURE);
693 693 }
694 694
695 695 aperbase = dp->agp->base;
696 696 koff = map->offset - aperbase;
697 697 length = ptob(btopr(len));
698 698 kva = map->dev_addr;
699 699 cookie = gfxp_umem_cookie_init(kva, length);
700 700 if (cookie == NULL) {
701 701 cmn_err(CE_WARN, "devmap:failed to get umem_cookie");
702 702 return (DDI_FAILURE);
703 703 }
704 704
705 705 if ((ret = devmap_umem_setup(dhp, dp->dip,
706 706 &drm_devmap_callbacks, cookie, 0, length, PROT_ALL,
707 707 IOMEM_DATA_UNCACHED | DEVMAP_ALLOW_REMAP, &dev_attr)) < 0) {
708 708 gfxp_umem_cookie_destroy(cookie);
709 709 cmn_err(CE_WARN, "devmap:failed, retval=%d", ret);
710 710 return (DDI_FAILURE);
711 711 }
712 712 *maplen = length;
713 713 break;
714 714
715 715 case _DRM_SCATTER_GATHER:
716 716 koff = map->offset - (unsigned long)(caddr_t)dp->sg->virtual;
717 717 kva = map->dev_addr + koff;
718 718 length = ptob(btopr(len));
719 719 if (length > map->size) {
720 720 cmn_err(CE_WARN, "offset=0x%lx, virtual=0x%p,"
721 721 "mapsize=0x%lx,len=0x%lx", map->offset,
722 722 dp->sg->virtual, map->size, len);
723 723 return (DDI_FAILURE);
724 724 }
725 725 cookie = gfxp_umem_cookie_init(kva, length);
726 726 if (cookie == NULL) {
727 727 cmn_err(CE_WARN, "devmap:failed to get umem_cookie");
728 728 return (DDI_FAILURE);
729 729 }
730 730 ret = devmap_umem_setup(dhp, dp->dip,
731 731 &drm_devmap_callbacks, cookie, 0, length, PROT_ALL,
732 732 IOMEM_DATA_UNCACHED | DEVMAP_ALLOW_REMAP, &dev_attr);
733 733 if (ret != 0) {
734 734 cmn_err(CE_WARN, "sun_devmap: umem_setup fail");
735 735 gfxp_umem_cookie_destroy(cookie);
736 736 return (DDI_FAILURE);
737 737 }
738 738 *maplen = length;
739 739 break;
740 740
741 741 case _DRM_TTM:
742 742 if (map->drm_umem_cookie == NULL)
743 743 return (EINVAL);
744 744
745 745 if (gfxp_devmap_umem_setup(dhp, dp->dip,
746 746 NULL, map->drm_umem_cookie, 0, map->size, PROT_ALL,
747 747 IOMEM_DATA_UC_WR_COMBINE | DEVMAP_ALLOW_REMAP,
748 748 &gem_dev_attr)) {
749 749 cmn_err(CE_WARN, "devmap:failed, retval=%d", ret);
750 750 return (DDI_FAILURE);
751 751 }
752 752 *maplen = map->size;
753 753 return (DDI_SUCCESS);
754 754
755 755 default:
756 756 return (DDI_FAILURE);
757 757 }
758 758 return (DDI_SUCCESS);
759 759
760 760 }
761 761
762 762 /*ARGSUSED*/
763 763 static int
764 764 drm_devmap_map(devmap_cookie_t dhc, dev_t dev, uint_t flags,
765 765 offset_t offset, size_t len, void **new_priv)
766 766 {
767 767 devmap_handle_t *dhp;
768 768 drm_inst_state_t *statep;
769 769 struct ddi_umem_cookie *cp;
770 770
771 771 statep = drm_sup_devt_to_state(dev);
772 772 ASSERT(statep != NULL);
773 773
774 774 /*
775 775 * This driver only supports MAP_SHARED,
776 776 * and doesn't support MAP_PRIVATE
777 777 */
778 778 if (flags & MAP_PRIVATE) {
779 779 cmn_err(CE_WARN, "!DRM driver doesn't support MAP_PRIVATE");
780 780 return (EINVAL);
781 781 }
782 782
783 783 mutex_enter(&statep->dis_ctxlock);
784 784 dhp = (devmap_handle_t *)dhc;
785 785 cp = (struct ddi_umem_cookie *)dhp->dh_cookie;
786 786 cp->cook_refcnt = 1;
787 787 mutex_exit(&statep->dis_ctxlock);
788 788 *new_priv = statep;
789 789
790 790 return (0);
791 791 }
792 792
793 793 /*ARGSUSED*/
794 794 static void
795 795 drm_devmap_unmap(devmap_cookie_t dhc, void *pvtp, offset_t off, size_t len,
796 796 devmap_cookie_t new_dhp1, void **new_pvtp1, devmap_cookie_t new_dhp2,
797 797 void **new_pvtp2)
798 798 {
799 799 devmap_handle_t *dhp;
800 800 devmap_handle_t *ndhp;
801 801 drm_inst_state_t *statep;
802 802 struct ddi_umem_cookie *cp;
803 803 struct ddi_umem_cookie *ncp;
804 804
805 805 dhp = (devmap_handle_t *)dhc;
806 806 statep = (drm_inst_state_t *)pvtp;
807 807
808 808 mutex_enter(&statep->dis_ctxlock);
809 809 cp = (struct ddi_umem_cookie *)dhp->dh_cookie;
810 810 if (new_dhp1 != NULL) {
811 811 ndhp = (devmap_handle_t *)new_dhp1;
812 812 ncp = (struct ddi_umem_cookie *)ndhp->dh_cookie;
813 813 ncp->cook_refcnt ++;
814 814 *new_pvtp1 = statep;
815 815 ASSERT(ncp == cp);
816 816 }
817 817
818 818 if (new_dhp2 != NULL) {
819 819 ndhp = (devmap_handle_t *)new_dhp2;
820 820 ncp = (struct ddi_umem_cookie *)ndhp->dh_cookie;
821 821 ncp->cook_refcnt ++;
822 822 *new_pvtp2 = statep;
823 823 ASSERT(ncp == cp);
824 824 }
825 825
826 826 cp->cook_refcnt --;
827 827 if (cp->cook_refcnt == 0) {
828 828 gfxp_umem_cookie_destroy(dhp->dh_cookie);
829 829 dhp->dh_cookie = NULL;
830 830 }
831 831 mutex_exit(&statep->dis_ctxlock);
832 832 }
833 833
834 834
835 835 /*ARGSUSED*/
836 836 static int
837 837 drm_devmap_dup(devmap_cookie_t dhc, void *pvtp, devmap_cookie_t new_dhc,
838 838 void **new_pvtp)
839 839 {
840 840 devmap_handle_t *dhp;
841 841 drm_inst_state_t *statep;
842 842 struct ddi_umem_cookie *cp;
843 843
844 844 statep = (drm_inst_state_t *)pvtp;
845 845 mutex_enter(&statep->dis_ctxlock);
846 846 dhp = (devmap_handle_t *)dhc;
847 847 cp = (struct ddi_umem_cookie *)dhp->dh_cookie;
848 848 cp->cook_refcnt ++;
849 849 mutex_exit(&statep->dis_ctxlock);
850 850 *new_pvtp = statep;
851 851
852 852 return (0);
853 853 }
854 854
855 855 int
856 856 drm_dev_to_instance(dev_t dev)
857 857 {
858 858 return (DEV2INST(dev));
859 859 }
860 860
861 861 /*
862 862 * drm_supp_alloc_drv_entry()
863 863 *
864 864 * Description:
865 865 * Create a DRM entry and add it into the instance list (drm_inst_head).
866 866 * Note that we don't allow a duplicated entry
867 867 */
868 868 static drm_inst_list_t *
869 869 drm_supp_alloc_drv_entry(dev_info_t *dip)
870 870 {
871 871 drm_inst_list_t **plist;
872 872 drm_inst_list_t *list;
873 873 drm_inst_list_t *entry;
874 874
875 875 /* protect the driver list */
876 876 mutex_enter(&drm_inst_list_lock);
877 877 plist = &drm_inst_head;
878 878 list = *plist;
879 879 while (list) {
880 880 if (list->disl_state.mis_dip == dip) {
881 881 mutex_exit(&drm_inst_list_lock);
882 882 cmn_err(CE_WARN, "%s%d already registered",
883 883 ddi_driver_name(dip), ddi_get_instance(dip));
884 884 return (NULL);
885 885 }
886 886 plist = &list->disl_next;
887 887 list = list->disl_next;
888 888 }
889 889
890 890 /* "dip" is not registered, create new one and add to list */
891 891 entry = kmem_zalloc(sizeof (*entry), KM_SLEEP);
892 892 *plist = entry;
893 893 entry->disl_state.mis_dip = dip;
894 894 mutex_init(&entry->disl_state.mis_lock, NULL, MUTEX_DRIVER, NULL);
895 895 mutex_init(&entry->disl_state.dis_ctxlock, NULL, MUTEX_DRIVER, NULL);
896 896 mutex_exit(&drm_inst_list_lock);
897 897
898 898 return (entry);
899 899
900 900 } /* drm_supp_alloc_drv_entry */
901 901
902 902 /*
903 903 * drm_supp_free_drv_entry()
904 904 */
905 905 static void
906 906 drm_supp_free_drv_entry(dev_info_t *dip)
907 907 {
908 908 drm_inst_list_t *list;
909 909 drm_inst_list_t **plist;
910 910 drm_inst_state_t *mstate;
911 911
912 912 /* protect the driver list */
913 913 mutex_enter(&drm_inst_list_lock);
914 914 plist = &drm_inst_head;
915 915 list = *plist;
916 916 while (list) {
917 917 if (list->disl_state.mis_dip == dip) {
918 918 *plist = list->disl_next;
919 919 mstate = &list->disl_state;
920 920 mutex_destroy(&mstate->mis_lock);
921 921 mutex_destroy(&mstate->dis_ctxlock);
922 922 kmem_free(list, sizeof (*list));
923 923 mutex_exit(&drm_inst_list_lock);
924 924 return;
925 925 }
926 926 plist = &list->disl_next;
927 927 list = list->disl_next;
928 928 }
929 929 mutex_exit(&drm_inst_list_lock);
930 930
931 931 } /* drm_supp_free_drv_entry() */
932 932
933 933 /*
934 934 * drm_sup_devt_to_state()
935 935 *
936 936 * description:
937 937 * Get the soft state of DRM instance by device number
938 938 */
939 939 static drm_inst_state_t *
940 940 drm_sup_devt_to_state(dev_t dev)
941 941 {
942 942 drm_inst_list_t *list;
943 943 drm_inst_state_t *mstate;
944 944 major_t major = getmajor(dev);
945 945 int instance = DEV2INST(dev);
946 946
947 947 mutex_enter(&drm_inst_list_lock);
948 948 list = drm_inst_head;
949 949 while (list) {
950 950 mstate = &list->disl_state;
951 951 mutex_enter(&mstate->mis_lock);
952 952
953 953 if ((mstate->mis_major == major) &&
954 954 (ddi_get_instance(mstate->mis_dip) == instance)) {
955 955 mutex_exit(&mstate->mis_lock);
956 956 mutex_exit(&drm_inst_list_lock);
957 957 return (mstate);
958 958 }
959 959
960 960 list = list->disl_next;
961 961 mutex_exit(&mstate->mis_lock);
962 962 }
963 963
964 964 mutex_exit(&drm_inst_list_lock);
965 965 return (NULL);
966 966
967 967 } /* drm_sup_devt_to_state() */
968 968
969 969 int
970 970 drm_supp_get_irq(void *handle)
971 971 {
972 972 drm_inst_list_t *list;
973 973 drm_inst_state_t *mstate;
974 974 int irq;
975 975
976 976 list = (drm_inst_list_t *)handle;
977 977 mstate = &list->disl_state;
978 978 ASSERT(mstate != NULL);
979 979 irq = pci_config_get8(mstate->mis_cfg_hdl, PCI_CONF_ILINE);
980 980 return (irq);
981 981 }
982 982
983 983 int
984 984 drm_supp_device_capability(void *handle, int capid)
985 985 {
986 986 drm_inst_list_t *list;
987 987 drm_inst_state_t *mstate;
988 988 uint8_t cap = 0;
989 989 uint16_t caps_ptr;
990 990
991 991 list = (drm_inst_list_t *)handle;
992 992 mstate = &list->disl_state;
993 993 ASSERT(mstate != NULL);
994 994
995 995 /* has capabilities list ? */
996 996 if ((pci_config_get16(mstate->mis_cfg_hdl, PCI_CONF_STAT) &
997 997 PCI_CONF_CAP_MASK) == 0)
998 998 return (NULL);
999 999
1000 1000 caps_ptr = pci_config_get8(mstate->mis_cfg_hdl, PCI_CONF_CAP_PTR);
1001 1001 while (caps_ptr != PCI_CAP_NEXT_PTR_NULL) {
1002 1002 cap = pci_config_get32(mstate->mis_cfg_hdl, caps_ptr);
1003 1003 if ((cap & PCI_CONF_CAPID_MASK) == capid)
1004 1004 return (cap);
1005 1005 caps_ptr = pci_config_get8(mstate->mis_cfg_hdl,
1006 1006 caps_ptr + PCI_CAP_NEXT_PTR);
1007 1007 }
1008 1008
1009 1009 return (0);
1010 1010 }
↓ open down ↓ |
954 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX