14cd9f15eSericj /* $NetBSD: bt485.c,v 1.2 2000/04/02 18:55:01 nathanw Exp $ */ 24cd9f15eSericj 34cd9f15eSericj /* 44cd9f15eSericj * Copyright (c) 1995, 1996 Carnegie-Mellon University. 54cd9f15eSericj * All rights reserved. 64cd9f15eSericj * 74cd9f15eSericj * Author: Chris G. Demetriou 84cd9f15eSericj * 94cd9f15eSericj * Permission to use, copy, modify and distribute this software and 104cd9f15eSericj * its documentation is hereby granted, provided that both the copyright 114cd9f15eSericj * notice and this permission notice appear in all copies of the 124cd9f15eSericj * software, derivative works or modified versions, and any portions 134cd9f15eSericj * thereof, and that both notices appear in supporting documentation. 144cd9f15eSericj * 154cd9f15eSericj * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" 164cd9f15eSericj * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND 174cd9f15eSericj * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. 184cd9f15eSericj * 194cd9f15eSericj * Carnegie Mellon requests users of this software to return to 204cd9f15eSericj * 214cd9f15eSericj * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU 224cd9f15eSericj * School of Computer Science 234cd9f15eSericj * Carnegie Mellon University 244cd9f15eSericj * Pittsburgh PA 15213-3890 254cd9f15eSericj * 264cd9f15eSericj * any improvements or extensions that they make and grant Carnegie the 274cd9f15eSericj * rights to redistribute these changes. 284cd9f15eSericj */ 294cd9f15eSericj 304cd9f15eSericj /* This code was derived from and originally located in sys/dev/pci/ 314cd9f15eSericj * NetBSD: tga_bt485.c,v 1.4 1999/03/24 05:51:21 mrg Exp 324cd9f15eSericj */ 334cd9f15eSericj 344cd9f15eSericj #include <sys/param.h> 354cd9f15eSericj #include <sys/systm.h> 364cd9f15eSericj #include <sys/device.h> 374cd9f15eSericj #include <sys/buf.h> 384cd9f15eSericj #include <sys/kernel.h> 394cd9f15eSericj #include <sys/malloc.h> 404cd9f15eSericj 414cd9f15eSericj #include <vm/vm.h> 424cd9f15eSericj 434cd9f15eSericj #include <dev/pci/pcivar.h> 444cd9f15eSericj #include <dev/ic/bt485reg.h> 454cd9f15eSericj #include <dev/ic/bt485var.h> 464cd9f15eSericj #include <dev/ic/ramdac.h> 474cd9f15eSericj 484cd9f15eSericj #include <dev/wscons/wsconsio.h> 494cd9f15eSericj 504cd9f15eSericj /* 514cd9f15eSericj * Functions exported via the RAMDAC configuration table. 524cd9f15eSericj */ 534cd9f15eSericj void bt485_init __P((struct ramdac_cookie *)); 544cd9f15eSericj int bt485_set_cmap __P((struct ramdac_cookie *, 554cd9f15eSericj struct wsdisplay_cmap *)); 564cd9f15eSericj int bt485_get_cmap __P((struct ramdac_cookie *, 574cd9f15eSericj struct wsdisplay_cmap *)); 584cd9f15eSericj int bt485_set_cursor __P((struct ramdac_cookie *, 594cd9f15eSericj struct wsdisplay_cursor *)); 604cd9f15eSericj int bt485_get_cursor __P((struct ramdac_cookie *, 614cd9f15eSericj struct wsdisplay_cursor *)); 624cd9f15eSericj int bt485_set_curpos __P((struct ramdac_cookie *, 634cd9f15eSericj struct wsdisplay_curpos *)); 644cd9f15eSericj int bt485_get_curpos __P((struct ramdac_cookie *, 654cd9f15eSericj struct wsdisplay_curpos *)); 664cd9f15eSericj int bt485_get_curmax __P((struct ramdac_cookie *, 674cd9f15eSericj struct wsdisplay_curpos *)); 684cd9f15eSericj 694cd9f15eSericj /* XXX const */ 704cd9f15eSericj struct ramdac_funcs bt485_funcsstruct = { 714cd9f15eSericj "Bt485", 724cd9f15eSericj bt485_register, 734cd9f15eSericj bt485_init, 744cd9f15eSericj bt485_set_cmap, 754cd9f15eSericj bt485_get_cmap, 764cd9f15eSericj bt485_set_cursor, 774cd9f15eSericj bt485_get_cursor, 784cd9f15eSericj bt485_set_curpos, 794cd9f15eSericj bt485_get_curpos, 804cd9f15eSericj bt485_get_curmax, 814cd9f15eSericj NULL, /* check_curcmap; not needed */ 824cd9f15eSericj NULL, /* set_curcmap; not needed */ 834cd9f15eSericj NULL, /* get_curcmap; not needed */ 844cd9f15eSericj }; 854cd9f15eSericj 864cd9f15eSericj /* 874cd9f15eSericj * Private data. 884cd9f15eSericj */ 894cd9f15eSericj struct bt485data { 904cd9f15eSericj void *cookie; /* This is what is passed 914cd9f15eSericj * around, and is probably 924cd9f15eSericj * struct tga_devconfig * 934cd9f15eSericj */ 944cd9f15eSericj 954cd9f15eSericj int (*ramdac_sched_update) __P((void *, void (*)(void *))); 964cd9f15eSericj void (*ramdac_wr) __P((void *, u_int, u_int8_t)); 974cd9f15eSericj u_int8_t (*ramdac_rd) __P((void *, u_int)); 984cd9f15eSericj 994cd9f15eSericj int changed; /* what changed; see below */ 1004cd9f15eSericj int curenb; /* cursor enabled */ 1014cd9f15eSericj struct wsdisplay_curpos curpos; /* current cursor position */ 1024cd9f15eSericj struct wsdisplay_curpos curhot; /* cursor hotspot */ 1034cd9f15eSericj char curcmap_r[2]; /* cursor colormap */ 1044cd9f15eSericj char curcmap_g[2]; 1054cd9f15eSericj char curcmap_b[2]; 1064cd9f15eSericj struct wsdisplay_curpos cursize; /* current cursor size */ 1074cd9f15eSericj char curimage[512]; /* cursor image data */ 1084cd9f15eSericj char curmask[512]; /* cursor mask data */ 1094cd9f15eSericj char cmap_r[256]; /* colormap */ 1104cd9f15eSericj char cmap_g[256]; 1114cd9f15eSericj char cmap_b[256]; 1124cd9f15eSericj }; 1134cd9f15eSericj 1144cd9f15eSericj #define DATA_ENB_CHANGED 0x01 /* cursor enable changed */ 1154cd9f15eSericj #define DATA_CURCMAP_CHANGED 0x02 /* cursor colormap changed */ 1164cd9f15eSericj #define DATA_CURSHAPE_CHANGED 0x04 /* cursor size, image, mask changed */ 1174cd9f15eSericj #define DATA_CMAP_CHANGED 0x08 /* colormap changed */ 1184cd9f15eSericj #define DATA_ALL_CHANGED 0x0f 1194cd9f15eSericj 1204cd9f15eSericj #define CURSOR_MAX_SIZE 64 1214cd9f15eSericj 1224cd9f15eSericj /* 1234cd9f15eSericj * Internal functions. 1244cd9f15eSericj */ 1254cd9f15eSericj inline void bt485_wr_i __P((struct bt485data *, u_int8_t, u_int8_t)); 1264cd9f15eSericj inline u_int8_t bt485_rd_i __P((struct bt485data *, u_int8_t)); 1274cd9f15eSericj void bt485_update __P((void *)); 1284cd9f15eSericj void bt485_update_curpos __P((struct bt485data *)); 1294cd9f15eSericj 1304cd9f15eSericj /*****************************************************************************/ 1314cd9f15eSericj 1324cd9f15eSericj /* 1334cd9f15eSericj * Functions exported via the RAMDAC configuration table. 1344cd9f15eSericj */ 1354cd9f15eSericj 1364cd9f15eSericj struct ramdac_funcs * 1374cd9f15eSericj bt485_funcs(void) 1384cd9f15eSericj { 1394cd9f15eSericj return &bt485_funcsstruct; 1404cd9f15eSericj } 1414cd9f15eSericj 1424cd9f15eSericj struct ramdac_cookie * 1434cd9f15eSericj bt485_register(v, sched_update, wr, rd) 1444cd9f15eSericj void *v; 1454cd9f15eSericj int (*sched_update)(void *, void (*)(void *)); 1464cd9f15eSericj void (*wr)(void *, u_int, u_int8_t); 1474cd9f15eSericj u_int8_t (*rd)(void *, u_int); 1484cd9f15eSericj { 1494cd9f15eSericj struct bt485data *data; 1504cd9f15eSericj /* 1514cd9f15eSericj * XXX -- comment out of date. rcd. 1524cd9f15eSericj * If we should allocate a new private info struct, do so. 1534cd9f15eSericj * Otherwise, use the one we have (if it's there), or 1544cd9f15eSericj * use the temporary one on the stack. 1554cd9f15eSericj */ 1564cd9f15eSericj data = malloc(sizeof *data, M_DEVBUF, M_WAITOK); 1574cd9f15eSericj /* XXX -- if !data */ 1584cd9f15eSericj data->cookie = v; 1594cd9f15eSericj data->ramdac_sched_update = sched_update; 1604cd9f15eSericj data->ramdac_wr = wr; 1614cd9f15eSericj data->ramdac_rd = rd; 1624cd9f15eSericj return (struct ramdac_cookie *)data; 1634cd9f15eSericj } 1644cd9f15eSericj 1654cd9f15eSericj /* 1664cd9f15eSericj * This function exists solely to provide a means to init 1674cd9f15eSericj * the RAMDAC without first registering. It is useful for 1684cd9f15eSericj * initializing the console early on. 1694cd9f15eSericj */ 1704cd9f15eSericj void 1714cd9f15eSericj bt485_cninit(v, sched_update, wr, rd) 1724cd9f15eSericj void *v; 1734cd9f15eSericj int (*sched_update)(void *, void (*)(void *)); 1744cd9f15eSericj void (*wr)(void *, u_int, u_int8_t); 1754cd9f15eSericj u_int8_t (*rd)(void *, u_int); 1764cd9f15eSericj { 1774cd9f15eSericj struct bt485data tmp, *data = &tmp; 1784cd9f15eSericj data->cookie = v; 1794cd9f15eSericj data->ramdac_sched_update = sched_update; 1804cd9f15eSericj data->ramdac_wr = wr; 1814cd9f15eSericj data->ramdac_rd = rd; 1824cd9f15eSericj bt485_init((struct ramdac_cookie *)data); 1834cd9f15eSericj } 1844cd9f15eSericj 1854cd9f15eSericj void 1864cd9f15eSericj bt485_init(rc) 1874cd9f15eSericj struct ramdac_cookie *rc; 1884cd9f15eSericj { 1894cd9f15eSericj u_int8_t regval; 1904cd9f15eSericj struct bt485data *data = (struct bt485data *)rc; 1914cd9f15eSericj int i; 1924cd9f15eSericj 1934cd9f15eSericj /* 1944cd9f15eSericj * Init the BT485 for normal operation. 1954cd9f15eSericj */ 1964cd9f15eSericj 1974cd9f15eSericj /* 1984cd9f15eSericj * Allow indirect register access. (Actually, this is 1994cd9f15eSericj * already enabled. In fact, if it is _disabled_, for 2004cd9f15eSericj * some reason the monitor appears to lose sync!!! (?!?!) 2014cd9f15eSericj */ 2024cd9f15eSericj regval = data->ramdac_rd(data->cookie, BT485_REG_COMMAND_0); 2034cd9f15eSericj regval |= 0x80; 2044cd9f15eSericj /* 2054cd9f15eSericj * Set the RAMDAC to 8 bit resolution, rather than 6 bit 2064cd9f15eSericj * resolution. 2074cd9f15eSericj */ 2084cd9f15eSericj regval |= 0x02; 2094cd9f15eSericj data->ramdac_wr(data->cookie, BT485_REG_COMMAND_0, regval); 2104cd9f15eSericj 2114cd9f15eSericj /* Set the RAMDAC to 8BPP (no interestion options). */ 2124cd9f15eSericj data->ramdac_wr(data->cookie, BT485_REG_COMMAND_1, 0x40); 2134cd9f15eSericj 2144cd9f15eSericj /* Disable the cursor (for now) */ 2154cd9f15eSericj regval = data->ramdac_rd(data->cookie, BT485_REG_COMMAND_2); 2164cd9f15eSericj regval &= ~0x03; 2174cd9f15eSericj regval |= 0x24; 2184cd9f15eSericj data->ramdac_wr(data->cookie, BT485_REG_COMMAND_2, regval); 2194cd9f15eSericj 2204cd9f15eSericj /* Use a 64x64x2 cursor */ 2214cd9f15eSericj regval = bt485_rd_i(data, BT485_IREG_COMMAND_3); 2224cd9f15eSericj regval |= 0x04; 2234cd9f15eSericj regval |= 0x08; 2244cd9f15eSericj bt485_wr_i(data, BT485_IREG_COMMAND_3, regval); 2254cd9f15eSericj 2264cd9f15eSericj /* Set the Pixel Mask to something useful */ 2274cd9f15eSericj data->ramdac_wr(data->cookie, BT485_REG_PIXMASK, 0xff); 2284cd9f15eSericj 2294cd9f15eSericj /* 2304cd9f15eSericj * Initalize the RAMDAC info struct to hold all of our 2314cd9f15eSericj * data, and fill it in. 2324cd9f15eSericj */ 2334cd9f15eSericj data->changed = DATA_ALL_CHANGED; 2344cd9f15eSericj 2354cd9f15eSericj data->curenb = 0; /* cursor disabled */ 2364cd9f15eSericj data->curpos.x = data->curpos.y = 0; /* right now at 0,0 */ 2374cd9f15eSericj data->curhot.x = data->curhot.y = 0; /* hot spot at 0,0 */ 2384cd9f15eSericj 2394cd9f15eSericj /* initial cursor colormap: 0 is black, 1 is white */ 2404cd9f15eSericj data->curcmap_r[0] = data->curcmap_g[0] = data->curcmap_b[0] = 0; 2414cd9f15eSericj data->curcmap_r[1] = data->curcmap_g[1] = data->curcmap_b[1] = 0xff; 2424cd9f15eSericj 2434cd9f15eSericj /* initial cursor data: 64x64 block of white. */ 2444cd9f15eSericj data->cursize.x = data->cursize.y = 64; 2454cd9f15eSericj for (i = 0; i < 512; i++) 2464cd9f15eSericj data->curimage[i] = data->curmask[i] = 0xff; 2474cd9f15eSericj 2484cd9f15eSericj /* Initial colormap: 0 is black, everything else is white */ 2494cd9f15eSericj data->cmap_r[0] = data->cmap_g[0] = data->cmap_b[0] = 0; 2504cd9f15eSericj for (i = 1; i < 256; i++) 2514cd9f15eSericj data->cmap_r[i] = data->cmap_g[i] = data->cmap_b[i] = 255; 2524cd9f15eSericj 2534cd9f15eSericj bt485_update((void *)data); 2544cd9f15eSericj } 2554cd9f15eSericj 2564cd9f15eSericj int 2574cd9f15eSericj bt485_set_cmap(rc, cmapp) 2584cd9f15eSericj struct ramdac_cookie *rc; 2594cd9f15eSericj struct wsdisplay_cmap *cmapp; 2604cd9f15eSericj { 2614cd9f15eSericj struct bt485data *data = (struct bt485data *)rc; 2624cd9f15eSericj int count, index, s; 2634cd9f15eSericj 264*7d068bd0Snate #ifdef DIAGNOSTIC 265*7d068bd0Snate if (rc == NULL) 266*7d068bd0Snate panic("bt485_set_cmap: rc"); 267*7d068bd0Snate if (cmapp == NULL) 268*7d068bd0Snate panic("bt485_set_cmap: cmapp"); 269*7d068bd0Snate #endif 2704cd9f15eSericj if ((u_int)cmapp->index >= 256 || 2714cd9f15eSericj ((u_int)cmapp->index + (u_int)cmapp->count) > 256) 2724cd9f15eSericj return (EINVAL); 2734cd9f15eSericj #if defined(UVM) 2744cd9f15eSericj if (!uvm_useracc(cmapp->red, cmapp->count, B_READ) || 2754cd9f15eSericj !uvm_useracc(cmapp->green, cmapp->count, B_READ) || 2764cd9f15eSericj !uvm_useracc(cmapp->blue, cmapp->count, B_READ)) 2774cd9f15eSericj return (EFAULT); 2784cd9f15eSericj #else 2794cd9f15eSericj if (!useracc(cmapp->red, cmapp->count, B_READ) || 2804cd9f15eSericj !useracc(cmapp->green, cmapp->count, B_READ) || 2814cd9f15eSericj !useracc(cmapp->blue, cmapp->count, B_READ)) 2824cd9f15eSericj return (EFAULT); 2834cd9f15eSericj #endif 2844cd9f15eSericj 2854cd9f15eSericj s = spltty(); 2864cd9f15eSericj 2874cd9f15eSericj index = cmapp->index; 2884cd9f15eSericj count = cmapp->count; 2894cd9f15eSericj copyin(cmapp->red, &data->cmap_r[index], count); 2904cd9f15eSericj copyin(cmapp->green, &data->cmap_g[index], count); 2914cd9f15eSericj copyin(cmapp->blue, &data->cmap_b[index], count); 2924cd9f15eSericj 2934cd9f15eSericj data->changed |= DATA_CMAP_CHANGED; 2944cd9f15eSericj 2954cd9f15eSericj data->ramdac_sched_update(data->cookie, bt485_update); 296*7d068bd0Snate delay(1); 2974cd9f15eSericj splx(s); 2984cd9f15eSericj 2994cd9f15eSericj return (0); 3004cd9f15eSericj } 3014cd9f15eSericj 3024cd9f15eSericj int 3034cd9f15eSericj bt485_get_cmap(rc, cmapp) 3044cd9f15eSericj struct ramdac_cookie *rc; 3054cd9f15eSericj struct wsdisplay_cmap *cmapp; 3064cd9f15eSericj { 3074cd9f15eSericj struct bt485data *data = (struct bt485data *)rc; 3084cd9f15eSericj int error, count, index; 3094cd9f15eSericj 3104cd9f15eSericj if ((u_int)cmapp->index >= 256 || 3114cd9f15eSericj ((u_int)cmapp->index + (u_int)cmapp->count) > 256) 3124cd9f15eSericj return (EINVAL); 3134cd9f15eSericj 3144cd9f15eSericj count = cmapp->count; 3154cd9f15eSericj index = cmapp->index; 3164cd9f15eSericj 3174cd9f15eSericj error = copyout(&data->cmap_r[index], cmapp->red, count); 3184cd9f15eSericj if (error) 3194cd9f15eSericj return (error); 3204cd9f15eSericj error = copyout(&data->cmap_g[index], cmapp->green, count); 3214cd9f15eSericj if (error) 3224cd9f15eSericj return (error); 3234cd9f15eSericj error = copyout(&data->cmap_b[index], cmapp->blue, count); 3244cd9f15eSericj return (error); 3254cd9f15eSericj } 3264cd9f15eSericj 3274cd9f15eSericj int 3284cd9f15eSericj bt485_set_cursor(rc, cursorp) 3294cd9f15eSericj struct ramdac_cookie *rc; 3304cd9f15eSericj struct wsdisplay_cursor *cursorp; 3314cd9f15eSericj { 3324cd9f15eSericj struct bt485data *data = (struct bt485data *)rc; 3334cd9f15eSericj int count, index, v, s; 3344cd9f15eSericj 3354cd9f15eSericj v = cursorp->which; 3364cd9f15eSericj 3374cd9f15eSericj /* 3384cd9f15eSericj * For DOCMAP and DOSHAPE, verify that parameters are OK 3394cd9f15eSericj * before we do anything that we can't recover from. 3404cd9f15eSericj */ 3414cd9f15eSericj if (v & WSDISPLAY_CURSOR_DOCMAP) { 3424cd9f15eSericj if ((u_int)cursorp->cmap.index > 2 || 3434cd9f15eSericj ((u_int)cursorp->cmap.index + 3444cd9f15eSericj (u_int)cursorp->cmap.count) > 2) 3454cd9f15eSericj return (EINVAL); 3464cd9f15eSericj count = cursorp->cmap.count; 3474cd9f15eSericj #if defined(UVM) 3484cd9f15eSericj if (!uvm_useracc(cursorp->cmap.red, count, B_READ) || 3494cd9f15eSericj !uvm_useracc(cursorp->cmap.green, count, B_READ) || 3504cd9f15eSericj !uvm_useracc(cursorp->cmap.blue, count, B_READ)) 3514cd9f15eSericj return (EFAULT); 3524cd9f15eSericj #else 3534cd9f15eSericj if (!useracc(cursorp->cmap.red, count, B_READ) || 3544cd9f15eSericj !useracc(cursorp->cmap.green, count, B_READ) || 3554cd9f15eSericj !useracc(cursorp->cmap.blue, count, B_READ)) 3564cd9f15eSericj return (EFAULT); 3574cd9f15eSericj #endif 3584cd9f15eSericj } 3594cd9f15eSericj if (v & WSDISPLAY_CURSOR_DOSHAPE) { 3604cd9f15eSericj if ((u_int)cursorp->size.x > CURSOR_MAX_SIZE || 3614cd9f15eSericj (u_int)cursorp->size.y > CURSOR_MAX_SIZE) 3624cd9f15eSericj return (EINVAL); 3634cd9f15eSericj count = (CURSOR_MAX_SIZE / NBBY) * data->cursize.y; 3644cd9f15eSericj #if defined(UVM) 3654cd9f15eSericj if (!uvm_useracc(cursorp->image, count, B_READ) || 3664cd9f15eSericj !uvm_useracc(cursorp->mask, count, B_READ)) 3674cd9f15eSericj return (EFAULT); 3684cd9f15eSericj #else 3694cd9f15eSericj if (!useracc(cursorp->image, count, B_READ) || 3704cd9f15eSericj !useracc(cursorp->mask, count, B_READ)) 3714cd9f15eSericj return (EFAULT); 3724cd9f15eSericj #endif 3734cd9f15eSericj } 3744cd9f15eSericj 3754cd9f15eSericj if (v & (WSDISPLAY_CURSOR_DOPOS | WSDISPLAY_CURSOR_DOCUR)) { 3764cd9f15eSericj if (v & WSDISPLAY_CURSOR_DOPOS) 3774cd9f15eSericj data->curpos = cursorp->pos; 3784cd9f15eSericj if (v & WSDISPLAY_CURSOR_DOCUR) 3794cd9f15eSericj data->curhot = cursorp->hot; 3804cd9f15eSericj bt485_update_curpos(data); 3814cd9f15eSericj } 3824cd9f15eSericj 3834cd9f15eSericj s = spltty(); 3844cd9f15eSericj 3854cd9f15eSericj /* Parameters are OK; perform the requested operations. */ 3864cd9f15eSericj if (v & WSDISPLAY_CURSOR_DOCUR) { 3874cd9f15eSericj data->curenb = cursorp->enable; 3884cd9f15eSericj data->changed |= DATA_ENB_CHANGED; 3894cd9f15eSericj } 3904cd9f15eSericj if (v & WSDISPLAY_CURSOR_DOCMAP) { 3914cd9f15eSericj count = cursorp->cmap.count; 3924cd9f15eSericj index = cursorp->cmap.index; 3934cd9f15eSericj copyin(cursorp->cmap.red, &data->curcmap_r[index], count); 3944cd9f15eSericj copyin(cursorp->cmap.green, &data->curcmap_g[index], count); 3954cd9f15eSericj copyin(cursorp->cmap.blue, &data->curcmap_b[index], count); 3964cd9f15eSericj data->changed |= DATA_CURCMAP_CHANGED; 3974cd9f15eSericj } 3984cd9f15eSericj if (v & WSDISPLAY_CURSOR_DOSHAPE) { 3994cd9f15eSericj data->cursize = cursorp->size; 4004cd9f15eSericj count = (CURSOR_MAX_SIZE / NBBY) * data->cursize.y; 4014cd9f15eSericj bzero(data->curimage, sizeof data->curimage); 4024cd9f15eSericj bzero(data->curmask, sizeof data->curmask); 4034cd9f15eSericj copyin(cursorp->image, data->curimage, count); /* can't fail */ 4044cd9f15eSericj copyin(cursorp->mask, data->curmask, count); /* can't fail */ 4054cd9f15eSericj data->changed |= DATA_CURSHAPE_CHANGED; 4064cd9f15eSericj } 4074cd9f15eSericj 4084cd9f15eSericj if (data->changed) 4094cd9f15eSericj data->ramdac_sched_update(data->cookie, bt485_update); 4104cd9f15eSericj splx(s); 4114cd9f15eSericj 4124cd9f15eSericj return (0); 4134cd9f15eSericj } 4144cd9f15eSericj 4154cd9f15eSericj int 4164cd9f15eSericj bt485_get_cursor(rc, cursorp) 4174cd9f15eSericj struct ramdac_cookie *rc; 4184cd9f15eSericj struct wsdisplay_cursor *cursorp; 4194cd9f15eSericj { 4204cd9f15eSericj struct bt485data *data = (struct bt485data *)rc; 4214cd9f15eSericj int error, count; 4224cd9f15eSericj 4234cd9f15eSericj /* we return everything they want */ 4244cd9f15eSericj cursorp->which = WSDISPLAY_CURSOR_DOALL; 4254cd9f15eSericj 4264cd9f15eSericj cursorp->enable = data->curenb; /* DOCUR */ 4274cd9f15eSericj cursorp->pos = data->curpos; /* DOPOS */ 4284cd9f15eSericj cursorp->hot = data->curhot; /* DOHOT */ 4294cd9f15eSericj 4304cd9f15eSericj cursorp->cmap.index = 0; /* DOCMAP */ 4314cd9f15eSericj cursorp->cmap.count = 2; 4324cd9f15eSericj if (cursorp->cmap.red != NULL) { 4334cd9f15eSericj error = copyout(data->curcmap_r, cursorp->cmap.red, 2); 4344cd9f15eSericj if (error) 4354cd9f15eSericj return (error); 4364cd9f15eSericj } 4374cd9f15eSericj if (cursorp->cmap.green != NULL) { 4384cd9f15eSericj error = copyout(data->curcmap_g, cursorp->cmap.green, 2); 4394cd9f15eSericj if (error) 4404cd9f15eSericj return (error); 4414cd9f15eSericj } 4424cd9f15eSericj if (cursorp->cmap.blue != NULL) { 4434cd9f15eSericj error = copyout(data->curcmap_b, cursorp->cmap.blue, 2); 4444cd9f15eSericj if (error) 4454cd9f15eSericj return (error); 4464cd9f15eSericj } 4474cd9f15eSericj 4484cd9f15eSericj cursorp->size = data->cursize; /* DOSHAPE */ 4494cd9f15eSericj if (cursorp->image != NULL) { 4504cd9f15eSericj count = (CURSOR_MAX_SIZE / NBBY) * data->cursize.y; 4514cd9f15eSericj error = copyout(data->curimage, cursorp->image, count); 4524cd9f15eSericj if (error) 4534cd9f15eSericj return (error); 4544cd9f15eSericj error = copyout(data->curmask, cursorp->mask, count); 4554cd9f15eSericj if (error) 4564cd9f15eSericj return (error); 4574cd9f15eSericj } 4584cd9f15eSericj 4594cd9f15eSericj return (0); 4604cd9f15eSericj } 4614cd9f15eSericj 4624cd9f15eSericj int 4634cd9f15eSericj bt485_set_curpos(rc, curposp) 4644cd9f15eSericj struct ramdac_cookie *rc; 4654cd9f15eSericj struct wsdisplay_curpos *curposp; 4664cd9f15eSericj { 4674cd9f15eSericj struct bt485data *data = (struct bt485data *)rc; 4684cd9f15eSericj 4694cd9f15eSericj data->curpos = *curposp; 4704cd9f15eSericj bt485_update_curpos(data); 4714cd9f15eSericj 4724cd9f15eSericj return (0); 4734cd9f15eSericj } 4744cd9f15eSericj 4754cd9f15eSericj int 4764cd9f15eSericj bt485_get_curpos(rc, curposp) 4774cd9f15eSericj struct ramdac_cookie *rc; 4784cd9f15eSericj struct wsdisplay_curpos *curposp; 4794cd9f15eSericj { 4804cd9f15eSericj struct bt485data *data = (struct bt485data *)rc; 4814cd9f15eSericj 4824cd9f15eSericj *curposp = data->curpos; 4834cd9f15eSericj return (0); 4844cd9f15eSericj } 4854cd9f15eSericj 4864cd9f15eSericj int 4874cd9f15eSericj bt485_get_curmax(rc, curposp) 4884cd9f15eSericj struct ramdac_cookie *rc; 4894cd9f15eSericj struct wsdisplay_curpos *curposp; 4904cd9f15eSericj { 4914cd9f15eSericj 4924cd9f15eSericj curposp->x = curposp->y = CURSOR_MAX_SIZE; 4934cd9f15eSericj return (0); 4944cd9f15eSericj } 4954cd9f15eSericj 4964cd9f15eSericj /*****************************************************************************/ 4974cd9f15eSericj 4984cd9f15eSericj /* 4994cd9f15eSericj * Internal functions. 5004cd9f15eSericj */ 5014cd9f15eSericj 5024cd9f15eSericj inline void 5034cd9f15eSericj bt485_wr_i(data, ireg, val) 5044cd9f15eSericj struct bt485data *data; 5054cd9f15eSericj u_int8_t ireg; 5064cd9f15eSericj u_int8_t val; 5074cd9f15eSericj { 5084cd9f15eSericj data->ramdac_wr(data->cookie, BT485_REG_PCRAM_WRADDR, ireg); 5094cd9f15eSericj data->ramdac_wr(data->cookie, BT485_REG_EXTENDED, val); 5104cd9f15eSericj } 5114cd9f15eSericj 5124cd9f15eSericj inline u_int8_t 5134cd9f15eSericj bt485_rd_i(data, ireg) 5144cd9f15eSericj struct bt485data *data; 5154cd9f15eSericj u_int8_t ireg; 5164cd9f15eSericj { 5174cd9f15eSericj data->ramdac_wr(data->cookie, BT485_REG_PCRAM_WRADDR, ireg); 5184cd9f15eSericj return (data->ramdac_rd(data->cookie, BT485_REG_EXTENDED)); 5194cd9f15eSericj } 5204cd9f15eSericj 5214cd9f15eSericj void 5224cd9f15eSericj bt485_update(vp) 5234cd9f15eSericj void *vp; 5244cd9f15eSericj { 5254cd9f15eSericj struct bt485data *data = vp; 5264cd9f15eSericj u_int8_t regval; 5274cd9f15eSericj int count, i, v; 5284cd9f15eSericj 5294cd9f15eSericj v = data->changed; 5304cd9f15eSericj data->changed = 0; 5314cd9f15eSericj 5324cd9f15eSericj if (v & DATA_ENB_CHANGED) { 5334cd9f15eSericj regval = data->ramdac_rd(data->cookie, BT485_REG_COMMAND_2); 5344cd9f15eSericj if (data->curenb) 5354cd9f15eSericj regval |= 0x01; 5364cd9f15eSericj else 5374cd9f15eSericj regval &= ~0x03; 5384cd9f15eSericj data->ramdac_wr(data->cookie, BT485_REG_COMMAND_2, regval); 5394cd9f15eSericj } 5404cd9f15eSericj 5414cd9f15eSericj if (v & DATA_CURCMAP_CHANGED) { 5424cd9f15eSericj /* addr[9:0] assumed to be 0 */ 5434cd9f15eSericj /* set addr[7:0] to 1 */ 5444cd9f15eSericj data->ramdac_wr(data->cookie, BT485_REG_COC_WRADDR, 0x01); 5454cd9f15eSericj 5464cd9f15eSericj /* spit out the cursor data */ 5474cd9f15eSericj for (i = 0; i < 2; i++) { 5484cd9f15eSericj data->ramdac_wr(data->cookie, BT485_REG_COCDATA, 5494cd9f15eSericj data->curcmap_r[i]); 5504cd9f15eSericj data->ramdac_wr(data->cookie, BT485_REG_COCDATA, 5514cd9f15eSericj data->curcmap_g[i]); 5524cd9f15eSericj data->ramdac_wr(data->cookie, BT485_REG_COCDATA, 5534cd9f15eSericj data->curcmap_b[i]); 5544cd9f15eSericj } 5554cd9f15eSericj } 5564cd9f15eSericj 5574cd9f15eSericj if (v & DATA_CURSHAPE_CHANGED) { 5584cd9f15eSericj count = (CURSOR_MAX_SIZE / NBBY) * data->cursize.y; 5594cd9f15eSericj 5604cd9f15eSericj /* 5614cd9f15eSericj * Write the cursor image data: 5624cd9f15eSericj * set addr[9:8] to 0, 5634cd9f15eSericj * set addr[7:0] to 0, 5644cd9f15eSericj * spit it all out. 5654cd9f15eSericj */ 5664cd9f15eSericj regval = bt485_rd_i(data, BT485_IREG_COMMAND_3); 5674cd9f15eSericj regval &= ~0x03; 5684cd9f15eSericj bt485_wr_i(data, BT485_IREG_COMMAND_3, regval); 5694cd9f15eSericj data->ramdac_wr(data->cookie, BT485_REG_PCRAM_WRADDR, 0); 5704cd9f15eSericj for (i = 0; i < count; i++) 5714cd9f15eSericj data->ramdac_wr(data->cookie, BT485_REG_CURSOR_RAM, 5724cd9f15eSericj data->curimage[i]); 5734cd9f15eSericj 5744cd9f15eSericj /* 5754cd9f15eSericj * Write the cursor mask data: 5764cd9f15eSericj * set addr[9:8] to 2, 5774cd9f15eSericj * set addr[7:0] to 0, 5784cd9f15eSericj * spit it all out. 5794cd9f15eSericj */ 5804cd9f15eSericj regval = bt485_rd_i(data, BT485_IREG_COMMAND_3); 5814cd9f15eSericj regval &= ~0x03; regval |= 0x02; 5824cd9f15eSericj bt485_wr_i(data, BT485_IREG_COMMAND_3, regval); 5834cd9f15eSericj data->ramdac_wr(data->cookie, BT485_REG_PCRAM_WRADDR, 0); 5844cd9f15eSericj for (i = 0; i < count; i++) 5854cd9f15eSericj data->ramdac_wr(data->cookie, BT485_REG_CURSOR_RAM, 5864cd9f15eSericj data->curmask[i]); 5874cd9f15eSericj 5884cd9f15eSericj /* set addr[9:0] back to 0 */ 5894cd9f15eSericj regval = bt485_rd_i(data, BT485_IREG_COMMAND_3); 5904cd9f15eSericj regval &= ~0x03; 5914cd9f15eSericj bt485_wr_i(data, BT485_IREG_COMMAND_3, regval); 5924cd9f15eSericj } 5934cd9f15eSericj 5944cd9f15eSericj if (v & DATA_CMAP_CHANGED) { 5954cd9f15eSericj /* addr[9:0] assumed to be 0 */ 5964cd9f15eSericj /* set addr[7:0] to 0 */ 5974cd9f15eSericj data->ramdac_wr(data->cookie, BT485_REG_PCRAM_WRADDR, 0x00); 5984cd9f15eSericj 5994cd9f15eSericj /* spit out the cursor data */ 6004cd9f15eSericj for (i = 0; i < 256; i++) { 6014cd9f15eSericj data->ramdac_wr(data->cookie, BT485_REG_PALETTE, 6024cd9f15eSericj data->cmap_r[i]); 6034cd9f15eSericj data->ramdac_wr(data->cookie, BT485_REG_PALETTE, 6044cd9f15eSericj data->cmap_g[i]); 6054cd9f15eSericj data->ramdac_wr(data->cookie, BT485_REG_PALETTE, 6064cd9f15eSericj data->cmap_b[i]); 6074cd9f15eSericj } 6084cd9f15eSericj } 6094cd9f15eSericj } 6104cd9f15eSericj 6114cd9f15eSericj void 6124cd9f15eSericj bt485_update_curpos(data) 6134cd9f15eSericj struct bt485data *data; 6144cd9f15eSericj { 6154cd9f15eSericj void *cookie = data->cookie; 6164cd9f15eSericj int s, x, y; 6174cd9f15eSericj 6184cd9f15eSericj s = spltty(); 6194cd9f15eSericj 6204cd9f15eSericj x = data->curpos.x + CURSOR_MAX_SIZE - data->curhot.x; 6214cd9f15eSericj y = data->curpos.y + CURSOR_MAX_SIZE - data->curhot.y; 6224cd9f15eSericj data->ramdac_wr(cookie, BT485_REG_CURSOR_X_LOW, x & 0xff); 6234cd9f15eSericj data->ramdac_wr(cookie, BT485_REG_CURSOR_X_HIGH, (x >> 8) & 0x0f); 6244cd9f15eSericj data->ramdac_wr(cookie, BT485_REG_CURSOR_Y_LOW, y & 0xff); 6254cd9f15eSericj data->ramdac_wr(cookie, BT485_REG_CURSOR_Y_HIGH, (y >> 8) & 0x0f); 6264cd9f15eSericj 6274cd9f15eSericj splx(s); 6284cd9f15eSericj } 629