Home | History | Annotate | Line # | Download | only in pci
tga.c revision 1.2
      1 /* $NetBSD: tga.c,v 1.2 1998/04/16 12:52:42 drochner Exp $ */
      2 
      3 /*
      4  * Copyright (c) 1995, 1996 Carnegie-Mellon University.
      5  * All rights reserved.
      6  *
      7  * Author: Chris G. Demetriou
      8  *
      9  * Permission to use, copy, modify and distribute this software and
     10  * its documentation is hereby granted, provided that both the copyright
     11  * notice and this permission notice appear in all copies of the
     12  * software, derivative works or modified versions, and any portions
     13  * thereof, and that both notices appear in supporting documentation.
     14  *
     15  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
     16  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
     17  * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
     18  *
     19  * Carnegie Mellon requests users of this software to return to
     20  *
     21  *  Software Distribution Coordinator  or  Software.Distribution (at) CS.CMU.EDU
     22  *  School of Computer Science
     23  *  Carnegie Mellon University
     24  *  Pittsburgh PA 15213-3890
     25  *
     26  * any improvements or extensions that they make and grant Carnegie the
     27  * rights to redistribute these changes.
     28  */
     29 
     30 #include <sys/param.h>
     31 #include <sys/systm.h>
     32 #include <sys/kernel.h>
     33 #include <sys/device.h>
     34 #include <sys/conf.h>
     35 #include <sys/malloc.h>
     36 #include <sys/buf.h>
     37 #include <sys/ioctl.h>
     38 
     39 #include <machine/bus.h>
     40 #include <machine/intr.h>
     41 
     42 #include <dev/pci/pcireg.h>
     43 #include <dev/pci/pcivar.h>
     44 #include <dev/pci/pcidevs.h>
     45 #include <dev/pci/tgareg.h>
     46 #include <dev/pci/tgavar.h>
     47 #include <dev/ic/bt485reg.h>
     48 
     49 #include <dev/rcons/raster.h>
     50 #include <dev/wscons/wsconsio.h>
     51 #include <dev/wscons/wscons_raster.h>
     52 #include <dev/wscons/wsdisplayvar.h>
     53 
     54 #ifdef __alpha__
     55 #include <machine/pte.h>
     56 #endif
     57 
     58 int	tgamatch __P((struct device *, struct cfdata *, void *));
     59 void	tgaattach __P((struct device *, struct device *, void *));
     60 int	tgaprint __P((void *, const char *));
     61 
     62 struct cfattach tga_ca = {
     63 	sizeof(struct tga_softc), tgamatch, tgaattach,
     64 };
     65 
     66 int	tga_identify __P((tga_reg_t *));
     67 const struct tga_conf *tga_getconf __P((int));
     68 void	tga_getdevconfig __P((bus_space_tag_t memt, pci_chipset_tag_t pc,
     69 	    pcitag_t tag, struct tga_devconfig *dc));
     70 
     71 struct tga_devconfig tga_console_dc;
     72 
     73 struct wsdisplay_emulops tga_emulops = {
     74 	rcons_cursor,			/* could use hardware cursor; punt */
     75 	rcons_putstr,
     76 	rcons_copycols,
     77 	rcons_erasecols,
     78 	rcons_copyrows,
     79 	rcons_eraserows,
     80 };
     81 
     82 struct wsscreen_descr tga_stdscreen = {
     83 	"std",
     84 	0, 0,	/* will be filled in */
     85 	&tga_emulops,
     86 	0, 0
     87 };
     88 
     89 const struct wsscreen_descr *_tga_scrlist[] = {
     90 	&tga_stdscreen,
     91 	/* XXX other formats, graphics screen? */
     92 };
     93 
     94 struct wsscreen_list tga_screenlist = {
     95 	sizeof(_tga_scrlist) / sizeof(struct wsscreen_descr *), _tga_scrlist
     96 };
     97 
     98 int	tga_ioctl __P((void *, u_long, caddr_t, int, struct proc *));
     99 int	tga_mmap __P((void *, off_t, int));
    100 static int	tga_alloc_screen __P((void *, const struct wsscreen_descr *,
    101 				      void **, int *, int *));
    102 static void	tga_free_screen __P((void *, void *));
    103 static void	tga_show_screen __P((void *, void *));
    104 static int	tga_load_font __P((void *, void *, int, int, int, void *));
    105 
    106 struct wsdisplay_accessops tga_accessops = {
    107 	tga_ioctl,
    108 	tga_mmap,
    109 	tga_alloc_screen,
    110 	tga_free_screen,
    111 	tga_show_screen,
    112 	tga_load_font
    113 };
    114 
    115 void	tga_blank __P((struct tga_devconfig *));
    116 void	tga_unblank __P((struct tga_devconfig *));
    117 
    118 int
    119 tgamatch(parent, match, aux)
    120 	struct device *parent;
    121 	struct cfdata *match;
    122 	void *aux;
    123 {
    124 	struct pci_attach_args *pa = aux;
    125 
    126 	if (PCI_VENDOR(pa->pa_id) != PCI_VENDOR_DEC ||
    127 	    PCI_PRODUCT(pa->pa_id) != PCI_PRODUCT_DEC_21030)
    128 		return (0);
    129 
    130 	return (10);
    131 }
    132 
    133 void
    134 tga_getdevconfig(memt, pc, tag, dc)
    135 	bus_space_tag_t memt;
    136 	pci_chipset_tag_t pc;
    137 	pcitag_t tag;
    138 	struct tga_devconfig *dc;
    139 {
    140 	const struct tga_conf *tgac;
    141 	const struct tga_ramdac_conf *tgar;
    142 	struct raster *rap;
    143 	struct rcons *rcp;
    144 	bus_size_t pcisize;
    145 	int i, flags;
    146 
    147 	dc->dc_memt = memt;
    148 	dc->dc_pc = pc;
    149 
    150 	dc->dc_pcitag = tag;
    151 
    152 	/* XXX magic number */
    153 	if (pci_mapreg_info(pc, tag, 0x10,
    154 	    PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT,
    155 	    &dc->dc_pcipaddr, &pcisize, &flags))
    156 		return;
    157 	if ((flags & BUS_SPACE_MAP_CACHEABLE) == 0)		/* XXX */
    158 		panic("tga memory not cacheable");
    159 
    160 	if (bus_space_map(memt, dc->dc_pcipaddr, pcisize,
    161 	    BUS_SPACE_MAP_CACHEABLE | BUS_SPACE_MAP_LINEAR, &dc->dc_vaddr))
    162 		return;
    163 #ifdef __alpha__
    164 	dc->dc_paddr = ALPHA_K0SEG_TO_PHYS(dc->dc_vaddr);	/* XXX */
    165 #endif
    166 
    167 	dc->dc_regs = (tga_reg_t *)(dc->dc_vaddr + TGA_MEM_CREGS);
    168 	dc->dc_tga_type = tga_identify(dc->dc_regs);
    169 	tgac = dc->dc_tgaconf = tga_getconf(dc->dc_tga_type);
    170 	if (tgac == NULL)
    171 		return;
    172 
    173 #if 0
    174 	/* XXX on the Alpha, pcisize = 4 * cspace_size. */
    175 	if (tgac->tgac_cspace_size != pcisize)			/* sanity */
    176 		panic("tga_getdevconfig: memory size mismatch?");
    177 #endif
    178 
    179 	tgar = tgac->tgac_ramdac;
    180 
    181 	switch (dc->dc_regs[TGA_REG_VHCR] & 0x1ff) {		/* XXX */
    182 	case 0:
    183 		dc->dc_wid = 8192;
    184 		break;
    185 
    186 	case 1:
    187 		dc->dc_wid = 8196;
    188 		break;
    189 
    190 	default:
    191 		dc->dc_wid = (dc->dc_regs[TGA_REG_VHCR] & 0x1ff) * 4; /* XXX */
    192 		break;
    193 	}
    194 
    195 	dc->dc_rowbytes = dc->dc_wid * (dc->dc_tgaconf->tgac_phys_depth / 8);
    196 
    197 	if ((dc->dc_regs[TGA_REG_VHCR] & 0x00000001) != 0 &&	/* XXX */
    198 	    (dc->dc_regs[TGA_REG_VHCR] & 0x80000000) != 0) {	/* XXX */
    199 		dc->dc_wid -= 4;
    200 		/*
    201 		 * XXX XXX turning off 'odd' shouldn't be necesssary,
    202 		 * XXX XXX but i can't make X work with the weird size.
    203 		 */
    204 		dc->dc_regs[TGA_REG_VHCR] &= ~0x80000001;
    205 		dc->dc_rowbytes =
    206 		    dc->dc_wid * (dc->dc_tgaconf->tgac_phys_depth / 8);
    207 	}
    208 
    209 	dc->dc_ht = (dc->dc_regs[TGA_REG_VVCR] & 0x7ff);	/* XXX */
    210 
    211 	/* XXX this seems to be what DEC does */
    212 	dc->dc_regs[TGA_REG_CCBR] = 0;
    213 	dc->dc_regs[TGA_REG_VVBR] = 1;
    214 	dc->dc_videobase = dc->dc_vaddr + tgac->tgac_dbuf[0] +
    215 	    1 * tgac->tgac_vvbr_units;
    216 	dc->dc_blanked = 1;
    217 	tga_unblank(dc);
    218 
    219 	/*
    220 	 * Set all bits in the pixel mask, to enable writes to all pixels.
    221 	 * It seems that the console firmware clears some of them
    222 	 * under some circumstances, which causes cute vertical stripes.
    223 	 */
    224 	dc->dc_regs[TGA_REG_GPXR_P] = 0xffffffff;
    225 
    226 	/* clear the screen */
    227 	for (i = 0; i < dc->dc_ht * dc->dc_rowbytes; i += sizeof(u_int32_t))
    228 		*(u_int32_t *)(dc->dc_videobase + i) = 0;
    229 
    230 	/* initialize the raster */
    231 	rap = &dc->dc_raster;
    232 	rap->width = dc->dc_wid;
    233 	rap->height = dc->dc_ht;
    234 	rap->depth = tgac->tgac_phys_depth;
    235 	rap->linelongs = dc->dc_rowbytes / sizeof(u_int32_t);
    236 	rap->pixels = (u_int32_t *)dc->dc_videobase;
    237 
    238 	/* initialize the raster console blitter */
    239 	rcp = &dc->dc_rcons;
    240 	rcp->rc_sp = rap;
    241 	rcp->rc_crow = rcp->rc_ccol = -1;
    242 	rcp->rc_crowp = &rcp->rc_crow;
    243 	rcp->rc_ccolp = &rcp->rc_ccol;
    244 	rcons_init(rcp, 34, 80);
    245 
    246 	tga_stdscreen.nrows = dc->dc_rcons.rc_maxrow;
    247 	tga_stdscreen.ncols = dc->dc_rcons.rc_maxcol;
    248 }
    249 
    250 void
    251 tgaattach(parent, self, aux)
    252 	struct device *parent, *self;
    253 	void *aux;
    254 {
    255 	struct pci_attach_args *pa = aux;
    256 	struct tga_softc *sc = (struct tga_softc *)self;
    257 	struct wsemuldisplaydev_attach_args aa;
    258 	pci_intr_handle_t intrh;
    259 	const char *intrstr;
    260 	u_int8_t rev;
    261 	int console;
    262 
    263 #ifdef __alpha__
    264 	console = (pa->pa_tag == tga_console_dc.dc_pcitag);
    265 #else
    266 	console = 0;
    267 #endif
    268 	if (console) {
    269 		sc->sc_dc = &tga_console_dc;
    270 		sc->nscreens = 1;
    271 	} else {
    272 		sc->sc_dc = (struct tga_devconfig *)
    273 		    malloc(sizeof(struct tga_devconfig), M_DEVBUF, M_WAITOK);
    274 		tga_getdevconfig(pa->pa_memt, pa->pa_pc, pa->pa_tag, sc->sc_dc);
    275 	}
    276 	if (sc->sc_dc->dc_vaddr == NULL) {
    277 		printf(": couldn't map memory space; punt!\n");
    278 		return;
    279 	}
    280 
    281 	/* XXX say what's going on. */
    282 	intrstr = NULL;
    283 	if (sc->sc_dc->dc_tgaconf->tgac_ramdac->tgar_intr != NULL) {
    284 		if (pci_intr_map(pa->pa_pc, pa->pa_intrtag, pa->pa_intrpin,
    285 		    pa->pa_intrline, &intrh)) {
    286 			printf(": couldn't map interrupt");
    287 			return;
    288 		}
    289 		intrstr = pci_intr_string(pa->pa_pc, intrh);
    290 		sc->sc_intr = pci_intr_establish(pa->pa_pc, intrh, IPL_TTY,
    291 		    sc->sc_dc->dc_tgaconf->tgac_ramdac->tgar_intr, sc->sc_dc);
    292 		if (sc->sc_intr == NULL) {
    293 			printf(": couldn't establish interrupt");
    294 			if (intrstr != NULL)
    295 				printf("at %s", intrstr);
    296 			printf("\n");
    297 			return;
    298 		}
    299 	}
    300 
    301 	/*
    302 	 * Initialize the RAMDAC and allocate any private storage it needs.
    303 	 * Initialization includes disabling cursor, setting a sane
    304 	 * colormap, etc.
    305 	 */
    306 	(*sc->sc_dc->dc_tgaconf->tgac_ramdac->tgar_init)(sc->sc_dc, 1);
    307 
    308 	printf(": DC21030 ");
    309 	rev = PCI_REVISION(pa->pa_class);
    310 	switch (rev) {
    311 	case 1: case 2: case 3:
    312 		printf("step %c", 'A' + rev - 1);
    313 		break;
    314 
    315 	default:
    316 		printf("unknown stepping (0x%x)", rev);
    317 		break;
    318 	}
    319 	printf(", ");
    320 
    321 	if (sc->sc_dc->dc_tgaconf == NULL) {
    322 		printf("unknown board configuration\n");
    323 		return;
    324 	}
    325 	printf("board type %s\n", sc->sc_dc->dc_tgaconf->tgac_name);
    326 	printf("%s: %d x %d, %dbpp, %s RAMDAC\n", sc->sc_dev.dv_xname,
    327 	    sc->sc_dc->dc_wid, sc->sc_dc->dc_ht,
    328 	    sc->sc_dc->dc_tgaconf->tgac_phys_depth,
    329 	    sc->sc_dc->dc_tgaconf->tgac_ramdac->tgar_name);
    330 
    331 	if (intrstr != NULL)
    332 		printf("%s: interrupting at %s\n", sc->sc_dev.dv_xname,
    333 		    intrstr);
    334 
    335 	aa.console = console;
    336 	aa.scrdata = &tga_screenlist;
    337 	aa.accessops = &tga_accessops;
    338 	aa.accesscookie = sc;
    339 
    340 	config_found(self, &aa, wsemuldisplaydevprint);
    341 }
    342 
    343 int
    344 tga_ioctl(v, cmd, data, flag, p)
    345 	void *v;
    346 	u_long cmd;
    347 	caddr_t data;
    348 	int flag;
    349 	struct proc *p;
    350 {
    351 	struct tga_softc *sc = v;
    352 	struct tga_devconfig *dc = sc->sc_dc;
    353 	const struct tga_ramdac_conf *tgar = dc->dc_tgaconf->tgac_ramdac;
    354 
    355 	switch (cmd) {
    356 	case WSDISPLAYIO_GTYPE:
    357 		*(u_int *)data = WSDISPLAY_TYPE_TGA;
    358 		return (0);
    359 
    360 	case WSDISPLAYIO_GINFO:
    361 #define	wsd_fbip ((struct wsdisplay_fbinfo *)data)
    362 		wsd_fbip->height = sc->sc_dc->dc_ht;
    363 		wsd_fbip->width = sc->sc_dc->dc_wid;
    364 		wsd_fbip->depth = sc->sc_dc->dc_tgaconf->tgac_phys_depth;
    365 		wsd_fbip->cmsize = 256;		/* XXX ??? */
    366 #undef fbt
    367 		return (0);
    368 
    369 	case WSDISPLAYIO_GETCMAP:
    370 		return (*tgar->tgar_get_cmap)(dc,
    371 		    (struct wsdisplay_cmap *)data);
    372 
    373 	case WSDISPLAYIO_PUTCMAP:
    374 		return (*tgar->tgar_set_cmap)(dc,
    375 		    (struct wsdisplay_cmap *)data);
    376 
    377 	case WSDISPLAYIO_GVIDEO:
    378 		if (*(u_int *)data == WSDISPLAYIO_VIDEO_OFF)
    379 			tga_blank(sc->sc_dc);
    380 		else
    381 			tga_unblank(sc->sc_dc);
    382 		return (0);
    383 
    384 	case WSDISPLAYIO_SVIDEO:
    385 		*(u_int *)data = dc->dc_blanked ?
    386 		    WSDISPLAYIO_VIDEO_OFF : WSDISPLAYIO_VIDEO_ON;
    387 		return (0);
    388 
    389 	case WSDISPLAYIO_GCURPOS:
    390 		return (*tgar->tgar_get_curpos)(dc,
    391 		    (struct wsdisplay_curpos *)data);
    392 
    393 	case WSDISPLAYIO_SCURPOS:
    394 		return (*tgar->tgar_set_curpos)(dc,
    395 		    (struct wsdisplay_curpos *)data);
    396 
    397 	case WSDISPLAYIO_GCURMAX:
    398 		return (*tgar->tgar_get_curmax)(dc,
    399 		    (struct wsdisplay_curpos *)data);
    400 
    401 	case WSDISPLAYIO_GCURSOR:
    402 		return (*tgar->tgar_get_cursor)(dc,
    403 		    (struct wsdisplay_cursor *)data);
    404 
    405 	case WSDISPLAYIO_SCURSOR:
    406 		return (*tgar->tgar_set_cursor)(dc,
    407 		    (struct wsdisplay_cursor *)data);
    408 	}
    409 	return (-1);
    410 }
    411 
    412 int
    413 tga_mmap(v, offset, prot)
    414 	void *v;
    415 	off_t offset;
    416 	int prot;
    417 {
    418 
    419 	/* XXX NEW MAPPING CODE... */
    420 
    421 #ifdef __alpha__
    422 	struct tga_softc *sc = v;
    423 
    424 	if (offset > sc->sc_dc->dc_tgaconf->tgac_cspace_size)
    425 		return -1;
    426 	return alpha_btop(sc->sc_dc->dc_paddr + offset);
    427 #else
    428 	return (-1);
    429 #endif
    430 }
    431 
    432 int
    433 tga_alloc_screen(v, type, cookiep, curxp, curyp)
    434 	void *v;
    435 	const struct wsscreen_descr *type;
    436 	void **cookiep;
    437 	int *curxp, *curyp;
    438 {
    439 	struct tga_softc *sc = v;
    440 
    441 	if (sc->nscreens > 0)
    442 		return (ENOMEM);
    443 
    444 	*cookiep = &sc->sc_dc->dc_rcons; /* one and only for now */
    445 	*curxp = 0;
    446 	*curyp = 0;
    447 	sc->nscreens++;
    448 	return (0);
    449 }
    450 
    451 void
    452 tga_free_screen(v, cookie)
    453 	void *v;
    454 	void *cookie;
    455 {
    456 	struct tga_softc *sc = v;
    457 
    458 	if (sc->sc_dc == &tga_console_dc)
    459 		panic("tga_free_screen: console");
    460 
    461 	sc->nscreens--;
    462 }
    463 
    464 void
    465 tga_show_screen(v, cookie)
    466 	void *v;
    467 	void *cookie;
    468 {
    469 }
    470 
    471 static int
    472 tga_load_font(v, cookie, first, num, stride, data)
    473 	void *v;
    474 	void *cookie;
    475 	int first, num, stride;
    476 	void *data;
    477 {
    478 	return (EINVAL);
    479 }
    480 
    481 int
    482 tga_cnattach(iot, memt, pc, bus, device, function)
    483 	bus_space_tag_t iot, memt;
    484 	pci_chipset_tag_t pc;
    485 	int bus, device, function;
    486 {
    487 	struct tga_devconfig *dcp = &tga_console_dc;
    488 
    489 	tga_getdevconfig(memt, pc,
    490 	    pci_make_tag(pc, bus, device, function), dcp);
    491 
    492 	/* sanity checks */
    493 	if (dcp->dc_vaddr == NULL)
    494 		panic("tga_console(%d, %d): couldn't map memory space",
    495 		    device, function);
    496 	if (dcp->dc_tgaconf == NULL)
    497 		panic("tga_console(%d, %d): unknown board configuration",
    498 		    device, function);
    499 
    500 	/*
    501 	 * Initialize the RAMDAC but DO NOT allocate any private storage.
    502 	 * Initialization includes disabling cursor, setting a sane
    503 	 * colormap, etc.  It will be reinitialized in tgaattach().
    504 	 */
    505 	(*dcp->dc_tgaconf->tgac_ramdac->tgar_init)(dcp, 0);
    506 
    507 	wsdisplay_cnattach(&tga_stdscreen, &dcp->dc_rcons,
    508 			   0, 0);
    509 
    510 	return(0);
    511 }
    512 
    513 /*
    514  * Functions to blank and unblank the display.
    515  */
    516 void
    517 tga_blank(dc)
    518 	struct tga_devconfig *dc;
    519 {
    520 
    521 	if (!dc->dc_blanked) {
    522 		dc->dc_blanked = 1;
    523 		dc->dc_regs[TGA_REG_VVVR] |= 0x02;		/* XXX */
    524 	}
    525 }
    526 
    527 void
    528 tga_unblank(dc)
    529 	struct tga_devconfig *dc;
    530 {
    531 
    532 	if (dc->dc_blanked) {
    533 		dc->dc_blanked = 0;
    534 		dc->dc_regs[TGA_REG_VVVR] &= ~0x02;		/* XXX */
    535 	}
    536 }
    537 
    538 /*
    539  * Functions to manipulate the built-in cursor handing hardware.
    540  */
    541 int
    542 tga_builtin_set_cursor(dc, cursorp)
    543 	struct tga_devconfig *dc;
    544 	struct wsdisplay_cursor *cursorp;
    545 {
    546 	int v;
    547 #if 0
    548 	int count;
    549 #endif
    550 
    551 	v = cursorp->which;
    552 #if 0
    553 	if (v & WSDISPLAY_CURSOR_DOCMAP)	/* XXX should be supported */
    554 		return EINVAL;
    555 	if (v & WSDISPLAY_CURSOR_DOSHAPE) {
    556 		if ((u_int)cursorp->size.x != 64 ||
    557 		    (u_int)cursorp->size.y > 64)
    558 			return (EINVAL);
    559 		/* The cursor is 2 bits deep, and there is no mask */
    560 		count = (cursorp->size.y * 64 * 2) / NBBY;
    561 		if (!useracc(cursorp->image, count, B_READ))
    562 			return (EFAULT);
    563 	}
    564 	if (v & WSDISPLAY_CURSOR_DOHOT)		/* not supported */
    565 		return EINVAL;
    566 #endif
    567 
    568 	/* parameters are OK; do it */
    569 	if (v & WSDISPLAY_CURSOR_DOCUR) {
    570 		if (cursorp->enable)
    571 			dc->dc_regs[TGA_REG_VVVR] |= 0x04;	/* XXX */
    572 		else
    573 			dc->dc_regs[TGA_REG_VVVR] &= ~0x04;	/* XXX */
    574 	}
    575 #if 0
    576 	if (v & WSDISPLAY_CURSOR_DOPOS) {
    577 		dc->dc_regs[TGA_REG_CXYR] = ((cursorp->pos.y & 0xfff) << 12) |
    578 		    (cursorp->pos.x & 0xfff);
    579 	}
    580 	if (v & WSDISPLAY_CURSOR_DOCMAP) {
    581 		/* XXX */
    582 	}
    583 	if (v & WSDISPLAY_CURSOR_DOSHAPE) {
    584 		dc->dc_regs[TGA_REG_CCBR] =
    585 		    (dc->dc_regs[TGA_REG_CCBR] & ~0xfc00) |
    586 		    (cursorp->size.y << 10);
    587 		copyin(cursorp->image, (char *)(dc->dc_vaddr +
    588 		    (dc->dc_regs[TGA_REG_CCBR] & 0x3ff)),
    589 		    count);				/* can't fail. */
    590 	}
    591 #endif
    592 	return (0);
    593 }
    594 
    595 int
    596 tga_builtin_get_cursor(dc, cursorp)
    597 	struct tga_devconfig *dc;
    598 	struct wsdisplay_cursor *cursorp;
    599 {
    600 	int count, error;
    601 
    602 	cursorp->which = WSDISPLAY_CURSOR_DOALL &
    603 	    ~(WSDISPLAY_CURSOR_DOHOT | WSDISPLAY_CURSOR_DOCMAP);
    604 	cursorp->enable = (dc->dc_regs[TGA_REG_VVVR] & 0x04) != 0;
    605 	cursorp->pos.x = dc->dc_regs[TGA_REG_CXYR] & 0xfff;
    606 	cursorp->pos.y = (dc->dc_regs[TGA_REG_CXYR] >> 12) & 0xfff;
    607 	cursorp->size.x = 64;
    608 	cursorp->size.y = (dc->dc_regs[TGA_REG_CCBR] >> 10) & 0x3f;
    609 
    610 	if (cursorp->image != NULL) {
    611 		count = (cursorp->size.y * 64 * 2) / NBBY;
    612 		error = copyout((char *)(dc->dc_vaddr +
    613 		      (dc->dc_regs[TGA_REG_CCBR] & 0x3ff)),
    614 		    cursorp->image, count);
    615 		if (error)
    616 			return (error);
    617 		/* No mask */
    618 	}
    619 	/* XXX No color map */
    620 	return (0);
    621 }
    622 
    623 int
    624 tga_builtin_set_curpos(dc, curposp)
    625 	struct tga_devconfig *dc;
    626 	struct wsdisplay_curpos *curposp;
    627 {
    628 
    629 	dc->dc_regs[TGA_REG_CXYR] =
    630 	    ((curposp->y & 0xfff) << 12) | (curposp->x & 0xfff);
    631 	return (0);
    632 }
    633 
    634 int
    635 tga_builtin_get_curpos(dc, curposp)
    636 	struct tga_devconfig *dc;
    637 	struct wsdisplay_curpos *curposp;
    638 {
    639 
    640 	curposp->x = dc->dc_regs[TGA_REG_CXYR] & 0xfff;
    641 	curposp->y = (dc->dc_regs[TGA_REG_CXYR] >> 12) & 0xfff;
    642 	return (0);
    643 }
    644 
    645 int
    646 tga_builtin_get_curmax(dc, curposp)
    647 	struct tga_devconfig *dc;
    648 	struct wsdisplay_curpos *curposp;
    649 {
    650 
    651 	curposp->x = curposp->y = 64;
    652 	return (0);
    653 }
    654