xref: /netbsd-src/sys/dev/ic/bt463.c (revision 8e9f762ce7d368111b68db7e9d33856219c4eb9b)
1*8e9f762cSriastradh /* $NetBSD: bt463.c,v 1.18 2018/01/24 05:35:58 riastradh Exp $ */
2c0a4c9e6Snathanw 
3c0a4c9e6Snathanw /*-
4c0a4c9e6Snathanw  * Copyright (c) 1998 The NetBSD Foundation, Inc.
5c0a4c9e6Snathanw  * All rights reserved.
6c0a4c9e6Snathanw  *
7c0a4c9e6Snathanw  * This code is derived from software contributed to The NetBSD Foundation
8c0a4c9e6Snathanw  * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
9c0a4c9e6Snathanw  * NASA Ames Research Center.
10c0a4c9e6Snathanw  *
11c0a4c9e6Snathanw  * Redistribution and use in source and binary forms, with or without
12c0a4c9e6Snathanw  * modification, are permitted provided that the following conditions
13c0a4c9e6Snathanw  * are met:
14c0a4c9e6Snathanw  * 1. Redistributions of source code must retain the above copyright
15c0a4c9e6Snathanw  *    notice, this list of conditions and the following disclaimer.
16c0a4c9e6Snathanw  * 2. Redistributions in binary form must reproduce the above copyright
17c0a4c9e6Snathanw  *    notice, this list of conditions and the following disclaimer in the
18c0a4c9e6Snathanw  *    documentation and/or other materials provided with the distribution.
19c0a4c9e6Snathanw  *
20c0a4c9e6Snathanw  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
21c0a4c9e6Snathanw  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22c0a4c9e6Snathanw  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23c0a4c9e6Snathanw  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
24c0a4c9e6Snathanw  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25c0a4c9e6Snathanw  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26c0a4c9e6Snathanw  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27c0a4c9e6Snathanw  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28c0a4c9e6Snathanw  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29c0a4c9e6Snathanw  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30c0a4c9e6Snathanw  * POSSIBILITY OF SUCH DAMAGE.
31c0a4c9e6Snathanw  */
32c0a4c9e6Snathanw 
33c0a4c9e6Snathanw /*
34c0a4c9e6Snathanw  * Copyright (c) 1995, 1996 Carnegie-Mellon University.
35c0a4c9e6Snathanw  * All rights reserved.
36c0a4c9e6Snathanw  *
37c0a4c9e6Snathanw  * Author: Chris G. Demetriou
38c0a4c9e6Snathanw  *
39c0a4c9e6Snathanw  * Permission to use, copy, modify and distribute this software and
40c0a4c9e6Snathanw  * its documentation is hereby granted, provided that both the copyright
41c0a4c9e6Snathanw  * notice and this permission notice appear in all copies of the
42c0a4c9e6Snathanw  * software, derivative works or modified versions, and any portions
43c0a4c9e6Snathanw  * thereof, and that both notices appear in supporting documentation.
44c0a4c9e6Snathanw  *
45c0a4c9e6Snathanw  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
46c0a4c9e6Snathanw  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
47c0a4c9e6Snathanw  * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
48c0a4c9e6Snathanw  *
49c0a4c9e6Snathanw  * Carnegie Mellon requests users of this software to return to
50c0a4c9e6Snathanw  *
51c0a4c9e6Snathanw  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
52c0a4c9e6Snathanw  *  School of Computer Science
53c0a4c9e6Snathanw  *  Carnegie Mellon University
54c0a4c9e6Snathanw  *  Pittsburgh PA 15213-3890
55c0a4c9e6Snathanw  *
56c0a4c9e6Snathanw  * any improvements or extensions that they make and grant Carnegie the
57c0a4c9e6Snathanw  * rights to redistribute these changes.
58c0a4c9e6Snathanw  */
59c0a4c9e6Snathanw 
60c0a4c9e6Snathanw  /* This code was derived from and originally located in sys/dev/pci/
61c0a4c9e6Snathanw   *	 NetBSD: tga_bt463.c,v 1.5 2000/03/04 10:27:59 elric Exp
62c0a4c9e6Snathanw   */
63c0a4c9e6Snathanw 
64a4bae8b0Slukem #include <sys/cdefs.h>
65*8e9f762cSriastradh __KERNEL_RCSID(0, "$NetBSD: bt463.c,v 1.18 2018/01/24 05:35:58 riastradh Exp $");
66a4bae8b0Slukem 
67c0a4c9e6Snathanw #include <sys/param.h>
68c0a4c9e6Snathanw #include <sys/systm.h>
69c0a4c9e6Snathanw #include <sys/device.h>
70c0a4c9e6Snathanw #include <sys/buf.h>
71c0a4c9e6Snathanw #include <sys/kernel.h>
72c0a4c9e6Snathanw #include <sys/malloc.h>
73314f1e97Smrg 
74c0a4c9e6Snathanw #include <dev/pci/pcivar.h>
75c0a4c9e6Snathanw #include <dev/pci/tgareg.h>
76c0a4c9e6Snathanw #include <dev/pci/tgavar.h>
77c0a4c9e6Snathanw #include <dev/ic/bt463reg.h>
78c0a4c9e6Snathanw #include <dev/ic/bt463var.h>
79c0a4c9e6Snathanw 
80c0a4c9e6Snathanw #include <dev/wscons/wsconsio.h>
81c0a4c9e6Snathanw 
82c0a4c9e6Snathanw /*
83c0a4c9e6Snathanw  * Functions exported via the RAMDAC configuration table.
84c0a4c9e6Snathanw  */
8518db93c7Sperry void	bt463_init(struct ramdac_cookie *);
8618db93c7Sperry int	bt463_set_cmap(struct ramdac_cookie *, struct wsdisplay_cmap *);
8718db93c7Sperry int	bt463_get_cmap(struct ramdac_cookie *, struct wsdisplay_cmap *);
8818db93c7Sperry int	bt463_set_cursor(struct ramdac_cookie *, struct wsdisplay_cursor *);
8918db93c7Sperry int	bt463_get_cursor(struct ramdac_cookie *, struct wsdisplay_cursor *);
9018db93c7Sperry int	bt463_set_curpos(struct ramdac_cookie *, struct wsdisplay_curpos *);
9118db93c7Sperry int	bt463_get_curpos(struct ramdac_cookie *, struct wsdisplay_curpos *);
9218db93c7Sperry int	bt463_get_curmax(struct ramdac_cookie *, struct wsdisplay_curpos *);
9318db93c7Sperry int	bt463_check_curcmap(struct ramdac_cookie *,
9418db93c7Sperry 	    struct wsdisplay_cursor *cursorp);
9518db93c7Sperry void	bt463_set_curcmap(struct ramdac_cookie *,
9618db93c7Sperry 	    struct wsdisplay_cursor *cursorp);
9718db93c7Sperry int	bt463_get_curcmap(struct ramdac_cookie *,
9818db93c7Sperry 	    struct wsdisplay_cursor *cursorp);
99c0a4c9e6Snathanw 
100c0a4c9e6Snathanw #ifdef BT463_DEBUG
10118db93c7Sperry int bt463_store(void *);
10218db93c7Sperry int bt463_debug(void *);
10318db93c7Sperry int bt463_readback(void *);
10418db93c7Sperry void	bt463_copyback(void *);
105c0a4c9e6Snathanw #endif
106c0a4c9e6Snathanw 
107c0a4c9e6Snathanw struct ramdac_funcs bt463_funcsstruct = {
108c0a4c9e6Snathanw 	"Bt463",
109c0a4c9e6Snathanw 	bt463_register,
110c0a4c9e6Snathanw 	bt463_init,
111c0a4c9e6Snathanw 	bt463_set_cmap,
112c0a4c9e6Snathanw 	bt463_get_cmap,
113c0a4c9e6Snathanw 	bt463_set_cursor,
114c0a4c9e6Snathanw 	bt463_get_cursor,
115c0a4c9e6Snathanw 	bt463_set_curpos,
116c0a4c9e6Snathanw 	bt463_get_curpos,
117c0a4c9e6Snathanw 	bt463_get_curmax,
118c0a4c9e6Snathanw 	bt463_check_curcmap,
119c0a4c9e6Snathanw 	bt463_set_curcmap,
120c0a4c9e6Snathanw 	bt463_get_curcmap,
12194448f7eSelric 	NULL,
122c0a4c9e6Snathanw };
123c0a4c9e6Snathanw 
124c0a4c9e6Snathanw /*
125c0a4c9e6Snathanw  * Private data.
126c0a4c9e6Snathanw  */
127c0a4c9e6Snathanw struct bt463data {
128c0a4c9e6Snathanw 	void            *cookie;        /* This is what is passed
129c0a4c9e6Snathanw 					 * around, and is probably
130c0a4c9e6Snathanw 					 * struct tga_devconfig *
131c0a4c9e6Snathanw 					 */
132c0a4c9e6Snathanw 
13318db93c7Sperry 	int             (*ramdac_sched_update)(void *, void (*)(void *));
13418db93c7Sperry 	void            (*ramdac_wr)(void *, u_int, u_int8_t);
13518db93c7Sperry 	u_int8_t        (*ramdac_rd)(void *, u_int);
136c0a4c9e6Snathanw 
137c0a4c9e6Snathanw 	int	changed;			/* what changed; see below */
138c0a4c9e6Snathanw 	char curcmap_r[2];			/* cursor colormap */
139c0a4c9e6Snathanw 	char curcmap_g[2];
140c0a4c9e6Snathanw 	char curcmap_b[2];
141e07f0b93Schs 	char tmpcurcmap_r[2];			/* tmp cursor colormap */
142e07f0b93Schs 	char tmpcurcmap_g[2];
143e07f0b93Schs 	char tmpcurcmap_b[2];
144c0a4c9e6Snathanw 	char cmap_r[BT463_NCMAP_ENTRIES];	/* colormap */
145c0a4c9e6Snathanw 	char cmap_g[BT463_NCMAP_ENTRIES];
146c0a4c9e6Snathanw 	char cmap_b[BT463_NCMAP_ENTRIES];
147c0a4c9e6Snathanw 	int window_type[16]; /* 16 24-bit window type table entries */
148c0a4c9e6Snathanw };
149c0a4c9e6Snathanw 
150a5598651Snathanw /* When we're doing console initialization, there's no
151a5598651Snathanw  * way to get our cookie back to the video card's softc
152a5598651Snathanw  * before we call sched_update. So we stash it here,
153a5598651Snathanw  * and bt463_update will look for it here first.
154a5598651Snathanw  */
155a5598651Snathanw static struct bt463data *console_data;
156a5598651Snathanw 
157a5598651Snathanw 
158c0a4c9e6Snathanw #define BTWREG(data, addr, val) do { bt463_wraddr((data), (addr)); \
159c0a4c9e6Snathanw 	(data)->ramdac_wr((data)->cookie, BT463_REG_IREG_DATA, (val)); } while (0)
160c0a4c9e6Snathanw #define BTWNREG(data, val) (data)->ramdac_wr((data)->cookie, \
161c0a4c9e6Snathanw 	BT463_REG_IREG_DATA, (val))
162c0a4c9e6Snathanw #define BTRREG(data, addr) (bt463_wraddr((data), (addr)), \
163c0a4c9e6Snathanw 	(data)->ramdac_rd((data)->cookie, BT463_REG_IREG_DATA))
164c0a4c9e6Snathanw #define BTRNREG(data) ((data)->ramdac_rd((data)->cookie, BT463_REG_IREG_DATA))
165c0a4c9e6Snathanw 
166c0a4c9e6Snathanw #define	DATA_CURCMAP_CHANGED	0x01	/* cursor colormap changed */
167c0a4c9e6Snathanw #define	DATA_CMAP_CHANGED	0x02	/* colormap changed */
168c0a4c9e6Snathanw #define	DATA_WTYPE_CHANGED	0x04	/* window type table changed */
169c0a4c9e6Snathanw #define	DATA_ALL_CHANGED	0x07
170c0a4c9e6Snathanw 
171c0a4c9e6Snathanw /*
172c0a4c9e6Snathanw  * Internal functions.
173c0a4c9e6Snathanw  */
174c0a4c9e6Snathanw 
17518db93c7Sperry void	bt463_update(void *);
176c0a4c9e6Snathanw 
177106e9eabSriastradh static inline void
bt463_wraddr(struct bt463data * data,u_int16_t ireg)178106e9eabSriastradh bt463_wraddr(struct bt463data *data, u_int16_t ireg)
179106e9eabSriastradh {
180106e9eabSriastradh 	data->ramdac_wr(data->cookie, BT463_REG_ADDR_LOW, ireg & 0xff);
181106e9eabSriastradh 	data->ramdac_wr(data->cookie, BT463_REG_ADDR_HIGH, (ireg >> 8) & 0xff);
182106e9eabSriastradh }
183c0a4c9e6Snathanw 
184c0a4c9e6Snathanw /*****************************************************************************/
185c0a4c9e6Snathanw 
186c0a4c9e6Snathanw /*
187c0a4c9e6Snathanw  * Functions exported via the RAMDAC configuration table.
188c0a4c9e6Snathanw  */
189c0a4c9e6Snathanw 
190c0a4c9e6Snathanw struct ramdac_funcs *
bt463_funcs(void)191c0a4c9e6Snathanw bt463_funcs(void)
192c0a4c9e6Snathanw {
193c0a4c9e6Snathanw 	return &bt463_funcsstruct;
194c0a4c9e6Snathanw }
195c0a4c9e6Snathanw 
196c0a4c9e6Snathanw struct ramdac_cookie *
bt463_register(void * v,int (* sched_update)(void *,void (*)(void *)),void (* wr)(void *,u_int,u_int8_t),u_int8_t (* rd)(void *,u_int))1971d7f24eaSmatt bt463_register(
1981d7f24eaSmatt 	void *v,
1991d7f24eaSmatt 	int (*sched_update)(void *, void (*)(void *)),
2001d7f24eaSmatt 	void (*wr)(void *, u_int, u_int8_t),
2011d7f24eaSmatt 	u_int8_t (*rd)(void *, u_int))
202c0a4c9e6Snathanw {
203c0a4c9e6Snathanw 	struct bt463data *data;
204c0a4c9e6Snathanw 	/*
205c0a4c9e6Snathanw 	 * XXX -- comment out of date.  rcd.
206c0a4c9e6Snathanw 	 * If we should allocate a new private info struct, do so.
207c0a4c9e6Snathanw 	 * Otherwise, use the one we have (if it's there), or
208c0a4c9e6Snathanw 	 * use the temporary one on the stack.
209c0a4c9e6Snathanw 	 */
210c0a4c9e6Snathanw 	data = malloc(sizeof *data, M_DEVBUF, M_WAITOK);
211c0a4c9e6Snathanw 	/* XXX -- if !data */
212c0a4c9e6Snathanw 	data->cookie = v;
213c0a4c9e6Snathanw 	data->ramdac_sched_update = sched_update;
214c0a4c9e6Snathanw 	data->ramdac_wr = wr;
215c0a4c9e6Snathanw 	data->ramdac_rd = rd;
216c0a4c9e6Snathanw 	return (struct ramdac_cookie *)data;
217c0a4c9e6Snathanw }
218c0a4c9e6Snathanw 
219c0a4c9e6Snathanw /*
220c0a4c9e6Snathanw  * This function exists solely to provide a means to init
221c0a4c9e6Snathanw  * the RAMDAC without first registering.  It is useful for
222c0a4c9e6Snathanw  * initializing the console early on.
223c0a4c9e6Snathanw  */
224c0a4c9e6Snathanw void
bt463_cninit(void * v,int (* sched_update)(void *,void (*)(void *)),void (* wr)(void *,u_int,u_int8_t),u_int8_t (* rd)(void *,u_int))2251d7f24eaSmatt bt463_cninit(
2261d7f24eaSmatt 	void *v,
2271d7f24eaSmatt 	int (*sched_update)(void *, void (*)(void *)),
2281d7f24eaSmatt 	void (*wr)(void *, u_int, u_int8_t),
2291d7f24eaSmatt 	u_int8_t (*rd)(void *, u_int))
230c0a4c9e6Snathanw {
231c0a4c9e6Snathanw 	struct bt463data tmp, *data = &tmp;
232c0a4c9e6Snathanw 	data->cookie = v;
233c0a4c9e6Snathanw 	data->ramdac_sched_update = sched_update;
234c0a4c9e6Snathanw 	data->ramdac_wr = wr;
235c0a4c9e6Snathanw 	data->ramdac_rd = rd;
236a5598651Snathanw 	/* Set up console_data so that when bt463_update is called back,
237a5598651Snathanw 	 * it can use the right information.
238a5598651Snathanw 	 */
239a5598651Snathanw 	console_data = data;
240c0a4c9e6Snathanw 	bt463_init((struct ramdac_cookie *)data);
241a5598651Snathanw 	console_data = NULL;
242c0a4c9e6Snathanw }
243c0a4c9e6Snathanw 
244c0a4c9e6Snathanw void
bt463_init(struct ramdac_cookie * rc)245454af1c0Sdsl bt463_init(struct ramdac_cookie *rc)
246c0a4c9e6Snathanw {
247c0a4c9e6Snathanw 	struct bt463data *data = (struct bt463data *)rc;
248c0a4c9e6Snathanw 
249c0a4c9e6Snathanw 	int i;
250c0a4c9e6Snathanw 
251c0a4c9e6Snathanw 	/*
252c0a4c9e6Snathanw 	 * Init the BT463 for normal operation.
253c0a4c9e6Snathanw 	 */
254c0a4c9e6Snathanw 
255c0a4c9e6Snathanw 
256c0a4c9e6Snathanw 	/*
257c0a4c9e6Snathanw 	 * Setup:
258c0a4c9e6Snathanw 	 * reg 0: 4:1 multiplexing, 25/75 blink.
259c0a4c9e6Snathanw 	 * reg 1: Overlay mapping: mapped to common palette,
260c0a4c9e6Snathanw 	 *        14 window type entries, 24-plane configuration mode,
261c0a4c9e6Snathanw 	 *        4 overlay planes, underlays disabled, no cursor.
262c0a4c9e6Snathanw 	 * reg 2: sync-on-green enabled, pedestal enabled.
263c0a4c9e6Snathanw 	 */
264c0a4c9e6Snathanw 
265c0a4c9e6Snathanw 	BTWREG(data, BT463_IREG_COMMAND_0, 0x40);
266c0a4c9e6Snathanw 	BTWREG(data, BT463_IREG_COMMAND_1, 0x48);
26794448f7eSelric 	BTWREG(data, BT463_IREG_COMMAND_2, 0x40);
268c0a4c9e6Snathanw 
269c0a4c9e6Snathanw 	/*
270c0a4c9e6Snathanw 	 * Initialize the read mask.
271c0a4c9e6Snathanw 	 */
272c0a4c9e6Snathanw 	bt463_wraddr(data, BT463_IREG_READ_MASK_P0_P7);
273c0a4c9e6Snathanw 	for (i = 0; i < 4; i++)
274c0a4c9e6Snathanw 		BTWNREG(data, 0xff);
275c0a4c9e6Snathanw 
276c0a4c9e6Snathanw 	/*
277c0a4c9e6Snathanw 	 * Initialize the blink mask.
278c0a4c9e6Snathanw 	 */
279c0a4c9e6Snathanw 	bt463_wraddr(data, BT463_IREG_BLINK_MASK_P0_P7);
280c0a4c9e6Snathanw 	for (i = 0; i < 4; i++)
281c0a4c9e6Snathanw 		BTWNREG(data, 0);
282c0a4c9e6Snathanw 
283c0a4c9e6Snathanw 
284c0a4c9e6Snathanw 	/*
285c0a4c9e6Snathanw 	 * Clear test register
286c0a4c9e6Snathanw 	 */
287c0a4c9e6Snathanw 	BTWREG(data, BT463_IREG_TEST, 0);
288c0a4c9e6Snathanw 
289c0a4c9e6Snathanw 	/*
2909fa0b176Swiz 	 * Initialize the RAMDAC info struct to hold all of our
291c0a4c9e6Snathanw 	 * data, and fill it in.
292c0a4c9e6Snathanw 	 */
293c0a4c9e6Snathanw 	data->changed = DATA_ALL_CHANGED;
294c0a4c9e6Snathanw 
295c0a4c9e6Snathanw 	/* initial cursor colormap: 0 is black, 1 is white */
296c0a4c9e6Snathanw 	data->curcmap_r[0] = data->curcmap_g[0] = data->curcmap_b[0] = 0;
297c0a4c9e6Snathanw 	data->curcmap_r[1] = data->curcmap_g[1] = data->curcmap_b[1] = 0xff;
298c0a4c9e6Snathanw 
299c0a4c9e6Snathanw 	/* Initial colormap: 0 is black, everything else is white */
300c0a4c9e6Snathanw 	data->cmap_r[0] = data->cmap_g[0] = data->cmap_b[0] = 0;
301c0a4c9e6Snathanw 	for (i = 1; i < 256; i++)
302c0a4c9e6Snathanw 		data->cmap_r[i] = data->cmap_g[i] = data->cmap_b[i] = 255;
303c0a4c9e6Snathanw 
304c0a4c9e6Snathanw 
305c0a4c9e6Snathanw 	/* Initialize the window type table:
306c0a4c9e6Snathanw 	 *
307c0a4c9e6Snathanw 	 * Entry 0: 24-plane truecolor, overlays enabled, bypassed.
308c0a4c9e6Snathanw 	 *
309c0a4c9e6Snathanw 	 *  Lookup table bypass:      yes (    1 << 23 & 0x800000)  800000
310c0a4c9e6Snathanw 	 *  Colormap address:       0x000 (0x000 << 17 & 0x7e0000)       0
311c0a4c9e6Snathanw 	 *  Overlay mask:             0xf (  0xf << 13 & 0x01e000)   1e000
312c0a4c9e6Snathanw 	 *  Overlay location:    P<27:24> (    0 << 12 & 0x001000)       0
313c0a4c9e6Snathanw 	 *  Display mode:       Truecolor (    0 <<  9 & 0x000e00)     000
314c0a4c9e6Snathanw 	 *  Number of planes:           8 (    8 <<  5 & 0x0001e0)     100
315c0a4c9e6Snathanw 	 *  Plane shift:                0 (    0 <<  0 & 0x00001f)       0
316c0a4c9e6Snathanw 	 *                                                        --------
317c0a4c9e6Snathanw 	 *                                                        0x81e100
318c0a4c9e6Snathanw 	 */
319c0a4c9e6Snathanw 	data->window_type[0] = 0x81e100;
320c0a4c9e6Snathanw 
321c0a4c9e6Snathanw 	/* Entry 1: 8-plane pseudocolor in the bottom 8 bits,
322c0a4c9e6Snathanw 	 *          overlays enabled, colormap starting at 0.
323c0a4c9e6Snathanw 	 *
324c0a4c9e6Snathanw 	 *  Lookup table bypass:       no (    0 << 23 & 0x800000)       0
325c0a4c9e6Snathanw 	 *  Colormap address:       0x000 (0x000 << 17 & 0x7e0000)       0
326c0a4c9e6Snathanw 	 *  Overlay mask:             0xf (  0xf << 13 & 0x01e000) 0x1e000
327c0a4c9e6Snathanw 	 *  Overlay location:    P<27:24> (    0 << 12 & 0x001000)       0
328c0a4c9e6Snathanw 	 *  Display mode:     Pseudocolor (    1 <<  9 & 0x000e00)   0x200
329c0a4c9e6Snathanw 	 *  Number of planes:           8 (    8 <<  5 & 0x0001e0)   0x100
330c0a4c9e6Snathanw 	 *  Plane shift:               16 ( 0x10 <<  0 & 0x00001f)      10
331c0a4c9e6Snathanw 	 *                                                        --------
332c0a4c9e6Snathanw 	 *                                                        0x01e310
333c0a4c9e6Snathanw 	 */
334c0a4c9e6Snathanw 	data->window_type[1] = 0x01e310;
335c0a4c9e6Snathanw 
336c0a4c9e6Snathanw 	/* The colormap interface to the world only supports one colormap,
337c0a4c9e6Snathanw 	 * so having an entry for the 'alternate' colormap in the bt463
338c0a4c9e6Snathanw 	 * probably isn't useful.
339c0a4c9e6Snathanw 	 */
340c0a4c9e6Snathanw 
341c0a4c9e6Snathanw 	/* Fill the remaining table entries with clones of entry 0 until we
342c0a4c9e6Snathanw 	 * figure out a better use for them.
343c0a4c9e6Snathanw 	 */
344c0a4c9e6Snathanw 
345c0a4c9e6Snathanw 	for (i = 2; i < BT463_NWTYPE_ENTRIES; i++) {
346c0a4c9e6Snathanw 		data->window_type[i] = 0x81e100;
347c0a4c9e6Snathanw 	}
348c0a4c9e6Snathanw 
349c0a4c9e6Snathanw 	data->ramdac_sched_update(data->cookie, bt463_update);
350c0a4c9e6Snathanw 
351c0a4c9e6Snathanw }
352c0a4c9e6Snathanw 
353c0a4c9e6Snathanw int
bt463_set_cmap(struct ramdac_cookie * rc,struct wsdisplay_cmap * cmapp)354454af1c0Sdsl bt463_set_cmap(struct ramdac_cookie *rc, struct wsdisplay_cmap *cmapp)
355c0a4c9e6Snathanw {
356c0a4c9e6Snathanw 	struct bt463data *data = (struct bt463data *)rc;
357ceb38aa7Sjdolecek 	u_int count, index;
358e07f0b93Schs 	uint8_t r[BT463_NCMAP_ENTRIES];
359e07f0b93Schs 	uint8_t g[BT463_NCMAP_ENTRIES];
360e07f0b93Schs 	uint8_t b[BT463_NCMAP_ENTRIES];
361e07f0b93Schs 	int s, error;
362c0a4c9e6Snathanw 
363ceb38aa7Sjdolecek 	if (cmapp->index >= BT463_NCMAP_ENTRIES ||
3648dd04cdcSitojun 	    cmapp->count > BT463_NCMAP_ENTRIES - cmapp->index)
365c0a4c9e6Snathanw 		return (EINVAL);
366c0a4c9e6Snathanw 
367c0a4c9e6Snathanw 	index = cmapp->index;
368c0a4c9e6Snathanw 	count = cmapp->count;
369e07f0b93Schs 	error = copyin(cmapp->red, &r[index], count);
370e07f0b93Schs 	if (error)
371e07f0b93Schs 		return error;
372e07f0b93Schs 	error = copyin(cmapp->green, &g[index], count);
373e07f0b93Schs 	if (error)
374e07f0b93Schs 		return error;
375e07f0b93Schs 	error = copyin(cmapp->blue, &b[index], count);
376e07f0b93Schs 	if (error)
377e07f0b93Schs 		return error;
378e07f0b93Schs 	s = spltty();
379e07f0b93Schs 	memcpy(&data->cmap_r[index], &r[index], count);
380e07f0b93Schs 	memcpy(&data->cmap_g[index], &g[index], count);
381e07f0b93Schs 	memcpy(&data->cmap_b[index], &b[index], count);
382c0a4c9e6Snathanw  	data->changed |= DATA_CMAP_CHANGED;
383c0a4c9e6Snathanw 	data->ramdac_sched_update(data->cookie, bt463_update);
384c0a4c9e6Snathanw 	splx(s);
385c0a4c9e6Snathanw 	return (0);
386c0a4c9e6Snathanw }
387c0a4c9e6Snathanw 
388c0a4c9e6Snathanw int
bt463_get_cmap(struct ramdac_cookie * rc,struct wsdisplay_cmap * cmapp)389454af1c0Sdsl bt463_get_cmap(struct ramdac_cookie *rc, struct wsdisplay_cmap *cmapp)
390c0a4c9e6Snathanw {
391c0a4c9e6Snathanw 	struct bt463data *data = (struct bt463data *)rc;
3928dd04cdcSitojun 	u_int count, index;
3938dd04cdcSitojun 	int error;
394c0a4c9e6Snathanw 
3958dd04cdcSitojun 	if (cmapp->index >= BT463_NCMAP_ENTRIES ||
3968dd04cdcSitojun 	    cmapp->count > BT463_NCMAP_ENTRIES - cmapp->index)
397c0a4c9e6Snathanw 		return (EINVAL);
398c0a4c9e6Snathanw 
399c0a4c9e6Snathanw 	count = cmapp->count;
400c0a4c9e6Snathanw 	index = cmapp->index;
401c0a4c9e6Snathanw 
402c0a4c9e6Snathanw 	error = copyout(&data->cmap_r[index], cmapp->red, count);
403c0a4c9e6Snathanw 	if (error)
404c0a4c9e6Snathanw 		return (error);
405c0a4c9e6Snathanw 	error = copyout(&data->cmap_g[index], cmapp->green, count);
406c0a4c9e6Snathanw 	if (error)
407c0a4c9e6Snathanw 		return (error);
408c0a4c9e6Snathanw 	error = copyout(&data->cmap_b[index], cmapp->blue, count);
409c0a4c9e6Snathanw 	return (error);
410c0a4c9e6Snathanw }
411c0a4c9e6Snathanw 
412c0a4c9e6Snathanw int
bt463_check_curcmap(struct ramdac_cookie * rc,struct wsdisplay_cursor * cursorp)413454af1c0Sdsl bt463_check_curcmap(struct ramdac_cookie *rc, struct wsdisplay_cursor *cursorp)
414c0a4c9e6Snathanw {
415e07f0b93Schs 	struct bt463data *data = (struct bt463data *)rc;
416e07f0b93Schs 	int count, index, error;
417c0a4c9e6Snathanw 
418e07f0b93Schs 	if (cursorp->cmap.index > 2 ||
419*8e9f762cSriastradh 	    cursorp->cmap.count > 2 - cursorp->cmap.index)
420c0a4c9e6Snathanw 		return (EINVAL);
421c0a4c9e6Snathanw 	count = cursorp->cmap.count;
422e07f0b93Schs 	index = cursorp->cmap.index;
423e07f0b93Schs 	error = copyin(cursorp->cmap.red, &data->tmpcurcmap_r[index], count);
424e07f0b93Schs 	if (error)
425e07f0b93Schs 		return error;
426e07f0b93Schs 	error = copyin(cursorp->cmap.green, &data->tmpcurcmap_g[index], count);
427e07f0b93Schs 	if (error)
428e07f0b93Schs 		return error;
429e07f0b93Schs 	error = copyin(cursorp->cmap.blue, &data->tmpcurcmap_b[index], count);
430e07f0b93Schs 	if (error)
431e07f0b93Schs 		return error;
432c0a4c9e6Snathanw 	return (0);
433c0a4c9e6Snathanw }
434c0a4c9e6Snathanw 
435c0a4c9e6Snathanw void
bt463_set_curcmap(struct ramdac_cookie * rc,struct wsdisplay_cursor * cursorp)436454af1c0Sdsl bt463_set_curcmap(struct ramdac_cookie *rc, struct wsdisplay_cursor *cursorp)
437c0a4c9e6Snathanw {
438c0a4c9e6Snathanw 	struct bt463data *data = (struct bt463data *)rc;
439c0a4c9e6Snathanw 	int count, index;
440c0a4c9e6Snathanw 
441c0a4c9e6Snathanw 	count = cursorp->cmap.count;
442c0a4c9e6Snathanw 	index = cursorp->cmap.index;
443e07f0b93Schs 	memcpy(&data->curcmap_r[index], &data->tmpcurcmap_r[index], count);
444e07f0b93Schs 	memcpy(&data->curcmap_g[index], &data->tmpcurcmap_g[index], count);
445e07f0b93Schs 	memcpy(&data->curcmap_b[index], &data->tmpcurcmap_b[index], count);
446c0a4c9e6Snathanw 	data->changed |= DATA_CURCMAP_CHANGED;
447c0a4c9e6Snathanw 	data->ramdac_sched_update(data->cookie, bt463_update);
448c0a4c9e6Snathanw }
449c0a4c9e6Snathanw 
450c0a4c9e6Snathanw int
bt463_get_curcmap(struct ramdac_cookie * rc,struct wsdisplay_cursor * cursorp)451454af1c0Sdsl bt463_get_curcmap(struct ramdac_cookie *rc, struct wsdisplay_cursor *cursorp)
452c0a4c9e6Snathanw {
453c0a4c9e6Snathanw 	struct bt463data *data = (struct bt463data *)rc;
454c0a4c9e6Snathanw 	int error;
455c0a4c9e6Snathanw 
456c0a4c9e6Snathanw 	cursorp->cmap.index = 0;	/* DOCMAP */
457c0a4c9e6Snathanw 	cursorp->cmap.count = 2;
458c0a4c9e6Snathanw 	if (cursorp->cmap.red != NULL) {
459c0a4c9e6Snathanw 		error = copyout(data->curcmap_r, cursorp->cmap.red, 2);
460c0a4c9e6Snathanw 		if (error)
461c0a4c9e6Snathanw 			return (error);
462c0a4c9e6Snathanw 	}
463c0a4c9e6Snathanw 	if (cursorp->cmap.green != NULL) {
464c0a4c9e6Snathanw 		error = copyout(data->curcmap_g, cursorp->cmap.green, 2);
465c0a4c9e6Snathanw 		if (error)
466c0a4c9e6Snathanw 			return (error);
467c0a4c9e6Snathanw 	}
468c0a4c9e6Snathanw 	if (cursorp->cmap.blue != NULL) {
469c0a4c9e6Snathanw 		error = copyout(data->curcmap_b, cursorp->cmap.blue, 2);
470c0a4c9e6Snathanw 		if (error)
471c0a4c9e6Snathanw 			return (error);
472c0a4c9e6Snathanw 	}
473c0a4c9e6Snathanw 	return (0);
474c0a4c9e6Snathanw }
475c0a4c9e6Snathanw 
476c0a4c9e6Snathanw 
477c0a4c9e6Snathanw /*****************************************************************************/
478c0a4c9e6Snathanw 
479c0a4c9e6Snathanw /*
480c0a4c9e6Snathanw  * Internal functions.
481c0a4c9e6Snathanw  */
482c0a4c9e6Snathanw 
483c0a4c9e6Snathanw #ifdef BT463_DEBUG
bt463_store(void * v)484c0a4c9e6Snathanw int bt463_store(void *v)
485c0a4c9e6Snathanw {
486c0a4c9e6Snathanw 	struct bt463data *data = (struct bt463data *)v;
487c0a4c9e6Snathanw 
488c0a4c9e6Snathanw 	data->changed = DATA_ALL_CHANGED;
489c0a4c9e6Snathanw 	data->ramdac_sched_update(data->cookie, bt463_update);
490c0a4c9e6Snathanw 	printf("Scheduled bt463 store\n");
491c0a4c9e6Snathanw 
492c0a4c9e6Snathanw 	return 0;
493c0a4c9e6Snathanw }
494c0a4c9e6Snathanw 
495c0a4c9e6Snathanw 
bt463_readback(void * v)496c0a4c9e6Snathanw int bt463_readback(void *v)
497c0a4c9e6Snathanw {
498c0a4c9e6Snathanw 	struct bt463data *data = (struct bt463data *)v;
499c0a4c9e6Snathanw 
500c0a4c9e6Snathanw 	data->ramdac_sched_update(data->cookie, bt463_copyback);
501c0a4c9e6Snathanw 	printf("Scheduled bt463 copyback\n");
502c0a4c9e6Snathanw 	return 0;
503c0a4c9e6Snathanw }
504c0a4c9e6Snathanw 
505c0a4c9e6Snathanw int
bt463_debug(void * v)506454af1c0Sdsl bt463_debug(void *v)
507c0a4c9e6Snathanw {
508c0a4c9e6Snathanw 	struct bt463data *data = (struct bt463data *)v;
509c0a4c9e6Snathanw 	int i;
510c0a4c9e6Snathanw 	u_int8_t val;
511c0a4c9e6Snathanw 
512c0a4c9e6Snathanw 	printf("BT463 main regs:\n");
513c0a4c9e6Snathanw 	for (i = 0x200; i < 0x20F; i ++) {
514c0a4c9e6Snathanw 	  val = BTRREG(data, i);
515c0a4c9e6Snathanw 	  printf("  $%04x %02x\n", i, val);
516c0a4c9e6Snathanw 	}
517c0a4c9e6Snathanw 
518c0a4c9e6Snathanw 	printf("BT463 revision register:\n");
519c0a4c9e6Snathanw 	  val = BTRREG(data, 0x220);
520c0a4c9e6Snathanw 	  printf("  $%04x %02x\n", 0x220, val);
521c0a4c9e6Snathanw 
522c0a4c9e6Snathanw 	printf("BT463 window type table (from softc):\n");
523c0a4c9e6Snathanw 
524c0a4c9e6Snathanw 	for (i = 0; i < BT463_NWTYPE_ENTRIES; i++) {
525c0a4c9e6Snathanw 	  printf("%02x %06x\n", i, data->window_type[i]);
526c0a4c9e6Snathanw 	}
527c0a4c9e6Snathanw 
528c0a4c9e6Snathanw 	return 0;
529c0a4c9e6Snathanw }
530c0a4c9e6Snathanw 
531c0a4c9e6Snathanw void
bt463_copyback(void * p)532454af1c0Sdsl bt463_copyback(void *p)
533c0a4c9e6Snathanw {
534c0a4c9e6Snathanw 	struct bt463data *data = (struct bt463data *)p;
535c0a4c9e6Snathanw 	int i;
536c0a4c9e6Snathanw 
537c0a4c9e6Snathanw 		for (i = 0; i < BT463_NWTYPE_ENTRIES; i++) {
538c0a4c9e6Snathanw 			bt463_wraddr(data, BT463_IREG_WINDOW_TYPE_TABLE + i);
539c0a4c9e6Snathanw 			data->window_type[i] = (BTRNREG(data) & 0xff);        /* B0-7   */
540c0a4c9e6Snathanw 			data->window_type[i] |= (BTRNREG(data) & 0xff) << 8;  /* B8-15  */
541c0a4c9e6Snathanw 			data->window_type[i] |= (BTRNREG(data) & 0xff) << 16; /* B16-23 */
542c0a4c9e6Snathanw 		}
543c0a4c9e6Snathanw }
544c0a4c9e6Snathanw #endif
545c0a4c9e6Snathanw 
546c0a4c9e6Snathanw void
bt463_update(void * p)547454af1c0Sdsl bt463_update(void *p)
548c0a4c9e6Snathanw {
549c0a4c9e6Snathanw 	struct bt463data *data = (struct bt463data *)p;
550c0a4c9e6Snathanw 	int i, v;
551c0a4c9e6Snathanw 
552a5598651Snathanw 	if (console_data != NULL) {
553a5598651Snathanw 		/* The cookie passed in from sched_update is incorrect. Use the
554a5598651Snathanw 		 * right one.
555a5598651Snathanw 		 */
556a5598651Snathanw 		data = console_data;
557a5598651Snathanw 	}
558a5598651Snathanw 
559c0a4c9e6Snathanw 	v = data->changed;
560c0a4c9e6Snathanw 
561c0a4c9e6Snathanw 	/* The Bt463 won't accept window type data except during a blanking
562c0a4c9e6Snathanw 	 * interval, so we do this early in the interrupt.
563c0a4c9e6Snathanw 	 * Blanking the screen might also be a good idea, but it can cause
564c0a4c9e6Snathanw 	 * unpleasant flashing and is hard to do from this side of the
565c0a4c9e6Snathanw 	 * ramdac interface.
566c0a4c9e6Snathanw 	 */
567c0a4c9e6Snathanw 	if (v & DATA_WTYPE_CHANGED) {
568c0a4c9e6Snathanw 		/* spit out the window type data */
569c0a4c9e6Snathanw 		for (i = 0; i < BT463_NWTYPE_ENTRIES; i++) {
570c0a4c9e6Snathanw 			bt463_wraddr(data, BT463_IREG_WINDOW_TYPE_TABLE + i);
571c0a4c9e6Snathanw 			BTWNREG(data, (data->window_type[i]) & 0xff);       /* B0-7   */
572c0a4c9e6Snathanw 			BTWNREG(data, (data->window_type[i] >> 8) & 0xff);  /* B8-15   */
573c0a4c9e6Snathanw 			BTWNREG(data, (data->window_type[i] >> 16) & 0xff); /* B16-23  */
574c0a4c9e6Snathanw 		}
575c0a4c9e6Snathanw 	}
576c0a4c9e6Snathanw 
577c0a4c9e6Snathanw 	if (v & DATA_CURCMAP_CHANGED) {
578c0a4c9e6Snathanw 		bt463_wraddr(data, BT463_IREG_CURSOR_COLOR_0);
579c0a4c9e6Snathanw 		/* spit out the cursor data */
580c0a4c9e6Snathanw 		for (i = 0; i < 2; i++) {
581c0a4c9e6Snathanw 			BTWNREG(data, data->curcmap_r[i]);
582c0a4c9e6Snathanw 			BTWNREG(data, data->curcmap_g[i]);
583c0a4c9e6Snathanw 			BTWNREG(data, data->curcmap_b[i]);
584c0a4c9e6Snathanw 		}
585c0a4c9e6Snathanw 	}
586c0a4c9e6Snathanw 
587c0a4c9e6Snathanw 	if (v & DATA_CMAP_CHANGED) {
588c0a4c9e6Snathanw 		bt463_wraddr(data, BT463_IREG_CPALETTE_RAM);
589c0a4c9e6Snathanw 		/* spit out the colormap data */
590c0a4c9e6Snathanw 		for (i = 0; i < BT463_NCMAP_ENTRIES; i++) {
591c0a4c9e6Snathanw 			data->ramdac_wr(data->cookie, BT463_REG_CMAP_DATA,
592c0a4c9e6Snathanw 				data->cmap_r[i]);
593c0a4c9e6Snathanw 			data->ramdac_wr(data->cookie, BT463_REG_CMAP_DATA,
594c0a4c9e6Snathanw 				data->cmap_g[i]);
595c0a4c9e6Snathanw 			data->ramdac_wr(data->cookie, BT463_REG_CMAP_DATA,
596c0a4c9e6Snathanw 				data->cmap_b[i]);
597c0a4c9e6Snathanw 		}
598c0a4c9e6Snathanw 	}
599c0a4c9e6Snathanw 
600c0a4c9e6Snathanw 	data->changed = 0;
601c0a4c9e6Snathanw }
602c0a4c9e6Snathanw 
6031d7f24eaSmatt int
bt463_set_cursor(struct ramdac_cookie * rc,struct wsdisplay_cursor * cur)6041d7f24eaSmatt bt463_set_cursor(
6051d7f24eaSmatt 	struct ramdac_cookie *rc,
6061d7f24eaSmatt 	struct wsdisplay_cursor *cur)
607c0a4c9e6Snathanw {
608c0a4c9e6Snathanw 	struct bt463data *data = (struct bt463data *)rc;
609c0a4c9e6Snathanw 	return tga_builtin_set_cursor(data->cookie, cur);
610c0a4c9e6Snathanw }
611c0a4c9e6Snathanw 
6121d7f24eaSmatt int
bt463_get_cursor(struct ramdac_cookie * rc,struct wsdisplay_cursor * cur)6131d7f24eaSmatt bt463_get_cursor(
6141d7f24eaSmatt 	struct ramdac_cookie *rc,
6151d7f24eaSmatt 	struct wsdisplay_cursor *cur)
616c0a4c9e6Snathanw {
617c0a4c9e6Snathanw 	struct bt463data *data = (struct bt463data *)rc;
618c0a4c9e6Snathanw 	return tga_builtin_get_cursor(data->cookie, cur);
619c0a4c9e6Snathanw }
620c0a4c9e6Snathanw 
6211d7f24eaSmatt int
bt463_set_curpos(struct ramdac_cookie * rc,struct wsdisplay_curpos * cur)6221d7f24eaSmatt bt463_set_curpos(
6231d7f24eaSmatt 	struct ramdac_cookie *rc,
6241d7f24eaSmatt 	struct wsdisplay_curpos *cur)
625c0a4c9e6Snathanw {
626c0a4c9e6Snathanw 	struct bt463data *data = (struct bt463data *)rc;
627c0a4c9e6Snathanw 	return tga_builtin_set_curpos(data->cookie, cur);
628c0a4c9e6Snathanw }
629c0a4c9e6Snathanw 
6301d7f24eaSmatt int
bt463_get_curpos(struct ramdac_cookie * rc,struct wsdisplay_curpos * cur)6311d7f24eaSmatt bt463_get_curpos(
6321d7f24eaSmatt 	struct ramdac_cookie *rc,
6331d7f24eaSmatt 	struct wsdisplay_curpos *cur)
634c0a4c9e6Snathanw {
635c0a4c9e6Snathanw 	struct bt463data *data = (struct bt463data *)rc;
636c0a4c9e6Snathanw 	return tga_builtin_get_curpos(data->cookie, cur);
637c0a4c9e6Snathanw }
638c0a4c9e6Snathanw 
6391d7f24eaSmatt int
bt463_get_curmax(struct ramdac_cookie * rc,struct wsdisplay_curpos * cur)6401d7f24eaSmatt bt463_get_curmax(
6411d7f24eaSmatt 	struct ramdac_cookie *rc,
6421d7f24eaSmatt 	struct wsdisplay_curpos *cur)
643c0a4c9e6Snathanw {
644c0a4c9e6Snathanw 	struct bt463data *data = (struct bt463data *)rc;
645c0a4c9e6Snathanw 	return tga_builtin_get_curmax(data->cookie, cur);
646c0a4c9e6Snathanw }
647