1 /* $NetBSD: gten.c,v 1.4 2002/03/17 19:40:49 atatat Exp $ */ 2 3 /*- 4 * Copyright (c) 2000 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Matt Thomas <matt@3am-software.com> 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 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. 18 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the NetBSD 21 * Foundation, Inc. and its contributors. 22 * 4. Neither the name of The NetBSD Foundation nor the names of its 23 * contributors may be used to endorse or promote products derived 24 * from this software without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 36 * POSSIBILITY OF SUCH DAMAGE. 37 */ 38 39 #include <sys/param.h> 40 #include <sys/buf.h> 41 #include <sys/conf.h> 42 #include <sys/device.h> 43 #include <sys/ioctl.h> 44 #include <sys/kernel.h> 45 #include <sys/malloc.h> 46 #include <sys/systm.h> 47 48 #include <uvm/uvm_extern.h> 49 50 #include <dev/pci/pcidevs.h> 51 #include <dev/pci/pcireg.h> 52 #include <dev/pci/pcivar.h> 53 54 #include <dev/wscons/wsconsio.h> 55 #include <dev/wscons/wsdisplayvar.h> 56 #include <dev/rasops/rasops.h> 57 58 #include <machine/bus.h> 59 #include <machine/gtenvar.h> 60 61 static int gten_match (struct device *, struct cfdata *, void *); 62 static void gten_attach (struct device *, struct device *, void *); 63 static int gten_print (void *, const char *); 64 65 struct cfattach gten_ca = { 66 sizeof(struct gten_softc), gten_match, gten_attach, 67 }; 68 69 static struct rasops_info gten_console_ri; 70 static pcitag_t gten_console_pcitag; 71 72 static struct wsscreen_descr gten_stdscreen = { 73 "std", 74 0, 0, 75 0, 76 0, 0, 77 WSSCREEN_REVERSE 78 }; 79 80 static const struct wsscreen_descr *_gten_scrlist[] = { 81 >en_stdscreen, 82 /* XXX other formats, graphics screen? */ 83 }; 84 85 static struct wsscreen_list gten_screenlist = { 86 sizeof(_gten_scrlist) / sizeof(struct wsscreen_descr *), _gten_scrlist 87 }; 88 89 static int gten_ioctl (void *, u_long, caddr_t, int, struct proc *); 90 static paddr_t gten_mmap (void *, off_t, int); 91 static int gten_alloc_screen (void *, const struct wsscreen_descr *, 92 void **, int *, int *, long *); 93 static void gten_free_screen (void *, void *); 94 static int gten_show_screen (void *, void *, int, 95 void (*) (void *, int, int), void *); 96 97 static struct wsdisplay_accessops gten_accessops = { 98 gten_ioctl, 99 gten_mmap, 100 gten_alloc_screen, 101 gten_free_screen, 102 gten_show_screen, 103 0 /* load_font */ 104 }; 105 106 static void gten_common_init (struct rasops_info *); 107 static int gten_getcmap (struct gten_softc *, struct wsdisplay_cmap *); 108 static int gten_putcmap (struct gten_softc *, struct wsdisplay_cmap *); 109 110 #define GTEN_VRAM_OFFSET 0xf00000 111 112 static int 113 gten_match(struct device *parent, struct cfdata *match, void *aux) 114 { 115 struct pci_attach_args *pa = aux; 116 117 if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_WD && 118 PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_WD_90C) 119 return 2; 120 121 return 0; 122 } 123 124 static void 125 gten_attach(struct device *parent, struct device *self, void *aux) 126 { 127 struct gten_softc *gt = (struct gten_softc *)self; 128 struct pci_attach_args *pa = aux; 129 struct wsemuldisplaydev_attach_args a; 130 int console = (pa->pa_tag == gten_console_pcitag); 131 int error; 132 char devinfo[256], pbuf[10]; 133 134 error = pci_mapreg_info(pa->pa_pc, pa->pa_tag, 0x14, 135 PCI_MAPREG_TYPE_MEM|PCI_MAPREG_MEM_TYPE_32BIT, 136 >->gt_memaddr, >->gt_memsize, NULL); 137 if (error) { 138 printf(": can't determine memory size: error=%d\n", 139 error); 140 return; 141 } 142 if (console) { 143 gt->gt_ri = >en_console_ri; 144 gt->gt_nscreens = 1; 145 } else { 146 MALLOC(gt->gt_ri, struct rasops_info *, sizeof(*gt->gt_ri), 147 M_DEVBUF, M_NOWAIT); 148 if (gt->gt_ri == NULL) { 149 printf(": can't alloc memory\n"); 150 return; 151 } 152 memset(gt->gt_ri, 0, sizeof(*gt->gt_ri)); 153 #if 0 154 error = pci_mapreg_map(pa, 0x14, 155 PCI_MAPREG_TYPE_MEM|PCI_MAPREG_MEM_TYPE_32BIT, 156 BUS_SPACE_MAP_LINEAR, NULL, 157 (bus_space_handle_t *) >->gt_ri->ri_bits, 158 NULL, NULL); 159 #else 160 error = bus_space_map(pa->pa_memt, gt->gt_memaddr + GTEN_VRAM_OFFSET, 161 960*1024, BUS_SPACE_MAP_LINEAR, 162 (bus_space_handle_t *) >->gt_ri->ri_bits); 163 #endif 164 if (error) { 165 printf(": can't map frame buffer: error=%d\n", error); 166 return; 167 } 168 169 gten_common_init(gt->gt_ri); 170 } 171 172 gt->gt_paddr = vtophys((vaddr_t)gt->gt_ri->ri_bits); 173 if (gt->gt_paddr == 0) { 174 printf(": cannot map framebuffer\n"); 175 return; 176 } 177 gt->gt_psize = gt->gt_memsize - GTEN_VRAM_OFFSET; 178 179 pci_devinfo(pa->pa_id, pa->pa_class, 0, devinfo); 180 printf(": %s\n", devinfo); 181 format_bytes(pbuf, sizeof(pbuf), gt->gt_psize); 182 printf("%s: %s, %dx%d, %dbpp\n", self->dv_xname, pbuf, 183 gt->gt_ri->ri_width, gt->gt_ri->ri_height, 184 gt->gt_ri->ri_depth); 185 #if defined(DEBUG) 186 printf("%s: text %dx%d, =+%d+%d\n", self->dv_xname, 187 gt->gt_ri->ri_cols, gt->gt_ri->ri_rows, 188 gt->gt_ri->ri_xorigin, gt->gt_ri->ri_yorigin); 189 190 { int i; 191 struct rasops_info *ri = gt->gt_ri; 192 for (i = 0; i < 64; i++) { 193 int j = i * ri->ri_stride; 194 int k = (ri->ri_height - i - 1) * gt->gt_ri->ri_stride; 195 memset(ri->ri_bits + j, 0, 64 - i); 196 memset(ri->ri_bits + j + 64 - i, 255, i); 197 198 memset(ri->ri_bits + j + ri->ri_width - 64 + i, 0, 64 - i); 199 memset(ri->ri_bits + j + ri->ri_width - 64, 255, i); 200 201 memset(ri->ri_bits + k, 0, 64 - i); 202 memset(ri->ri_bits + k + 64 - i, 255, i); 203 204 memset(ri->ri_bits + k + ri->ri_width - 64 + i, 0, 64 - i); 205 memset(ri->ri_bits + k + ri->ri_width - 64, 255, i); 206 }} 207 #endif 208 209 gt->gt_cmap_red[0] = gt->gt_cmap_green[0] = gt->gt_cmap_blue[0] = 0; 210 gt->gt_cmap_red[15] = gt->gt_cmap_red[255] = 0xff; 211 gt->gt_cmap_green[15] = gt->gt_cmap_green[255] = 0xff; 212 gt->gt_cmap_blue[15] = gt->gt_cmap_blue[255] = 0xff; 213 214 a.console = console; 215 a.scrdata = >en_screenlist; 216 a.accessops = >en_accessops; 217 a.accesscookie = gt; 218 219 config_found(self, &a, wsemuldisplaydevprint); 220 } 221 222 static void 223 gten_common_init(struct rasops_info *ri) 224 { 225 int32_t addr, width, height, linebytes, depth; 226 int i, screenbytes; 227 228 /* initialize rasops */ 229 ri->ri_width = 640; 230 ri->ri_height = 480; 231 ri->ri_depth = 8; 232 ri->ri_stride = 640; 233 ri->ri_flg = RI_FORCEMONO | RI_FULLCLEAR; 234 235 rasops_init(ri, 30, 80); 236 /* black on white */ 237 ri->ri_devcmap[0] = 0xffffffff; /* bg */ 238 ri->ri_devcmap[1] = 0; /* fg */ 239 240 memset(ri->ri_bits, 0xff, ri->ri_stride * ri->ri_height); 241 242 gten_stdscreen.nrows = ri->ri_rows; 243 gten_stdscreen.ncols = ri->ri_cols; 244 gten_stdscreen.textops = &ri->ri_ops; 245 gten_stdscreen.capabilities = ri->ri_caps; 246 } 247 248 static int 249 gten_ioctl(v, cmd, data, flag, p) 250 void *v; 251 u_long cmd; 252 caddr_t data; 253 int flag; 254 struct proc *p; 255 { 256 struct gten_softc *gt = v; 257 struct wsdisplay_fbinfo *wdf; 258 struct grfinfo *gm; 259 260 switch (cmd) { 261 case WSDISPLAYIO_GTYPE: 262 *(u_int *)data = WSDISPLAY_TYPE_PCIMISC; /* XXX ? */ 263 return 0; 264 265 case WSDISPLAYIO_GINFO: 266 wdf = (void *)data; 267 wdf->height = gt->gt_ri->ri_height; 268 wdf->width = gt->gt_ri->ri_width; 269 wdf->depth = gt->gt_ri->ri_depth; 270 wdf->cmsize = 256; 271 return 0; 272 273 case WSDISPLAYIO_GETCMAP: 274 return gten_getcmap(gt, (struct wsdisplay_cmap *)data); 275 276 case WSDISPLAYIO_PUTCMAP: 277 return gten_putcmap(gt, (struct wsdisplay_cmap *)data); 278 } 279 return EPASSTHROUGH; 280 } 281 282 static paddr_t 283 gten_mmap(v, offset, prot) 284 void *v; 285 off_t offset; 286 int prot; 287 { 288 struct gten_softc *gt = v; 289 290 if (offset >= 0 && offset < gt->gt_psize) 291 return gt->gt_paddr + offset; 292 if (offset >= 0x1000000 && offset < gt->gt_memsize) 293 return gt->gt_memaddr + offset - 0x1000000; 294 295 return -1; 296 } 297 298 static int 299 gten_alloc_screen(v, type, cookiep, curxp, curyp, attrp) 300 void *v; 301 const struct wsscreen_descr *type; 302 void **cookiep; 303 int *curxp, *curyp; 304 long *attrp; 305 { 306 struct gten_softc *gt = v; 307 struct rasops_info *ri = gt->gt_ri; 308 long defattr; 309 310 if (gt->gt_nscreens > 0) 311 return (ENOMEM); 312 313 *cookiep = ri; /* one and only for now */ 314 *curxp = 0; 315 *curyp = 0; 316 (*ri->ri_ops.alloc_attr)(ri, 0, 0, 0, &defattr); 317 *attrp = defattr; 318 gt->gt_nscreens++; 319 return 0; 320 } 321 322 static void 323 gten_free_screen(v, cookie) 324 void *v; 325 void *cookie; 326 { 327 struct gten_softc *gt = v; 328 329 if (gt->gt_ri == >en_console_ri) 330 panic("gten_free_screen: console"); 331 332 gt->gt_nscreens--; 333 } 334 335 static int 336 gten_show_screen(v, cookie, waitok, cb, cbarg) 337 void *v; 338 void *cookie; 339 int waitok; 340 void (*cb) (void *, int, int); 341 void *cbarg; 342 { 343 return (0); 344 } 345 346 int 347 gten_cnattach(pci_chipset_tag_t pc, bus_space_tag_t memt) 348 { 349 struct rasops_info *ri = >en_console_ri; 350 u_int32_t mapreg, id, mask, mapsize; 351 long defattr; 352 pcitag_t tag; 353 int s, error; 354 bus_size_t bussize; 355 bus_addr_t busaddr; 356 357 tag = pci_make_tag(pc, 0, 14, 0); 358 359 id = pci_conf_read(pc, tag, PCI_ID_REG); 360 if (PCI_VENDOR(id) != PCI_VENDOR_WD || 361 PCI_PRODUCT(id) != PCI_PRODUCT_WD_90C) 362 return ENXIO; 363 364 mapreg = pci_conf_read(pc, tag, 0x14); 365 if (PCI_MAPREG_TYPE(mapreg) != PCI_MAPREG_TYPE_MEM || 366 PCI_MAPREG_MEM_TYPE(mapreg) != PCI_MAPREG_MEM_TYPE_32BIT) 367 return ENXIO; 368 369 s = splhigh(); 370 pci_conf_write(pc, tag, 0x14, 0xffffffff); 371 mask = pci_conf_read(pc, tag, 0x14); 372 pci_conf_write(pc, tag, 0x14, mapreg); 373 splx(s); 374 bussize = PCI_MAPREG_MEM_SIZE(mask); 375 busaddr = PCI_MAPREG_MEM_ADDR(mapreg); 376 377 error = bus_space_map(memt, busaddr + GTEN_VRAM_OFFSET, 960*1024, 378 BUS_SPACE_MAP_LINEAR, (bus_space_handle_t *) &ri->ri_bits); 379 if (error) 380 return error; 381 382 gten_common_init(ri); 383 384 (*ri->ri_ops.alloc_attr)(ri, 0, 0, 0, &defattr); 385 wsdisplay_cnattach(>en_stdscreen, ri, 0, 0, defattr); 386 387 gten_console_pcitag = tag; 388 389 return 0; 390 } 391 392 static int 393 gten_getcmap(gt, cm) 394 struct gten_softc *gt; 395 struct wsdisplay_cmap *cm; 396 { 397 u_int index = cm->index; 398 u_int count = cm->count; 399 int error; 400 401 if (index >= 256 || count > 256 || index + count > 256) 402 return EINVAL; 403 404 error = copyout(>->gt_cmap_red[index], cm->red, count); 405 if (error) 406 return error; 407 error = copyout(>->gt_cmap_green[index], cm->green, count); 408 if (error) 409 return error; 410 error = copyout(>->gt_cmap_blue[index], cm->blue, count); 411 if (error) 412 return error; 413 414 return 0; 415 } 416 417 static int 418 gten_putcmap(gt, cm) 419 struct gten_softc *gt; 420 struct wsdisplay_cmap *cm; 421 { 422 int index = cm->index; 423 int count = cm->count; 424 int i; 425 u_char *r, *g, *b; 426 427 if (cm->index >= 256 || cm->count > 256 || 428 (cm->index + cm->count) > 256) 429 return EINVAL; 430 if (!uvm_useracc(cm->red, cm->count, B_READ) || 431 !uvm_useracc(cm->green, cm->count, B_READ) || 432 !uvm_useracc(cm->blue, cm->count, B_READ)) 433 return EFAULT; 434 copyin(cm->red, >->gt_cmap_red[index], count); 435 copyin(cm->green, >->gt_cmap_green[index], count); 436 copyin(cm->blue, >->gt_cmap_blue[index], count); 437 438 r = >->gt_cmap_red[index]; 439 g = >->gt_cmap_green[index]; 440 b = >->gt_cmap_blue[index]; 441 442 #if 0 443 for (i = 0; i < count; i++) { 444 OF_call_method_1("color!", dc->dc_ih, 4, *r, *g, *b, index); 445 r++, g++, b++, index++; 446 } 447 #endif 448 449 return 0; 450 } 451