1 /* $NetBSD: grf_compat.c,v 1.7 2001/04/30 17:12:03 wiz Exp $ */ 2 3 /* 4 * Copyright (C) 1999 Scott Reynolds 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. The name of the author may not be used to endorse or promote products 16 * derived from this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 */ 29 30 /* 31 * macfb compatibility with legacy grf devices 32 */ 33 34 #include <sys/param.h> 35 #include <sys/systm.h> 36 #include <sys/cdefs.h> 37 #include <sys/conf.h> 38 #include <sys/device.h> 39 #include <sys/errno.h> 40 #include <sys/ioctl.h> 41 #include <sys/malloc.h> 42 #include <sys/mman.h> 43 #include <sys/proc.h> 44 #include <sys/resourcevar.h> 45 #include <sys/vnode.h> 46 47 #include <machine/autoconf.h> 48 #include <machine/bus.h> 49 #include <machine/grfioctl.h> 50 51 #include <mac68k/nubus/nubus.h> 52 #include <mac68k/dev/grfvar.h> 53 #include <mac68k/dev/macfbvar.h> 54 55 #include <miscfs/specfs/specdev.h> 56 57 #include <uvm/uvm_extern.h> 58 #include <uvm/uvm_map.h> 59 60 cdev_decl(grf); 61 62 void grf_scinit __P((struct grf_softc *, const char *, int)); 63 void grf_init __P((int)); 64 void grfattach __P((int)); 65 int grfmap __P((dev_t, struct macfb_softc *, caddr_t *, struct proc *)); 66 int grfunmap __P((dev_t, struct macfb_softc *, caddr_t, struct proc *)); 67 68 /* Non-private for the benefit of libkvm. */ 69 struct grf_softc *grf_softc; 70 int numgrf = 0; 71 72 /* 73 * Initialize a softc to sane defaults. 74 */ 75 void 76 grf_scinit(sc, name, unit) 77 struct grf_softc *sc; 78 const char *name; 79 int unit; 80 { 81 memset(sc, 0, sizeof(struct grf_softc)); 82 snprintf(sc->sc_xname, sizeof(sc->sc_xname), "%s%d", name, unit); 83 sc->mfb_sc = NULL; 84 } 85 86 /* 87 * (Re-)initialize the grf_softc block so that at least the requested 88 * number of elements has been allocated. If this results in more 89 * elements than we had prior to getting here, we initialize each of 90 * them to avoid problems down the road. 91 */ 92 void 93 grf_init(n) 94 int n; 95 { 96 struct grf_softc *sc; 97 int i; 98 99 if (n >= numgrf) { 100 i = numgrf; 101 numgrf = n + 1; 102 103 if (grf_softc == NULL) 104 sc = (struct grf_softc *) 105 malloc(numgrf * sizeof(*sc), 106 M_DEVBUF, M_NOWAIT); 107 else 108 sc = (struct grf_softc *) 109 realloc(grf_softc, numgrf * sizeof(*sc), 110 M_DEVBUF, M_NOWAIT); 111 if (sc == NULL) { 112 printf("WARNING: no memory for grf emulation\n"); 113 if (grf_softc != NULL) 114 free(grf_softc, M_DEVBUF); 115 return; 116 } 117 grf_softc = sc; 118 119 /* Initialize per-softc structures. */ 120 while (i < numgrf) { 121 grf_scinit(&grf_softc[i], "grf", i); 122 i++; 123 } 124 } 125 } 126 127 /* 128 * Called by main() during pseudo-device attachment. If we had a 129 * way to configure additional grf devices later, this would actually 130 * allocate enough space for them. As it stands, it's nonsensical, 131 * so other than a basic sanity check we do nothing. 132 */ 133 void 134 grfattach(n) 135 int n; 136 { 137 if (n <= 0) { 138 #ifdef DIAGNOSTIC 139 panic("grfattach: count <= 0"); 140 #endif 141 return; 142 } 143 144 #if 0 /* XXX someday, if we implement a way to attach after autoconfig */ 145 grf_init(n); 146 #endif 147 } 148 149 /* 150 * Called from macfb_attach() after setting up the frame buffer. Since 151 * there is a 1:1 correspondence between the macfb device and the grf 152 * device, the only bit of information we really need is the macfb_softc. 153 */ 154 void 155 grf_attach(sc, unit) 156 struct macfb_softc *sc; 157 int unit; 158 { 159 grf_init(unit); 160 161 if (unit < numgrf) 162 grf_softc[unit].mfb_sc = sc; 163 } 164 165 /* 166 * Standard device ops 167 */ 168 int 169 grfopen(dev, flag, mode, p) 170 dev_t dev; 171 int flag; 172 int mode; 173 struct proc *p; 174 { 175 struct grf_softc *sc; 176 int unit = GRFUNIT(dev); 177 int rv = 0; 178 179 if (grf_softc == NULL || unit >= numgrf) 180 return ENXIO; 181 182 sc = &grf_softc[unit]; 183 if (sc->mfb_sc == NULL) 184 rv = ENXIO; 185 186 return rv; 187 } 188 189 int 190 grfclose(dev, flag, mode, p) 191 dev_t dev; 192 int flag; 193 int mode; 194 struct proc *p; 195 { 196 struct grf_softc *sc; 197 int unit = GRFUNIT(dev); 198 int rv = 0; 199 200 if (grf_softc == NULL || unit >= numgrf) 201 return ENXIO; 202 203 sc = &grf_softc[unit]; 204 if (sc->mfb_sc != NULL) 205 macfb_clear(sc->mfb_sc->sc_dc); /* clear the display */ 206 else 207 rv = ENXIO; 208 209 return rv; 210 } 211 212 int 213 grfread(dev, uio, ioflag) 214 dev_t dev; 215 struct uio *uio; 216 int ioflag; 217 { 218 return ENXIO; 219 } 220 221 int 222 grfwrite(dev, uio, ioflag) 223 dev_t dev; 224 struct uio *uio; 225 int ioflag; 226 { 227 return ENXIO; 228 } 229 230 int 231 grfioctl(dev, cmd, data, flag, p) 232 dev_t dev; 233 u_long cmd; 234 caddr_t data; 235 int flag; 236 struct proc *p; 237 { 238 struct grf_softc *sc; 239 struct macfb_devconfig *dc; 240 #if defined(GRF_COMPAT) || (NGRF > 0) 241 struct grfinfo *gd; 242 #endif /* GRF_COMPAT || (NGRF > 0) */ 243 struct grfmode *gm; 244 int unit = GRFUNIT(dev); 245 int rv; 246 247 if (grf_softc == NULL || unit >= numgrf) 248 return ENXIO; 249 250 sc = &grf_softc[unit]; 251 if (sc->mfb_sc == NULL) 252 return ENXIO; 253 254 dc = sc->mfb_sc->sc_dc; 255 256 switch (cmd) { 257 #if defined(GRF_COMPAT) || (NGRF > 0) 258 case GRFIOCGINFO: 259 gd = (struct grfinfo *)data; 260 memset(gd, 0, sizeof(struct grfinfo)); 261 gd->gd_fbaddr = (caddr_t)dc->dc_paddr; 262 gd->gd_fbsize = dc->dc_size; 263 gd->gd_colors = (short)(1 << dc->dc_depth); 264 gd->gd_planes = (short)dc->dc_depth; 265 gd->gd_fbwidth = dc->dc_wid; 266 gd->gd_fbheight = dc->dc_ht; 267 gd->gd_fbrowbytes = dc->dc_rowbytes; 268 gd->gd_dwidth = dc->dc_raster.width; 269 gd->gd_dheight = dc->dc_raster.height; 270 rv = 0; 271 break; 272 #endif /* GRF_COMPAT || (NGRF > 0) */ 273 274 case GRFIOCON: 275 case GRFIOCOFF: 276 /* Nothing to do */ 277 rv = 0; 278 break; 279 280 #if defined(GRF_COMPAT) || (NGRF > 0) 281 case GRFIOCMAP: 282 rv = grfmap(dev, sc->mfb_sc, (caddr_t *)data, p); 283 break; 284 285 case GRFIOCUNMAP: 286 rv = grfunmap(dev, sc->mfb_sc, *(caddr_t *)data, p); 287 break; 288 #endif /* GRF_COMPAT || (NGRF > 0) */ 289 290 case GRFIOCGMODE: 291 gm = (struct grfmode *)data; 292 memset(gm, 0, sizeof(struct grfmode)); 293 gm->fbbase = (char *)dc->dc_vaddr; 294 gm->fbsize = dc->dc_size; 295 gm->fboff = dc->dc_offset; 296 gm->rowbytes = dc->dc_rowbytes; 297 gm->width = dc->dc_wid; 298 gm->height = dc->dc_ht; 299 gm->psize = dc->dc_depth; 300 rv = 0; 301 break; 302 303 case GRFIOCLISTMODES: 304 case GRFIOCGETMODE: 305 case GRFIOCSETMODE: 306 /* NONE of these operations are (officially) supported. */ 307 default: 308 rv = EINVAL; 309 break; 310 } 311 return rv; 312 } 313 314 int 315 grfpoll(dev, events, p) 316 dev_t dev; 317 int events; 318 struct proc *p; 319 { 320 return EINVAL; 321 } 322 323 paddr_t 324 grfmmap(dev, off, prot) 325 dev_t dev; 326 off_t off; 327 int prot; 328 { 329 struct grf_softc *sc; 330 struct macfb_devconfig *dc; 331 paddr_t addr; 332 int unit = GRFUNIT(dev); 333 334 if (grf_softc == NULL || unit >= numgrf) 335 return ENXIO; 336 337 sc = &grf_softc[unit]; 338 if (sc->mfb_sc == NULL) 339 return ENXIO; 340 341 dc = sc->mfb_sc->sc_dc; 342 343 if (off >= 0 && 344 off < m68k_round_page(dc->dc_offset + dc->dc_size)) 345 addr = m68k_btop(dc->dc_paddr + off); 346 else 347 addr = (-1); /* XXX bogus */ 348 349 return addr; 350 } 351 352 int 353 grfmap(dev, sc, addrp, p) 354 dev_t dev; 355 struct macfb_softc *sc; 356 caddr_t *addrp; 357 struct proc *p; 358 { 359 struct specinfo si; 360 struct vnode vn; 361 u_long len; 362 int error, flags; 363 364 *addrp = (caddr_t)sc->sc_dc->dc_paddr; 365 len = m68k_round_page(sc->sc_dc->dc_offset + sc->sc_dc->dc_size); 366 flags = MAP_SHARED | MAP_FIXED; 367 368 vn.v_type = VCHR; /* XXX */ 369 vn.v_specinfo = &si; /* XXX */ 370 vn.v_rdev = dev; /* XXX */ 371 372 error = uvm_mmap(&p->p_vmspace->vm_map, (vaddr_t *)addrp, 373 (vsize_t)len, VM_PROT_ALL, VM_PROT_ALL, 374 flags, (caddr_t)&vn, 0, p->p_rlimit[RLIMIT_MEMLOCK].rlim_cur); 375 376 /* Offset into page: */ 377 *addrp += sc->sc_dc->dc_offset; 378 379 return (error); 380 } 381 382 int 383 grfunmap(dev, sc, addr, p) 384 dev_t dev; 385 struct macfb_softc *sc; 386 caddr_t addr; 387 struct proc *p; 388 { 389 vm_size_t size; 390 391 addr -= sc->sc_dc->dc_offset; 392 393 if (addr <= 0) 394 return (-1); 395 396 size = m68k_round_page(sc->sc_dc->dc_offset + sc->sc_dc->dc_size); 397 uvm_unmap(&p->p_vmspace->vm_map, (vaddr_t)addr, (vaddr_t)addr + size); 398 return 0; 399 } 400