1 /* $NetBSD: cgsix.c,v 1.19 2005/02/27 00:27:49 perry Exp $ */ 2 3 /*- 4 * Copyright (c) 1998 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Paul Kranenburg. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the NetBSD 21 * Foundation, Inc. and its contributors. 22 * 4. Neither the name of The NetBSD Foundation nor the names of its 23 * contributors may be used to endorse or promote products derived 24 * from this software without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 36 * POSSIBILITY OF SUCH DAMAGE. 37 */ 38 39 /* 40 * Copyright (c) 1993 41 * The Regents of the University of California. All rights reserved. 42 * 43 * This software was developed by the Computer Systems Engineering group 44 * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and 45 * contributed to Berkeley. 46 * 47 * All advertising materials mentioning features or use of this software 48 * must display the following acknowledgement: 49 * This product includes software developed by the University of 50 * California, Lawrence Berkeley Laboratory. 51 * 52 * Redistribution and use in source and binary forms, with or without 53 * modification, are permitted provided that the following conditions 54 * are met: 55 * 1. Redistributions of source code must retain the above copyright 56 * notice, this list of conditions and the following disclaimer. 57 * 2. Redistributions in binary form must reproduce the above copyright 58 * notice, this list of conditions and the following disclaimer in the 59 * documentation and/or other materials provided with the distribution. 60 * 3. Neither the name of the University nor the names of its contributors 61 * may be used to endorse or promote products derived from this software 62 * without specific prior written permission. 63 * 64 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 65 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 66 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 67 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 68 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 69 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 70 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 71 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 72 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 73 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 74 * SUCH DAMAGE. 75 * 76 * @(#)cgsix.c 8.4 (Berkeley) 1/21/94 77 */ 78 79 /* 80 * color display (cgsix) driver. 81 * 82 * Does not handle interrupts, even though they can occur. 83 * 84 * XXX should defer colormap updates to vertical retrace interrupts 85 */ 86 87 #include <sys/cdefs.h> 88 __KERNEL_RCSID(0, "$NetBSD: cgsix.c,v 1.19 2005/02/27 00:27:49 perry Exp $"); 89 90 #include <sys/param.h> 91 #include <sys/systm.h> 92 #include <sys/buf.h> 93 #include <sys/device.h> 94 #include <sys/ioctl.h> 95 #include <sys/malloc.h> 96 #include <sys/mman.h> 97 #include <sys/tty.h> 98 #include <sys/conf.h> 99 100 #ifdef DEBUG 101 #include <sys/proc.h> 102 #include <sys/syslog.h> 103 #endif 104 105 #include <uvm/uvm_extern.h> 106 107 #include <machine/bus.h> 108 109 #include <dev/sun/fbio.h> 110 #include <dev/sun/fbvar.h> 111 112 #include <dev/sun/btreg.h> 113 #include <dev/sun/btvar.h> 114 #include <dev/sun/cgsixreg.h> 115 #include <dev/sun/cgsixvar.h> 116 #include <dev/sun/pfourreg.h> 117 118 #include <dev/wscons/wsconsio.h> 119 #include <dev/wsfont/wsfont.h> 120 #include <dev/rasops/rasops.h> 121 122 #include "opt_wsemul.h" 123 124 static void cg6_unblank(struct device *); 125 126 extern struct cfdriver cgsix_cd; 127 128 dev_type_open(cgsixopen); 129 dev_type_close(cgsixclose); 130 dev_type_ioctl(cgsixioctl); 131 dev_type_mmap(cgsixmmap); 132 133 const struct cdevsw cgsix_cdevsw = { 134 cgsixopen, cgsixclose, noread, nowrite, cgsixioctl, 135 nostop, notty, nopoll, cgsixmmap, nokqfilter, 136 }; 137 138 /* frame buffer generic driver */ 139 static struct fbdriver cg6_fbdriver = { 140 cg6_unblank, cgsixopen, cgsixclose, cgsixioctl, nopoll, cgsixmmap, 141 nokqfilter 142 }; 143 144 static void cg6_reset (struct cgsix_softc *); 145 static void cg6_loadcmap (struct cgsix_softc *, int, int); 146 static void cg6_loadomap (struct cgsix_softc *); 147 static void cg6_setcursor (struct cgsix_softc *);/* set position */ 148 static void cg6_loadcursor (struct cgsix_softc *);/* set shape */ 149 150 struct wsscreen_descr cgsix_defaultscreen = { 151 "std", 152 0, 0, /* will be filled in -- XXX shouldn't, it's global */ 153 0, /* textops */ 154 0, 0, /* font width/height */ 155 WSSCREEN_REVERSE /* capabilities */ 156 }; 157 158 static int cgsix_ioctl __P((void *, u_long, caddr_t, int, struct proc *)); 159 static paddr_t cgsix_mmap __P((void *, off_t, int)); 160 static int cgsix_alloc_screen __P((void *, const struct wsscreen_descr *, 161 void **, int *, int *, long *)); 162 static void cgsix_free_screen __P((void *, void *)); 163 static int cgsix_show_screen __P((void *, void *, int, 164 void (*) (void *, int, int), void *)); 165 int cgsix_putcmap(struct cgsix_softc *, struct wsdisplay_cmap *); 166 int cgsix_getcmap(struct cgsix_softc *, struct wsdisplay_cmap *); 167 168 struct wsdisplay_accessops cgsix_accessops = { 169 cgsix_ioctl, 170 cgsix_mmap, 171 cgsix_alloc_screen, 172 cgsix_free_screen, 173 cgsix_show_screen, 174 NULL, /* load_font */ 175 NULL, /* pollc */ 176 NULL, /* getwschar */ 177 NULL, /* putwschar */ 178 NULL /* scroll */ 179 }; 180 181 const struct wsscreen_descr *_cgsix_scrlist[] = { 182 &cgsix_defaultscreen 183 }; 184 185 struct wsscreen_list cgsix_screenlist = { 186 sizeof(_cgsix_scrlist) / sizeof(struct wsscreen_descr *), 187 _cgsix_scrlist 188 }; 189 190 #ifdef RASTERCONSOLE 191 int cgsix_use_rasterconsole = 1; 192 #endif 193 194 /* 195 * cg6 accelerated console routines. 196 * 197 * Note that buried in this code in several places is the assumption 198 * that pixels are exactly one byte wide. Since this is cg6-specific 199 * code, this seems safe. This assumption resides in things like the 200 * use of ri_emuwidth without messing around with ri_pelbytes, or the 201 * assumption that ri_font->fontwidth is the right thing to multiply 202 * character-cell counts by to get byte counts. 203 */ 204 205 /* 206 * Magic values for blitter 207 */ 208 209 /* Values for the mode register */ 210 #define CG6_MODE ( \ 211 0x00200000 /* GX_BLIT_SRC */ \ 212 | 0x00020000 /* GX_MODE_COLOR8 */ \ 213 | 0x00008000 /* GX_DRAW_RENDER */ \ 214 | 0x00002000 /* GX_BWRITE0_ENABLE */ \ 215 | 0x00001000 /* GX_BWRITE1_DISABLE */ \ 216 | 0x00000200 /* GX_BREAD_0 */ \ 217 | 0x00000080 /* GX_BDISP_0 */ \ 218 ) 219 #define CG6_MODE_MASK ( \ 220 0x00300000 /* GX_BLIT_ALL */ \ 221 | 0x00060000 /* GX_MODE_ALL */ \ 222 | 0x00018000 /* GX_DRAW_ALL */ \ 223 | 0x00006000 /* GX_BWRITE0_ALL */ \ 224 | 0x00001800 /* GX_BWRITE1_ALL */ \ 225 | 0x00000600 /* GX_BREAD_ALL */ \ 226 | 0x00000180 /* GX_BDISP_ALL */ \ 227 ) 228 229 /* Value for the alu register for screen-to-screen copies */ 230 #define CG6_ALU_COPY ( \ 231 0x80000000 /* GX_PLANE_ONES (ignore planemask register) */ \ 232 | 0x20000000 /* GX_PIXEL_ONES (ignore pixelmask register) */ \ 233 | 0x00800000 /* GX_ATTR_SUPP (function unknown) */ \ 234 | 0x00000000 /* GX_RAST_BOOL (function unknown) */ \ 235 | 0x00000000 /* GX_PLOT_PLOT (function unknown) */ \ 236 | 0x08000000 /* GX_PATTERN_ONES (ignore pattern) */ \ 237 | 0x01000000 /* GX_POLYG_OVERLAP (unsure - handle overlap?) */ \ 238 | 0x0000cccc /* ALU = src */ \ 239 ) 240 241 /* Value for the alu register for region fills */ 242 #define CG6_ALU_FILL ( \ 243 0x80000000 /* GX_PLANE_ONES (ignore planemask register) */ \ 244 | 0x20000000 /* GX_PIXEL_ONES (ignore pixelmask register) */ \ 245 | 0x00800000 /* GX_ATTR_SUPP (function unknown) */ \ 246 | 0x00000000 /* GX_RAST_BOOL (function unknown) */ \ 247 | 0x00000000 /* GX_PLOT_PLOT (function unknown) */ \ 248 | 0x08000000 /* GX_PATTERN_ONES (ignore pattern) */ \ 249 | 0x01000000 /* GX_POLYG_OVERLAP (unsure - handle overlap?) */ \ 250 | 0x0000ff00 /* ALU = fg color */ \ 251 ) 252 253 /* Value for the alu register for toggling an area */ 254 #define CG6_ALU_FLIP ( \ 255 0x80000000 /* GX_PLANE_ONES (ignore planemask register) */ \ 256 | 0x20000000 /* GX_PIXEL_ONES (ignore pixelmask register) */ \ 257 | 0x00800000 /* GX_ATTR_SUPP (function unknown) */ \ 258 | 0x00000000 /* GX_RAST_BOOL (function unknown) */ \ 259 | 0x00000000 /* GX_PLOT_PLOT (function unknown) */ \ 260 | 0x08000000 /* GX_PATTERN_ONES (ignore pattern) */ \ 261 | 0x01000000 /* GX_POLYG_OVERLAP (unsure - handle overlap?) */ \ 262 | 0x00005555 /* ALU = ~dst */ \ 263 ) 264 265 /* 266 * Wait for a blit to finish. 267 * 0x8000000 bit: function unknown; 0x20000000 bit: GX_BLT_INPROGRESS 268 */ 269 #define CG6_BLIT_WAIT(fbc) do { \ 270 while (((fbc)->fbc_blit & 0xa0000000) == 0xa0000000) \ 271 /*EMPTY*/; \ 272 } while (0) 273 274 /* 275 * Wait for a drawing operation to finish, or at least get queued. 276 * 0x8000000 bit: function unknown; 0x20000000 bit: GX_FULL 277 */ 278 #define CG6_DRAW_WAIT(fbc) do { \ 279 while (((fbc)->fbc_draw & 0xa0000000) == 0xa0000000) \ 280 /*EMPTY*/; \ 281 } while (0) 282 283 /* 284 * Wait for the whole engine to go idle. This may not matter in our case; 285 * I'm not sure whether blits are actually queued or not. It more likely 286 * is intended for lines and such that do get queued. 287 * 0x10000000 bit: GX_INPROGRESS 288 */ 289 #define CG6_DRAIN(fbc) do { \ 290 while ((fbc)->fbc_s & 0x10000000) \ 291 /*EMPTY*/; \ 292 } while (0) 293 294 static void cg6_ras_init(struct cgsix_softc *); 295 static void cg6_ras_copyrows(void *, int, int, int); 296 static void cg6_ras_copycols(void *, int, int, int, int); 297 static void cg6_ras_erasecols(void *, int, int, int, long int); 298 static void cg6_ras_eraserows(void *, int, int, long int); 299 static void cg6_ras_do_cursor(struct rasops_info *); 300 301 static void 302 cg6_ras_init(struct cgsix_softc *sc) 303 { 304 volatile struct cg6_fbc *fbc = sc->sc_fbc; 305 306 CG6_DRAIN(fbc); 307 fbc->fbc_mode &= ~CG6_MODE_MASK; 308 fbc->fbc_mode |= CG6_MODE; 309 } 310 311 static void 312 cg6_ras_copyrows(void *cookie, int src, int dst, int n) 313 { 314 struct rasops_info *ri; 315 volatile struct cg6_fbc *fbc; 316 317 ri = cookie; 318 if (dst == src) 319 return; 320 if (src < 0) { 321 n += src; 322 src = 0; 323 } 324 if (src+n > ri->ri_rows) 325 n = ri->ri_rows - src; 326 if (dst < 0) { 327 n += dst; 328 dst = 0; 329 } 330 if (dst+n > ri->ri_rows) 331 n = ri->ri_rows - dst; 332 if (n <= 0) 333 return; 334 n *= ri->ri_font->fontheight; 335 src *= ri->ri_font->fontheight; 336 dst *= ri->ri_font->fontheight; 337 fbc = ((struct cgsix_softc *)ri->ri_hw)->sc_fbc; 338 fbc->fbc_clip = 0; 339 fbc->fbc_s = 0; 340 fbc->fbc_offx = 0; 341 fbc->fbc_offy = 0; 342 fbc->fbc_clipminx = 0; 343 fbc->fbc_clipminy = 0; 344 fbc->fbc_clipmaxx = ri->ri_width - 1; 345 fbc->fbc_clipmaxy = ri->ri_height - 1; 346 fbc->fbc_alu = CG6_ALU_COPY; 347 fbc->fbc_x0 = ri->ri_xorigin; 348 fbc->fbc_y0 = ri->ri_yorigin + src; 349 fbc->fbc_x1 = ri->ri_xorigin + ri->ri_emuwidth - 1; 350 fbc->fbc_y1 = ri->ri_yorigin + src + n - 1; 351 fbc->fbc_x2 = ri->ri_xorigin; 352 fbc->fbc_y2 = ri->ri_yorigin + dst; 353 fbc->fbc_x3 = ri->ri_xorigin + ri->ri_emuwidth - 1; 354 fbc->fbc_y3 = ri->ri_yorigin + dst + n - 1; 355 CG6_BLIT_WAIT(fbc); 356 CG6_DRAIN(fbc); 357 } 358 359 static void 360 cg6_ras_copycols(void *cookie, int row, int src, int dst, int n) 361 { 362 struct rasops_info *ri; 363 volatile struct cg6_fbc *fbc; 364 365 ri = cookie; 366 if (dst == src) 367 return; 368 if ((row < 0) || (row >= ri->ri_rows)) 369 return; 370 if (src < 0) { 371 n += src; 372 src = 0; 373 } 374 if (src+n > ri->ri_cols) 375 n = ri->ri_cols - src; 376 if (dst < 0) { 377 n += dst; 378 dst = 0; 379 } 380 if (dst+n > ri->ri_cols) 381 n = ri->ri_cols - dst; 382 if (n <= 0) 383 return; 384 n *= ri->ri_font->fontwidth; 385 src *= ri->ri_font->fontwidth; 386 dst *= ri->ri_font->fontwidth; 387 row *= ri->ri_font->fontheight; 388 fbc = ((struct cgsix_softc *)ri->ri_hw)->sc_fbc; 389 fbc->fbc_clip = 0; 390 fbc->fbc_s = 0; 391 fbc->fbc_offx = 0; 392 fbc->fbc_offy = 0; 393 fbc->fbc_clipminx = 0; 394 fbc->fbc_clipminy = 0; 395 fbc->fbc_clipmaxx = ri->ri_width - 1; 396 fbc->fbc_clipmaxy = ri->ri_height - 1; 397 fbc->fbc_alu = CG6_ALU_COPY; 398 fbc->fbc_x0 = ri->ri_xorigin + src; 399 fbc->fbc_y0 = ri->ri_yorigin + row; 400 fbc->fbc_x1 = ri->ri_xorigin + src + n - 1; 401 fbc->fbc_y1 = ri->ri_yorigin + row + ri->ri_font->fontheight - 1; 402 fbc->fbc_x2 = ri->ri_xorigin + dst; 403 fbc->fbc_y2 = ri->ri_yorigin + row; 404 fbc->fbc_x3 = ri->ri_xorigin + dst + n - 1; 405 fbc->fbc_y3 = ri->ri_yorigin + row + ri->ri_font->fontheight - 1; 406 CG6_BLIT_WAIT(fbc); 407 CG6_DRAIN(fbc); 408 } 409 410 static void 411 cg6_ras_erasecols(void *cookie, int row, int col, int n, long int attr) 412 { 413 struct rasops_info *ri; 414 volatile struct cg6_fbc *fbc; 415 416 ri = cookie; 417 if ((row < 0) || (row >= ri->ri_rows)) 418 return; 419 if (col < 0) { 420 n += col; 421 col = 0; 422 } 423 if (col+n > ri->ri_cols) 424 n = ri->ri_cols - col; 425 if (n <= 0) 426 return; 427 n *= ri->ri_font->fontwidth; 428 col *= ri->ri_font->fontwidth; 429 row *= ri->ri_font->fontheight; 430 fbc = ((struct cgsix_softc *)ri->ri_hw)->sc_fbc; 431 fbc->fbc_clip = 0; 432 fbc->fbc_s = 0; 433 fbc->fbc_offx = 0; 434 fbc->fbc_offy = 0; 435 fbc->fbc_clipminx = 0; 436 fbc->fbc_clipminy = 0; 437 fbc->fbc_clipmaxx = ri->ri_width - 1; 438 fbc->fbc_clipmaxy = ri->ri_height - 1; 439 fbc->fbc_alu = CG6_ALU_FILL; 440 fbc->fbc_fg = ri->ri_devcmap[(attr >> 16) & 0xf]; 441 fbc->fbc_arecty = ri->ri_yorigin + row; 442 fbc->fbc_arectx = ri->ri_xorigin + col; 443 fbc->fbc_arecty = ri->ri_yorigin + row + ri->ri_font->fontheight - 1; 444 fbc->fbc_arectx = ri->ri_xorigin + col + n - 1; 445 CG6_DRAW_WAIT(fbc); 446 CG6_DRAIN(fbc); 447 } 448 449 static void 450 cg6_ras_eraserows(void *cookie, int row, int n, long int attr) 451 { 452 struct rasops_info *ri; 453 volatile struct cg6_fbc *fbc; 454 455 ri = cookie; 456 if (row < 0) { 457 n += row; 458 row = 0; 459 } 460 if (row+n > ri->ri_rows) 461 n = ri->ri_rows - row; 462 if (n <= 0) 463 return; 464 fbc = ((struct cgsix_softc *)ri->ri_hw)->sc_fbc; 465 fbc->fbc_clip = 0; 466 fbc->fbc_s = 0; 467 fbc->fbc_offx = 0; 468 fbc->fbc_offy = 0; 469 fbc->fbc_clipminx = 0; 470 fbc->fbc_clipminy = 0; 471 fbc->fbc_clipmaxx = ri->ri_width - 1; 472 fbc->fbc_clipmaxy = ri->ri_height - 1; 473 fbc->fbc_alu = CG6_ALU_FILL; 474 fbc->fbc_fg = ri->ri_devcmap[(attr >> 16) & 0xf]; 475 if ((n == ri->ri_rows) && (ri->ri_flg & RI_FULLCLEAR)) { 476 fbc->fbc_arecty = 0; 477 fbc->fbc_arectx = 0; 478 fbc->fbc_arecty = ri->ri_height - 1; 479 fbc->fbc_arectx = ri->ri_width - 1; 480 } else { 481 row *= ri->ri_font->fontheight; 482 fbc->fbc_arecty = ri->ri_yorigin + row; 483 fbc->fbc_arectx = ri->ri_xorigin; 484 fbc->fbc_arecty = ri->ri_yorigin + row + (n * ri->ri_font->fontheight) - 1; 485 fbc->fbc_arectx = ri->ri_xorigin + ri->ri_emuwidth - 1; 486 } 487 CG6_DRAW_WAIT(fbc); 488 CG6_DRAIN(fbc); 489 } 490 491 /* 492 * Really want something more like fg^bg here, but that would be more 493 * or less impossible to migrate to colors. So we hope there's 494 * something not too inappropriate in the colormap...besides, it's what 495 * the non-accelerated code did. :-) 496 */ 497 static void 498 cg6_ras_do_cursor(struct rasops_info *ri) 499 { 500 volatile struct cg6_fbc *fbc; 501 int row; 502 int col; 503 504 row = ri->ri_crow * ri->ri_font->fontheight; 505 col = ri->ri_ccol * ri->ri_font->fontwidth; 506 fbc = ((struct cgsix_softc *)ri->ri_hw)->sc_fbc; 507 fbc->fbc_clip = 0; 508 fbc->fbc_s = 0; 509 fbc->fbc_offx = 0; 510 fbc->fbc_offy = 0; 511 fbc->fbc_clipminx = 0; 512 fbc->fbc_clipminy = 0; 513 fbc->fbc_clipmaxx = ri->ri_width - 1; 514 fbc->fbc_clipmaxy = ri->ri_height - 1; 515 fbc->fbc_alu = CG6_ALU_FLIP; 516 fbc->fbc_arecty = ri->ri_yorigin + row; 517 fbc->fbc_arectx = ri->ri_xorigin + col; 518 fbc->fbc_arecty = ri->ri_yorigin + row + ri->ri_font->fontheight - 1; 519 fbc->fbc_arectx = ri->ri_xorigin + col + ri->ri_font->fontwidth - 1; 520 CG6_DRAW_WAIT(fbc); 521 CG6_DRAIN(fbc); 522 } 523 524 void 525 cg6attach(sc, name, isconsole) 526 struct cgsix_softc *sc; 527 char *name; 528 int isconsole; 529 { 530 struct fbdevice *fb = &sc->sc_fb; 531 struct wsemuldisplaydev_attach_args aa; 532 struct rasops_info *ri = &fb->fb_rinfo; 533 unsigned long defattr; 534 535 fb->fb_driver = &cg6_fbdriver; 536 537 /* Don't have to map the pfour register on the cgsix. */ 538 fb->fb_pfour = NULL; 539 540 fb->fb_type.fb_cmsize = 256; 541 fb->fb_type.fb_size = fb->fb_type.fb_height * fb->fb_linebytes; 542 printf(": %s, %d x %d", name, 543 fb->fb_type.fb_width, fb->fb_type.fb_height); 544 if(sc->sc_fhc) { 545 sc->sc_fhcrev = (*sc->sc_fhc >> FHC_REV_SHIFT) & 546 (FHC_REV_MASK >> FHC_REV_SHIFT); 547 } else 548 sc->sc_fhcrev=-1; 549 printf(", rev %d", sc->sc_fhcrev); 550 551 /* reset cursor & frame buffer controls */ 552 cg6_reset(sc); 553 554 /* enable video */ 555 sc->sc_thc->thc_misc |= THC_MISC_VIDEN; 556 557 if (isconsole) { 558 printf(" (console)"); 559 560 /* this is the old console attachment stuff - we shouldn't need it anymore */ 561 #ifdef RASTERCONSOLE 562 if (cgsix_use_rasterconsole) { 563 fbrcons_init(&sc->sc_fb); 564 sc->sc_fb.fb_rinfo.ri_hw = sc; 565 sc->sc_fb.fb_rinfo.ri_ops.copyrows = cg6_ras_copyrows; 566 sc->sc_fb.fb_rinfo.ri_ops.copycols = cg6_ras_copycols; 567 sc->sc_fb.fb_rinfo.ri_ops.erasecols = cg6_ras_erasecols; 568 sc->sc_fb.fb_rinfo.ri_ops.eraserows = cg6_ras_eraserows; 569 sc->sc_fb.fb_rinfo.ri_do_cursor = cg6_ras_do_cursor; 570 cg6_ras_init(sc); 571 } 572 #endif 573 } 574 575 fb_attach(&sc->sc_fb, isconsole); 576 577 /* setup rasops and so on for wsdisplay */ 578 wsfont_init(); 579 /* fill in rasops_info */ 580 ri->ri_hw=sc; 581 ri->ri_width = fb->fb_type.fb_width; 582 ri->ri_height = fb->fb_type.fb_height; 583 ri->ri_depth = 8; 584 ri->ri_stride = fb->fb_linebytes; 585 ri->ri_bits = fb->fb_pixels; 586 ri->ri_flg = RI_FORCEMONO | RI_CENTER | RI_CLEAR; 587 rasops_init(ri, fb->fb_type.fb_height/16, fb->fb_type.fb_width/8); 588 ri->ri_ops.copyrows = cg6_ras_copyrows; 589 ri->ri_ops.copycols = cg6_ras_copycols; 590 ri->ri_ops.erasecols = cg6_ras_erasecols; 591 ri->ri_ops.eraserows = cg6_ras_eraserows; 592 ri->ri_do_cursor = cg6_ras_do_cursor; 593 cg6_ras_init(sc); 594 cgsix_defaultscreen.nrows = ri->ri_rows; 595 cgsix_defaultscreen.ncols = ri->ri_cols; 596 cgsix_defaultscreen.textops = &ri->ri_ops; 597 cgsix_defaultscreen.capabilities = ri->ri_caps; 598 if(isconsole) { 599 (*ri->ri_ops.allocattr)(ri, 0,0,0, &defattr); 600 wsdisplay_cnattach(&cgsix_defaultscreen, ri, 0, 0, defattr); 601 } 602 603 /* set up a colour map matching the terminal emulation in use */ 604 #ifdef WSEMUL_SUN 605 sc->sc_cmap.cm_map[0][0]=255; 606 sc->sc_cmap.cm_map[0][1]=255; 607 sc->sc_cmap.cm_map[0][2]=255; 608 sc->sc_cmap.cm_map[254][0]=255; 609 sc->sc_cmap.cm_map[254][1]=255; 610 sc->sc_cmap.cm_map[254][2]=255; 611 sc->sc_cmap.cm_map[1][0]=0; 612 sc->sc_cmap.cm_map[1][1]=0; 613 sc->sc_cmap.cm_map[1][2]=0; 614 sc->sc_cmap.cm_map[255][0]=0; 615 sc->sc_cmap.cm_map[255][1]=0; 616 sc->sc_cmap.cm_map[255][2]=0; 617 cg6_loadcmap(sc,0,256); 618 #elif defined(WSEMUL_VT100) 619 /* here we should steal the VT100 colour map from rasops */ 620 #endif 621 622 aa.console = isconsole; 623 aa.scrdata = &cgsix_screenlist; 624 aa.accessops = &cgsix_accessops; 625 aa.accesscookie = sc; 626 printf("\n"); 627 628 config_found(&sc->sc_dev, &aa, wsemuldisplaydevprint); 629 630 } 631 632 633 int 634 cgsixopen(dev, flags, mode, p) 635 dev_t dev; 636 int flags, mode; 637 struct proc *p; 638 { 639 int unit = minor(dev); 640 641 if (unit >= cgsix_cd.cd_ndevs || cgsix_cd.cd_devs[unit] == NULL) 642 return (ENXIO); 643 return (0); 644 } 645 646 int 647 cgsixclose(dev, flags, mode, p) 648 dev_t dev; 649 int flags, mode; 650 struct proc *p; 651 { 652 struct cgsix_softc *sc = cgsix_cd.cd_devs[minor(dev)]; 653 654 cg6_reset(sc); 655 656 /* (re-)initialize the default color map */ 657 bt_initcmap(&sc->sc_cmap, 256); 658 cg6_loadcmap(sc, 0, 256); 659 660 return (0); 661 } 662 663 int 664 cgsixioctl(dev, cmd, data, flags, p) 665 dev_t dev; 666 u_long cmd; 667 caddr_t data; 668 int flags; 669 struct proc *p; 670 { 671 struct cgsix_softc *sc = cgsix_cd.cd_devs[minor(dev)]; 672 union cursor_cmap tcm; 673 uint32_t image[32], mask[32]; 674 u_int count; 675 int v, error; 676 677 #ifdef CGSIX_DEBUG 678 printf("cgsixioctl(%ld)\n",cmd); 679 #endif 680 681 switch (cmd) { 682 683 case FBIOGTYPE: 684 *(struct fbtype *)data = sc->sc_fb.fb_type; 685 break; 686 687 case FBIOGATTR: 688 #define fba ((struct fbgattr *)data) 689 fba->real_type = sc->sc_fb.fb_type.fb_type; 690 fba->owner = 0; /* XXX ??? */ 691 fba->fbtype = sc->sc_fb.fb_type; 692 fba->sattr.flags = 0; 693 fba->sattr.emu_type = sc->sc_fb.fb_type.fb_type; 694 fba->sattr.dev_specific[0] = -1; 695 fba->emu_types[0] = sc->sc_fb.fb_type.fb_type; 696 fba->emu_types[1] = -1; 697 #undef fba 698 break; 699 700 case FBIOGETCMAP: 701 #define p ((struct fbcmap *)data) 702 return (bt_getcmap(p, &sc->sc_cmap, 256, 1)); 703 704 case FBIOPUTCMAP: 705 /* copy to software map */ 706 error = bt_putcmap(p, &sc->sc_cmap, 256, 1); 707 if (error) 708 return (error); 709 /* now blast them into the chip */ 710 /* XXX should use retrace interrupt */ 711 cg6_loadcmap(sc, p->index, p->count); 712 #undef p 713 break; 714 715 case FBIOGVIDEO: 716 *(int *)data = sc->sc_blanked; 717 break; 718 719 case FBIOSVIDEO: 720 if (*(int *)data) 721 cg6_unblank(&sc->sc_dev); 722 else if (!sc->sc_blanked) { 723 sc->sc_blanked = 1; 724 sc->sc_thc->thc_misc &= ~THC_MISC_VIDEN; 725 } 726 break; 727 728 /* these are for both FBIOSCURSOR and FBIOGCURSOR */ 729 #define p ((struct fbcursor *)data) 730 #define cc (&sc->sc_cursor) 731 732 case FBIOGCURSOR: 733 /* do not quite want everything here... */ 734 p->set = FB_CUR_SETALL; /* close enough, anyway */ 735 p->enable = cc->cc_enable; 736 p->pos = cc->cc_pos; 737 p->hot = cc->cc_hot; 738 p->size = cc->cc_size; 739 740 /* begin ugh ... can we lose some of this crap?? */ 741 if (p->image != NULL) { 742 count = cc->cc_size.y * 32 / NBBY; 743 error = copyout(cc->cc_bits[1], p->image, count); 744 if (error) 745 return (error); 746 error = copyout(cc->cc_bits[0], p->mask, count); 747 if (error) 748 return (error); 749 } 750 if (p->cmap.red != NULL) { 751 error = bt_getcmap(&p->cmap, 752 (union bt_cmap *)&cc->cc_color, 2, 1); 753 if (error) 754 return (error); 755 } else { 756 p->cmap.index = 0; 757 p->cmap.count = 2; 758 } 759 /* end ugh */ 760 break; 761 762 case FBIOSCURSOR: 763 /* 764 * For setcmap and setshape, verify parameters, so that 765 * we do not get halfway through an update and then crap 766 * out with the software state screwed up. 767 */ 768 v = p->set; 769 if (v & FB_CUR_SETCMAP) { 770 /* 771 * This use of a temporary copy of the cursor 772 * colormap is not terribly efficient, but these 773 * copies are small (8 bytes)... 774 */ 775 tcm = cc->cc_color; 776 error = bt_putcmap(&p->cmap, (union bt_cmap *)&tcm, 2, 1); 777 if (error) 778 return (error); 779 } 780 if (v & FB_CUR_SETSHAPE) { 781 if ((u_int)p->size.x > 32 || (u_int)p->size.y > 32) 782 return (EINVAL); 783 count = p->size.y * 32 / NBBY; 784 error = copyin(p->image, image, count); 785 if (error) 786 return error; 787 error = copyin(p->mask, mask, count); 788 if (error) 789 return error; 790 } 791 792 /* parameters are OK; do it */ 793 if (v & (FB_CUR_SETCUR | FB_CUR_SETPOS | FB_CUR_SETHOT)) { 794 if (v & FB_CUR_SETCUR) 795 cc->cc_enable = p->enable; 796 if (v & FB_CUR_SETPOS) 797 cc->cc_pos = p->pos; 798 if (v & FB_CUR_SETHOT) 799 cc->cc_hot = p->hot; 800 cg6_setcursor(sc); 801 } 802 if (v & FB_CUR_SETCMAP) { 803 cc->cc_color = tcm; 804 cg6_loadomap(sc); /* XXX defer to vertical retrace */ 805 } 806 if (v & FB_CUR_SETSHAPE) { 807 cc->cc_size = p->size; 808 count = p->size.y * 32 / NBBY; 809 memset(cc->cc_bits, 0, sizeof cc->cc_bits); 810 memcpy(cc->cc_bits[1], image, count); 811 memcpy(cc->cc_bits[0], mask, count); 812 cg6_loadcursor(sc); 813 } 814 break; 815 816 #undef p 817 #undef cc 818 819 case FBIOGCURPOS: 820 *(struct fbcurpos *)data = sc->sc_cursor.cc_pos; 821 break; 822 823 case FBIOSCURPOS: 824 sc->sc_cursor.cc_pos = *(struct fbcurpos *)data; 825 cg6_setcursor(sc); 826 break; 827 828 case FBIOGCURMAX: 829 /* max cursor size is 32x32 */ 830 ((struct fbcurpos *)data)->x = 32; 831 ((struct fbcurpos *)data)->y = 32; 832 break; 833 834 default: 835 #ifdef DEBUG 836 log(LOG_NOTICE, "cgsixioctl(0x%lx) (%s[%d])\n", cmd, 837 p->p_comm, p->p_pid); 838 #endif 839 return (ENOTTY); 840 } 841 return (0); 842 } 843 844 /* 845 * Clean up hardware state (e.g., after bootup or after X crashes). 846 */ 847 static void 848 cg6_reset(sc) 849 struct cgsix_softc *sc; 850 { 851 volatile struct cg6_tec_xxx *tec; 852 int fhc; 853 volatile struct bt_regs *bt; 854 855 /* hide the cursor, just in case */ 856 sc->sc_thc->thc_cursxy = (THC_CURSOFF << 16) | THC_CURSOFF; 857 858 /* turn off frobs in transform engine (makes X11 work) */ 859 tec = sc->sc_tec; 860 tec->tec_mv = 0; 861 tec->tec_clip = 0; 862 tec->tec_vdc = 0; 863 864 /* take care of hardware bugs in old revisions */ 865 if (sc->sc_fhcrev < 5) { 866 /* 867 * Keep current resolution; set CPU to 68020, set test 868 * window (size 1Kx1K), and for rev 1, disable dest cache. 869 */ 870 fhc = (*sc->sc_fhc & FHC_RES_MASK) | FHC_CPU_68020 | 871 FHC_TEST | 872 (11 << FHC_TESTX_SHIFT) | (11 << FHC_TESTY_SHIFT); 873 if (sc->sc_fhcrev < 2) 874 fhc |= FHC_DST_DISABLE; 875 *sc->sc_fhc = fhc; 876 } 877 878 /* Enable cursor in Brooktree DAC. */ 879 bt = sc->sc_bt; 880 bt->bt_addr = 0x06 << 24; 881 bt->bt_ctrl |= 0x03 << 24; 882 } 883 884 static void 885 cg6_setcursor(sc) 886 struct cgsix_softc *sc; 887 { 888 889 /* we need to subtract the hot-spot value here */ 890 #define COORD(f) (sc->sc_cursor.cc_pos.f - sc->sc_cursor.cc_hot.f) 891 sc->sc_thc->thc_cursxy = sc->sc_cursor.cc_enable ? 892 ((COORD(x) << 16) | (COORD(y) & 0xffff)) : 893 (THC_CURSOFF << 16) | THC_CURSOFF; 894 #undef COORD 895 } 896 897 static void 898 cg6_loadcursor(sc) 899 struct cgsix_softc *sc; 900 { 901 volatile struct cg6_thc *thc; 902 u_int edgemask, m; 903 int i; 904 905 /* 906 * Keep the top size.x bits. Here we *throw out* the top 907 * size.x bits from an all-one-bits word, introducing zeros in 908 * the top size.x bits, then invert all the bits to get what 909 * we really wanted as our mask. But this fails if size.x is 910 * 32---a sparc uses only the low 5 bits of the shift count--- 911 * so we have to special case that. 912 */ 913 edgemask = ~0; 914 if (sc->sc_cursor.cc_size.x < 32) 915 edgemask = ~(edgemask >> sc->sc_cursor.cc_size.x); 916 thc = sc->sc_thc; 917 for (i = 0; i < 32; i++) { 918 m = sc->sc_cursor.cc_bits[0][i] & edgemask; 919 thc->thc_cursmask[i] = m; 920 thc->thc_cursbits[i] = m & sc->sc_cursor.cc_bits[1][i]; 921 } 922 } 923 924 /* 925 * Load a subset of the current (new) colormap into the color DAC. 926 */ 927 static void 928 cg6_loadcmap(sc, start, ncolors) 929 struct cgsix_softc *sc; 930 int start, ncolors; 931 { 932 volatile struct bt_regs *bt; 933 u_int *ip, i; 934 int count; 935 936 ip = &sc->sc_cmap.cm_chip[BT_D4M3(start)]; /* start/4 * 3 */ 937 count = BT_D4M3(start + ncolors - 1) - BT_D4M3(start) + 3; 938 bt = sc->sc_bt; 939 bt->bt_addr = BT_D4M4(start) << 24; 940 while (--count >= 0) { 941 i = *ip++; 942 /* hardware that makes one want to pound boards with hammers */ 943 bt->bt_cmap = i; 944 bt->bt_cmap = i << 8; 945 bt->bt_cmap = i << 16; 946 bt->bt_cmap = i << 24; 947 } 948 } 949 950 /* 951 * Load the cursor (overlay `foreground' and `background') colors. 952 */ 953 static void 954 cg6_loadomap(sc) 955 struct cgsix_softc *sc; 956 { 957 volatile struct bt_regs *bt; 958 u_int i; 959 960 bt = sc->sc_bt; 961 bt->bt_addr = 0x01 << 24; /* set background color */ 962 i = sc->sc_cursor.cc_color.cm_chip[0]; 963 bt->bt_omap = i; /* R */ 964 bt->bt_omap = i << 8; /* G */ 965 bt->bt_omap = i << 16; /* B */ 966 967 bt->bt_addr = 0x03 << 24; /* set foreground color */ 968 bt->bt_omap = i << 24; /* R */ 969 i = sc->sc_cursor.cc_color.cm_chip[1]; 970 bt->bt_omap = i; /* G */ 971 bt->bt_omap = i << 8; /* B */ 972 } 973 974 static void 975 cg6_unblank(dev) 976 struct device *dev; 977 { 978 struct cgsix_softc *sc = (struct cgsix_softc *)dev; 979 980 if (sc->sc_blanked) { 981 sc->sc_blanked = 0; 982 sc->sc_thc->thc_misc |= THC_MISC_VIDEN; 983 } 984 } 985 986 /* XXX the following should be moved to a "user interface" header */ 987 /* 988 * Base addresses at which users can mmap() the various pieces of a cg6. 989 * Note that although the Brooktree color registers do not occupy 8K, 990 * the X server dies if we do not allow it to map 8K there (it just maps 991 * from 0x70000000 forwards, as a contiguous chunk). 992 */ 993 #define CG6_USER_FBC 0x70000000 994 #define CG6_USER_TEC 0x70001000 995 #define CG6_USER_BTREGS 0x70002000 996 #define CG6_USER_FHC 0x70004000 997 #define CG6_USER_THC 0x70005000 998 #define CG6_USER_ROM 0x70006000 999 #define CG6_USER_RAM 0x70016000 1000 #define CG6_USER_DHC 0x80000000 1001 1002 struct mmo { 1003 u_long mo_uaddr; /* user (virtual) address */ 1004 u_long mo_size; /* size, or 0 for video ram size */ 1005 u_long mo_physoff; /* offset from sc_physadr */ 1006 }; 1007 1008 /* 1009 * Return the address that would map the given device at the given 1010 * offset, allowing for the given protection, or return -1 for error. 1011 * 1012 * XXX needs testing against `demanding' applications (e.g., aviator) 1013 */ 1014 paddr_t 1015 cgsixmmap(dev, off, prot) 1016 dev_t dev; 1017 off_t off; 1018 int prot; 1019 { 1020 struct cgsix_softc *sc = cgsix_cd.cd_devs[minor(dev)]; 1021 struct mmo *mo; 1022 u_int u, sz; 1023 static struct mmo mmo[] = { 1024 { CG6_USER_RAM, 0, CGSIX_RAM_OFFSET }, 1025 1026 /* do not actually know how big most of these are! */ 1027 { CG6_USER_FBC, 1, CGSIX_FBC_OFFSET }, 1028 { CG6_USER_TEC, 1, CGSIX_TEC_OFFSET }, 1029 { CG6_USER_BTREGS, 8192 /* XXX */, CGSIX_BT_OFFSET }, 1030 { CG6_USER_FHC, 1, CGSIX_FHC_OFFSET }, 1031 { CG6_USER_THC, sizeof(struct cg6_thc), CGSIX_THC_OFFSET }, 1032 { CG6_USER_ROM, 65536, CGSIX_ROM_OFFSET }, 1033 { CG6_USER_DHC, 1, CGSIX_DHC_OFFSET }, 1034 }; 1035 #define NMMO (sizeof mmo / sizeof *mmo) 1036 1037 if (off & PGOFSET) 1038 panic("cgsixmmap"); 1039 1040 /* 1041 * Entries with size 0 map video RAM (i.e., the size in fb data). 1042 * 1043 * Since we work in pages, the fact that the map offset table's 1044 * sizes are sometimes bizarre (e.g., 1) is effectively ignored: 1045 * one byte is as good as one page. 1046 */ 1047 for (mo = mmo; mo < &mmo[NMMO]; mo++) { 1048 if ((u_long)off < mo->mo_uaddr) 1049 continue; 1050 u = off - mo->mo_uaddr; 1051 sz = mo->mo_size ? mo->mo_size : sc->sc_fb.fb_type.fb_size; 1052 if (u < sz) { 1053 return (bus_space_mmap(sc->sc_bustag, 1054 sc->sc_paddr, u+mo->mo_physoff, 1055 prot, BUS_SPACE_MAP_LINEAR)); 1056 } 1057 } 1058 1059 #ifdef DEBUG 1060 { 1061 struct proc *p = curlwp->l_proc; /* XXX */ 1062 log(LOG_NOTICE, "cgsixmmap(0x%llx) (%s[%d])\n", 1063 (long long)off, p->p_comm, p->p_pid); 1064 } 1065 #endif 1066 return (-1); /* not a user-map offset */ 1067 } 1068 1069 /* dummies for multiple screen handling */ 1070 int 1071 cgsix_alloc_screen(v, type, cookiep, curxp, curyp, attrp) 1072 void *v; 1073 const struct wsscreen_descr *type; 1074 void **cookiep; 1075 int *curxp, *curyp; 1076 long *attrp; 1077 { 1078 /*struct cg6_softc *sc = v; 1079 struct rasops_info *ri = &sc->sc_dc->dc_ri; 1080 long defattr;*/ 1081 1082 return (ENOMEM); 1083 } 1084 1085 void 1086 cgsix_free_screen(v, cookie) 1087 void *v; 1088 void *cookie; 1089 { 1090 /*struct cg6_softc *sc = v;*/ 1091 } 1092 1093 int 1094 cgsix_show_screen(v, cookie, waitok, cb, cbarg) 1095 void *v; 1096 void *cookie; 1097 int waitok; 1098 void (*cb) __P((void *, int, int)); 1099 void *cbarg; 1100 { 1101 1102 return (0); 1103 } 1104 1105 int 1106 cgsix_ioctl(void *v, u_long cmd, caddr_t data, int flag, struct proc *p) 1107 { 1108 /* we'll probably need to add more stuff here */ 1109 struct cgsix_softc *sc = v; 1110 struct wsdisplay_fbinfo *wdf; 1111 struct rasops_info *ri = &sc->sc_fb.fb_rinfo; 1112 #ifdef CGSIX_DEBUG 1113 printf("cgsix_ioctl(%ld)\n",cmd); 1114 #endif 1115 switch (cmd) { 1116 case WSDISPLAYIO_GTYPE: 1117 *(u_int *)data = WSDISPLAY_TYPE_SUNTCX; 1118 return 0; 1119 case WSDISPLAYIO_GINFO: 1120 wdf = (void *)data; 1121 wdf->height = ri->ri_height; 1122 wdf->width = ri->ri_width; 1123 wdf->depth = ri->ri_depth; 1124 wdf->cmsize = 256; 1125 return 0; 1126 1127 case WSDISPLAYIO_GETCMAP: 1128 return cgsix_getcmap(sc, (struct wsdisplay_cmap *)data); 1129 case WSDISPLAYIO_PUTCMAP: 1130 return cgsix_putcmap(sc, (struct wsdisplay_cmap *)data); 1131 1132 #ifdef notyet 1133 case WSDISPLAYIO_SMODE: 1134 { 1135 int new_mode=*(int*)data; 1136 if(new_mode!=sc->sc_mode) 1137 { 1138 sc->sc_mode=new_mode; 1139 if(new_mode==WSDISPLAYIO_MODE_EMUL) 1140 { 1141 /* we'll probably want to reset the console into a known state here 1142 just in case the Xserver crashed or didn't properly clean up after 1143 itself for whetever reason */ 1144 } 1145 } 1146 } 1147 #endif 1148 } 1149 return EPASSTHROUGH; 1150 } 1151 1152 paddr_t 1153 cgsix_mmap(void *v, off_t offset, int prot) 1154 { 1155 struct cgsix_softc *sc = v; 1156 /* how do I get the real RAM size? */ 1157 int ramsize=sc->sc_fb.fb_type.fb_height * sc->sc_fb.fb_linebytes; 1158 if(offset<ramsize) { 1159 return bus_space_mmap(sc->sc_bustag,sc->sc_paddr,CGSIX_RAM_OFFSET+offset,prot,BUS_SPACE_MAP_LINEAR); 1160 } 1161 /* I'm not at all sure this is the right thing to do */ 1162 return cgsixmmap(0,offset,prot); /* assume we're minor dev 0 for now */ 1163 } 1164 1165 int 1166 cgsix_putcmap(struct cgsix_softc *sc, struct wsdisplay_cmap *cm) 1167 { 1168 u_int index = cm->index; 1169 u_int count = cm->count; 1170 int error,i; 1171 1172 if (index >= 256 || count > 256 || index + count > 256) 1173 return EINVAL; 1174 1175 for(i=0;i<count;i++) 1176 { 1177 error = copyin(&cm->red[i], &sc->sc_cmap.cm_map[index+i][0], 1); 1178 if (error) 1179 return error; 1180 error = copyin(&cm->green[i], &sc->sc_cmap.cm_map[index+i][1], 1); 1181 if (error) 1182 return error; 1183 error = copyin(&cm->blue[i], &sc->sc_cmap.cm_map[index+i][2], 1); 1184 if (error) 1185 return error; 1186 } 1187 cg6_loadcmap(sc,index,count); 1188 1189 return 0; 1190 } 1191 1192 int cgsix_getcmap(struct cgsix_softc *sc, struct wsdisplay_cmap *cm) 1193 { 1194 u_int index = cm->index; 1195 u_int count = cm->count; 1196 int error,i; 1197 1198 if (index >= 256 || count > 256 || index + count > 256) 1199 return EINVAL; 1200 1201 for(i=0;i<count;i++) 1202 { 1203 error = copyout(&sc->sc_cmap.cm_map[index+i][0], &cm->red[i],1); 1204 if (error) 1205 return error; 1206 error = copyout(&sc->sc_cmap.cm_map[index+i][1], &cm->green[i],1); 1207 if (error) 1208 return error; 1209 error = copyout(&sc->sc_cmap.cm_map[index+i][2], &cm->blue[i],1); 1210 if (error) 1211 return error; 1212 } 1213 1214 return 0; 1215 } 1216