xref: /netbsd-src/sys/arch/prep/pci/gten.c (revision c7fb772b85b2b5d4cfb282f868f454b4701534fd)
1*c7fb772bSthorpej /*	$NetBSD: gten.c,v 1.24 2021/08/07 16:19:03 thorpej Exp $	*/
2305bef72Smatt 
3305bef72Smatt /*-
4305bef72Smatt  * Copyright (c) 2000 The NetBSD Foundation, Inc.
5305bef72Smatt  * All rights reserved.
6305bef72Smatt  *
7305bef72Smatt  * This code is derived from software contributed to The NetBSD Foundation
8305bef72Smatt  * by Matt Thomas <matt@3am-software.com>
9305bef72Smatt  *
10305bef72Smatt  * Redistribution and use in source and binary forms, with or without
11305bef72Smatt  * modification, are permitted provided that the following conditions
12305bef72Smatt  * are met:
13305bef72Smatt  * 1. Redistributions of source code must retain the above copyright
14305bef72Smatt  *    notice, this list of conditions and the following disclaimer.
15305bef72Smatt  * 2. Redistributions in binary form must reproduce the above copyright
16305bef72Smatt  *    notice, this list of conditions and the following disclaimer in the
17305bef72Smatt  *    documentation and/or other materials provided with the distribution.
18305bef72Smatt  *
19305bef72Smatt  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20305bef72Smatt  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21305bef72Smatt  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22305bef72Smatt  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23305bef72Smatt  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24305bef72Smatt  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25305bef72Smatt  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26305bef72Smatt  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27305bef72Smatt  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28305bef72Smatt  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29305bef72Smatt  * POSSIBILITY OF SUCH DAMAGE.
30305bef72Smatt  */
310b76f4efSmatt 
32ed517291Slukem #include <sys/cdefs.h>
33*c7fb772bSthorpej __KERNEL_RCSID(0, "$NetBSD: gten.c,v 1.24 2021/08/07 16:19:03 thorpej Exp $");
34ed517291Slukem 
350b76f4efSmatt #include <sys/param.h>
360b76f4efSmatt #include <sys/buf.h>
370b76f4efSmatt #include <sys/conf.h>
380b76f4efSmatt #include <sys/device.h>
390b76f4efSmatt #include <sys/ioctl.h>
400b76f4efSmatt #include <sys/kernel.h>
41d206c345Sthorpej #include <sys/kmem.h>
420b76f4efSmatt #include <sys/systm.h>
430b76f4efSmatt 
440b76f4efSmatt #include <uvm/uvm_extern.h>
450b76f4efSmatt 
460b76f4efSmatt #include <dev/pci/pcidevs.h>
470b76f4efSmatt #include <dev/pci/pcireg.h>
480b76f4efSmatt #include <dev/pci/pcivar.h>
490b76f4efSmatt 
500b76f4efSmatt #include <dev/wscons/wsconsio.h>
510b76f4efSmatt #include <dev/wscons/wsdisplayvar.h>
520b76f4efSmatt #include <dev/rasops/rasops.h>
530b76f4efSmatt 
545a5fb3acSdyoung #include <sys/bus.h>
550b76f4efSmatt #include <machine/gtenvar.h>
560b76f4efSmatt 
5705b09539Smatt static	int	gten_match(device_t, cfdata_t, void *);
5805b09539Smatt static	void	gten_attach(device_t, device_t, void *);
59305bef72Smatt static	int	gten_print(void *, const char *);
600b76f4efSmatt 
6105b09539Smatt CFATTACH_DECL_NEW(gten, sizeof(struct gten_softc),
6289bf5a8fSthorpej     gten_match, gten_attach, NULL, NULL);
630b76f4efSmatt 
640b76f4efSmatt static struct rasops_info gten_console_ri;
650b76f4efSmatt static pcitag_t gten_console_pcitag;
660b76f4efSmatt 
670b76f4efSmatt static struct wsscreen_descr gten_stdscreen = {
680b76f4efSmatt 	"std",
690b76f4efSmatt 	0, 0,
700b76f4efSmatt 	0,
710b76f4efSmatt 	0, 0,
720b76f4efSmatt 	WSSCREEN_REVERSE
730b76f4efSmatt };
740b76f4efSmatt 
750b76f4efSmatt static const struct wsscreen_descr *_gten_scrlist[] = {
760b76f4efSmatt 	&gten_stdscreen,
770b76f4efSmatt 	/* XXX other formats, graphics screen? */
780b76f4efSmatt };
790b76f4efSmatt 
800b76f4efSmatt static struct wsscreen_list gten_screenlist = {
810b76f4efSmatt 	sizeof(_gten_scrlist) / sizeof(struct wsscreen_descr *), _gten_scrlist
820b76f4efSmatt };
830b76f4efSmatt 
8453524e44Schristos static int gten_ioctl(void *, void *, u_long, void *, int, struct proc *);
857a51d4ddSjmmv static paddr_t gten_mmap(void *, void *, off_t, int);
860b76f4efSmatt static int gten_alloc_screen(void *, const struct wsscreen_descr *,
870b76f4efSmatt 			     void **, int *, int *, long *);
880b76f4efSmatt static void gten_free_screen(void *, void *);
890b76f4efSmatt static int gten_show_screen(void *, void *, int,
900b76f4efSmatt 			    void (*) (void *, int, int), void *);
910b76f4efSmatt 
92305bef72Smatt static struct wsdisplay_accessops gten_accessops = {
930b76f4efSmatt 	gten_ioctl,
940b76f4efSmatt 	gten_mmap,
950b76f4efSmatt 	gten_alloc_screen,
960b76f4efSmatt 	gten_free_screen,
970b76f4efSmatt 	gten_show_screen,
980b76f4efSmatt 	0 /* load_font */
990b76f4efSmatt };
1000b76f4efSmatt 
1010b76f4efSmatt static void gten_common_init(struct rasops_info *);
1020b76f4efSmatt static int gten_getcmap(struct gten_softc *, struct wsdisplay_cmap *);
1030b76f4efSmatt static int gten_putcmap(struct gten_softc *, struct wsdisplay_cmap *);
1040b76f4efSmatt 
105305bef72Smatt #define	GTEN_VRAM_OFFSET	0xf00000
106305bef72Smatt 
107305bef72Smatt static int
gten_match(device_t parent,cfdata_t match,void * aux)10805b09539Smatt gten_match(device_t parent, cfdata_t match, void *aux)
1090b76f4efSmatt {
1100b76f4efSmatt 	struct pci_attach_args *pa = aux;
1110b76f4efSmatt 
1120b76f4efSmatt 	if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_WD &&
1130b76f4efSmatt 	    PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_WD_90C)
1140b76f4efSmatt 		return 2;
1150b76f4efSmatt 
1160b76f4efSmatt 	return 0;
1170b76f4efSmatt }
1180b76f4efSmatt 
119305bef72Smatt static void
gten_attach(device_t parent,device_t self,void * aux)12005b09539Smatt gten_attach(device_t parent, device_t self, void *aux)
1210b76f4efSmatt {
12205b09539Smatt 	struct gten_softc *gt = device_private(self);
1230b76f4efSmatt 	struct pci_attach_args *pa = aux;
1240b76f4efSmatt 	struct wsemuldisplaydev_attach_args a;
1250b76f4efSmatt 	int console = (pa->pa_tag == gten_console_pcitag);
1260b76f4efSmatt 	int error;
1270b76f4efSmatt 	char devinfo[256], pbuf[10];
1280b76f4efSmatt 
1290b76f4efSmatt 	error = pci_mapreg_info(pa->pa_pc, pa->pa_tag, 0x14,
1300b76f4efSmatt 		PCI_MAPREG_TYPE_MEM|PCI_MAPREG_MEM_TYPE_32BIT,
1310b76f4efSmatt 		&gt->gt_memaddr, &gt->gt_memsize, NULL);
1320b76f4efSmatt 	if (error) {
133d974db0aSgarbled 		aprint_error(": can't determine memory size: error=%d\n",
1340b76f4efSmatt 			error);
1350b76f4efSmatt 		return;
1360b76f4efSmatt 	}
13705b09539Smatt 	gt->gt_dev = self;
1380b76f4efSmatt 	if (console) {
1390b76f4efSmatt 		gt->gt_ri = &gten_console_ri;
1400b76f4efSmatt 		gt->gt_nscreens = 1;
1410b76f4efSmatt 	} else {
142d206c345Sthorpej 		gt->gt_ri = kmem_zalloc(sizeof(*gt->gt_ri),
143d206c345Sthorpej 			KM_SLEEP);
1440b76f4efSmatt #if 0
1450b76f4efSmatt 		error = pci_mapreg_map(pa, 0x14,
1460b76f4efSmatt 			PCI_MAPREG_TYPE_MEM|PCI_MAPREG_MEM_TYPE_32BIT,
1470b76f4efSmatt 			BUS_SPACE_MAP_LINEAR, NULL,
1480b76f4efSmatt 			(bus_space_handle_t *) &gt->gt_ri->ri_bits,
1490b76f4efSmatt 			NULL, NULL);
1500b76f4efSmatt #else
151305bef72Smatt 		error = bus_space_map(pa->pa_memt, gt->gt_memaddr + GTEN_VRAM_OFFSET,
152305bef72Smatt 			960*1024, BUS_SPACE_MAP_LINEAR,
1530b76f4efSmatt 			(bus_space_handle_t *) &gt->gt_ri->ri_bits);
1540b76f4efSmatt #endif
1550b76f4efSmatt 		if (error) {
156d974db0aSgarbled 			aprint_error(": can't map frame buffer: error=%d\n",
157d974db0aSgarbled 			    error);
1580b76f4efSmatt 			return;
1590b76f4efSmatt 		}
1600b76f4efSmatt 
1610b76f4efSmatt 		gten_common_init(gt->gt_ri);
1620b76f4efSmatt 	}
1630b76f4efSmatt 
1640b76f4efSmatt 	gt->gt_paddr = vtophys((vaddr_t)gt->gt_ri->ri_bits);
1650b76f4efSmatt 	if (gt->gt_paddr == 0) {
166d974db0aSgarbled 		aprint_error(": cannot map framebuffer\n");
1670b76f4efSmatt 		return;
1680b76f4efSmatt 	}
169305bef72Smatt 	gt->gt_psize = gt->gt_memsize - GTEN_VRAM_OFFSET;
1700b76f4efSmatt 
17161230437Sitojun 	pci_devinfo(pa->pa_id, pa->pa_class, 0, devinfo, sizeof(devinfo));
172d974db0aSgarbled 	aprint_normal(": %s\n", devinfo);
173305bef72Smatt 	format_bytes(pbuf, sizeof(pbuf), gt->gt_psize);
17405b09539Smatt 	aprint_normal_dev(self, "%s: %s, %dx%d, %dbpp\n", pbuf,
175305bef72Smatt 	       gt->gt_ri->ri_width, gt->gt_ri->ri_height,
176305bef72Smatt 	       gt->gt_ri->ri_depth);
177305bef72Smatt #if defined(DEBUG)
17805b09539Smatt 	aprint_debug_dev(self, "%s: text %dx%d, =+%d+%d\n",
179305bef72Smatt 	       gt->gt_ri->ri_cols, gt->gt_ri->ri_rows,
180305bef72Smatt 	       gt->gt_ri->ri_xorigin, gt->gt_ri->ri_yorigin);
181305bef72Smatt 
182305bef72Smatt 	{ int i;
183305bef72Smatt 	  struct rasops_info *ri = gt->gt_ri;
184305bef72Smatt 	for (i = 0; i < 64; i++) {
185305bef72Smatt 		int j = i * ri->ri_stride;
186305bef72Smatt 		int k = (ri->ri_height - i - 1) * gt->gt_ri->ri_stride;
187305bef72Smatt 		memset(ri->ri_bits + j, 0, 64 - i);
188305bef72Smatt 		memset(ri->ri_bits + j + 64 - i, 255, i);
189305bef72Smatt 
190305bef72Smatt 		memset(ri->ri_bits + j + ri->ri_width - 64 + i, 0, 64 - i);
191305bef72Smatt 		memset(ri->ri_bits + j + ri->ri_width - 64, 255, i);
192305bef72Smatt 
193305bef72Smatt 		memset(ri->ri_bits + k, 0, 64 - i);
194305bef72Smatt 		memset(ri->ri_bits + k + 64 - i, 255, i);
195305bef72Smatt 
196305bef72Smatt 		memset(ri->ri_bits + k + ri->ri_width - 64 + i, 0, 64 - i);
197305bef72Smatt 		memset(ri->ri_bits + k + ri->ri_width - 64, 255, i);
198305bef72Smatt 	}}
199305bef72Smatt #endif
2000b76f4efSmatt 
2010b76f4efSmatt 	gt->gt_cmap_red[0] = gt->gt_cmap_green[0] = gt->gt_cmap_blue[0] = 0;
2020b76f4efSmatt 	gt->gt_cmap_red[15] = gt->gt_cmap_red[255] = 0xff;
2030b76f4efSmatt 	gt->gt_cmap_green[15] = gt->gt_cmap_green[255] = 0xff;
2040b76f4efSmatt 	gt->gt_cmap_blue[15] = gt->gt_cmap_blue[255] = 0xff;
2050b76f4efSmatt 
2060b76f4efSmatt 	a.console = console;
2070b76f4efSmatt 	a.scrdata = &gten_screenlist;
2080b76f4efSmatt 	a.accessops = &gten_accessops;
2090b76f4efSmatt 	a.accesscookie = gt;
2100b76f4efSmatt 
211*c7fb772bSthorpej 	config_found(self, &a, wsemuldisplaydevprint, CFARGS_NONE);
2120b76f4efSmatt }
2130b76f4efSmatt 
2140b76f4efSmatt static void
gten_common_init(struct rasops_info * ri)2150b76f4efSmatt gten_common_init(struct rasops_info *ri)
2160b76f4efSmatt {
2170b76f4efSmatt 	int32_t addr, width, height, linebytes, depth;
2180b76f4efSmatt 	int i, screenbytes;
2190b76f4efSmatt 
2200b76f4efSmatt 	/* initialize rasops */
2210b76f4efSmatt 	ri->ri_width = 640;
2220b76f4efSmatt 	ri->ri_height = 480;
2230b76f4efSmatt 	ri->ri_depth = 8;
2240b76f4efSmatt 	ri->ri_stride = 640;
225305bef72Smatt 	ri->ri_flg = RI_FORCEMONO | RI_FULLCLEAR;
2260b76f4efSmatt 
227305bef72Smatt 	rasops_init(ri, 30, 80);
2280b76f4efSmatt 	/* black on white */
2290b76f4efSmatt 	ri->ri_devcmap[0] = 0xffffffff;			/* bg */
2300b76f4efSmatt 	ri->ri_devcmap[1] = 0;				/* fg */
2310b76f4efSmatt 
232305bef72Smatt 	memset(ri->ri_bits, 0xff, ri->ri_stride * ri->ri_height);
233305bef72Smatt 
2340b76f4efSmatt 	gten_stdscreen.nrows = ri->ri_rows;
2350b76f4efSmatt 	gten_stdscreen.ncols = ri->ri_cols;
2360b76f4efSmatt 	gten_stdscreen.textops = &ri->ri_ops;
2370b76f4efSmatt 	gten_stdscreen.capabilities = ri->ri_caps;
2380b76f4efSmatt }
2390b76f4efSmatt 
240305bef72Smatt static int
gten_ioctl(void * v,void * vs,u_long cmd,void * data,int flag,struct proc * p)24153524e44Schristos gten_ioctl(void *v, void *vs, u_long cmd, void *data, int flag,
242cfbb4ec2Sgarbled     struct proc *p)
2430b76f4efSmatt {
2440b76f4efSmatt 	struct gten_softc *gt = v;
2450b76f4efSmatt 	struct wsdisplay_fbinfo *wdf;
2460b76f4efSmatt 	struct grfinfo *gm;
2470b76f4efSmatt 
2480b76f4efSmatt 	switch (cmd) {
2490b76f4efSmatt 	case WSDISPLAYIO_GTYPE:
2500b76f4efSmatt 		*(u_int *)data = WSDISPLAY_TYPE_PCIMISC;	/* XXX ? */
2510b76f4efSmatt 		return 0;
2520b76f4efSmatt 
2530b76f4efSmatt 	case WSDISPLAYIO_GINFO:
2540b76f4efSmatt 		wdf = (void *)data;
2550b76f4efSmatt 		wdf->height = gt->gt_ri->ri_height;
2560b76f4efSmatt 		wdf->width = gt->gt_ri->ri_width;
2570b76f4efSmatt 		wdf->depth = gt->gt_ri->ri_depth;
2580b76f4efSmatt 		wdf->cmsize = 256;
2590b76f4efSmatt 		return 0;
2600b76f4efSmatt 
2610b76f4efSmatt 	case WSDISPLAYIO_GETCMAP:
2620b76f4efSmatt 		return gten_getcmap(gt, (struct wsdisplay_cmap *)data);
2630b76f4efSmatt 
2640b76f4efSmatt 	case WSDISPLAYIO_PUTCMAP:
2650b76f4efSmatt 		return gten_putcmap(gt, (struct wsdisplay_cmap *)data);
2660b76f4efSmatt 	}
26731144d99Satatat 	return EPASSTHROUGH;
2680b76f4efSmatt }
2690b76f4efSmatt 
270305bef72Smatt static paddr_t
gten_mmap(void * v,void * vs,off_t offset,int prot)271cfbb4ec2Sgarbled gten_mmap(void *v, void *vs, off_t offset, int prot)
2720b76f4efSmatt {
2730b76f4efSmatt 	struct gten_softc *gt = v;
2740b76f4efSmatt 
275305bef72Smatt 	if (offset >= 0 && offset < gt->gt_psize)
2760b76f4efSmatt 		return gt->gt_paddr + offset;
277305bef72Smatt 	if (offset >= 0x1000000 && offset < gt->gt_memsize)
278305bef72Smatt 		return gt->gt_memaddr + offset - 0x1000000;
2790b76f4efSmatt 
2800b76f4efSmatt 	return -1;
2810b76f4efSmatt }
2820b76f4efSmatt 
283305bef72Smatt static int
gten_alloc_screen(void * v,const struct wsscreen_descr * type,void ** cookiep,int * curxp,int * curyp,long * attrp)284cfbb4ec2Sgarbled gten_alloc_screen(void *v, const struct wsscreen_descr *type, void **cookiep,
285cfbb4ec2Sgarbled     int *curxp, int *curyp, long *attrp)
2860b76f4efSmatt {
2870b76f4efSmatt 	struct gten_softc *gt = v;
2880b76f4efSmatt 	struct rasops_info *ri = gt->gt_ri;
2890b76f4efSmatt 	long defattr;
2900b76f4efSmatt 
2910b76f4efSmatt 	if (gt->gt_nscreens > 0)
2920b76f4efSmatt 		return (ENOMEM);
2930b76f4efSmatt 
2940b76f4efSmatt 	*cookiep = ri;			/* one and only for now */
2950b76f4efSmatt 	*curxp = 0;
2960b76f4efSmatt 	*curyp = 0;
2973d826105Sjunyoung 	(*ri->ri_ops.allocattr)(ri, 0, 0, 0, &defattr);
2980b76f4efSmatt 	*attrp = defattr;
2990b76f4efSmatt 	gt->gt_nscreens++;
3000b76f4efSmatt 	return 0;
3010b76f4efSmatt }
3020b76f4efSmatt 
303305bef72Smatt static void
gten_free_screen(void * v,void * cookie)304cfbb4ec2Sgarbled gten_free_screen(void *v, void *cookie)
3050b76f4efSmatt {
3060b76f4efSmatt 	struct gten_softc *gt = v;
3070b76f4efSmatt 
3080b76f4efSmatt 	if (gt->gt_ri == &gten_console_ri)
3090b76f4efSmatt 		panic("gten_free_screen: console");
3100b76f4efSmatt 
3110b76f4efSmatt 	gt->gt_nscreens--;
3120b76f4efSmatt }
3130b76f4efSmatt 
314305bef72Smatt static int
gten_show_screen(void * v,void * cookie,int waitok,void (* cb)(void *,int,int),void * cbarg)315cfbb4ec2Sgarbled gten_show_screen(void *v, void *cookie, int waitok,
316cfbb4ec2Sgarbled     void (*cb)(void *, int, int), void *cbarg)
3170b76f4efSmatt {
3180b76f4efSmatt 	return (0);
3190b76f4efSmatt }
3200b76f4efSmatt 
3210b76f4efSmatt int
gten_cnattach(pci_chipset_tag_t pc,bus_space_tag_t memt)3225410bbdbSkleink gten_cnattach(pci_chipset_tag_t pc, bus_space_tag_t memt)
3230b76f4efSmatt {
3240b76f4efSmatt 	struct rasops_info *ri = &gten_console_ri;
3250b76f4efSmatt 	u_int32_t mapreg, id, mask, mapsize;
3260b76f4efSmatt 	long defattr;
3270b76f4efSmatt 	pcitag_t tag;
3280b76f4efSmatt 	int s, error;
3290b76f4efSmatt 	bus_size_t bussize;
3300b76f4efSmatt 	bus_addr_t busaddr;
3310b76f4efSmatt 
3325410bbdbSkleink 	tag = pci_make_tag(pc, 0, 14, 0);
3330b76f4efSmatt 
3345410bbdbSkleink 	id = pci_conf_read(pc, tag, PCI_ID_REG);
3350b76f4efSmatt 	if (PCI_VENDOR(id) != PCI_VENDOR_WD ||
3360b76f4efSmatt 	    PCI_PRODUCT(id) != PCI_PRODUCT_WD_90C)
3370b76f4efSmatt 		return ENXIO;
3380b76f4efSmatt 
3395410bbdbSkleink 	mapreg = pci_conf_read(pc, tag, 0x14);
3400b76f4efSmatt 	if (PCI_MAPREG_TYPE(mapreg) != PCI_MAPREG_TYPE_MEM ||
3410b76f4efSmatt 	    PCI_MAPREG_MEM_TYPE(mapreg) != PCI_MAPREG_MEM_TYPE_32BIT)
3420b76f4efSmatt 		return ENXIO;
3430b76f4efSmatt 
3440b76f4efSmatt         s = splhigh();
3455410bbdbSkleink         pci_conf_write(pc, tag, 0x14, 0xffffffff);
3465410bbdbSkleink         mask = pci_conf_read(pc, tag, 0x14);
3475410bbdbSkleink         pci_conf_write(pc, tag, 0x14, mapreg);
3480b76f4efSmatt 	splx(s);
3490b76f4efSmatt 	bussize = PCI_MAPREG_MEM_SIZE(mask);
3500b76f4efSmatt 	busaddr = PCI_MAPREG_MEM_ADDR(mapreg);
3510b76f4efSmatt 
352305bef72Smatt 	error = bus_space_map(memt, busaddr + GTEN_VRAM_OFFSET, 960*1024,
3530b76f4efSmatt 		BUS_SPACE_MAP_LINEAR, (bus_space_handle_t *) &ri->ri_bits);
3540b76f4efSmatt 	if (error)
3550b76f4efSmatt 		return error;
3560b76f4efSmatt 
3570b76f4efSmatt 	gten_common_init(ri);
3580b76f4efSmatt 
3593d826105Sjunyoung 	(*ri->ri_ops.allocattr)(ri, 0, 0, 0, &defattr);
3600b76f4efSmatt 	wsdisplay_cnattach(&gten_stdscreen, ri, 0, 0, defattr);
3610b76f4efSmatt 
3620b76f4efSmatt 	gten_console_pcitag = tag;
3630b76f4efSmatt 
3640b76f4efSmatt 	return 0;
3650b76f4efSmatt }
3660b76f4efSmatt 
367305bef72Smatt static int
gten_getcmap(struct gten_softc * gt,struct wsdisplay_cmap * cm)368cfbb4ec2Sgarbled gten_getcmap(struct gten_softc *gt, struct wsdisplay_cmap *cm)
3690b76f4efSmatt {
3700b76f4efSmatt 	u_int index = cm->index;
3710b76f4efSmatt 	u_int count = cm->count;
3720b76f4efSmatt 	int error;
3730b76f4efSmatt 
3740b76f4efSmatt 	if (index >= 256 || count > 256 || index + count > 256)
3750b76f4efSmatt 		return EINVAL;
3760b76f4efSmatt 
3770b76f4efSmatt 	error = copyout(&gt->gt_cmap_red[index],   cm->red,   count);
3780b76f4efSmatt 	if (error)
3790b76f4efSmatt 		return error;
3800b76f4efSmatt 	error = copyout(&gt->gt_cmap_green[index], cm->green, count);
3810b76f4efSmatt 	if (error)
3820b76f4efSmatt 		return error;
3830b76f4efSmatt 	error = copyout(&gt->gt_cmap_blue[index],  cm->blue,  count);
3840b76f4efSmatt 	if (error)
3850b76f4efSmatt 		return error;
3860b76f4efSmatt 
3870b76f4efSmatt 	return 0;
3880b76f4efSmatt }
3890b76f4efSmatt 
390305bef72Smatt static int
gten_putcmap(struct gten_softc * gt,struct wsdisplay_cmap * cm)391cfbb4ec2Sgarbled gten_putcmap(struct gten_softc *gt, struct wsdisplay_cmap *cm)
3920b76f4efSmatt {
3930b76f4efSmatt 	int index = cm->index;
3940b76f4efSmatt 	int count = cm->count;
395e07f0b93Schs 	int i, error;
396e07f0b93Schs 	u_char rbuf[256], gbuf[256], bbuf[256];
3970b76f4efSmatt 
3980b76f4efSmatt 	if (cm->index >= 256 || cm->count > 256 ||
3990b76f4efSmatt 	    (cm->index + cm->count) > 256)
4000b76f4efSmatt 		return EINVAL;
401e07f0b93Schs 	error = copyin(cm->red, &rbuf[index], count);
402e07f0b93Schs 	if (error)
403e07f0b93Schs 		return error;
404e07f0b93Schs 	error = copyin(cm->green, &gbuf[index], count);
405e07f0b93Schs 	if (error)
406e07f0b93Schs 		return error;
407e07f0b93Schs 	error = copyin(cm->blue, &bbuf[index], count);
408e07f0b93Schs 	if (error)
409e07f0b93Schs 		return error;
4100b76f4efSmatt 
411e07f0b93Schs 	memcpy(&gt->gt_cmap_red[index], &rbuf[index], count);
412e07f0b93Schs 	memcpy(&gt->gt_cmap_green[index], &gbuf[index], count);
413e07f0b93Schs 	memcpy(&gt->gt_cmap_blue[index], &bbuf[index], count);
4140b76f4efSmatt 	return 0;
4150b76f4efSmatt }
416