1 /* $NetBSD: genfb_grfbus.c,v 1.3 2024/12/09 10:32:53 nat Exp $ */ 2 3 /* NetBSD: simplefb.c,v 1.7 2019/01/30 00:55:04 jmcneill Exp */ 4 /*- 5 * Copyright (c) 2017 Jared McNeill <jmcneill (at) invisible.ca> 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 22 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 23 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 24 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 25 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 */ 29 30 /* NetBSD: macfb.c,v 1.20 2012/10/27 17:17:59 chs Exp */ 31 /* 32 * Copyright (c) 1998 Matt DeBergalis 33 * All rights reserved. 34 * 35 * Redistribution and use in source and binary forms, with or without 36 * modification, are permitted provided that the following conditions 37 * are met: 38 * 1. Redistributions of source code must retain the above copyright 39 * notice, this list of conditions and the following disclaimer. 40 * 2. Redistributions in binary form must reproduce the above copyright 41 * notice, this list of conditions and the following disclaimer in the 42 * documentation and/or other materials provided with the distribution. 43 * 3. All advertising materials mentioning features or use of this software 44 * must display the following acknowledgement: 45 * This product includes software developed by Matt DeBergalis 46 * 4. The name of the author may not be used to endorse or promote products 47 * derived from this software without specific prior written permission 48 * 49 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 50 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 51 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 52 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 53 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 54 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 55 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 56 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 57 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 58 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 59 */ 60 61 #include "opt_wsdisplay_compat.h" 62 63 #include <sys/cdefs.h> 64 __KERNEL_RCSID(0, "$NetBSD: genfb_grfbus.c,v 1.3 2024/12/09 10:32:53 nat Exp $"); 65 66 #include <sys/param.h> 67 #include <sys/bus.h> 68 #include <sys/device.h> 69 #include <sys/systm.h> 70 71 #include <machine/cpu.h> 72 #include <machine/bus.h> 73 74 #include <machine/video.h> 75 #include <machine/grfioctl.h> 76 #include <mac68k/nubus/nubus.h> 77 #include <mac68k/dev/grfvar.h> 78 79 #include <dev/wsfb/genfbvar.h> 80 81 struct genfb_grfbus_softc { 82 struct genfb_softc sc_gen; 83 84 uint32_t sc_width; 85 uint32_t sc_height; 86 uint8_t sc_depth; 87 uint16_t sc_stride; 88 89 paddr_t sc_paddr; 90 vaddr_t sc_vaddr; 91 92 void (*sc_set_mapreg)(void *, int, int, int, int); 93 struct grfbus_softc *sc_parent; 94 }; 95 96 static int genfb_grfbus_ioctl(void *, void *, u_long, void *, int, lwp_t *); 97 static paddr_t genfb_grfbus_mmap(void *, void *, off_t, int); 98 99 static struct genfb_ops gfb_ops = { 100 .genfb_ioctl = genfb_grfbus_ioctl, 101 .genfb_mmap = genfb_grfbus_mmap, 102 }; 103 104 static struct genfb_colormap_callback gfb_cmcb; 105 106 static int __unused 107 genfb_grfbus_is_console(paddr_t addr) 108 { 109 110 if (addr != mac68k_video.mv_phys && 111 (addr >= 0xf9000000 && addr <= 0xfeffffff)) { 112 /* 113 * This is in the NuBus standard slot space range, so we 114 * may well have to look at 0xFssxxxxx, too. Mask off the 115 * slot number and duplicate it in bits 20-23, per IM:V 116 * pp 459, 463, and IM:VI ch 30 p 17. 117 * Note: this is an ugly hack and I wish I knew what 118 * to do about it. -- sr 119 */ 120 addr = (paddr_t)(((u_long)addr & 0xff0fffff) | 121 (((u_long)addr & 0x0f000000) >> 4)); 122 } 123 return ((mac68k_machine.serial_console & 0x03) == 0 124 && (addr == mac68k_video.mv_phys)); 125 } 126 127 static int 128 genfb_grfbus_ioctl(void *v, void *vs, u_long cmd, void *data, int flag, lwp_t *l) 129 { 130 struct genfb_grfbus_softc * const sc = v; 131 #if 0 132 struct wsdisplayio_bus_id *busid; 133 #endif 134 struct wsdisplayio_fbinfo *fbi; 135 struct rasops_info *ri; 136 int error; 137 u_int video; 138 139 switch (cmd) { 140 case WSDISPLAYIO_GTYPE: 141 *(u_int *)data = WSDISPLAY_TYPE_GENFB; 142 return 0; 143 #if 0 144 case WSDISPLAYIO_GET_BUSID: 145 busid = data; 146 busid->bus_type = WSDISPLAYIO_BUS_GRFBUS; 147 return 0; 148 #endif 149 case WSDISPLAYIO_GET_FBINFO: 150 fbi = data; 151 ri = &sc->sc_gen.vd.active->scr_ri; 152 error = wsdisplayio_get_fbinfo(ri, fbi); 153 if (error == 0) { 154 /* 155 * XXX 156 * if the fb isn't page aligned, tell wsfb to skip the 157 * unaligned part 158 */ 159 fbi->fbi_fboffset = m68k_page_offset(sc->sc_paddr); 160 } 161 return error; 162 case WSDISPLAYIO_SVIDEO: 163 video = *(u_int *)data; 164 if (video == WSDISPLAYIO_VIDEO_OFF) 165 pmf_event_inject(NULL, PMFE_DISPLAY_OFF); 166 else if (video == WSDISPLAYIO_VIDEO_ON) 167 pmf_event_inject(NULL, PMFE_DISPLAY_ON); 168 else 169 return EINVAL; 170 return 0; 171 default: 172 return EPASSTHROUGH; 173 } 174 } 175 176 static paddr_t 177 genfb_grfbus_mmap(void *v, void *vs, off_t off, int prot) 178 { 179 struct genfb_grfbus_softc * const sc = v; 180 181 if (off < 0 || off >= m68k_page_offset(sc->sc_paddr) + 182 sc->sc_gen.sc_fbsize) 183 return -1; 184 185 return m68k_btop(m68k_trunc_page(sc->sc_paddr) + off); 186 } 187 188 static int 189 genfb_grfbus_attach_genfb(struct genfb_grfbus_softc *sc) 190 { 191 device_t dev = sc->sc_gen.sc_dev; 192 prop_dictionary_t dict = device_properties(dev); 193 bool is_console; 194 195 prop_dictionary_set_uint32(dict, "width", sc->sc_width); 196 prop_dictionary_set_uint32(dict, "height", sc->sc_height); 197 prop_dictionary_set_uint8(dict, "depth", sc->sc_depth); 198 prop_dictionary_set_uint16(dict, "linebytes", sc->sc_stride); 199 200 prop_dictionary_set_uint32(dict, "address", sc->sc_paddr); 201 prop_dictionary_set_uint64(dict, "virtual_address", sc->sc_vaddr); 202 203 if (sc->sc_set_mapreg != NULL) { 204 gfb_cmcb.gcc_cookie = sc->sc_parent; 205 gfb_cmcb.gcc_set_mapreg = sc->sc_set_mapreg; 206 prop_dictionary_set_uint64(dict, "cmap_callback", 207 (uint64_t)(uintptr_t)&gfb_cmcb); 208 } 209 210 genfb_init(&sc->sc_gen); 211 212 if (sc->sc_gen.sc_width == 0 || sc->sc_gen.sc_fbsize == 0) { 213 aprint_normal(": disabled\n"); 214 return ENXIO; 215 } 216 217 aprint_naive("\n"); 218 aprint_normal(": colormap callback %sprovided\n", 219 sc->sc_set_mapreg != NULL ? "" : "not "); 220 221 is_console = genfb_grfbus_is_console(sc->sc_paddr); 222 if (is_console) 223 aprint_normal_dev(sc->sc_gen.sc_dev, 224 "switching to framebuffer console\n"); 225 prop_dictionary_set_bool(dict, "is_console", is_console); 226 227 genfb_attach(&sc->sc_gen, &gfb_ops); 228 229 return 0; 230 } 231 232 static int 233 genfb_grfbus_match(device_t parent, cfdata_t cf, void *aux) 234 { 235 236 return 1; 237 } 238 239 static void 240 genfb_grfbus_attach(device_t parent, device_t self, void *aux) 241 { 242 struct genfb_grfbus_softc * const sc = device_private(self); 243 struct grfbus_attach_args *ga = aux; 244 struct grfmode *gm = ga->ga_grfmode; 245 246 sc->sc_gen.sc_dev = self; 247 248 sc->sc_width = gm->width; 249 sc->sc_height = gm->height; 250 251 /* 252 * XXX: tested on Quadra 840AV 253 */ 254 sc->sc_depth = gm->psize == 16 ? 15 : gm->psize; 255 256 sc->sc_stride = gm->rowbytes; 257 sc->sc_paddr = ga->ga_phys + gm->fboff; 258 sc->sc_vaddr = (vaddr_t)gm->fbbase + gm->fboff; 259 sc->sc_set_mapreg = ga->ga_set_mapreg; 260 sc->sc_parent = ga->ga_parent; 261 262 genfb_grfbus_attach_genfb(sc); 263 } 264 265 CFATTACH_DECL_NEW(genfb_grfbus, sizeof(struct genfb_grfbus_softc), 266 genfb_grfbus_match, genfb_grfbus_attach, NULL, NULL); 267