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 >en_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_memaddr, >->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 = >en_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_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_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 = >en_screenlist;
2080b76f4efSmatt a.accessops = >en_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 == >en_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 = >en_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(>en_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_cmap_red[index], cm->red, count);
3780b76f4efSmatt if (error)
3790b76f4efSmatt return error;
3800b76f4efSmatt error = copyout(>->gt_cmap_green[index], cm->green, count);
3810b76f4efSmatt if (error)
3820b76f4efSmatt return error;
3830b76f4efSmatt error = copyout(>->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_cmap_red[index], &rbuf[index], count);
412e07f0b93Schs memcpy(>->gt_cmap_green[index], &gbuf[index], count);
413e07f0b93Schs memcpy(>->gt_cmap_blue[index], &bbuf[index], count);
4140b76f4efSmatt return 0;
4150b76f4efSmatt }
416