1 /* $OpenBSD: vgafb.c,v 1.41 2012/08/30 21:54:13 mpi Exp $ */ 2 /* $NetBSD: vga.c,v 1.3 1996/12/02 22:24:54 cgd Exp $ */ 3 4 /* 5 * Copyright (c) 1995, 1996 Carnegie-Mellon University. 6 * All rights reserved. 7 * 8 * Author: Chris G. Demetriou 9 * 10 * Permission to use, copy, modify and distribute this software and 11 * its documentation is hereby granted, provided that both the copyright 12 * notice and this permission notice appear in all copies of the 13 * software, derivative works or modified versions, and any portions 14 * thereof, and that both notices appear in supporting documentation. 15 * 16 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" 17 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND 18 * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. 19 * 20 * Carnegie Mellon requests users of this software to return to 21 * 22 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU 23 * School of Computer Science 24 * Carnegie Mellon University 25 * Pittsburgh PA 15213-3890 26 * 27 * any improvements or extensions that they make and grant Carnegie the 28 * rights to redistribute these changes. 29 */ 30 31 #include <sys/param.h> 32 #include <sys/systm.h> 33 #include <sys/kernel.h> 34 #include <sys/device.h> 35 #include <sys/buf.h> 36 37 #include <uvm/uvm_extern.h> 38 39 #include <machine/bus.h> 40 41 #include <dev/cons.h> 42 #include <dev/ofw/openfirm.h> 43 #include <macppc/macppc/ofw_machdep.h> 44 45 #include <dev/wscons/wsconsio.h> 46 #include <dev/wscons/wsdisplayvar.h> 47 #include <dev/rasops/rasops.h> 48 #include <dev/wsfont/wsfont.h> 49 50 #include <macppc/pci/vgafbvar.h> 51 52 struct cfdriver vgafb_cd = { 53 NULL, "vgafb", DV_DULL, 54 }; 55 56 void vgafb_setcolor(struct vga_config *vc, unsigned int index, 57 u_int8_t r, u_int8_t g, u_int8_t b); 58 void vgafb_restore_default_colors(struct vga_config *vc); 59 60 struct vgafb_devconfig { 61 struct rasops_info dc_rinfo; /* raster display data */ 62 int dc_blanked; /* currently had video disabled */ 63 }; 64 65 extern struct vga_config vgafb_pci_console_vc; 66 struct vgafb_devconfig vgafb_console_dc; 67 68 struct wsscreen_descr vgafb_stdscreen = { 69 "std", 70 0, 0, /* will be filled in -- XXX shouldn't, it's global */ 71 0, 72 0, 0, 73 WSSCREEN_UNDERLINE | WSSCREEN_HILIT | 74 WSSCREEN_REVERSE | WSSCREEN_WSCOLORS 75 }; 76 const struct wsscreen_descr *vgafb_scrlist[] = { 77 &vgafb_stdscreen, 78 /* XXX other formats, graphics screen? */ 79 }; 80 81 struct wsscreen_list vgafb_screenlist = { 82 sizeof(vgafb_scrlist) / sizeof(struct wsscreen_descr *), vgafb_scrlist 83 }; 84 85 struct wsdisplay_accessops vgafb_accessops = { 86 vgafb_ioctl, 87 vgafb_mmap, 88 vgafb_alloc_screen, 89 vgafb_free_screen, 90 vgafb_show_screen, 91 NULL, /* load_font */ 92 NULL, /* scrollback */ 93 NULL, /* getchar */ 94 vgafb_burn, /* burner */ 95 }; 96 97 int vgafb_getcmap(struct vga_config *vc, struct wsdisplay_cmap *cm); 98 int vgafb_putcmap(struct vga_config *vc, struct wsdisplay_cmap *cm); 99 100 #define FONT_WIDTH 8 101 #define FONT_HEIGHT 16 102 103 #ifdef APERTURE 104 extern int allowaperture; 105 #endif 106 107 108 void 109 vgafb_init(bus_space_tag_t iot, bus_space_tag_t memt, struct vga_config *vc, 110 u_int32_t membase, size_t memsize, u_int32_t mmiobase, size_t mmiosize) 111 { 112 vc->vc_iot = iot; 113 vc->vc_memt = memt; 114 vc->vc_paddr = membase; 115 116 if (mmiosize != 0) 117 if (bus_space_map(vc->vc_memt, mmiobase, mmiosize, 0, 118 &vc->vc_mmioh)) 119 panic("vgafb_init: couldn't map mmio"); 120 121 /* memsize should only be visible region for console */ 122 memsize = cons_height * cons_linebytes; 123 if (bus_space_map(vc->vc_memt, membase, memsize, 124 /* XXX */ppc_proc_is_64b ? 0 : 1, &vc->vc_memh)) 125 panic("vgafb_init: can't map mem space"); 126 127 vc->vc_crow = vc->vc_ccol = 0; /* Has to be some onscreen value */ 128 vc->vc_so = 0; 129 130 /* clear screen, frob cursor, etc.? */ 131 /* 132 */ 133 134 vc->vc_at = 0x00 | 0xf; /* black bg|white fg */ 135 vc->vc_so_at = 0x00 | 0xf | 0x80; /* black bg|white fg|blink */ 136 137 if (cons_depth == 8) { 138 vgafb_restore_default_colors(vc); 139 } 140 } 141 142 void 143 vgafb_restore_default_colors(struct vga_config *vc) 144 { 145 int i; 146 147 for (i = 0; i < 256; i++) { 148 const u_char *color; 149 150 color = &rasops_cmap[i * 3]; 151 vgafb_setcolor(vc, i, color[0], color[1], color[2]); 152 } 153 } 154 155 void 156 vgafb_wsdisplay_attach(struct device *parent, struct vga_config *vc, 157 int console) 158 { 159 struct wsemuldisplaydev_attach_args aa; 160 161 aa.console = console; 162 aa.scrdata = &vgafb_screenlist; 163 aa.accessops = &vgafb_accessops; 164 aa.accesscookie = vc; 165 aa.defaultscreens = 0; 166 167 /* no need to keep the burner function if no hw support */ 168 if (cons_backlight_available == 0) 169 vgafb_accessops.burn_screen = NULL; 170 else { 171 vc->vc_backlight_on = WSDISPLAYIO_VIDEO_OFF; 172 vgafb_burn(vc, WSDISPLAYIO_VIDEO_ON, 0); /* paranoia */ 173 } 174 175 config_found(parent, &aa, wsemuldisplaydevprint); 176 } 177 178 int 179 vgafb_ioctl(void *v, u_long cmd, caddr_t data, int flag, struct proc *p) 180 { 181 struct vga_config *vc = v; 182 struct wsdisplay_fbinfo *wdf; 183 184 switch (cmd) { 185 case WSDISPLAYIO_GTYPE: 186 *(u_int *)data = WSDISPLAY_TYPE_PCIVGA; 187 return 0; 188 case WSDISPLAYIO_GINFO: 189 wdf = (void *)data; 190 wdf->height = cons_height; 191 wdf->width = cons_width; 192 wdf->depth = cons_depth; 193 wdf->cmsize = 256; 194 return 0; 195 196 case WSDISPLAYIO_LINEBYTES: 197 *(u_int *)data = cons_linebytes; 198 return 0; 199 200 case WSDISPLAYIO_GETCMAP: 201 return vgafb_getcmap(vc, (struct wsdisplay_cmap *)data); 202 203 case WSDISPLAYIO_PUTCMAP: 204 return vgafb_putcmap(vc, (struct wsdisplay_cmap *)data); 205 206 case WSDISPLAYIO_SMODE: 207 vc->vc_mode = *(u_int *)data; 208 /* track the state of the display, 209 * if returning to WSDISPLAYIO_MODE_EMUL 210 * restore the last palette, workaround for 211 * bad accellerated X servers that does not restore 212 * the correct palette. 213 */ 214 if (cons_depth == 8) 215 vgafb_restore_default_colors(vc); 216 break; 217 218 case WSDISPLAYIO_GETPARAM: 219 { 220 struct wsdisplay_param *dp = (struct wsdisplay_param *)data; 221 222 switch (dp->param) { 223 case WSDISPLAYIO_PARAM_BRIGHTNESS: 224 if (cons_backlight_available != 0) { 225 dp->min = MIN_BRIGHTNESS; 226 dp->max = MAX_BRIGHTNESS; 227 dp->curval = cons_brightness; 228 return 0; 229 } 230 return -1; 231 case WSDISPLAYIO_PARAM_BACKLIGHT: 232 if (cons_backlight_available != 0) { 233 dp->min = 0; 234 dp->max = 1; 235 dp->curval = vc->vc_backlight_on; 236 return 0; 237 } else 238 return -1; 239 } 240 } 241 return -1; 242 243 case WSDISPLAYIO_SETPARAM: 244 { 245 struct wsdisplay_param *dp = (struct wsdisplay_param *)data; 246 247 switch (dp->param) { 248 case WSDISPLAYIO_PARAM_BRIGHTNESS: 249 if (cons_backlight_available == 1) { 250 of_setbrightness(dp->curval); 251 return 0; 252 } else 253 return -1; 254 case WSDISPLAYIO_PARAM_BACKLIGHT: 255 if (cons_backlight_available != 0) { 256 vgafb_burn(vc, 257 dp->curval ? WSDISPLAYIO_VIDEO_ON : 258 WSDISPLAYIO_VIDEO_OFF, 0); 259 return 0; 260 } else 261 return -1; 262 } 263 } 264 return -1; 265 266 case WSDISPLAYIO_SVIDEO: 267 case WSDISPLAYIO_GVIDEO: 268 break; 269 270 case WSDISPLAYIO_GCURPOS: 271 case WSDISPLAYIO_SCURPOS: 272 case WSDISPLAYIO_GCURMAX: 273 case WSDISPLAYIO_GCURSOR: 274 case WSDISPLAYIO_SCURSOR: 275 default: 276 return -1; /* not supported yet */ 277 } 278 279 return (0); 280 } 281 282 paddr_t 283 vgafb_mmap(void *v, off_t off, int prot) 284 { 285 struct vga_config *vc = v; 286 287 if (off & PGOFSET) 288 return (-1); 289 290 switch (vc->vc_mode) { 291 case WSDISPLAYIO_MODE_MAPPED: 292 #ifdef APERTURE 293 if (allowaperture == 0) 294 return (-1); 295 #endif 296 297 if (vc->mmiosize == 0) 298 return (-1); 299 300 if (off >= vc->membase && off < (vc->membase + vc->memsize)) 301 return (off); 302 303 if (off >= vc->mmiobase && off < (vc->mmiobase+vc->mmiosize)) 304 return (off); 305 break; 306 307 case WSDISPLAYIO_MODE_DUMBFB: 308 if (off >= 0x00000 && off < vc->memsize) 309 return (vc->vc_paddr + off); 310 break; 311 312 } 313 314 return (-1); 315 } 316 317 int 318 vgafb_cnattach(bus_space_tag_t iot, bus_space_tag_t memt, int type, int check) 319 { 320 struct vga_config *vc = &vgafb_pci_console_vc; 321 struct vgafb_devconfig *dc = &vgafb_console_dc; 322 struct rasops_info *ri = &dc->dc_rinfo; 323 long defattr; 324 int i; 325 326 vgafb_init(iot, memt, vc, cons_addr, cons_linebytes * cons_height,0, 0); 327 328 ri->ri_flg = RI_CENTER; 329 ri->ri_depth = cons_depth; 330 ri->ri_bits = (void *)vc->vc_memh; 331 ri->ri_width = cons_width; 332 ri->ri_height = cons_height; 333 ri->ri_stride = cons_linebytes; 334 ri->ri_hw = dc; 335 336 /* Clear the screen */ 337 for (i = 0; i < cons_linebytes * cons_height; i++) 338 bus_space_write_1(memt, vc->vc_memh, i, 0); 339 340 rasops_init(ri, 160, 160); /* XXX */ 341 342 vgafb_stdscreen.nrows = ri->ri_rows; 343 vgafb_stdscreen.ncols = ri->ri_cols; 344 vgafb_stdscreen.textops = &ri->ri_ops; 345 346 ri->ri_ops.alloc_attr(ri, 0, 0, 0, &defattr); 347 348 wsdisplay_cnattach(&vgafb_stdscreen, ri, 0, 0, defattr); 349 vc->nscreens++; 350 351 return (0); 352 } 353 354 struct { 355 u_int8_t r; 356 u_int8_t g; 357 u_int8_t b; 358 } vgafb_color[256]; 359 360 void 361 vgafb_setcolor(struct vga_config *vc, unsigned int index, u_int8_t r, 362 u_int8_t g, u_int8_t b) 363 { 364 vc->vc_cmap_red[index] = r; 365 vc->vc_cmap_green[index] = g; 366 vc->vc_cmap_blue[index] = b; 367 368 vgafb_color[index].r = r; 369 vgafb_color[index].g = g; 370 vgafb_color[index].b = b; 371 OF_call_method_1("set-colors", cons_display_ofh, 3, 372 &vgafb_color[index], index, 1); 373 } 374 375 int 376 vgafb_getcmap(struct vga_config *vc, struct wsdisplay_cmap *cm) 377 { 378 u_int index = cm->index; 379 u_int count = cm->count; 380 int error; 381 382 if (index >= 256 || count > 256 - index) 383 return EINVAL; 384 385 error = copyout(&vc->vc_cmap_red[index], cm->red, count); 386 if (error) 387 return error; 388 error = copyout(&vc->vc_cmap_green[index], cm->green, count); 389 if (error) 390 return error; 391 error = copyout(&vc->vc_cmap_blue[index], cm->blue, count); 392 if (error) 393 return error; 394 395 return 0; 396 } 397 398 int 399 vgafb_putcmap(struct vga_config *vc, struct wsdisplay_cmap *cm) 400 { 401 u_int index = cm->index; 402 u_int count = cm->count; 403 u_int i; 404 int error; 405 u_int8_t *r, *g, *b; 406 407 if (index >= 256 || count > 256 - index) 408 return EINVAL; 409 410 if ((error = copyin(cm->red, &vc->vc_cmap_red[index], count)) != 0) 411 return (error); 412 if ((error = copyin(cm->green, &vc->vc_cmap_green[index], count)) != 0) 413 return (error); 414 if ((error = copyin(cm->blue, &vc->vc_cmap_blue[index], count)) != 0) 415 return (error); 416 417 r = &(vc->vc_cmap_red[index]); 418 g = &(vc->vc_cmap_green[index]); 419 b = &(vc->vc_cmap_blue[index]); 420 421 for (i = 0; i < count; i++) { 422 vgafb_color[i].r = *r; 423 vgafb_color[i].g = *g; 424 vgafb_color[i].b = *b; 425 r++, g++, b++; 426 } 427 OF_call_method_1("set-colors", cons_display_ofh, 3, 428 &vgafb_color, index, count); 429 return 0; 430 } 431 432 void 433 vgafb_burn(void *v, u_int on, u_int flags) 434 { 435 struct vga_config *vc = v; 436 437 if (cons_backlight_available == 1 && 438 vc->vc_backlight_on != on) { 439 if (on == WSDISPLAYIO_VIDEO_ON) { 440 OF_call_method_1("backlight-on", cons_display_ofh, 0); 441 } else { 442 OF_call_method_1("backlight-off", cons_display_ofh, 0); 443 } 444 vc->vc_backlight_on = on; 445 } 446 } 447 448 int 449 vgafb_alloc_screen(void *v, const struct wsscreen_descr *type, void **cookiep, 450 int *curxp, int *curyp, long *attrp) 451 { 452 struct vga_config *vc = v; 453 long defattr; 454 455 if (vc->nscreens > 0) 456 return (ENOMEM); 457 458 *cookiep = &vc->dc_rinfo; /* one and only for now */ 459 *curxp = 0; 460 *curyp = 0; 461 vc->dc_rinfo.ri_ops.alloc_attr(&vc->dc_rinfo, 0, 0, 0, &defattr); 462 *attrp = defattr; 463 464 vc->nscreens++; 465 466 return (0); 467 } 468 469 void 470 vgafb_free_screen(void *v, void *cookie) 471 { 472 struct vga_config *vc = v; 473 474 if (vc == &vgafb_pci_console_vc) 475 panic("vgafb_free_screen: console"); 476 477 vc->nscreens--; 478 } 479 480 int 481 vgafb_show_screen(void *v, void *cookie, int waitok, 482 void (*cb)(void *, int, int), void *cbarg) 483 { 484 return (0); 485 } 486