xref: /netbsd-src/sys/dev/ic/bt485.c (revision 8e9f762ce7d368111b68db7e9d33856219c4eb9b)
1*8e9f762cSriastradh /* $NetBSD: bt485.c,v 1.18 2018/01/24 05:35:58 riastradh Exp $ */
2b16807c5Selric 
3b16807c5Selric /*
4b16807c5Selric  * Copyright (c) 1995, 1996 Carnegie-Mellon University.
5b16807c5Selric  * All rights reserved.
6b16807c5Selric  *
7b16807c5Selric  * Author: Chris G. Demetriou
8b16807c5Selric  *
9b16807c5Selric  * Permission to use, copy, modify and distribute this software and
10b16807c5Selric  * its documentation is hereby granted, provided that both the copyright
11b16807c5Selric  * notice and this permission notice appear in all copies of the
12b16807c5Selric  * software, derivative works or modified versions, and any portions
13b16807c5Selric  * thereof, and that both notices appear in supporting documentation.
14b16807c5Selric  *
15b16807c5Selric  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
16b16807c5Selric  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
17b16807c5Selric  * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
18b16807c5Selric  *
19b16807c5Selric  * Carnegie Mellon requests users of this software to return to
20b16807c5Selric  *
21b16807c5Selric  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
22b16807c5Selric  *  School of Computer Science
23b16807c5Selric  *  Carnegie Mellon University
24b16807c5Selric  *  Pittsburgh PA 15213-3890
25b16807c5Selric  *
26b16807c5Selric  * any improvements or extensions that they make and grant Carnegie the
27b16807c5Selric  * rights to redistribute these changes.
28b16807c5Selric  */
29b16807c5Selric 
30b16807c5Selric  /* This code was derived from and originally located in sys/dev/pci/
31b16807c5Selric   *	 NetBSD: tga_bt485.c,v 1.4 1999/03/24 05:51:21 mrg Exp
32b16807c5Selric   */
33b16807c5Selric 
34a4bae8b0Slukem #include <sys/cdefs.h>
35*8e9f762cSriastradh __KERNEL_RCSID(0, "$NetBSD: bt485.c,v 1.18 2018/01/24 05:35:58 riastradh Exp $");
36a4bae8b0Slukem 
37b16807c5Selric #include <sys/param.h>
38b16807c5Selric #include <sys/systm.h>
39b16807c5Selric #include <sys/device.h>
40b16807c5Selric #include <sys/buf.h>
41b16807c5Selric #include <sys/kernel.h>
42b16807c5Selric #include <sys/malloc.h>
43314f1e97Smrg 
44b16807c5Selric #include <dev/pci/pcivar.h>
45b16807c5Selric #include <dev/ic/bt485reg.h>
46b16807c5Selric #include <dev/ic/bt485var.h>
47b16807c5Selric #include <dev/ic/ramdac.h>
48b16807c5Selric 
49b16807c5Selric #include <dev/wscons/wsconsio.h>
50b16807c5Selric 
51b16807c5Selric /*
52b16807c5Selric  * Functions exported via the RAMDAC configuration table.
53b16807c5Selric  */
5418db93c7Sperry void	bt485_init(struct ramdac_cookie *);
5518db93c7Sperry int	bt485_set_cmap(struct ramdac_cookie *, struct wsdisplay_cmap *);
5618db93c7Sperry int	bt485_get_cmap(struct ramdac_cookie *, struct wsdisplay_cmap *);
5718db93c7Sperry int	bt485_set_cursor(struct ramdac_cookie *, struct wsdisplay_cursor *);
5818db93c7Sperry int	bt485_get_cursor(struct ramdac_cookie *, struct wsdisplay_cursor *);
5918db93c7Sperry int	bt485_set_curpos(struct ramdac_cookie *, struct wsdisplay_curpos *);
6018db93c7Sperry int	bt485_get_curpos(struct ramdac_cookie *, struct wsdisplay_curpos *);
6118db93c7Sperry int	bt485_get_curmax(struct ramdac_cookie *, struct wsdisplay_curpos *);
62b16807c5Selric 
63b16807c5Selric /* XXX const */
64b16807c5Selric struct ramdac_funcs bt485_funcsstruct = {
65b16807c5Selric 	"Bt485",
66c66f54d7Snathanw 	bt485_register,
67b16807c5Selric 	bt485_init,
68b16807c5Selric 	bt485_set_cmap,
69b16807c5Selric 	bt485_get_cmap,
70b16807c5Selric 	bt485_set_cursor,
71b16807c5Selric 	bt485_get_cursor,
72b16807c5Selric 	bt485_set_curpos,
73b16807c5Selric 	bt485_get_curpos,
74b16807c5Selric 	bt485_get_curmax,
75b16807c5Selric 	NULL,			/* check_curcmap; not needed */
76b16807c5Selric 	NULL,			/* set_curcmap; not needed */
77b16807c5Selric 	NULL,			/* get_curcmap; not needed */
7894448f7eSelric 	NULL,			/* no dot clock to set */
79b16807c5Selric };
80b16807c5Selric 
81b16807c5Selric /*
82b16807c5Selric  * Private data.
83b16807c5Selric  */
84b16807c5Selric struct bt485data {
85b16807c5Selric 	void            *cookie;        /* This is what is passed
86b16807c5Selric 					 * around, and is probably
87b16807c5Selric 					 * struct tga_devconfig *
88b16807c5Selric 					 */
89b16807c5Selric 
9018db93c7Sperry 	int             (*ramdac_sched_update)(void *, void (*)(void *));
9118db93c7Sperry 	void            (*ramdac_wr)(void *, u_int, u_int8_t);
9218db93c7Sperry 	u_int8_t        (*ramdac_rd)(void *, u_int);
93b16807c5Selric 
94b16807c5Selric 	int	changed;			/* what changed; see below */
95b16807c5Selric 	int	curenb;				/* cursor enabled */
96b16807c5Selric 	struct wsdisplay_curpos curpos;		/* current cursor position */
97b16807c5Selric 	struct wsdisplay_curpos curhot;		/* cursor hotspot */
98b16807c5Selric 	char curcmap_r[2];			/* cursor colormap */
99b16807c5Selric 	char curcmap_g[2];
100b16807c5Selric 	char curcmap_b[2];
101b16807c5Selric 	struct wsdisplay_curpos cursize;	/* current cursor size */
102b16807c5Selric 	char curimage[512];			/* cursor image data */
103b16807c5Selric 	char curmask[512];			/* cursor mask data */
104b16807c5Selric 	char cmap_r[256];				/* colormap */
105b16807c5Selric 	char cmap_g[256];
106b16807c5Selric 	char cmap_b[256];
107b16807c5Selric };
108b16807c5Selric 
109b16807c5Selric #define	DATA_ENB_CHANGED	0x01	/* cursor enable changed */
110b16807c5Selric #define	DATA_CURCMAP_CHANGED	0x02	/* cursor colormap changed */
111b16807c5Selric #define	DATA_CURSHAPE_CHANGED	0x04	/* cursor size, image, mask changed */
112b16807c5Selric #define	DATA_CMAP_CHANGED	0x08	/* colormap changed */
113b16807c5Selric #define	DATA_ALL_CHANGED	0x0f
114b16807c5Selric 
115b16807c5Selric #define	CURSOR_MAX_SIZE		64
116b16807c5Selric 
117b16807c5Selric /*
118b16807c5Selric  * Internal functions.
119b16807c5Selric  */
120106e9eabSriastradh 
12118db93c7Sperry void	bt485_update(void *);
12218db93c7Sperry void	bt485_update_curpos(struct bt485data *);
123b16807c5Selric 
124106e9eabSriastradh static inline void
bt485_wr_i(struct bt485data * data,u_int8_t ireg,u_int8_t val)125106e9eabSriastradh bt485_wr_i(struct bt485data *data, u_int8_t ireg, u_int8_t val)
126106e9eabSriastradh {
127106e9eabSriastradh 	data->ramdac_wr(data->cookie, BT485_REG_PCRAM_WRADDR, ireg);
128106e9eabSriastradh 	data->ramdac_wr(data->cookie, BT485_REG_EXTENDED, val);
129106e9eabSriastradh }
130106e9eabSriastradh 
131106e9eabSriastradh static inline u_int8_t
bt485_rd_i(struct bt485data * data,u_int8_t ireg)132106e9eabSriastradh bt485_rd_i(struct bt485data *data, u_int8_t ireg)
133106e9eabSriastradh {
134106e9eabSriastradh 	data->ramdac_wr(data->cookie, BT485_REG_PCRAM_WRADDR, ireg);
135106e9eabSriastradh 	return (data->ramdac_rd(data->cookie, BT485_REG_EXTENDED));
136106e9eabSriastradh }
137106e9eabSriastradh 
138b16807c5Selric /*****************************************************************************/
139b16807c5Selric 
140b16807c5Selric /*
141b16807c5Selric  * Functions exported via the RAMDAC configuration table.
142b16807c5Selric  */
143b16807c5Selric 
144b16807c5Selric struct ramdac_funcs *
bt485_funcs(void)145b16807c5Selric bt485_funcs(void)
146b16807c5Selric {
147b16807c5Selric 	return &bt485_funcsstruct;
148b16807c5Selric }
149b16807c5Selric 
150b16807c5Selric struct ramdac_cookie *
bt485_register(void * v,int (* sched_update)(void *,void (*)(void *)),void (* wr)(void *,u_int,u_int8_t),u_int8_t (* rd)(void *,u_int))1511d7f24eaSmatt bt485_register(
1521d7f24eaSmatt 	void *v,
1531d7f24eaSmatt 	int (*sched_update)(void *, void (*)(void *)),
1541d7f24eaSmatt 	void (*wr)(void *, u_int, u_int8_t),
1551d7f24eaSmatt 	u_int8_t (*rd)(void *, u_int))
156b16807c5Selric {
157b16807c5Selric 	struct bt485data *data;
158b16807c5Selric 	/*
159b16807c5Selric 	 * XXX -- comment out of date.  rcd.
160b16807c5Selric 	 * If we should allocate a new private info struct, do so.
161b16807c5Selric 	 * Otherwise, use the one we have (if it's there), or
162b16807c5Selric 	 * use the temporary one on the stack.
163b16807c5Selric 	 */
164b16807c5Selric 	data = malloc(sizeof *data, M_DEVBUF, M_WAITOK);
165b16807c5Selric 	/* XXX -- if !data */
166b16807c5Selric 	data->cookie = v;
167b16807c5Selric 	data->ramdac_sched_update = sched_update;
168b16807c5Selric 	data->ramdac_wr = wr;
169b16807c5Selric 	data->ramdac_rd = rd;
170b16807c5Selric 	return (struct ramdac_cookie *)data;
171b16807c5Selric }
172b16807c5Selric 
173b16807c5Selric /*
174b16807c5Selric  * This function exists solely to provide a means to init
175b16807c5Selric  * the RAMDAC without first registering.  It is useful for
176b16807c5Selric  * initializing the console early on.
177b16807c5Selric  */
178b16807c5Selric void
bt485_cninit(void * v,int (* sched_update)(void *,void (*)(void *)),void (* wr)(void *,u_int,u_int8_t),u_int8_t (* rd)(void *,u_int))1791d7f24eaSmatt bt485_cninit(
1801d7f24eaSmatt 	void *v,
1811d7f24eaSmatt 	int (*sched_update)(void *, void (*)(void *)),
1821d7f24eaSmatt 	void (*wr)(void *, u_int, u_int8_t),
1831d7f24eaSmatt 	u_int8_t (*rd)(void *, u_int))
184b16807c5Selric {
185b16807c5Selric 	struct bt485data tmp, *data = &tmp;
186b16807c5Selric 	data->cookie = v;
187b16807c5Selric 	data->ramdac_sched_update = sched_update;
188b16807c5Selric 	data->ramdac_wr = wr;
189b16807c5Selric 	data->ramdac_rd = rd;
190b16807c5Selric 	bt485_init((struct ramdac_cookie *)data);
191b16807c5Selric }
192b16807c5Selric 
193b16807c5Selric void
bt485_init(struct ramdac_cookie * rc)194454af1c0Sdsl bt485_init(struct ramdac_cookie *rc)
195b16807c5Selric {
196b16807c5Selric 	u_int8_t regval;
197b16807c5Selric 	struct bt485data *data = (struct bt485data *)rc;
198b16807c5Selric 	int i;
199b16807c5Selric 
200b16807c5Selric 	/*
201b16807c5Selric 	 * Init the BT485 for normal operation.
202b16807c5Selric 	 */
203b16807c5Selric 
204b16807c5Selric 	/*
205b16807c5Selric 	 * Allow indirect register access.  (Actually, this is
206b16807c5Selric 	 * already enabled.  In fact, if it is _disabled_, for
207b16807c5Selric 	 * some reason the monitor appears to lose sync!!! (?!?!)
208b16807c5Selric 	 */
209b16807c5Selric 	regval = data->ramdac_rd(data->cookie, BT485_REG_COMMAND_0);
210b16807c5Selric 	regval |= 0x80;
211b16807c5Selric 	/*
212b16807c5Selric 	 * Set the RAMDAC to 8 bit resolution, rather than 6 bit
213b16807c5Selric 	 * resolution.
214b16807c5Selric 	 */
215b16807c5Selric 	regval |= 0x02;
216b16807c5Selric 	data->ramdac_wr(data->cookie, BT485_REG_COMMAND_0, regval);
217b16807c5Selric 
218b16807c5Selric 	/* Set the RAMDAC to 8BPP (no interestion options). */
219b16807c5Selric 	data->ramdac_wr(data->cookie, BT485_REG_COMMAND_1, 0x40);
220b16807c5Selric 
221b16807c5Selric 	/* Disable the cursor (for now) */
222b16807c5Selric 	regval = data->ramdac_rd(data->cookie, BT485_REG_COMMAND_2);
223b16807c5Selric 	regval &= ~0x03;
224b16807c5Selric 	regval |= 0x24;
225b16807c5Selric 	data->ramdac_wr(data->cookie, BT485_REG_COMMAND_2, regval);
226b16807c5Selric 
227b16807c5Selric 	/* Use a 64x64x2 cursor */
228b16807c5Selric 	regval = bt485_rd_i(data, BT485_IREG_COMMAND_3);
229b16807c5Selric 	regval |= 0x04;
230b16807c5Selric 	regval |= 0x08;
231b16807c5Selric 	bt485_wr_i(data, BT485_IREG_COMMAND_3, regval);
232b16807c5Selric 
233b16807c5Selric 	/* Set the Pixel Mask to something useful */
234b16807c5Selric 	data->ramdac_wr(data->cookie, BT485_REG_PIXMASK, 0xff);
235b16807c5Selric 
236b16807c5Selric 	/*
2379fa0b176Swiz 	 * Initialize the RAMDAC info struct to hold all of our
238b16807c5Selric 	 * data, and fill it in.
239b16807c5Selric 	 */
240b16807c5Selric 	data->changed = DATA_ALL_CHANGED;
241b16807c5Selric 
242b16807c5Selric 	data->curenb = 0;				/* cursor disabled */
243b16807c5Selric 	data->curpos.x = data->curpos.y = 0;		/* right now at 0,0 */
244b16807c5Selric 	data->curhot.x = data->curhot.y = 0;		/* hot spot at 0,0 */
245b16807c5Selric 
246b16807c5Selric 	/* initial cursor colormap: 0 is black, 1 is white */
247b16807c5Selric 	data->curcmap_r[0] = data->curcmap_g[0] = data->curcmap_b[0] = 0;
248b16807c5Selric 	data->curcmap_r[1] = data->curcmap_g[1] = data->curcmap_b[1] = 0xff;
249b16807c5Selric 
250b16807c5Selric 	/* initial cursor data: 64x64 block of white. */
251b16807c5Selric 	data->cursize.x = data->cursize.y = 64;
252b16807c5Selric 	for (i = 0; i < 512; i++)
253b16807c5Selric 		data->curimage[i] = data->curmask[i] = 0xff;
254b16807c5Selric 
255b16807c5Selric 	/* Initial colormap: 0 is black, everything else is white */
256b16807c5Selric 	data->cmap_r[0] = data->cmap_g[0] = data->cmap_b[0] = 0;
257b16807c5Selric 	for (i = 1; i < 256; i++)
258b16807c5Selric 		data->cmap_r[i] = data->cmap_g[i] = data->cmap_b[i] = 255;
259b16807c5Selric 
260b16807c5Selric 	bt485_update((void *)data);
261b16807c5Selric }
262b16807c5Selric 
263b16807c5Selric int
bt485_set_cmap(struct ramdac_cookie * rc,struct wsdisplay_cmap * cmapp)264454af1c0Sdsl bt485_set_cmap(struct ramdac_cookie *rc, struct wsdisplay_cmap *cmapp)
265b16807c5Selric {
266b16807c5Selric 	struct bt485data *data = (struct bt485data *)rc;
267ceb38aa7Sjdolecek 	u_int count, index;
268e07f0b93Schs 	uint8_t r[256], g[256], b[256];
269e07f0b93Schs 	int s, error;
270b16807c5Selric 
2718dd04cdcSitojun 	if (cmapp->index >= 256 || cmapp->count > 256 - cmapp->index)
272b16807c5Selric 		return (EINVAL);
273b16807c5Selric 
274b16807c5Selric 	index = cmapp->index;
275b16807c5Selric 	count = cmapp->count;
276e07f0b93Schs 	error = copyin(cmapp->red, &r[index], count);
277e07f0b93Schs 	if (error)
278e07f0b93Schs 		return error;
279e07f0b93Schs 	error = copyin(cmapp->green, &g[index], count);
280e07f0b93Schs 	if (error)
281e07f0b93Schs 		return error;
282e07f0b93Schs 	error = copyin(cmapp->blue, &b[index], count);
283e07f0b93Schs 	if (error)
284e07f0b93Schs 		return error;
285e07f0b93Schs 	s = spltty();
286e07f0b93Schs 	memcpy(&data->cmap_r[index], &r[index], count);
287e07f0b93Schs 	memcpy(&data->cmap_g[index], &g[index], count);
288e07f0b93Schs 	memcpy(&data->cmap_b[index], &b[index], count);
289b16807c5Selric 	data->changed |= DATA_CMAP_CHANGED;
290b16807c5Selric 	data->ramdac_sched_update(data->cookie, bt485_update);
291b16807c5Selric 	splx(s);
292b16807c5Selric 	return (0);
293b16807c5Selric }
294b16807c5Selric 
295b16807c5Selric int
bt485_get_cmap(struct ramdac_cookie * rc,struct wsdisplay_cmap * cmapp)296454af1c0Sdsl bt485_get_cmap(struct ramdac_cookie *rc, struct wsdisplay_cmap *cmapp)
297b16807c5Selric {
298b16807c5Selric 	struct bt485data *data = (struct bt485data *)rc;
2998dd04cdcSitojun 	u_int count, index;
3008dd04cdcSitojun 	int error;
301b16807c5Selric 
3028dd04cdcSitojun 	if (cmapp->index >= 256 || cmapp->count > 256 - cmapp->index )
303b16807c5Selric 		return (EINVAL);
304b16807c5Selric 
305b16807c5Selric 	count = cmapp->count;
306b16807c5Selric 	index = cmapp->index;
307b16807c5Selric 	error = copyout(&data->cmap_r[index], cmapp->red, count);
308b16807c5Selric 	if (error)
309b16807c5Selric 		return (error);
310b16807c5Selric 	error = copyout(&data->cmap_g[index], cmapp->green, count);
311b16807c5Selric 	if (error)
312b16807c5Selric 		return (error);
313b16807c5Selric 	error = copyout(&data->cmap_b[index], cmapp->blue, count);
314b16807c5Selric 	return (error);
315b16807c5Selric }
316b16807c5Selric 
317b16807c5Selric int
bt485_set_cursor(struct ramdac_cookie * rc,struct wsdisplay_cursor * cursorp)318454af1c0Sdsl bt485_set_cursor(struct ramdac_cookie *rc, struct wsdisplay_cursor *cursorp)
319b16807c5Selric {
320b16807c5Selric 	struct bt485data *data = (struct bt485data *)rc;
321e07f0b93Schs 	u_int count = 0, icount = 0, index = 0, v;
322e07f0b93Schs 	char r[2], g[2], b[2], image[512], mask[512];
323e07f0b93Schs 	int s, error;
324b16807c5Selric 
325b16807c5Selric 	v = cursorp->which;
326b16807c5Selric 
327b16807c5Selric 	/*
328e07f0b93Schs 	 * For DOCMAP and DOSHAPE, copy in the new data
329b16807c5Selric 	 * before we do anything that we can't recover from.
330b16807c5Selric 	 */
331b16807c5Selric 	if (v & WSDISPLAY_CURSOR_DOCMAP) {
332ceb38aa7Sjdolecek 		if (cursorp->cmap.index > 2 ||
333*8e9f762cSriastradh 		    cursorp->cmap.count > 2 - cursorp->cmap.index)
334b16807c5Selric 			return (EINVAL);
335b16807c5Selric 		count = cursorp->cmap.count;
336e07f0b93Schs 		index = cursorp->cmap.index;
337e07f0b93Schs 		error = copyin(cursorp->cmap.red, &r[index], count);
338e07f0b93Schs 		if (error)
339e07f0b93Schs 			return error;
340e07f0b93Schs 		error = copyin(cursorp->cmap.green, &g[index], count);
341e07f0b93Schs 		if (error)
342e07f0b93Schs 			return error;
343e07f0b93Schs 		error = copyin(cursorp->cmap.blue, &b[index], count);
344e07f0b93Schs 		if (error)
345e07f0b93Schs 			return error;
346b16807c5Selric 	}
347b16807c5Selric 	if (v & WSDISPLAY_CURSOR_DOSHAPE) {
348ceb38aa7Sjdolecek 		if (cursorp->size.x > CURSOR_MAX_SIZE ||
349ceb38aa7Sjdolecek 		    cursorp->size.y > CURSOR_MAX_SIZE)
350b16807c5Selric 			return (EINVAL);
351e07f0b93Schs 		icount = (CURSOR_MAX_SIZE / NBBY) * data->cursize.y;
352e07f0b93Schs 		error = copyin(cursorp->image, image, icount);
353e07f0b93Schs 		if (error)
354e07f0b93Schs 			return error;
355e07f0b93Schs 		error = copyin(cursorp->mask, mask, icount);
356e07f0b93Schs 		if (error)
357e07f0b93Schs 			return error;
358b16807c5Selric 	}
359b16807c5Selric 
360b16807c5Selric 	if (v & (WSDISPLAY_CURSOR_DOPOS | WSDISPLAY_CURSOR_DOCUR)) {
361b16807c5Selric 		if (v & WSDISPLAY_CURSOR_DOPOS)
362b16807c5Selric 			data->curpos = cursorp->pos;
363b16807c5Selric 		if (v & WSDISPLAY_CURSOR_DOCUR)
364b16807c5Selric 			data->curhot = cursorp->hot;
365b16807c5Selric 		bt485_update_curpos(data);
366b16807c5Selric 	}
367b16807c5Selric 
368b16807c5Selric 	s = spltty();
369b16807c5Selric 
370e07f0b93Schs 	/* Data is all available; perform the requested operations. */
371b16807c5Selric 	if (v & WSDISPLAY_CURSOR_DOCUR) {
372b16807c5Selric 		data->curenb = cursorp->enable;
373b16807c5Selric 		data->changed |= DATA_ENB_CHANGED;
374b16807c5Selric 	}
375b16807c5Selric 	if (v & WSDISPLAY_CURSOR_DOCMAP) {
376e07f0b93Schs 		memcpy(&data->curcmap_r[index], &r[index], count);
377e07f0b93Schs 		memcpy(&data->curcmap_g[index], &g[index], count);
378e07f0b93Schs 		memcpy(&data->curcmap_b[index], &b[index], count);
379b16807c5Selric 		data->changed |= DATA_CURCMAP_CHANGED;
380b16807c5Selric 	}
381b16807c5Selric 	if (v & WSDISPLAY_CURSOR_DOSHAPE) {
382b16807c5Selric 		data->cursize = cursorp->size;
383b16807c5Selric 		count = (CURSOR_MAX_SIZE / NBBY) * data->cursize.y;
3840884f20bSthorpej 		memset(data->curimage, 0, sizeof data->curimage);
3850884f20bSthorpej 		memset(data->curmask, 0, sizeof data->curmask);
386e07f0b93Schs 		memcpy(data->curimage, image, icount);
387e07f0b93Schs 		memcpy(data->curmask, mask, icount);
388b16807c5Selric 		data->changed |= DATA_CURSHAPE_CHANGED;
389b16807c5Selric 	}
390b16807c5Selric 
391b16807c5Selric 	if (data->changed)
392b16807c5Selric 		data->ramdac_sched_update(data->cookie, bt485_update);
393b16807c5Selric 	splx(s);
394b16807c5Selric 
395b16807c5Selric 	return (0);
396b16807c5Selric }
397b16807c5Selric 
398b16807c5Selric int
bt485_get_cursor(struct ramdac_cookie * rc,struct wsdisplay_cursor * cursorp)399454af1c0Sdsl bt485_get_cursor(struct ramdac_cookie *rc, struct wsdisplay_cursor *cursorp)
400b16807c5Selric {
401b16807c5Selric 	struct bt485data *data = (struct bt485data *)rc;
402b16807c5Selric 	int error, count;
403b16807c5Selric 
404b16807c5Selric 	/* we return everything they want */
405b16807c5Selric 	cursorp->which = WSDISPLAY_CURSOR_DOALL;
406b16807c5Selric 
407b16807c5Selric 	cursorp->enable = data->curenb;	/* DOCUR */
408b16807c5Selric 	cursorp->pos = data->curpos;	/* DOPOS */
409b16807c5Selric 	cursorp->hot = data->curhot;	/* DOHOT */
410b16807c5Selric 
411b16807c5Selric 	cursorp->cmap.index = 0;	/* DOCMAP */
412b16807c5Selric 	cursorp->cmap.count = 2;
413b16807c5Selric 	if (cursorp->cmap.red != NULL) {
414b16807c5Selric 		error = copyout(data->curcmap_r, cursorp->cmap.red, 2);
415b16807c5Selric 		if (error)
416b16807c5Selric 			return (error);
417b16807c5Selric 	}
418b16807c5Selric 	if (cursorp->cmap.green != NULL) {
419b16807c5Selric 		error = copyout(data->curcmap_g, cursorp->cmap.green, 2);
420b16807c5Selric 		if (error)
421b16807c5Selric 			return (error);
422b16807c5Selric 	}
423b16807c5Selric 	if (cursorp->cmap.blue != NULL) {
424b16807c5Selric 		error = copyout(data->curcmap_b, cursorp->cmap.blue, 2);
425b16807c5Selric 		if (error)
426b16807c5Selric 			return (error);
427b16807c5Selric 	}
428b16807c5Selric 
429b16807c5Selric 	cursorp->size = data->cursize;	/* DOSHAPE */
430b16807c5Selric 	if (cursorp->image != NULL) {
431b16807c5Selric 		count = (CURSOR_MAX_SIZE / NBBY) * data->cursize.y;
432b16807c5Selric 		error = copyout(data->curimage, cursorp->image, count);
433b16807c5Selric 		if (error)
434b16807c5Selric 			return (error);
435b16807c5Selric 		error = copyout(data->curmask, cursorp->mask, count);
436b16807c5Selric 		if (error)
437b16807c5Selric 			return (error);
438b16807c5Selric 	}
439b16807c5Selric 
440b16807c5Selric 	return (0);
441b16807c5Selric }
442b16807c5Selric 
443b16807c5Selric int
bt485_set_curpos(struct ramdac_cookie * rc,struct wsdisplay_curpos * curposp)444454af1c0Sdsl bt485_set_curpos(struct ramdac_cookie *rc, struct wsdisplay_curpos *curposp)
445b16807c5Selric {
446b16807c5Selric 	struct bt485data *data = (struct bt485data *)rc;
447b16807c5Selric 
448b16807c5Selric 	data->curpos = *curposp;
449b16807c5Selric 	bt485_update_curpos(data);
450b16807c5Selric 
451b16807c5Selric 	return (0);
452b16807c5Selric }
453b16807c5Selric 
454b16807c5Selric int
bt485_get_curpos(struct ramdac_cookie * rc,struct wsdisplay_curpos * curposp)455454af1c0Sdsl bt485_get_curpos(struct ramdac_cookie *rc, struct wsdisplay_curpos *curposp)
456b16807c5Selric {
457b16807c5Selric 	struct bt485data *data = (struct bt485data *)rc;
458b16807c5Selric 
459b16807c5Selric 	*curposp = data->curpos;
460b16807c5Selric 	return (0);
461b16807c5Selric }
462b16807c5Selric 
463b16807c5Selric int
bt485_get_curmax(struct ramdac_cookie * rc,struct wsdisplay_curpos * curposp)464454af1c0Sdsl bt485_get_curmax(struct ramdac_cookie *rc, struct wsdisplay_curpos *curposp)
465b16807c5Selric {
466b16807c5Selric 
467b16807c5Selric 	curposp->x = curposp->y = CURSOR_MAX_SIZE;
468b16807c5Selric 	return (0);
469b16807c5Selric }
470b16807c5Selric 
471b16807c5Selric /*****************************************************************************/
472b16807c5Selric 
473b16807c5Selric /*
474b16807c5Selric  * Internal functions.
475b16807c5Selric  */
476b16807c5Selric 
477b16807c5Selric void
bt485_update(void * vp)478454af1c0Sdsl bt485_update(void *vp)
479b16807c5Selric {
480b16807c5Selric 	struct bt485data *data = vp;
481b16807c5Selric 	u_int8_t regval;
482b16807c5Selric 	int count, i, v;
483b16807c5Selric 
484b16807c5Selric 	v = data->changed;
485b16807c5Selric 	data->changed = 0;
486b16807c5Selric 
487b16807c5Selric 	if (v & DATA_ENB_CHANGED) {
488b16807c5Selric 		regval = data->ramdac_rd(data->cookie, BT485_REG_COMMAND_2);
489b16807c5Selric 		if (data->curenb)
490b16807c5Selric 			regval |= 0x01;
491b16807c5Selric 		else
492b16807c5Selric 			regval &= ~0x03;
493b16807c5Selric                 data->ramdac_wr(data->cookie, BT485_REG_COMMAND_2, regval);
494b16807c5Selric 	}
495b16807c5Selric 
496b16807c5Selric 	if (v & DATA_CURCMAP_CHANGED) {
497b16807c5Selric 		/* addr[9:0] assumed to be 0 */
498b16807c5Selric 		/* set addr[7:0] to 1 */
499b16807c5Selric                 data->ramdac_wr(data->cookie, BT485_REG_COC_WRADDR, 0x01);
500b16807c5Selric 
501b16807c5Selric 		/* spit out the cursor data */
502b16807c5Selric 		for (i = 0; i < 2; i++) {
503b16807c5Selric                 	data->ramdac_wr(data->cookie, BT485_REG_COCDATA,
504b16807c5Selric 			    data->curcmap_r[i]);
505b16807c5Selric                 	data->ramdac_wr(data->cookie, BT485_REG_COCDATA,
506b16807c5Selric 			    data->curcmap_g[i]);
507b16807c5Selric                 	data->ramdac_wr(data->cookie, BT485_REG_COCDATA,
508b16807c5Selric 			    data->curcmap_b[i]);
509b16807c5Selric 		}
510b16807c5Selric 	}
511b16807c5Selric 
512b16807c5Selric 	if (v & DATA_CURSHAPE_CHANGED) {
513b16807c5Selric 		count = (CURSOR_MAX_SIZE / NBBY) * data->cursize.y;
514b16807c5Selric 
515b16807c5Selric 		/*
516b16807c5Selric 		 * Write the cursor image data:
517b16807c5Selric 		 *	set addr[9:8] to 0,
518b16807c5Selric 		 *	set addr[7:0] to 0,
519b16807c5Selric 		 *	spit it all out.
520b16807c5Selric 		 */
521b16807c5Selric 		regval = bt485_rd_i(data, BT485_IREG_COMMAND_3);
522b16807c5Selric 		regval &= ~0x03;
523b16807c5Selric 		bt485_wr_i(data, BT485_IREG_COMMAND_3, regval);
524b16807c5Selric                 data->ramdac_wr(data->cookie, BT485_REG_PCRAM_WRADDR, 0);
525b16807c5Selric 		for (i = 0; i < count; i++)
526b16807c5Selric 			data->ramdac_wr(data->cookie, BT485_REG_CURSOR_RAM,
527b16807c5Selric 			    data->curimage[i]);
528b16807c5Selric 
529b16807c5Selric 		/*
530b16807c5Selric 		 * Write the cursor mask data:
531b16807c5Selric 		 *	set addr[9:8] to 2,
532b16807c5Selric 		 *	set addr[7:0] to 0,
533b16807c5Selric 		 *	spit it all out.
534b16807c5Selric 		 */
535b16807c5Selric 		regval = bt485_rd_i(data, BT485_IREG_COMMAND_3);
536b16807c5Selric 		regval &= ~0x03; regval |= 0x02;
537b16807c5Selric 		bt485_wr_i(data, BT485_IREG_COMMAND_3, regval);
538b16807c5Selric                 data->ramdac_wr(data->cookie, BT485_REG_PCRAM_WRADDR, 0);
539b16807c5Selric 		for (i = 0; i < count; i++)
540b16807c5Selric 			data->ramdac_wr(data->cookie, BT485_REG_CURSOR_RAM,
541b16807c5Selric 			    data->curmask[i]);
542b16807c5Selric 
543b16807c5Selric 		/* set addr[9:0] back to 0 */
544b16807c5Selric 		regval = bt485_rd_i(data, BT485_IREG_COMMAND_3);
545b16807c5Selric 		regval &= ~0x03;
546b16807c5Selric 		bt485_wr_i(data, BT485_IREG_COMMAND_3, regval);
547b16807c5Selric 	}
548b16807c5Selric 
549b16807c5Selric 	if (v & DATA_CMAP_CHANGED) {
550b16807c5Selric 		/* addr[9:0] assumed to be 0 */
551b16807c5Selric 		/* set addr[7:0] to 0 */
552b16807c5Selric                 data->ramdac_wr(data->cookie, BT485_REG_PCRAM_WRADDR, 0x00);
553b16807c5Selric 
554b16807c5Selric 		/* spit out the cursor data */
555b16807c5Selric 		for (i = 0; i < 256; i++) {
556b16807c5Selric                 	data->ramdac_wr(data->cookie, BT485_REG_PALETTE,
557b16807c5Selric 			    data->cmap_r[i]);
558b16807c5Selric                 	data->ramdac_wr(data->cookie, BT485_REG_PALETTE,
559b16807c5Selric 			    data->cmap_g[i]);
560b16807c5Selric                 	data->ramdac_wr(data->cookie, BT485_REG_PALETTE,
561b16807c5Selric 			    data->cmap_b[i]);
562b16807c5Selric 		}
563b16807c5Selric 	}
564b16807c5Selric }
565b16807c5Selric 
566b16807c5Selric void
bt485_update_curpos(struct bt485data * data)567454af1c0Sdsl bt485_update_curpos(struct bt485data *data)
568b16807c5Selric {
569b16807c5Selric 	void *cookie = data->cookie;
570b16807c5Selric 	int s, x, y;
571b16807c5Selric 
572b16807c5Selric 	s = spltty();
573b16807c5Selric 
574b16807c5Selric 	x = data->curpos.x + CURSOR_MAX_SIZE - data->curhot.x;
575b16807c5Selric 	y = data->curpos.y + CURSOR_MAX_SIZE - data->curhot.y;
576b16807c5Selric 	data->ramdac_wr(cookie, BT485_REG_CURSOR_X_LOW, x & 0xff);
577b16807c5Selric 	data->ramdac_wr(cookie, BT485_REG_CURSOR_X_HIGH, (x >> 8) & 0x0f);
578b16807c5Selric 	data->ramdac_wr(cookie, BT485_REG_CURSOR_Y_LOW, y & 0xff);
579b16807c5Selric 	data->ramdac_wr(cookie, BT485_REG_CURSOR_Y_HIGH, (y >> 8) & 0x0f);
580b16807c5Selric 
581b16807c5Selric 	splx(s);
582b16807c5Selric }
583