vgafb.c revision 1.31
1/* $OpenBSD: vgafb.c,v 1.31 2006/05/30 20:59:56 matthieu 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/wscons/wscons_raster.h> 48#include <dev/rasops/rasops.h> 49#include <dev/wsfont/wsfont.h> 50 51#include <macppc/pci/vgafbvar.h> 52 53struct cfdriver vgafb_cd = { 54 NULL, "vgafb", DV_DULL, 55}; 56 57void vgafb_setcolor(struct vgafb_config *vc, unsigned int index, 58 u_int8_t r, u_int8_t g, u_int8_t b); 59void vgafb_restore_default_colors(struct vgafb_config *vc); 60 61struct vgafb_devconfig { 62 struct rasops_info dc_rinfo; /* raster display data */ 63 int dc_blanked; /* currently had video disabled */ 64}; 65 66struct vgafb_devconfig vgafb_console_dc; 67 68struct 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}; 76const struct wsscreen_descr *vgafb_scrlist[] = { 77 &vgafb_stdscreen, 78 /* XXX other formats, graphics screen? */ 79}; 80 81struct wsscreen_list vgafb_screenlist = { 82 sizeof(vgafb_scrlist) / sizeof(struct wsscreen_descr *), vgafb_scrlist 83}; 84 85struct 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 97int vgafb_getcmap(struct vgafb_config *vc, struct wsdisplay_cmap *cm); 98int vgafb_putcmap(struct vgafb_config *vc, struct wsdisplay_cmap *cm); 99 100#define FONT_WIDTH 8 101#define FONT_HEIGHT 16 102 103#ifdef APERTURE 104extern int allowaperture; 105#endif 106 107/* 108 * The following functions implement back-end configuration grabbing 109 * and attachment. 110 */ 111int 112vgafb_common_probe(bus_space_tag_t iot, bus_space_tag_t memt, u_int32_t iobase, 113 size_t iosize, u_int32_t membase, size_t memsize, u_int32_t mmiobase, 114 size_t mmiosize) 115{ 116 bus_space_handle_t ioh_b, ioh_c, ioh_d, memh, mmioh; 117 int gotio_b, gotio_c, gotio_d, gotmem, gotmmio, rv; 118 119 gotio_b = gotio_c = gotio_d = gotmem = gotmmio = rv = 0; 120 121 if (iosize != 0) { 122 if (bus_space_map(iot, iobase+0x3b0, 0xc, 0, &ioh_b)) 123 goto bad; 124 gotio_b = 1; 125 if (bus_space_map(iot, iobase+0x3c0, 0x10, 0, &ioh_c)) 126 goto bad; 127 gotio_c = 1; 128 if (bus_space_map(iot, iobase+0x3d0, 0x10, 0, &ioh_d)) 129 goto bad; 130 gotio_d = 1; 131 } 132 if (mmiosize != 0) { 133 if (bus_space_map(iot, mmiobase, mmiosize, 0, &mmioh)) 134 goto bad; 135 gotmmio = 1; 136 } 137 138 rv = 1; 139 140bad: 141 if (gotio_b) 142 bus_space_unmap(iot, ioh_b, 0xc); 143 if (gotio_c) 144 bus_space_unmap(iot, ioh_c, 0x10); 145 if (gotio_d) 146 bus_space_unmap(iot, ioh_d, 0x10); 147 if (gotmmio) 148 bus_space_unmap(memt, mmioh, mmiosize); 149 if (gotmem) 150 bus_space_unmap(memt, memh, memsize); 151 152 return (rv); 153} 154 155void 156vgafb_common_setup(bus_space_tag_t iot, bus_space_tag_t memt, 157 struct vgafb_config *vc, u_int32_t iobase, size_t iosize, 158 u_int32_t membase, size_t memsize, u_int32_t mmiobase, size_t mmiosize) 159{ 160 vc->vc_iot = iot; 161 vc->vc_memt = memt; 162 vc->vc_paddr = membase; 163 164 if (iosize != 0) { 165 if (bus_space_map(vc->vc_iot, iobase+0x3b0, 0xc, 0, &vc->vc_ioh_b)) 166 panic("vgafb_common_setup: couldn't map io b"); 167 if (bus_space_map(vc->vc_iot, iobase+0x3c0, 0x10, 0, &vc->vc_ioh_c)) 168 panic("vgafb_common_setup: couldn't map io c"); 169 if (bus_space_map(vc->vc_iot, iobase+0x3d0, 0x10, 0, &vc->vc_ioh_d)) 170 panic("vgafb_common_setup: couldn't map io d"); 171 } 172 if (mmiosize != 0) 173 if (bus_space_map(vc->vc_memt, mmiobase, mmiosize, 0, 174 &vc->vc_mmioh)) 175 panic("vgafb_common_setup: couldn't map mmio"); 176 177 /* memsize should only be visible region for console */ 178 memsize = cons_height * cons_linebytes; 179 if (bus_space_map(vc->vc_memt, membase, memsize, 180 /* XXX */ppc_proc_is_64b ? 0 : 1, &vc->vc_memh)) 181 panic("vgafb_common_setup: couldn't map memory"); 182 cons_display_mem_h = vc->vc_memh; 183 vc->vc_ofh = cons_display_ofh; 184 185 186 vc->vc_crow = vc->vc_ccol = 0; /* Has to be some onscreen value */ 187 vc->vc_so = 0; 188 189 /* clear screen, frob cursor, etc.? */ 190 /* 191 */ 192 193 vc->vc_at = 0x00 | 0xf; /* black bg|white fg */ 194 vc->vc_so_at = 0x00 | 0xf | 0x80; /* black bg|white fg|blink */ 195 196 if (cons_depth == 8) { 197 vgafb_restore_default_colors(vc); 198 } 199} 200 201void 202vgafb_restore_default_colors(struct vgafb_config *vc) 203{ 204 int i; 205 206 for (i = 0; i < 256; i++) { 207 const u_char *color; 208 209 color = &rasops_cmap[i * 3]; 210 vgafb_setcolor(vc, i, color[0], color[1], color[2]); 211 } 212} 213 214void 215vgafb_wsdisplay_attach(struct device *parent, struct vgafb_config *vc, 216 int console) 217{ 218 struct wsemuldisplaydev_attach_args aa; 219 220 aa.console = console; 221 aa.scrdata = &vgafb_screenlist; 222 aa.accessops = &vgafb_accessops; 223 aa.accesscookie = vc; 224 225 /* no need to keep the burner function if no hw support */ 226 if (cons_backlight_available == 0) 227 vgafb_accessops.burn_screen = NULL; 228 else { 229 vc->vc_backlight_on = WSDISPLAYIO_VIDEO_OFF; 230 vgafb_burn(vc, WSDISPLAYIO_VIDEO_ON, 0); /* paranoia */ 231 } 232 233 config_found(parent, &aa, wsemuldisplaydevprint); 234} 235 236int 237vgafb_ioctl(void *v, u_long cmd, caddr_t data, int flag, struct proc *p) 238{ 239 struct vgafb_config *vc = v; 240 struct wsdisplay_fbinfo *wdf; 241 242 switch (cmd) { 243 case WSDISPLAYIO_GTYPE: 244 *(u_int *)data = WSDISPLAY_TYPE_PCIVGA; 245 return 0; 246 case WSDISPLAYIO_GINFO: 247 wdf = (void *)data; 248 wdf->height = cons_height; 249 wdf->width = cons_width; 250 wdf->depth = cons_depth; 251 wdf->cmsize = 256; 252 return 0; 253 254 case WSDISPLAYIO_LINEBYTES: 255 *(u_int *)data = cons_linebytes; 256 return 0; 257 258 case WSDISPLAYIO_GETCMAP: 259 return vgafb_getcmap(vc, (struct wsdisplay_cmap *)data); 260 261 case WSDISPLAYIO_PUTCMAP: 262 return vgafb_putcmap(vc, (struct wsdisplay_cmap *)data); 263 264 case WSDISPLAYIO_SMODE: 265 vc->vc_mode = *(u_int *)data; 266 /* track the state of the display, 267 * if returning to WSDISPLAYIO_MODE_EMUL 268 * restore the last palette, workaround for 269 * bad accellerated X servers that does not restore 270 * the correct palette. 271 */ 272 if (cons_depth == 8) 273 vgafb_restore_default_colors(vc); 274 break; 275 276 case WSDISPLAYIO_GETPARAM: 277 { 278 struct wsdisplay_param *dp = (struct wsdisplay_param *)data; 279 280 switch (dp->param) { 281 case WSDISPLAYIO_PARAM_BRIGHTNESS: 282 if (cons_backlight_available != 0) { 283 dp->min = MIN_BRIGHTNESS; 284 dp->max = MAX_BRIGHTNESS; 285 dp->curval = cons_brightness; 286 return 0; 287 } 288 return -1; 289 case WSDISPLAYIO_PARAM_BACKLIGHT: 290 if (cons_backlight_available != 0) { 291 dp->min = 0; 292 dp->max = 1; 293 dp->curval = vc->vc_backlight_on; 294 return 0; 295 } else 296 return -1; 297 } 298 } 299 return -1; 300 301 case WSDISPLAYIO_SETPARAM: 302 { 303 struct wsdisplay_param *dp = (struct wsdisplay_param *)data; 304 305 switch (dp->param) { 306 case WSDISPLAYIO_PARAM_BRIGHTNESS: 307 if (cons_backlight_available == 1) { 308 of_setbrightness(dp->curval); 309 return 0; 310 } else 311 return -1; 312 case WSDISPLAYIO_PARAM_BACKLIGHT: 313 if (cons_backlight_available != 0) { 314 vgafb_burn(vc, 315 dp->curval ? WSDISPLAYIO_VIDEO_ON : 316 WSDISPLAYIO_VIDEO_OFF, 0); 317 return 0; 318 } else 319 return -1; 320 } 321 } 322 return -1; 323 324 case WSDISPLAYIO_SVIDEO: 325 case WSDISPLAYIO_GVIDEO: 326 break; 327 328 case WSDISPLAYIO_GCURPOS: 329 case WSDISPLAYIO_SCURPOS: 330 case WSDISPLAYIO_GCURMAX: 331 case WSDISPLAYIO_GCURSOR: 332 case WSDISPLAYIO_SCURSOR: 333 default: 334 return -1; /* not supported yet */ 335 } 336 337 return (0); 338} 339 340paddr_t 341vgafb_mmap(void *v, off_t offset, int prot) 342{ 343 struct vgafb_config *vc = v; 344 bus_space_handle_t h; 345 346 switch (vc->vc_mode) { 347 case WSDISPLAYIO_MODE_MAPPED: 348#ifdef APERTURE 349 if (allowaperture == 0) { 350 h = -1; 351 break; 352 } 353#endif 354 if (offset >= 0xa0000 && offset < 0xfffff) 355 h = offset; 356 /* XXX the following are probably wrong. 357 we want physical addresses here, not virtual ones */ 358 else if (offset >= 0x10000000 && offset < 0x10040000 ) 359 /* 256KB of iohb */ 360 h = vc->vc_ioh_b; 361 else if (offset >= 0x10040000 && offset < 0x10080000) 362 /* 256KB of iohc */ 363 h = vc->vc_ioh_c; 364 else if (offset >= 0x18880000 && offset < 0x100c0000) 365 /* 256KB of iohd */ 366 h = vc->vc_ioh_d; 367 else if (offset >= 0x20000000 && offset < 0x20000000+vc->mmiosize) 368 /* mmiosize... */ 369 h = vc->vc_mmioh + (offset - 0x20000000); 370 else if (offset >= vc->membase && (offset < vc->membase+vc->memsize)) { 371 /* allow mmapping of memory */ 372 h = offset; 373 } else if (offset >= vc->mmiobase && 374 (offset < vc->mmiobase+vc->mmiosize)) { 375 /* allow mmapping of mmio space */ 376 h = offset; 377 378 } else { 379 h = -1; 380 } 381 break; 382 383 case WSDISPLAYIO_MODE_DUMBFB: 384 if (offset >= 0x00000 && offset < vc->memsize) 385 h = vc->vc_paddr + offset; 386 break; 387 388 } 389 return h; 390} 391 392 393void 394vgafb_cnprobe(struct consdev *cp) 395{ 396 if (cons_displaytype != 1) 397 return; 398 399 cp->cn_pri = CN_INTERNAL; 400} 401 402void 403vgafb_cnattach(bus_space_tag_t iot, bus_space_tag_t memt, void *pc, int bus, 404 int device, int function) 405{ 406 long defattr; 407 408 struct vgafb_devconfig *dc = &vgafb_console_dc; 409 struct rasops_info *ri = &dc->dc_rinfo; 410 411 ri->ri_flg = RI_CENTER; 412 ri->ri_depth = cons_depth; 413 ri->ri_bits = (void *)cons_display_mem_h; 414 ri->ri_width = cons_width; 415 ri->ri_height = cons_height; 416 ri->ri_stride = cons_linebytes; 417 ri->ri_hw = dc; 418 419 rasops_init(ri, 160, 160); /* XXX */ 420 421 vgafb_stdscreen.nrows = ri->ri_rows; 422 vgafb_stdscreen.ncols = ri->ri_cols; 423 vgafb_stdscreen.textops = &ri->ri_ops; 424 ri->ri_ops.alloc_attr(ri, 0, 0, 0, &defattr); 425 426 wsdisplay_cnattach(&vgafb_stdscreen, ri, 0, 0, defattr); 427} 428 429struct { 430 u_int8_t r; 431 u_int8_t g; 432 u_int8_t b; 433} vgafb_color[256]; 434 435void 436vgafb_setcolor(struct vgafb_config *vc, unsigned int index, u_int8_t r, 437 u_int8_t g, u_int8_t b) 438{ 439 vc->vc_cmap_red[index] = r; 440 vc->vc_cmap_green[index] = g; 441 vc->vc_cmap_blue[index] = b; 442 443 vgafb_color[index].r = r; 444 vgafb_color[index].g = g; 445 vgafb_color[index].b = b; 446 OF_call_method_1("set-colors", cons_display_ofh, 3, 447 &vgafb_color[index], index, 1); 448} 449 450int 451vgafb_getcmap(struct vgafb_config *vc, struct wsdisplay_cmap *cm) 452{ 453 u_int index = cm->index; 454 u_int count = cm->count; 455 int error; 456 457 if (index >= 256 || count > 256 - index) 458 return EINVAL; 459 460 error = copyout(&vc->vc_cmap_red[index], cm->red, count); 461 if (error) 462 return error; 463 error = copyout(&vc->vc_cmap_green[index], cm->green, count); 464 if (error) 465 return error; 466 error = copyout(&vc->vc_cmap_blue[index], cm->blue, count); 467 if (error) 468 return error; 469 470 return 0; 471} 472 473int 474vgafb_putcmap(struct vgafb_config *vc, struct wsdisplay_cmap *cm) 475{ 476 u_int index = cm->index; 477 u_int count = cm->count; 478 u_int i; 479 int error; 480 u_int8_t *r, *g, *b; 481 482 if (index >= 256 || count > 256 - index) 483 return EINVAL; 484 485 if ((error = copyin(cm->red, &vc->vc_cmap_red[index], count)) != 0) 486 return (error); 487 if ((error = copyin(cm->green, &vc->vc_cmap_green[index], count)) != 0) 488 return (error); 489 if ((error = copyin(cm->blue, &vc->vc_cmap_blue[index], count)) != 0) 490 return (error); 491 492 r = &(vc->vc_cmap_red[index]); 493 g = &(vc->vc_cmap_green[index]); 494 b = &(vc->vc_cmap_blue[index]); 495 496 for (i = 0; i < count; i++) { 497 vgafb_color[i].r = *r; 498 vgafb_color[i].g = *g; 499 vgafb_color[i].b = *b; 500 r++, g++, b++; 501 } 502 OF_call_method_1("set-colors", cons_display_ofh, 3, 503 &vgafb_color, index, count); 504 return 0; 505} 506 507void 508vgafb_burn(void *v, u_int on, u_int flags) 509{ 510 struct vgafb_config *vc = v; 511 512 if (cons_backlight_available == 1 && 513 vc->vc_backlight_on != on) { 514 if (on == WSDISPLAYIO_VIDEO_ON) { 515 OF_call_method_1("backlight-on", cons_display_ofh, 0); 516 } else { 517 OF_call_method_1("backlight-off", cons_display_ofh, 0); 518 } 519 vc->vc_backlight_on = on; 520 } 521} 522