1 /* $NetBSD: gten.c,v 1.17 2008/04/28 20:23:33 martin Exp $ */
4 * Copyright (c) 2000 The NetBSD Foundation, Inc.
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Matt Thomas <matt@3am-software.com>
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
32 #include <sys/cdefs.h>
33 __KERNEL_RCSID(0, "$NetBSD: gten.c,v 1.17 2008/04/28 20:23:33 martin Exp $");
35 #include <sys/param.h>
38 #include <sys/device.h>
39 #include <sys/ioctl.h>
40 #include <sys/kernel.h>
41 #include <sys/malloc.h>
42 #include <sys/systm.h>
44 #include <uvm/uvm_extern.h>
46 #include <dev/pci/pcidevs.h>
47 #include <dev/pci/pcireg.h>
48 #include <dev/pci/pcivar.h>
50 #include <dev/wscons/wsconsio.h>
51 #include <dev/wscons/wsdisplayvar.h>
52 #include <dev/rasops/rasops.h>
54 #include <machine/bus.h>
55 #include <machine/gtenvar.h>
57 static int gten_match(struct device
*, struct cfdata
*, void *);
58 static void gten_attach(struct device
*, struct device
*, void *);
59 static int gten_print(void *, const char *);
61 CFATTACH_DECL(gten
, sizeof(struct gten_softc
),
62 gten_match
, gten_attach
, NULL
, NULL
);
64 static struct rasops_info gten_console_ri
;
65 static pcitag_t gten_console_pcitag
;
67 static struct wsscreen_descr gten_stdscreen
= {
75 static const struct wsscreen_descr
*_gten_scrlist
[] = {
77 /* XXX other formats, graphics screen? */
80 static struct wsscreen_list gten_screenlist
= {
81 sizeof(_gten_scrlist
) / sizeof(struct wsscreen_descr
*), _gten_scrlist
84 static int gten_ioctl(void *, void *, u_long
, void *, int, struct proc
*);
85 static paddr_t
gten_mmap(void *, void *, off_t
, int);
86 static int gten_alloc_screen(void *, const struct wsscreen_descr
*,
87 void **, int *, int *, long *);
88 static void gten_free_screen(void *, void *);
89 static int gten_show_screen(void *, void *, int,
90 void (*) (void *, int, int), void *);
92 static struct wsdisplay_accessops gten_accessops
= {
101 static void gten_common_init(struct rasops_info
*);
102 static int gten_getcmap(struct gten_softc
*, struct wsdisplay_cmap
*);
103 static int gten_putcmap(struct gten_softc
*, struct wsdisplay_cmap
*);
105 #define GTEN_VRAM_OFFSET 0xf00000
108 gten_match(struct device
*parent
, struct cfdata
*match
, void *aux
)
110 struct pci_attach_args
*pa
= aux
;
112 if (PCI_VENDOR(pa
->pa_id
) == PCI_VENDOR_WD
&&
113 PCI_PRODUCT(pa
->pa_id
) == PCI_PRODUCT_WD_90C
)
120 gten_attach(struct device
*parent
, struct device
*self
, void *aux
)
122 struct gten_softc
*gt
= (struct gten_softc
*)self
;
123 struct pci_attach_args
*pa
= aux
;
124 struct wsemuldisplaydev_attach_args a
;
125 int console
= (pa
->pa_tag
== gten_console_pcitag
);
127 char devinfo
[256], pbuf
[10];
129 error
= pci_mapreg_info(pa
->pa_pc
, pa
->pa_tag
, 0x14,
130 PCI_MAPREG_TYPE_MEM
|PCI_MAPREG_MEM_TYPE_32BIT
,
131 >
->gt_memaddr
, >
->gt_memsize
, NULL
);
133 aprint_error(": can't determine memory size: error=%d\n",
138 gt
->gt_ri
= >en_console_ri
;
141 gt
->gt_ri
= malloc(sizeof(*gt
->gt_ri
),
142 M_DEVBUF
, M_NOWAIT
|M_ZERO
);
143 if (gt
->gt_ri
== NULL
) {
144 aprint_error(": can't alloc memory\n");
148 error
= pci_mapreg_map(pa
, 0x14,
149 PCI_MAPREG_TYPE_MEM
|PCI_MAPREG_MEM_TYPE_32BIT
,
150 BUS_SPACE_MAP_LINEAR
, NULL
,
151 (bus_space_handle_t
*) >
->gt_ri
->ri_bits
,
154 error
= bus_space_map(pa
->pa_memt
, gt
->gt_memaddr
+ GTEN_VRAM_OFFSET
,
155 960*1024, BUS_SPACE_MAP_LINEAR
,
156 (bus_space_handle_t
*) >
->gt_ri
->ri_bits
);
159 aprint_error(": can't map frame buffer: error=%d\n",
164 gten_common_init(gt
->gt_ri
);
167 gt
->gt_paddr
= vtophys((vaddr_t
)gt
->gt_ri
->ri_bits
);
168 if (gt
->gt_paddr
== 0) {
169 aprint_error(": cannot map framebuffer\n");
172 gt
->gt_psize
= gt
->gt_memsize
- GTEN_VRAM_OFFSET
;
174 pci_devinfo(pa
->pa_id
, pa
->pa_class
, 0, devinfo
, sizeof(devinfo
));
175 aprint_normal(": %s\n", devinfo
);
176 format_bytes(pbuf
, sizeof(pbuf
), gt
->gt_psize
);
177 aprint_normal("%s: %s, %dx%d, %dbpp\n", self
->dv_xname
, pbuf
,
178 gt
->gt_ri
->ri_width
, gt
->gt_ri
->ri_height
,
179 gt
->gt_ri
->ri_depth
);
181 aprint_debug("%s: text %dx%d, =+%d+%d\n", self
->dv_xname
,
182 gt
->gt_ri
->ri_cols
, gt
->gt_ri
->ri_rows
,
183 gt
->gt_ri
->ri_xorigin
, gt
->gt_ri
->ri_yorigin
);
186 struct rasops_info
*ri
= gt
->gt_ri
;
187 for (i
= 0; i
< 64; i
++) {
188 int j
= i
* ri
->ri_stride
;
189 int k
= (ri
->ri_height
- i
- 1) * gt
->gt_ri
->ri_stride
;
190 memset(ri
->ri_bits
+ j
, 0, 64 - i
);
191 memset(ri
->ri_bits
+ j
+ 64 - i
, 255, i
);
193 memset(ri
->ri_bits
+ j
+ ri
->ri_width
- 64 + i
, 0, 64 - i
);
194 memset(ri
->ri_bits
+ j
+ ri
->ri_width
- 64, 255, i
);
196 memset(ri
->ri_bits
+ k
, 0, 64 - i
);
197 memset(ri
->ri_bits
+ k
+ 64 - i
, 255, i
);
199 memset(ri
->ri_bits
+ k
+ ri
->ri_width
- 64 + i
, 0, 64 - i
);
200 memset(ri
->ri_bits
+ k
+ ri
->ri_width
- 64, 255, i
);
204 gt
->gt_cmap_red
[0] = gt
->gt_cmap_green
[0] = gt
->gt_cmap_blue
[0] = 0;
205 gt
->gt_cmap_red
[15] = gt
->gt_cmap_red
[255] = 0xff;
206 gt
->gt_cmap_green
[15] = gt
->gt_cmap_green
[255] = 0xff;
207 gt
->gt_cmap_blue
[15] = gt
->gt_cmap_blue
[255] = 0xff;
210 a
.scrdata
= >en_screenlist
;
211 a
.accessops
= >en_accessops
;
214 config_found(self
, &a
, wsemuldisplaydevprint
);
218 gten_common_init(struct rasops_info
*ri
)
220 int32_t addr
, width
, height
, linebytes
, depth
;
223 /* initialize rasops */
228 ri
->ri_flg
= RI_FORCEMONO
| RI_FULLCLEAR
;
230 rasops_init(ri
, 30, 80);
232 ri
->ri_devcmap
[0] = 0xffffffff; /* bg */
233 ri
->ri_devcmap
[1] = 0; /* fg */
235 memset(ri
->ri_bits
, 0xff, ri
->ri_stride
* ri
->ri_height
);
237 gten_stdscreen
.nrows
= ri
->ri_rows
;
238 gten_stdscreen
.ncols
= ri
->ri_cols
;
239 gten_stdscreen
.textops
= &ri
->ri_ops
;
240 gten_stdscreen
.capabilities
= ri
->ri_caps
;
244 gten_ioctl(void *v
, void *vs
, u_long cmd
, void *data
, int flag
,
247 struct gten_softc
*gt
= v
;
248 struct wsdisplay_fbinfo
*wdf
;
252 case WSDISPLAYIO_GTYPE
:
253 *(u_int
*)data
= WSDISPLAY_TYPE_PCIMISC
; /* XXX ? */
256 case WSDISPLAYIO_GINFO
:
258 wdf
->height
= gt
->gt_ri
->ri_height
;
259 wdf
->width
= gt
->gt_ri
->ri_width
;
260 wdf
->depth
= gt
->gt_ri
->ri_depth
;
264 case WSDISPLAYIO_GETCMAP
:
265 return gten_getcmap(gt
, (struct wsdisplay_cmap
*)data
);
267 case WSDISPLAYIO_PUTCMAP
:
268 return gten_putcmap(gt
, (struct wsdisplay_cmap
*)data
);
274 gten_mmap(void *v
, void *vs
, off_t offset
, int prot
)
276 struct gten_softc
*gt
= v
;
278 if (offset
>= 0 && offset
< gt
->gt_psize
)
279 return gt
->gt_paddr
+ offset
;
280 if (offset
>= 0x1000000 && offset
< gt
->gt_memsize
)
281 return gt
->gt_memaddr
+ offset
- 0x1000000;
287 gten_alloc_screen(void *v
, const struct wsscreen_descr
*type
, void **cookiep
,
288 int *curxp
, int *curyp
, long *attrp
)
290 struct gten_softc
*gt
= v
;
291 struct rasops_info
*ri
= gt
->gt_ri
;
294 if (gt
->gt_nscreens
> 0)
297 *cookiep
= ri
; /* one and only for now */
300 (*ri
->ri_ops
.allocattr
)(ri
, 0, 0, 0, &defattr
);
307 gten_free_screen(void *v
, void *cookie
)
309 struct gten_softc
*gt
= v
;
311 if (gt
->gt_ri
== >en_console_ri
)
312 panic("gten_free_screen: console");
318 gten_show_screen(void *v
, void *cookie
, int waitok
,
319 void (*cb
)(void *, int, int), void *cbarg
)
325 gten_cnattach(pci_chipset_tag_t pc
, bus_space_tag_t memt
)
327 struct rasops_info
*ri
= >en_console_ri
;
328 u_int32_t mapreg
, id
, mask
, mapsize
;
335 tag
= pci_make_tag(pc
, 0, 14, 0);
337 id
= pci_conf_read(pc
, tag
, PCI_ID_REG
);
338 if (PCI_VENDOR(id
) != PCI_VENDOR_WD
||
339 PCI_PRODUCT(id
) != PCI_PRODUCT_WD_90C
)
342 mapreg
= pci_conf_read(pc
, tag
, 0x14);
343 if (PCI_MAPREG_TYPE(mapreg
) != PCI_MAPREG_TYPE_MEM
||
344 PCI_MAPREG_MEM_TYPE(mapreg
) != PCI_MAPREG_MEM_TYPE_32BIT
)
348 pci_conf_write(pc
, tag
, 0x14, 0xffffffff);
349 mask
= pci_conf_read(pc
, tag
, 0x14);
350 pci_conf_write(pc
, tag
, 0x14, mapreg
);
352 bussize
= PCI_MAPREG_MEM_SIZE(mask
);
353 busaddr
= PCI_MAPREG_MEM_ADDR(mapreg
);
355 error
= bus_space_map(memt
, busaddr
+ GTEN_VRAM_OFFSET
, 960*1024,
356 BUS_SPACE_MAP_LINEAR
, (bus_space_handle_t
*) &ri
->ri_bits
);
360 gten_common_init(ri
);
362 (*ri
->ri_ops
.allocattr
)(ri
, 0, 0, 0, &defattr
);
363 wsdisplay_cnattach(>en_stdscreen
, ri
, 0, 0, defattr
);
365 gten_console_pcitag
= tag
;
371 gten_getcmap(struct gten_softc
*gt
, struct wsdisplay_cmap
*cm
)
373 u_int index
= cm
->index
;
374 u_int count
= cm
->count
;
377 if (index
>= 256 || count
> 256 || index
+ count
> 256)
380 error
= copyout(>
->gt_cmap_red
[index
], cm
->red
, count
);
383 error
= copyout(>
->gt_cmap_green
[index
], cm
->green
, count
);
386 error
= copyout(>
->gt_cmap_blue
[index
], cm
->blue
, count
);
394 gten_putcmap(struct gten_softc
*gt
, struct wsdisplay_cmap
*cm
)
396 int index
= cm
->index
;
397 int count
= cm
->count
;
399 u_char rbuf
[256], gbuf
[256], bbuf
[256];
401 if (cm
->index
>= 256 || cm
->count
> 256 ||
402 (cm
->index
+ cm
->count
) > 256)
404 error
= copyin(cm
->red
, &rbuf
[index
], count
);
407 error
= copyin(cm
->green
, &gbuf
[index
], count
);
410 error
= copyin(cm
->blue
, &bbuf
[index
], count
);
414 memcpy(>
->gt_cmap_red
[index
], &rbuf
[index
], count
);
415 memcpy(>
->gt_cmap_green
[index
], &gbuf
[index
], count
);
416 memcpy(>
->gt_cmap_blue
[index
], &bbuf
[index
], count
);