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