/* $NetBSD: darwin_ioframebuffer.c,v 1.31 2003/12/29 01:34:02 manu Exp $ */ /*- * Copyright (c) 2003 The NetBSD Foundation, Inc. * All rights reserved. * * This code is derived from software contributed to The NetBSD Foundation * by Emmanuel Dreyfus. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the NetBSD * Foundation, Inc. and its contributors. * 4. Neither the name of The NetBSD Foundation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #include __KERNEL_RCSID(0, "$NetBSD: darwin_ioframebuffer.c,v 1.31 2003/12/29 01:34:02 manu Exp $"); #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "ioconf.h" /* Redefined from sys/dev/wscons/wsdisplay.c */ extern const struct cdevsw wsdisplay_cdevsw; #define WSDISPLAYMINOR(unit, screen) (((unit) << 8) | (screen)) static int darwin_findscreen(dev_t *, int, int); static struct uvm_object *darwin_ioframebuffer_shmem = NULL; static void darwin_ioframebuffer_shmeminit(vaddr_t); /* This is ugly, but we hope to see it going away quickly */ static char darwin_iofbconfig[] = "IOFBModesAID0xeeDMAAACAAAAAYAAMgAAAAAAAgAQAAAAAAAAAAAAAAAAAAAAAAAAID0x3eAID0x82DMAAACAAAAAYAAPAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAID0x3AID0xe8DMAAACAAAAAYAAPAAAAAAAAgAQAAAAAAAAAAAAAAAAAAAAAAAAID0x37DMAAACAAAAAYAARgAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAID0x5AIDDMAAACgAAAAeAAPAAAAAAAAgAQAAAAAAAAAAAAAAAAAAAAAAAAID0x38AIDDMAAACgAAAAeAAMgAAAAAAAgAQAAAAAAAAAAAAAAAAAAAAAAAAID0x3fAID0x96DMAAACgAAAAeAAPAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAID0x6AID0x8cDMAAACgAAAAeAAQwAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAID0x7AID0x98DMAAACgAAAAeAASAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAID0x8AID0x9aDMAAACgAAAAeAASwAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAID0x9AID0x9eDMAAACgAAAAeAAVQAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAID0xaAID0xa0DMAAACgAAAA2YASwAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAID0xeAIDDMAAAC0AAAAeAAMgAAAAAAAgAQAAAAAAAAAAAAAAAAAAAAAAAAID0x4bAIDDMAAAC0AAAAeAAPAAAAAAAAgAQAAAAAAAAAAAAAAAAAAAAAAAAID0x4dAIDDMAAAC0AAAAkAAMgAAAAAAAgAQAAAAAAAAAAAAAAAAAAAAAAAAID0x4cAIDDMAAAC0AAAAkAAPAAAAAAAAgAQAAAAAAAAAAAAAAAAAAAAAAAAID0x4eAIDDMAAADIAAAAlgAMgAAAAAAAgAQAAAAAAAAAAAAAAAAAAAAAAAAID0x40AID0xb4DMAAADIAAAAlgAOAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAID0xfAID0xb6DMAAADIAAAAlgAPAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAID0x10AIDDMAAADIAAAAlgAPAAAAAAAAgAQAAAAAAAAAAAAAAAAAAAAAAAAID0x39AID0x2aID0x2dDF0x400DMAAADIAAAAlgAAAAAAAAAAgAABAAAAAAAAAAAAAAAAAAAAAAADF0x100DMAAADIAAAAlgAPAAAAAAAAgAAAQAAAAAAAAAAAAAAAAAAAAAAID0x32AID0xb8DMAAADIAAAAlgASAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAID0x11AID0xbaDMAAADIAAAAlgASwAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAID0x12AIDID0x46DFDMAID0xbcDMAAADIAAAAlgAVQAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAID0x13AIDDMAAADQAAAAnAAMgAAAAAAAgAQAAAAAAAAAAAAAAAAAAAAAAAAID0x41AIDDMAAADQAAAAnAAPAAAAAAAAgAQAAAAAAAAAAAAAAAAAAAAAAAAID0x3aAID0xaaDMAAADQAAAAnAASwAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAID0x17DMAAADVAAAAoAAPAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAID0x18AID0xbeDMAAAEAAAAAwAAPAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAID0x19AIDID0x2eDF0x407DMAAAEAAAAAwAAAAAAAAAAAgAABAcAAAAAAAAAAAAAAAAAAAAAAIDID0x33DFDMAAAEAAAAAwAAPAAAAAAAAgAAAQAAAAAAAAAAAAAAAAAAAAAAAID0xc8DMAAAEAAAAAwAARgAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAID0x1aAID0xccDMAAAEAAAAAwAASwAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAID0x1bAID0xd2DMID0x1cAID0xd0DMAAAEAAAAAwAAVQAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAID0x1dAID0xdcDMAAAEgAAAA2YASwAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAID0x21AID0xfaDMAAAFAAAAA8AASwAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAID0x22AID0x104DMAAAFAAAABAAAPAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAID0x23AID0x106DMAAAFAAAABAAASwAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAID0x24IODisplayConnectFlags0x0"; static char darwin_ioframebuffer_properties[] = "IOClassAppleBacklightDisplayIOProbeScore0xbb8IOProviderClassIODisplayConnectCFBundleIdentifiercom.apple.iokit.IOGraphicsFamilyIOMatchCategoryIODefaultMatchCategoryIODisplayConnectFlagsAAAIxA==AppleDisplayType0x2AppleSense0x400DisplayVendorID0x756e6b6eDisplayProductID0x20000IODisplayParametersbrightnessmax0x73min0x3avalue0x7fcommitreg0x0IODisplayGUID0x610000000000000Power Management protected data{ 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 }Power Management private data{ this object = 0114c800, interested driver = 0114c800, driverDesire = 0, deviceDesire = 0, ourDesiredPowerState = 0, previousReqest = 0 }"; struct mach_iokit_property darwin_ioframebuffer_properties_array[] = { { "IOFBDependentID", NULL }, { "IOFBDependentIndex", NULL }, { "graphic-options", "0x0"}, { "IOFBConfig", darwin_iofbconfig }, { "IOFBMemorySize", "0x1000000"}, { "AAPL,boot-display", ""}, { NULL, 0} }; struct mach_iokit_devclass darwin_ioframebuffer_devclass = { "IOProviderClass" "IOFramebuffer", { &mach_ioroot_devclass, NULL }, darwin_ioframebuffer_properties, darwin_ioframebuffer_properties_array, darwin_ioframebuffer_connect_method_scalari_scalaro, darwin_ioframebuffer_connect_method_scalari_structo, darwin_ioframebuffer_connect_method_structi_structo, darwin_ioframebuffer_connect_method_scalari_structi, darwin_ioframebuffer_connect_map_memory, "IOFramebuffer", NULL, }; int darwin_ioframebuffer_connect_method_scalari_scalaro(args) struct mach_trap_args *args; { mach_io_connect_method_scalari_scalaro_request_t *req = args->smsg; mach_io_connect_method_scalari_scalaro_reply_t *rep = args->rmsg; size_t *msglen = args->rsize; struct lwp *l = args->l; int maxoutcount; int error; #ifdef DEBUG_DARWIN printf("darwin_ioframebuffer_connect_method_scalari_scalaro()\n"); #endif rep->rep_outcount = 0; maxoutcount = req->req_in[req->req_incount]; switch (req->req_selector) { case DARWIN_IOFBCREATESHAREDCURSOR: { /* Create the shared memory containing cursor information */ int shmemvers; int maxwidth; int maxheight; size_t memsize; vaddr_t kvaddr; shmemvers = req->req_in[0]; /* 0x2 */ maxwidth = req->req_in[1]; /* 0x20 */ maxheight = req->req_in[2]; /* 0x20 */ #ifdef DEBUG_DARWIN printf("DARWIN_IOFBCREATESHAREDCURSOR: shmemvers = %d, " "maxwidth = %d, maxheight = %d\n", shmemvers, maxwidth, maxheight); #endif if (darwin_ioframebuffer_shmem == NULL) { memsize = round_page(sizeof(*darwin_ioframebuffer_shmem)); darwin_ioframebuffer_shmem = uao_create(memsize, 0); error = uvm_map(kernel_map, &kvaddr, memsize, darwin_ioframebuffer_shmem, 0, PAGE_SIZE, UVM_MAPFLAG(UVM_PROT_RW, UVM_PROT_RW, UVM_INH_SHARE, UVM_ADV_RANDOM, 0)); if (error != 0) { uao_detach(darwin_ioframebuffer_shmem); darwin_ioframebuffer_shmem = NULL; return mach_msg_error(args, error); } if ((error = uvm_map_pageable(kernel_map, kvaddr, kvaddr + memsize, FALSE, 0)) != 0) { uao_detach(darwin_ioframebuffer_shmem); darwin_ioframebuffer_shmem = NULL; return mach_msg_error(args, error); } darwin_ioframebuffer_shmeminit(kvaddr); } /* No output, the zone is mapped during another call */ rep->rep_outcount = 0; break; } case DARWIN_IOFBSETSTARTUPDISPLAYMODE: { darwin_iodisplaymodeid mode; darwin_ioindex depth; mode = req->req_in[0]; depth = req->req_in[1]; #ifdef DEBUG_DARWIN printf("DARWIN_IOFBSETSTARTUPDISPLAYMODE: mode = %d, " "depth = %d\n", mode, depth); #endif /* Nothing for now */ break; } case DARWIN_IOFBSETDISPLAYMODE: { darwin_iodisplaymodeid mode; darwin_ioindex depth; mode = req->req_in[0]; depth = req->req_in[1]; #ifdef DEBUG_DARWIN printf("DARWIN_IOFBSETDISPLAYMODE: mode = %d, " "depth = %d\n", mode, depth); #endif /* Nothing for now */ break; } case DARWIN_IOFBGETCURRENTDISPLAYMODE: { /* Get current display mode and depth. No input args */ #ifdef DEBUG_DARWIN printf("DARWIN_IOFBGETCURRENTDISPLAYMODE\n"); #endif if (maxoutcount < 2) return mach_msg_error(args, EINVAL); rep->rep_outcount = 2; rep->rep_out[0] = 0x2e; /* mode XXX */ rep->rep_out[1] = 0; /* depth (0=>8b 1=>15b 2=>24b) */ break; } case DARWIN_IOFBSETCURSORVISIBLE: { mach_boolean_t visible; visible = req->req_in[0]; #ifdef DEBUG_DARWIN printf("DARWIN_IOFBSETCURSORVISIBLE: visible = %d\n", visible); #endif /* Nothing for now */ break; } case DARWIN_IOFBGETATTRIBUTE: { /* Get attribute value */ char *name; name = (char *)&req->req_in[0]; #ifdef DEBUG_DARWIN printf("DARWIN_IOFBGETATTRIBUTE: name = %s\n", name); #endif /* We only heard about the mrdf attribute. What is it? */ if (memcmp(name, "mrdf", 4) == 0) { if (maxoutcount < 1) return mach_msg_error(args, EINVAL); rep->rep_outcount = 1; rep->rep_out[0] = 0; /* XXX */ } else { #ifdef DEBUG_DARWIN printf("Unknown attribute %c%c%c%c\n", req->req_in[0], req->req_in[1], req->req_in[2], req->req_in[3]); #endif return mach_msg_error(args, EINVAL); } break; } case DARWIN_IOFBGETVRAMMAPOFFSET: { darwin_iopixelaperture aperture; /* 0 XXX Current aperture? */ struct darwin_emuldata *ded = l->l_proc->p_emuldata; aperture = req->req_in[0]; #ifdef DEBUG_DARWIN printf("DARWIN_IOFBGETVRAMMAPOFFSET: aperture = %d\n", aperture); #endif if (maxoutcount < 1) return mach_msg_error(args, EINVAL); rep->rep_outcount = 1; rep->rep_out[0] = (int)ded->ded_vramoffset; break; } default: #ifdef DEBUG_DARWIN printf("Unknown selector %d\n", req->req_selector); #endif return mach_msg_error(args, EINVAL); break; } *msglen = sizeof(*rep) - ((16 - rep->rep_outcount) * sizeof(int)); mach_set_header(rep, req, *msglen); mach_set_trailer(rep, *msglen); return 0; } int darwin_ioframebuffer_connect_method_scalari_structo(args) struct mach_trap_args *args; { mach_io_connect_method_scalari_structo_request_t *req = args->smsg; mach_io_connect_method_scalari_structo_reply_t *rep = args->rmsg; size_t *msglen = args->rsize; int maxoutcount; #ifdef DEBUG_DARWIN printf("darwin_ioframebuffer_connect_method_scalari_structo()\n"); #endif rep->rep_outcount = 0; maxoutcount = req->req_in[req->req_incount]; switch(req->req_selector) { case DARWIN_IOFBGETPIXELINFORMATION: { /* Get bit per pixel, etc... */ darwin_iodisplaymodeid displaymode; darwin_ioindex depth; darwin_iopixelaperture aperture; darwin_iopixelinformation *pixelinfo; displaymode = req->req_in[0]; /* 0x2e */ depth = req->req_in[1]; /* 0 or 1 */ aperture = req->req_in[2]; /* 0 */ #ifdef DEBUG_DARWIN printf("DARWIN_IOFBGETPIXELINFORMATION: displaymode = %d, " "depth = %d, aperture = %d\n", displaymode, depth, aperture); #endif pixelinfo = (darwin_iopixelinformation *)&rep->rep_out[0]; if (maxoutcount < sizeof(*pixelinfo)) return mach_msg_error(args, EINVAL); /* * darwin_iopixelinformation is shorter than the buffer * usually supplied, but Darwin still returns the whole buffer */ rep->rep_outcount = maxoutcount; memset(pixelinfo, 0, maxoutcount * sizeof(int)); switch (depth) { case 0: /* 8 bpp */ pixelinfo->bytesperrow = 0x400; pixelinfo->bytesperplane = 0; pixelinfo->bitsperpixel = 0x8; pixelinfo->pixeltype = DARWIN_IOFB_CLUTPIXELS; pixelinfo->componentcount = 1; pixelinfo->bitspercomponent = 8; pixelinfo->componentmasks[0] = 0x000000ff; memcpy(&pixelinfo->pixelformat, "PPPPPPPP", 8); pixelinfo->flags = 0; pixelinfo->activewidth = 0; pixelinfo->activeheight = 0; break; case 1: /* 15 bpp */ pixelinfo->bytesperrow = 0x800; pixelinfo->bytesperplane = 0; pixelinfo->bitsperpixel = 0x10; pixelinfo->pixeltype = DARWIN_IOFB_RGBDIRECTPIXELS; pixelinfo->componentcount = 3; pixelinfo->bitspercomponent = 5; pixelinfo->componentmasks[0] = 0x00007c00; /* Red */ pixelinfo->componentmasks[1] = 0x000003e0; /* Green */ pixelinfo->componentmasks[2] = 0x0000001f; /* Blue */ memcpy(&pixelinfo->pixelformat, "-RRRRRGGGGGBBBBB", 16); pixelinfo->flags = 0; pixelinfo->activewidth = 0; pixelinfo->activeheight = 0; break; case 2: /* 24 bpp */ pixelinfo->bytesperrow = 0x1000; pixelinfo->bytesperplane = 0; pixelinfo->bitsperpixel = 0x20; pixelinfo->pixeltype = DARWIN_IOFB_RGBDIRECTPIXELS; pixelinfo->componentcount = 3; pixelinfo->bitspercomponent = 8; pixelinfo->componentmasks[0] = 0x00ff0000; /* Red */ pixelinfo->componentmasks[1] = 0x0000ff00; /* Green */ pixelinfo->componentmasks[2] = 0x000000ff; /* Blue */ memcpy(&pixelinfo->pixelformat, "--------RRRRRRRRGGGGGGGGBBBBBBBB", 32); pixelinfo->flags = 0; pixelinfo->activewidth = 0; pixelinfo->activeheight = 0; break; default: printf("unknown depth %d\n", depth); break; } /* Probably useless */ rep->rep_out[158] = 0x4; rep->rep_out[162] = 0x3; break; } default: #ifdef DEBUG_DARWIN printf("Unknown selector %d\n", req->req_selector); #endif return mach_msg_error(args, EINVAL); break; } *msglen = sizeof(*rep) - (4096 - rep->rep_outcount); mach_set_header(rep, req, *msglen); mach_set_trailer(rep, *msglen); return 0; } int darwin_ioframebuffer_connect_method_structi_structo(args) struct mach_trap_args *args; { mach_io_connect_method_structi_structo_request_t *req = args->smsg; mach_io_connect_method_structi_structo_reply_t *rep = args->rmsg; size_t *msglen = args->rsize; int maxoutcount; #ifdef DEBUG_DARWIN printf("darwin_ioframebuffer_connect_method_structi_structo()\n"); #endif rep->rep_outcount = 0; /* maxoutcount is word aligned */ maxoutcount = req->req_in[(req->req_incount & ~0x3UL) + 4]; switch(req->req_selector) { case DARWIN_IOFBSETBOUNDS: { darwin_iogbounds *bounds; bounds = (darwin_iogbounds *)&req->req_in[0]; #ifdef DEBUG_DARWIN printf("DARWIN_IOFBSETBOUNDS: bounds (%d, %d) - (%d, %d)\n", bounds->minx, bounds->miny, bounds->maxx, bounds->maxy); #endif /* Nothing yet */ break; } default: #ifdef DEBUG_DARWIN printf("Unknown selector %d\n", req->req_selector); #endif return mach_msg_error(args, EINVAL); break; } *msglen = sizeof(*rep) - (4096 - rep->rep_outcount); mach_set_header(rep, req, *msglen); mach_set_trailer(rep, *msglen); return 0; } int darwin_ioframebuffer_connect_map_memory(args) struct mach_trap_args *args; { mach_io_connect_map_memory_request_t *req = args->smsg; mach_io_connect_map_memory_reply_t *rep = args->rmsg; size_t *msglen = args->rsize; struct proc *p = args->l->l_proc; int error = 0; size_t memsize; size_t len; vaddr_t pvaddr; #ifdef DEBUG_DARWIN printf("darwin_ioframebuffer_connect_map_memory()\n"); #endif switch (req->req_memtype) { case DARWIN_IOFRAMEBUFFER_CURSOR_MEMORY: if (darwin_ioframebuffer_shmem == NULL) return mach_msg_error(args, error); len = sizeof(struct darwin_ioframebuffer_shmem); memsize = round_page(len); uao_reference(darwin_ioframebuffer_shmem); pvaddr = VM_DEFAULT_ADDRESS(p->p_vmspace->vm_daddr, memsize); if ((error = uvm_map(&p->p_vmspace->vm_map, &pvaddr, memsize, darwin_ioframebuffer_shmem, 0, PAGE_SIZE, UVM_MAPFLAG(UVM_PROT_RW, UVM_PROT_RW, UVM_INH_SHARE, UVM_ADV_RANDOM, 0))) != 0) return mach_msg_error(args, error); #ifdef DEBUG_DARWIN printf("pvaddr = 0x%08lx\n", (long)pvaddr); #endif break; case DARWIN_IOFRAMEBUFFER_VRAM_MEMORY: case DARWIN_IOFRAMEBUFFER_SYSTEM_APERTURE: { dev_t device; const struct cdevsw *wsdisplay; int unit; int mode, screen; struct wsdisplay_fbinfo fbi; struct darwin_emuldata *ded; struct vnode *vp; /* * Use unit given by sysctl emul.darwin.ioframebuffer.unit * and emul.darwin.ioframebuffer.screen */ unit = darwin_ioframebuffer_unit; screen = darwin_ioframebuffer_screen; if ((error = darwin_findscreen(&device, unit, screen)) != 0) return mach_msg_error(args, error); if ((wsdisplay = cdevsw_lookup(device)) == NULL) return mach_msg_error(args, ENXIO); /* Find the framebuffer's size */ if ((error = (wsdisplay->d_ioctl)(device, WSDISPLAYIO_GINFO, (caddr_t)&fbi, 0, p)) != 0) { #ifdef DEBUG_DARWIN printf("*** Cannot get screen params ***\n"); #endif return mach_msg_error(args, error); } #ifdef DEBUG_DARWIN printf("framebuffer: %d x %d x %d\n", fbi.width, fbi.height, fbi.depth); #endif len = round_page(fbi.height * fbi.width * fbi.depth / 8); /* * The framebuffer cannot be mapped if the console is * not in graphic mode. We will do the switch, but it * screws the console. Therefore we attempt to restore * its original state on process exit. ded->ded_wsdev * is used to remember the console device. If it is not * NODEV on process exit, we use it to restore text mode. */ ded = (struct darwin_emuldata *)p->p_emuldata; if ((error = (wsdisplay->d_ioctl)(device, WSDISPLAYIO_GMODE, (caddr_t)&mode, 0, p)) != 0) { #ifdef DEBUG_DARWIN printf("*** Cannot get console state ***\n"); #endif return mach_msg_error(args, ENODEV); } if (mode == WSDISPLAYIO_MODE_EMUL) ded->ded_wsdev = device; /* Switch to graphic mode */ mode = WSDISPLAYIO_MODE_MAPPED; if ((error = (wsdisplay->d_ioctl)(device, WSDISPLAYIO_SMODE, (caddr_t)&mode, 0, p)) != 0) { #ifdef DEBUG_DARWIN printf("*** Cannot switch to graphic mode ***\n"); #endif return mach_msg_error(args, ENODEV); } if ((error = cdevvp(device, &vp)) != 0) { #ifdef DEBUG_DARWIN printf("*** cdevvp failed ***\n"); #endif return mach_msg_error(args, error); } pvaddr = 0; if ((error = uvm_mmap(&p->p_vmspace->vm_map, &pvaddr, len, UVM_PROT_RW, UVM_PROT_RW, MAP_SHARED, vp, 0, p->p_rlimit[RLIMIT_MEMLOCK].rlim_cur)) != 0) { #ifdef DEBUG_DARWIN printf("*** uvm_mmap failed ***\n"); #endif return mach_msg_error(args, error); } #ifdef DEBUG_DARWIN printf("mapped framebuffer at %p\n", (void *)pvaddr); #endif break; } default: #ifdef DEBUG_DARWIN printf("unimplemented memtype %d\n", req->req_memtype); #endif return mach_msg_error(args, EINVAL); break; } *msglen = sizeof(*rep); mach_set_header(rep, req, *msglen); rep->rep_retval = 0; rep->rep_addr = pvaddr; rep->rep_len = len; mach_set_trailer(rep, *msglen); /* Track VRAM offset for connect_method IOFBGETVRAMMAPOFFSET */ if (req->req_memtype == DARWIN_IOFRAMEBUFFER_VRAM_MEMORY) { struct darwin_emuldata *ded; ded = p->p_emuldata; /* * This seems to be the offset of the framebuffer * within the VRAM. For now 0, as we are only * able to map the framebuffer. */ ded->ded_vramoffset = (void *)(pvaddr - pvaddr); } return 0; } void darwin_ioframebuffer_shmeminit(kvaddr) vaddr_t kvaddr; { struct darwin_ioframebuffer_shmem *shmem; shmem = (struct darwin_ioframebuffer_shmem *)kvaddr; return; } int darwin_ioframebuffer_connect_method_scalari_structi(args) struct mach_trap_args *args; { mach_io_connect_method_scalari_structi_request_t *req = args->smsg; mach_io_connect_method_scalari_structi_reply_t *rep = args->rmsg; size_t *msglen = args->rsize; struct proc *p = args->l->l_proc; int scalar_len; int struct_len; char *struct_data; #ifdef DEBUG_DARWIN printf("darwin_ioframebuffer_connect_method_scalari_structi()\n"); #endif scalar_len = req->req_incount; struct_len = req->req_in[scalar_len]; struct_data = (char *)&req->req_in[scalar_len + 1]; switch (req->req_selector) { case DARWIN_IOFBSETCOLORCONVERTTABLE: { int select; int *data; size_t tablelen; select = req->req_in[0]; tablelen = struct_len / sizeof(*data); #ifdef DEBUG_DARWIN printf("DARWIN_IOFBSETCOLORCONVERTTABLE: select = %d, " "tablelen = %d\n", select, tablelen); #endif if (tablelen == 0) break; data = (int *)struct_data; break; } case DARWIN_IOFBSETGAMMATABLE: { int entries; int count; int width; int *data; entries = req->req_in[0]; count = req->req_in[1]; width = req->req_in[2]; #ifdef DEBUG_DARWIN printf("DARWIN_IOFBSETGAMMATABLE: entries = %d, " "count = %d, width = %d\n", entries, count, width); #endif data = &req->req_in[3]; break; } case DARWIN_IOFBSETCLUTWITHENTRIES: { int index; int option; struct darwin_iocolorentry *clut; size_t clutlen; size_t tablen; size_t kcolorsz; caddr_t sg = stackgap_init(p, 0); int error; struct wsdisplay_cmap cmap; u_char *red; u_char *green; u_char *blue; u_char kred[256]; u_char kgreen[256]; u_char kblue[256]; int unit, screen; dev_t dev; const struct cdevsw *wsdisplay; int i; index = req->req_in[0]; option = req->req_in[1]; clutlen = struct_len / sizeof(*clut); clut = (struct darwin_iocolorentry *)struct_data; if ((clutlen == 0) || (index >= 256)) break; #ifdef DEBUG_DARWIN printf("DARWIN_IOFBSETCLUTWITHENTRIES: index = %d, " "option = %d, clutlen = %d\n", index, option, clutlen); #endif /* * Find wsdisplay. Use the screen given by sysctl * emul.darwin.ioframebuffer.screen */ unit = darwin_ioframebuffer_unit; screen = darwin_ioframebuffer_screen; if ((error = darwin_findscreen(&dev, unit, screen)) != 0) return mach_msg_error(args, error); if ((wsdisplay = cdevsw_lookup(dev)) == NULL) return mach_msg_error(args, ENXIO); /* * We only support 256 entries */ if (index + clutlen > 256) clutlen = 256 - index; /* * Big tables will not fit in the stackgap. * We have to split the data. */ if (clutlen <= 128) tablen = clutlen; else tablen = 128; kcolorsz = sizeof(u_char) * tablen; red = stackgap_alloc(p, &sg, kcolorsz); green = stackgap_alloc(p, &sg, kcolorsz); blue = stackgap_alloc(p, &sg, kcolorsz); do { for (i = 0; i < tablen; i++) { kred[i] = (u_char)(clut->red >> 8); kgreen[i] = (u_char)(clut->green >> 8); kblue[i] = (u_char)(clut->blue >> 8); clut++; } cmap.index = index; cmap.count = tablen; cmap.red = red; cmap.green = green; cmap.blue = blue; if (((error = copyout(kred, red, kcolorsz)) != 0) || ((error = copyout(kgreen, green, kcolorsz)) != 0) || ((error = copyout(kblue, blue, kcolorsz)) != 0)) return mach_msg_error(args, error); if ((error = (wsdisplay->d_ioctl)(dev, WSDISPLAYIO_PUTCMAP, (caddr_t)&cmap, 0, p)) != 0) return mach_msg_error(args, error); index += tablen; clutlen -= tablen; if (clutlen <= 128) tablen = clutlen; } while (clutlen > 0); break; } default: #ifdef DEBUG_DARWIN printf("Unknown selector %d\n", req->req_selector); #endif return mach_msg_error(args, EINVAL); break; } *msglen = sizeof(*rep); mach_set_header(rep, req, *msglen); rep->rep_retval = 0; mach_set_trailer(rep, *msglen); return 0; } /* Find a wsdisplay from unit and screen */ static int darwin_findscreen(dev, unit, screen) dev_t *dev; int unit, screen; { struct device *dv; struct wsdisplay_softc *sc; int major, minor; /* Find a wsdisplay */ TAILQ_FOREACH(dv, &alldevs, dv_list) if ((dv->dv_cfdriver == &wsdisplay_cd) && (dv->dv_unit == unit)) break; if (dv == NULL) return ENODEV; sc = (struct wsdisplay_softc *)dv; /* Derive the device number */ major = cdevsw_lookup_major(&wsdisplay_cdevsw); minor = WSDISPLAYMINOR(dv->dv_unit, screen); *dev = makedev(major, minor); #ifdef DEBUG_DARWIN printf("ioframebuffer uses major = %d, minor = %d\n", major, minor); #endif return 0; }