Print this page
7127 remove -Wno-missing-braces from Makefile.uts
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/uts/intel/io/vgatext/vgatext.c
+++ new/usr/src/uts/intel/io/vgatext/vgatext.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21
22 22 /*
23 23 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
24 24 * Use is subject to license terms.
25 25 */
26 26
27 27 /* Copyright (c) 1990, 1991 UNIX System Laboratories, Inc. */
28 28 /* Copyright (c) 1984, 1986, 1987, 1988, 1989, 1990 AT&T */
29 29 /* All Rights Reserved */
30 30
31 31 #include <sys/errno.h>
32 32 #include <sys/types.h>
33 33 #include <sys/conf.h>
34 34 #include <sys/kmem.h>
35 35 #include <sys/visual_io.h>
36 36 #include <sys/font.h>
37 37 #include <sys/fbio.h>
38 38
39 39 #include <sys/ddi.h>
40 40 #include <sys/stat.h>
41 41 #include <sys/sunddi.h>
42 42 #include <sys/file.h>
43 43 #include <sys/open.h>
44 44 #include <sys/modctl.h>
45 45 #include <sys/vgareg.h>
46 46 #include <sys/vgasubr.h>
47 47 #include <sys/pci.h>
48 48 #include <sys/kd.h>
49 49 #include <sys/ddi_impldefs.h>
50 50 #include <sys/sunldi.h>
51 51 #include <sys/agpgart.h>
52 52 #include <sys/agp/agpdefs.h>
53 53 #include <sys/agp/agpmaster_io.h>
54 54
55 55 #define MYNAME "vgatext"
56 56
57 57 /*
58 58 * Each instance of this driver has 2 minor nodes:
59 59 * 0: for common graphics operations
60 60 * 1: for agpmaster operations
61 61 */
62 62 #define GFX_MINOR 0
63 63 #define AGPMASTER_MINOR 1
64 64
65 65 #define MY_NBITSMINOR 1
66 66 #define DEV2INST(dev) (getminor(dev) >> MY_NBITSMINOR)
67 67 #define DEV2MINOR(dev) (getminor(dev) & ((1 << MY_NBITSMINOR) - 1))
68 68 #define INST2NODE1(inst) ((inst) << MY_NBITSMINOR + GFX_MINOR)
69 69 #define INST2NODE2(inst) (((inst) << MY_NBITSMINOR) + AGPMASTER_MINOR)
70 70
71 71 /* I don't know exactly where these should be defined, but this is a */
72 72 /* heck of a lot better than constants in the code. */
73 73 #define TEXT_ROWS 25
74 74 #define TEXT_COLS 80
75 75
76 76 #define VGA_BRIGHT_WHITE 0x0f
77 77 #define VGA_BLACK 0x00
78 78
79 79 #define VGA_REG_ADDR 0x3c0
80 80 #define VGA_REG_SIZE 0x20
81 81
82 82 #define VGA_MEM_ADDR 0xa0000
83 83 #define VGA_MEM_SIZE 0x20000
84 84
85 85 #define VGA_MMAP_FB_BASE VGA_MEM_ADDR
86 86
87 87 /*
88 88 * This variable allows for this driver to suspend even if it
89 89 * shouldn't. Note that by setting it, the framebuffer will probably
90 90 * not come back. So use it with a serial console, or with serial
91 91 * line debugging (say, for example, if this driver is being modified
92 92 * to support _some_ hardware doing suspend and resume).
93 93 */
94 94 int vgatext_force_suspend = 0;
95 95
96 96 static int vgatext_open(dev_t *, int, int, cred_t *);
97 97 static int vgatext_close(dev_t, int, int, cred_t *);
98 98 static int vgatext_ioctl(dev_t, int, intptr_t, int, cred_t *, int *);
99 99 static int vgatext_devmap(dev_t, devmap_cookie_t, offset_t, size_t,
100 100 size_t *, uint_t);
101 101
102 102 static struct cb_ops cb_vgatext_ops = {
103 103 vgatext_open, /* cb_open */
104 104 vgatext_close, /* cb_close */
105 105 nodev, /* cb_strategy */
106 106 nodev, /* cb_print */
107 107 nodev, /* cb_dump */
108 108 nodev, /* cb_read */
109 109 nodev, /* cb_write */
110 110 vgatext_ioctl, /* cb_ioctl */
111 111 vgatext_devmap, /* cb_devmap */
112 112 nodev, /* cb_mmap */
113 113 ddi_devmap_segmap, /* cb_segmap */
114 114 nochpoll, /* cb_chpoll */
115 115 ddi_prop_op, /* cb_prop_op */
116 116 0, /* cb_stream */
117 117 D_NEW | D_MTSAFE /* cb_flag */
118 118 };
119 119
120 120 static int vgatext_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg,
121 121 void **result);
122 122 static int vgatext_attach(dev_info_t *, ddi_attach_cmd_t);
123 123 static int vgatext_detach(dev_info_t *, ddi_detach_cmd_t);
124 124
125 125 static struct vis_identifier text_ident = { "SUNWtext" };
126 126
127 127 static struct dev_ops vgatext_ops = {
128 128 DEVO_REV, /* devo_rev */
129 129 0, /* devo_refcnt */
130 130 vgatext_info, /* devo_getinfo */
131 131 nulldev, /* devo_identify */
132 132 nulldev, /* devo_probe */
133 133 vgatext_attach, /* devo_attach */
134 134 vgatext_detach, /* devo_detach */
135 135 nodev, /* devo_reset */
136 136 &cb_vgatext_ops, /* devo_cb_ops */
137 137 (struct bus_ops *)NULL, /* devo_bus_ops */
138 138 NULL, /* power */
139 139 ddi_quiesce_not_needed, /* quiesce */
140 140 };
141 141
142 142 struct vgatext_softc {
143 143 struct vgaregmap regs;
144 144 struct vgaregmap fb;
145 145 off_t fb_size;
146 146 int fb_regno;
147 147 dev_info_t *devi;
148 148 int mode; /* KD_TEXT or KD_GRAPHICS */
149 149 caddr_t text_base; /* hardware text base */
150 150 char shadow[TEXT_ROWS*TEXT_COLS*2];
151 151 caddr_t current_base; /* hardware or shadow */
152 152 struct {
153 153 boolean_t visible;
154 154 int row;
155 155 int col;
156 156 } cursor;
157 157 struct vis_polledio polledio;
158 158 struct {
159 159 unsigned char red;
160 160 unsigned char green;
161 161 unsigned char blue;
162 162 } colormap[VGA8_CMAP_ENTRIES];
163 163 unsigned char attrib_palette[VGA_ATR_NUM_PLT];
164 164 agp_master_softc_t *agp_master; /* NULL means not PCI, for AGP */
165 165 ddi_acc_handle_t *pci_cfg_hdlp; /* PCI conf handle */
166 166 unsigned int flags;
167 167 kmutex_t lock;
168 168 };
169 169
170 170 #define VGATEXT_FLAG_CONSOLE 0x00000001
171 171 #define VGATEXT_IS_CONSOLE(softc) ((softc)->flags & VGATEXT_FLAG_CONSOLE)
172 172
173 173 static int vgatext_devinit(struct vgatext_softc *, struct vis_devinit *data);
174 174 static void vgatext_cons_copy(struct vgatext_softc *,
175 175 struct vis_conscopy *);
176 176 static void vgatext_cons_display(struct vgatext_softc *,
177 177 struct vis_consdisplay *);
178 178 static void vgatext_cons_cursor(struct vgatext_softc *,
179 179 struct vis_conscursor *);
180 180 static void vgatext_polled_copy(struct vis_polledio_arg *,
181 181 struct vis_conscopy *);
182 182 static void vgatext_polled_display(struct vis_polledio_arg *,
183 183 struct vis_consdisplay *);
184 184 static void vgatext_polled_cursor(struct vis_polledio_arg *,
185 185 struct vis_conscursor *);
186 186 static void vgatext_init(struct vgatext_softc *);
187 187 static void vgatext_set_text(struct vgatext_softc *);
188 188 #if defined(USE_BORDERS)
189 189 static void vgatext_init_graphics(struct vgatext_softc *);
190 190 #endif
191 191 static int vgatext_kdsetmode(struct vgatext_softc *softc, int mode);
192 192 static void vgatext_setfont(struct vgatext_softc *softc);
193 193 static void vgatext_get_cursor(struct vgatext_softc *softc,
194 194 screen_pos_t *row, screen_pos_t *col);
195 195 static void vgatext_set_cursor(struct vgatext_softc *softc, int row, int col);
196 196 static void vgatext_hide_cursor(struct vgatext_softc *softc);
197 197 static void vgatext_save_colormap(struct vgatext_softc *softc);
198 198 static void vgatext_restore_colormap(struct vgatext_softc *softc);
199 199 static int vgatext_get_pci_reg_index(dev_info_t *const devi,
200 200 unsigned long himask, unsigned long hival, unsigned long addr,
201 201 off_t *offset);
202 202 static int vgatext_get_isa_reg_index(dev_info_t *const devi,
203 203 unsigned long hival, unsigned long addr, off_t *offset);
204 204 static void *vgatext_softc_head;
205 205 static char vgatext_silent;
206 206 static char happyface_boot;
↓ open down ↓ |
206 lines elided |
↑ open up ↑ |
207 207
208 208 /* Loadable Driver stuff */
209 209
210 210 static struct modldrv modldrv = {
211 211 &mod_driverops, /* Type of module. This one is a driver */
212 212 "VGA text driver", /* Name of the module. */
213 213 &vgatext_ops, /* driver ops */
214 214 };
215 215
216 216 static struct modlinkage modlinkage = {
217 - MODREV_1, (void *) &modldrv, NULL
217 + MODREV_1, { (void *) &modldrv, NULL }
218 218 };
219 219
220 220 typedef enum pc_colors {
221 221 pc_black = 0,
222 222 pc_blue = 1,
223 223 pc_green = 2,
224 224 pc_cyan = 3,
225 225 pc_red = 4,
226 226 pc_magenta = 5,
227 227 pc_brown = 6,
228 228 pc_white = 7,
229 229 pc_grey = 8,
230 230 pc_brt_blue = 9,
231 231 pc_brt_green = 10,
232 232 pc_brt_cyan = 11,
233 233 pc_brt_red = 12,
234 234 pc_brt_magenta = 13,
235 235 pc_yellow = 14,
236 236 pc_brt_white = 15
237 237 } pc_colors_t;
238 238
239 239 static const unsigned char solaris_color_to_pc_color[16] = {
240 240 pc_brt_white, /* 0 - brt_white */
241 241 pc_black, /* 1 - black */
242 242 pc_blue, /* 2 - blue */
243 243 pc_green, /* 3 - green */
244 244 pc_cyan, /* 4 - cyan */
245 245 pc_red, /* 5 - red */
246 246 pc_magenta, /* 6 - magenta */
247 247 pc_brown, /* 7 - brown */
248 248 pc_white, /* 8 - white */
249 249 pc_grey, /* 9 - gery */
250 250 pc_brt_blue, /* 10 - brt_blue */
251 251 pc_brt_green, /* 11 - brt_green */
252 252 pc_brt_cyan, /* 12 - brt_cyan */
253 253 pc_brt_red, /* 13 - brt_red */
254 254 pc_brt_magenta, /* 14 - brt_magenta */
255 255 pc_yellow /* 15 - yellow */
256 256 };
257 257
258 258 static ddi_device_acc_attr_t i8xx_dev_access = {
259 259 DDI_DEVICE_ATTR_V0,
260 260 DDI_NEVERSWAP_ACC,
261 261 DDI_STRICTORDER_ACC
262 262 };
263 263
264 264 static ddi_device_acc_attr_t dev_attr = {
265 265 DDI_DEVICE_ATTR_V0,
266 266 DDI_NEVERSWAP_ACC,
267 267 DDI_STRICTORDER_ACC,
268 268 };
269 269
270 270 int
271 271 _init(void)
272 272 {
273 273 int e;
274 274
275 275 if ((e = ddi_soft_state_init(&vgatext_softc_head,
276 276 sizeof (struct vgatext_softc), 1)) != 0) {
277 277 return (e);
278 278 }
279 279
280 280 e = mod_install(&modlinkage);
281 281
282 282 if (e) {
283 283 ddi_soft_state_fini(&vgatext_softc_head);
284 284 }
285 285 return (e);
286 286 }
287 287
288 288 int
289 289 _fini(void)
290 290 {
291 291 int e;
292 292
293 293 if ((e = mod_remove(&modlinkage)) != 0)
294 294 return (e);
295 295
296 296 ddi_soft_state_fini(&vgatext_softc_head);
297 297
298 298 return (0);
299 299 }
300 300
301 301 int
302 302 _info(struct modinfo *modinfop)
303 303 {
304 304 return (mod_info(&modlinkage, modinfop));
305 305 }
306 306
307 307 /* default structure for FBIOGATTR ioctl */
308 308 static struct fbgattr vgatext_attr = {
309 309 /* real_type owner */
310 310 FBTYPE_SUNFAST_COLOR, 0,
311 311 /* fbtype: type h w depth cms size */
312 312 { FBTYPE_SUNFAST_COLOR, TEXT_ROWS, TEXT_COLS, 1, 256, 0 },
313 313 /* fbsattr: flags emu_type dev_specific */
314 314 { 0, FBTYPE_SUN4COLOR, { 0 } },
315 315 /* emu_types */
316 316 { -1 }
317 317 };
318 318
319 319 /*
320 320 * handy macros
321 321 */
322 322
323 323 #define getsoftc(instance) ((struct vgatext_softc *) \
324 324 ddi_get_soft_state(vgatext_softc_head, (instance)))
325 325
326 326 #define STREQ(a, b) (strcmp((a), (b)) == 0)
327 327
328 328 /*
329 329 * NOTE: this function is duplicated here and in gfx_private/vgatext while
330 330 * we work on a set of commitable interfaces to sunpci.c.
331 331 *
332 332 * Use the class code to determine if the device is a PCI-to-PCI bridge.
333 333 * Returns: B_TRUE if the device is a bridge.
334 334 * B_FALSE if the device is not a bridge or the property cannot be
335 335 * retrieved.
336 336 */
337 337 static boolean_t
338 338 is_pci_bridge(dev_info_t *dip)
339 339 {
340 340 uint32_t class_code;
341 341
342 342 class_code = (uint32_t)ddi_prop_get_int(DDI_DEV_T_ANY, dip,
343 343 DDI_PROP_DONTPASS, "class-code", 0xffffffff);
344 344
345 345 if (class_code == 0xffffffff || class_code == DDI_PROP_NOT_FOUND)
346 346 return (B_FALSE);
347 347
348 348 class_code &= 0x00ffff00;
349 349 if (class_code == ((PCI_CLASS_BRIDGE << 16) | (PCI_BRIDGE_PCI << 8)))
350 350 return (B_TRUE);
351 351
352 352 return (B_FALSE);
353 353 }
354 354
355 355 static void
356 356 vgatext_check_for_console(dev_info_t *devi, struct vgatext_softc *softc,
357 357 int pci_pcie_bus)
358 358 {
359 359 ddi_acc_handle_t pci_conf;
360 360 dev_info_t *pdevi;
361 361 uint16_t data16;
362 362
363 363 /*
364 364 * Based on Section 11.3, "PCI Display Subsystem Initialization",
365 365 * of the 1.1 PCI-to-PCI Bridge Architecture Specification
366 366 * determine if this is the boot console device. First, see
367 367 * if the SBIOS has turned on PCI I/O for this device. Then if
368 368 * this is PCI/PCI-E, verify the parent bridge has VGAEnable set.
369 369 */
370 370
371 371 if (pci_config_setup(devi, &pci_conf) != DDI_SUCCESS) {
372 372 cmn_err(CE_WARN,
373 373 MYNAME ": can't get PCI conf handle");
374 374 return;
375 375 }
376 376
377 377 data16 = pci_config_get16(pci_conf, PCI_CONF_COMM);
378 378 if (data16 & PCI_COMM_IO)
379 379 softc->flags |= VGATEXT_FLAG_CONSOLE;
380 380
381 381 pci_config_teardown(&pci_conf);
382 382
383 383 /* If IO not enabled or ISA/EISA, just return */
384 384 if (!(softc->flags & VGATEXT_FLAG_CONSOLE) || !pci_pcie_bus)
385 385 return;
386 386
387 387 /*
388 388 * Check for VGA Enable in the Bridge Control register for all
389 389 * PCI/PCIEX parents. If not set all the way up the chain,
390 390 * this cannot be the boot console.
391 391 */
392 392
393 393 pdevi = devi;
394 394 while (pdevi = ddi_get_parent(pdevi)) {
395 395 int error;
396 396 ddi_acc_handle_t ppci_conf;
397 397 char *parent_type = NULL;
398 398
399 399 error = ddi_prop_lookup_string(DDI_DEV_T_ANY, pdevi,
400 400 DDI_PROP_DONTPASS, "device_type", &parent_type);
401 401 if (error != DDI_SUCCESS) {
402 402 return;
403 403 }
404 404
405 405 /* Verify still on the PCI/PCIEX parent tree */
406 406 if (!STREQ(parent_type, "pci") &&
407 407 !STREQ(parent_type, "pciex")) {
408 408 ddi_prop_free(parent_type);
409 409 return;
410 410 }
411 411
412 412 ddi_prop_free(parent_type);
413 413 parent_type = NULL;
414 414
415 415 /* VGAEnable is set only for PCI-to-PCI bridges. */
416 416 if (is_pci_bridge(pdevi) == B_FALSE)
417 417 continue;
418 418
419 419 if (pci_config_setup(pdevi, &ppci_conf) != DDI_SUCCESS)
420 420 continue;
421 421
422 422 data16 = pci_config_get16(ppci_conf, PCI_BCNF_BCNTRL);
423 423 pci_config_teardown(&ppci_conf);
424 424
425 425 if (!(data16 & PCI_BCNF_BCNTRL_VGA_ENABLE)) {
426 426 softc->flags &= ~VGATEXT_FLAG_CONSOLE;
427 427 return;
428 428 }
429 429 }
430 430 }
431 431
432 432 static int
433 433 vgatext_attach(dev_info_t *devi, ddi_attach_cmd_t cmd)
434 434 {
435 435 struct vgatext_softc *softc;
436 436 int unit = ddi_get_instance(devi);
437 437 int error;
438 438 char *parent_type = NULL;
439 439 int reg_rnumber;
440 440 int agpm = 0;
441 441 off_t reg_offset;
442 442 off_t mem_offset;
443 443 char buf[80], *cons;
444 444 int pci_pcie_bus = 0;
445 445
446 446
447 447 switch (cmd) {
448 448 case DDI_ATTACH:
449 449 break;
450 450
451 451 case DDI_RESUME:
452 452 /*
453 453 * Though vgatext doesn't really know how to resume
454 454 * on a generic framebuffer, we should succeed, as
455 455 * it is far better to have no console, than potentiall
456 456 * have no machine.
457 457 */
458 458 return (DDI_SUCCESS);
459 459 default:
460 460 return (DDI_FAILURE);
461 461 }
462 462
463 463 /* DDI_ATTACH */
464 464
465 465 /* Allocate softc struct */
466 466 if (ddi_soft_state_zalloc(vgatext_softc_head, unit) != DDI_SUCCESS) {
467 467 return (DDI_FAILURE);
468 468 }
469 469 softc = getsoftc(unit);
470 470
471 471 /* link it in */
472 472 softc->devi = devi;
473 473 ddi_set_driver_private(devi, softc);
474 474
475 475 softc->polledio.arg = (struct vis_polledio_arg *)softc;
476 476 softc->polledio.display = vgatext_polled_display;
477 477 softc->polledio.copy = vgatext_polled_copy;
478 478 softc->polledio.cursor = vgatext_polled_cursor;
479 479
480 480 mutex_init(&(softc->lock), NULL, MUTEX_DRIVER, NULL);
481 481
482 482 error = ddi_prop_lookup_string(DDI_DEV_T_ANY, ddi_get_parent(devi),
483 483 DDI_PROP_DONTPASS, "device_type", &parent_type);
484 484 if (error != DDI_SUCCESS) {
485 485 cmn_err(CE_WARN, MYNAME ": can't determine parent type.");
486 486 goto fail;
487 487 }
488 488
489 489 if (STREQ(parent_type, "isa") || STREQ(parent_type, "eisa")) {
490 490 reg_rnumber = vgatext_get_isa_reg_index(devi, 1, VGA_REG_ADDR,
491 491 ®_offset);
492 492 if (reg_rnumber < 0) {
493 493 cmn_err(CE_WARN,
494 494 MYNAME ": can't find reg entry for registers");
495 495 error = DDI_FAILURE;
496 496 goto fail;
497 497 }
498 498 softc->fb_regno = vgatext_get_isa_reg_index(devi, 0,
499 499 VGA_MEM_ADDR, &mem_offset);
500 500 if (softc->fb_regno < 0) {
501 501 cmn_err(CE_WARN,
502 502 MYNAME ": can't find reg entry for memory");
503 503 error = DDI_FAILURE;
504 504 goto fail;
505 505 }
506 506 } else if (STREQ(parent_type, "pci") || STREQ(parent_type, "pciex")) {
507 507 pci_pcie_bus = 1;
508 508 reg_rnumber = vgatext_get_pci_reg_index(devi,
509 509 PCI_REG_ADDR_M|PCI_REG_REL_M,
510 510 PCI_ADDR_IO|PCI_RELOCAT_B, VGA_REG_ADDR,
511 511 ®_offset);
512 512 if (reg_rnumber < 0) {
513 513 cmn_err(CE_WARN,
514 514 MYNAME ": can't find reg entry for registers");
515 515 error = DDI_FAILURE;
516 516 goto fail;
517 517 }
518 518 softc->fb_regno = vgatext_get_pci_reg_index(devi,
519 519 PCI_REG_ADDR_M|PCI_REG_REL_M,
520 520 PCI_ADDR_MEM32|PCI_RELOCAT_B, VGA_MEM_ADDR,
521 521 &mem_offset);
522 522 if (softc->fb_regno < 0) {
523 523 cmn_err(CE_WARN,
524 524 MYNAME ": can't find reg entry for memory");
525 525 error = DDI_FAILURE;
526 526 goto fail;
527 527 }
528 528 agpm = 1; /* should have AGP master support */
529 529 } else {
530 530 cmn_err(CE_WARN, MYNAME ": unknown parent type \"%s\".",
531 531 parent_type);
532 532 error = DDI_FAILURE;
533 533 goto fail;
534 534 }
535 535 ddi_prop_free(parent_type);
536 536 parent_type = NULL;
537 537
538 538 error = ddi_regs_map_setup(devi, reg_rnumber,
539 539 (caddr_t *)&softc->regs.addr, reg_offset, VGA_REG_SIZE,
540 540 &dev_attr, &softc->regs.handle);
541 541 if (error != DDI_SUCCESS)
542 542 goto fail;
543 543 softc->regs.mapped = B_TRUE;
544 544
545 545 softc->fb_size = VGA_MEM_SIZE;
546 546
547 547 error = ddi_regs_map_setup(devi, softc->fb_regno,
548 548 (caddr_t *)&softc->fb.addr,
549 549 mem_offset, softc->fb_size,
550 550 &dev_attr, &softc->fb.handle);
551 551 if (error != DDI_SUCCESS)
552 552 goto fail;
553 553 softc->fb.mapped = B_TRUE;
554 554
555 555 if (ddi_get8(softc->regs.handle,
556 556 softc->regs.addr + VGA_MISC_R) & VGA_MISC_IOA_SEL)
557 557 softc->text_base = (caddr_t)softc->fb.addr + VGA_COLOR_BASE;
558 558 else
559 559 softc->text_base = (caddr_t)softc->fb.addr + VGA_MONO_BASE;
560 560
561 561 if (ddi_prop_lookup_string(DDI_DEV_T_ANY, ddi_root_node(),
562 562 DDI_PROP_DONTPASS, "console", &cons) == DDI_SUCCESS) {
563 563 if (strcmp(cons, "graphics") == 0) {
564 564 happyface_boot = 1;
565 565 vgatext_silent = 1;
566 566 softc->current_base = softc->shadow;
567 567 } else {
568 568 softc->current_base = softc->text_base;
569 569 }
570 570 ddi_prop_free(cons);
571 571 } else {
572 572 softc->current_base = softc->text_base;
573 573 }
574 574
575 575 (void) sprintf(buf, "text-%d", unit);
576 576 error = ddi_create_minor_node(devi, buf, S_IFCHR,
577 577 INST2NODE1(unit), DDI_NT_DISPLAY, NULL);
578 578 if (error != DDI_SUCCESS)
579 579 goto fail;
580 580
581 581 error = ddi_prop_create(makedevice(DDI_MAJOR_T_UNKNOWN, unit),
582 582 devi, DDI_PROP_CANSLEEP, DDI_KERNEL_IOCTL, NULL, 0);
583 583 if (error != DDI_SUCCESS)
584 584 goto fail;
585 585
586 586 vgatext_check_for_console(devi, softc, pci_pcie_bus);
587 587
588 588 /* only do this if not in graphics mode */
589 589 if ((vgatext_silent == 0) && (VGATEXT_IS_CONSOLE(softc))) {
590 590 vgatext_init(softc);
591 591 vgatext_save_colormap(softc);
592 592 }
593 593
594 594 if (agpm != 0) { /* try AGP master attach */
595 595 /* setup mapping for PCI config space access */
596 596 softc->pci_cfg_hdlp = (ddi_acc_handle_t *)
597 597 kmem_zalloc(sizeof (ddi_acc_handle_t), KM_SLEEP);
598 598 error = pci_config_setup(devi, softc->pci_cfg_hdlp);
599 599 if (error != DDI_SUCCESS) {
600 600 cmn_err(CE_WARN, "vgatext_attach: "
601 601 "PCI configuration space setup failed");
602 602 goto fail;
603 603 }
604 604
605 605 (void) agpmaster_attach(softc->devi, &softc->agp_master,
606 606 *softc->pci_cfg_hdlp, INST2NODE2(unit));
607 607 }
608 608
609 609 return (DDI_SUCCESS);
610 610
611 611 fail:
612 612 if (parent_type != NULL)
613 613 ddi_prop_free(parent_type);
614 614 (void) vgatext_detach(devi, DDI_DETACH);
615 615 return (error);
616 616 }
617 617
618 618 static int
619 619 vgatext_detach(dev_info_t *devi, ddi_detach_cmd_t cmd)
620 620 {
621 621 int instance = ddi_get_instance(devi);
622 622 struct vgatext_softc *softc = getsoftc(instance);
623 623
624 624
625 625 switch (cmd) {
626 626 case DDI_DETACH:
627 627 if (softc->agp_master != NULL) { /* agp initiated */
628 628 agpmaster_detach(&softc->agp_master);
629 629 pci_config_teardown(softc->pci_cfg_hdlp);
630 630 }
631 631
632 632 if (softc->fb.mapped)
633 633 ddi_regs_map_free(&softc->fb.handle);
634 634 if (softc->regs.mapped)
635 635 ddi_regs_map_free(&softc->regs.handle);
636 636 mutex_destroy(&(softc->lock));
637 637 ddi_remove_minor_node(devi, NULL);
638 638 (void) ddi_soft_state_free(vgatext_softc_head, instance);
639 639 return (DDI_SUCCESS);
640 640
641 641 case DDI_SUSPEND:
642 642 /*
643 643 * This is a generic VGA file, and therefore, cannot
644 644 * understand how to deal with suspend and resume on
645 645 * a generic interface. So we fail any attempt to
646 646 * suspend. At some point in the future, we might use
647 647 * this as an entrypoint for display drivers and this
648 648 * assumption may change.
649 649 *
650 650 * However, from a platform development perspective,
651 651 * it is important that this driver suspend if a
652 652 * developer is using a serial console and/or working
653 653 * on a framebuffer driver that will support suspend
654 654 * and resume. Therefore, we have this module tunable
655 655 * (purposely using a long name) that will allow for
656 656 * suspend it it is set. Otherwise we fail.
657 657 */
658 658 if (vgatext_force_suspend != 0)
659 659 return (DDI_SUCCESS);
660 660 else
661 661 return (DDI_FAILURE);
662 662
663 663 default:
664 664 cmn_err(CE_WARN, "vgatext_detach: unknown cmd 0x%x\n", cmd);
665 665 return (DDI_FAILURE);
666 666 }
667 667 }
668 668
669 669 /*ARGSUSED*/
670 670 static int
671 671 vgatext_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result)
672 672 {
673 673 dev_t dev;
674 674 int error;
675 675 int instance;
676 676 struct vgatext_softc *softc;
677 677
678 678 error = DDI_SUCCESS;
679 679
680 680 dev = (dev_t)arg;
681 681 instance = DEV2INST(dev);
682 682 softc = getsoftc(instance);
683 683
684 684 switch (infocmd) {
685 685 case DDI_INFO_DEVT2DEVINFO:
686 686 if (softc == NULL || softc->devi == NULL) {
687 687 error = DDI_FAILURE;
688 688 } else {
689 689 *result = (void *) softc->devi;
690 690 error = DDI_SUCCESS;
691 691 }
692 692 break;
693 693 case DDI_INFO_DEVT2INSTANCE:
694 694 *result = (void *)(uintptr_t)instance;
695 695 error = DDI_SUCCESS;
696 696 break;
697 697 default:
698 698 error = DDI_FAILURE;
699 699 break;
700 700 }
701 701 return (error);
702 702 }
703 703
704 704
705 705 /*ARGSUSED*/
706 706 static int
707 707 vgatext_open(dev_t *devp, int flag, int otyp, cred_t *cred)
708 708 {
709 709 struct vgatext_softc *softc = getsoftc(DEV2INST(*devp));
710 710
711 711 if (softc == NULL || otyp == OTYP_BLK)
712 712 return (ENXIO);
713 713
714 714 return (0);
715 715 }
716 716
717 717 /*ARGSUSED*/
718 718 static int
719 719 vgatext_close(dev_t devp, int flag, int otyp, cred_t *cred)
720 720 {
721 721 return (0);
722 722 }
723 723
724 724 static int
725 725 do_gfx_ioctl(int cmd, intptr_t data, int mode, struct vgatext_softc *softc)
726 726 {
727 727 static char kernel_only[] =
728 728 "do_gfx_ioctl: %s is a kernel only ioctl";
729 729 int err;
730 730 int kd_mode;
731 731
732 732 switch (cmd) {
733 733 case KDSETMODE:
734 734 return (vgatext_kdsetmode(softc, (int)data));
735 735
736 736 case KDGETMODE:
737 737 kd_mode = softc->mode;
738 738 if (ddi_copyout(&kd_mode, (void *)data, sizeof (int), mode))
739 739 return (EFAULT);
740 740 break;
741 741
742 742 case VIS_GETIDENTIFIER:
743 743 if (ddi_copyout(&text_ident, (void *)data,
744 744 sizeof (struct vis_identifier), mode))
745 745 return (EFAULT);
746 746 break;
747 747
748 748 case VIS_DEVINIT:
749 749
750 750 if (!(mode & FKIOCTL)) {
751 751 cmn_err(CE_CONT, kernel_only, "VIS_DEVINIT");
752 752 return (ENXIO);
753 753 }
754 754
755 755 err = vgatext_devinit(softc, (struct vis_devinit *)data);
756 756 if (err != 0) {
757 757 cmn_err(CE_WARN,
758 758 "vgatext_ioctl: could not initialize console");
759 759 return (err);
760 760 }
761 761 break;
762 762
763 763 case VIS_CONSCOPY: /* move */
764 764 {
765 765 struct vis_conscopy pma;
766 766
767 767 if (ddi_copyin((void *)data, &pma,
768 768 sizeof (struct vis_conscopy), mode))
769 769 return (EFAULT);
770 770
771 771 vgatext_cons_copy(softc, &pma);
772 772 break;
773 773 }
774 774
775 775 case VIS_CONSDISPLAY: /* display */
776 776 {
777 777 struct vis_consdisplay display_request;
778 778
779 779 if (ddi_copyin((void *)data, &display_request,
780 780 sizeof (display_request), mode))
781 781 return (EFAULT);
782 782
783 783 vgatext_cons_display(softc, &display_request);
784 784 break;
785 785 }
786 786
787 787 case VIS_CONSCURSOR:
788 788 {
789 789 struct vis_conscursor cursor_request;
790 790
791 791 if (ddi_copyin((void *)data, &cursor_request,
792 792 sizeof (cursor_request), mode))
793 793 return (EFAULT);
794 794
795 795 vgatext_cons_cursor(softc, &cursor_request);
796 796
797 797 if (cursor_request.action == VIS_GET_CURSOR &&
798 798 ddi_copyout(&cursor_request, (void *)data,
799 799 sizeof (cursor_request), mode))
800 800 return (EFAULT);
801 801 break;
802 802 }
803 803
804 804 case VIS_GETCMAP:
805 805 case VIS_PUTCMAP:
806 806 case FBIOPUTCMAP:
807 807 case FBIOGETCMAP:
808 808 /*
809 809 * At the moment, text mode is not considered to have
810 810 * a color map.
811 811 */
812 812 return (EINVAL);
813 813
814 814 case FBIOGATTR:
815 815 if (copyout(&vgatext_attr, (void *)data,
816 816 sizeof (struct fbgattr)))
817 817 return (EFAULT);
818 818 break;
819 819
820 820 case FBIOGTYPE:
821 821 if (copyout(&vgatext_attr.fbtype, (void *)data,
822 822 sizeof (struct fbtype)))
823 823 return (EFAULT);
824 824 break;
825 825
826 826 default:
827 827 return (ENXIO);
828 828 }
829 829 return (0);
830 830 }
831 831
832 832
833 833 /*ARGSUSED*/
834 834 static int
835 835 vgatext_ioctl(
836 836 dev_t dev,
837 837 int cmd,
838 838 intptr_t data,
839 839 int mode,
840 840 cred_t *cred,
841 841 int *rval)
842 842 {
843 843 struct vgatext_softc *softc = getsoftc(DEV2INST(dev));
844 844 int err;
845 845
846 846 switch (DEV2MINOR(dev)) {
847 847 case GFX_MINOR:
848 848 mutex_enter(&(softc->lock));
849 849 err = do_gfx_ioctl(cmd, data, mode, softc);
850 850 mutex_exit(&(softc->lock));
851 851 break;
852 852
853 853 case AGPMASTER_MINOR:
854 854 err = agpmaster_ioctl(dev, cmd, data, mode, cred, rval,
855 855 softc->agp_master);
856 856 break;
857 857
858 858 default:
859 859 /* not a valid minor node */
860 860 return (EBADF);
861 861 }
862 862 return (err);
863 863 }
864 864
865 865 static void
866 866 vgatext_save_text(struct vgatext_softc *softc)
867 867 {
868 868 unsigned i;
869 869
870 870 for (i = 0; i < sizeof (softc->shadow); i++)
871 871 softc->shadow[i] = softc->current_base[i];
872 872 }
873 873
874 874 static void
875 875 vgatext_progressbar_stop()
876 876 {
877 877 extern void progressbar_stop(void);
878 878
879 879 if (vgatext_silent == 1) {
880 880 vgatext_silent = 0;
881 881 progressbar_stop();
882 882 }
883 883 }
884 884
885 885 static void
886 886 vgatext_kdsettext(struct vgatext_softc *softc)
887 887 {
888 888 int i;
889 889
890 890 vgatext_init(softc);
891 891 for (i = 0; i < sizeof (softc->shadow); i++) {
892 892 softc->text_base[i] = softc->shadow[i];
893 893 }
894 894 softc->current_base = softc->text_base;
895 895 if (softc->cursor.visible) {
896 896 vgatext_set_cursor(softc,
897 897 softc->cursor.row, softc->cursor.col);
898 898 }
899 899 vgatext_restore_colormap(softc);
900 900 }
901 901
902 902 static void
903 903 vgatext_kdsetgraphics(struct vgatext_softc *softc)
904 904 {
905 905 vgatext_progressbar_stop();
906 906 vgatext_save_text(softc);
907 907 softc->current_base = softc->shadow;
908 908 #if defined(USE_BORDERS)
909 909 vgatext_init_graphics(softc);
910 910 #endif
911 911 }
912 912
913 913 static int
914 914 vgatext_kdsetmode(struct vgatext_softc *softc, int mode)
915 915 {
916 916 if ((mode == softc->mode) || (!VGATEXT_IS_CONSOLE(softc)))
917 917 return (0);
918 918
919 919 switch (mode) {
920 920 case KD_TEXT:
921 921 vgatext_kdsettext(softc);
922 922 break;
923 923
924 924 case KD_GRAPHICS:
925 925 vgatext_kdsetgraphics(softc);
926 926 break;
927 927
928 928 case KD_RESETTEXT:
929 929 /*
930 930 * In order to avoid racing with a starting X server,
931 931 * this needs to be a test and set that is performed in
932 932 * a single (softc->lock protected) ioctl into this driver.
933 933 */
934 934 if (softc->mode == KD_TEXT && vgatext_silent == 1) {
935 935 vgatext_progressbar_stop();
936 936 vgatext_kdsettext(softc);
937 937 }
938 938 break;
939 939
940 940 default:
941 941 return (EINVAL);
942 942 }
943 943 softc->mode = mode;
944 944 return (0);
945 945 }
946 946
947 947 /*ARGSUSED*/
948 948 static int
949 949 vgatext_devmap(dev_t dev, devmap_cookie_t dhp, offset_t off, size_t len,
950 950 size_t *maplen, uint_t model)
951 951 {
952 952 struct vgatext_softc *softc;
953 953 int err;
954 954 size_t length;
955 955
956 956
957 957 softc = getsoftc(DEV2INST(dev));
958 958 if (softc == NULL) {
959 959 cmn_err(CE_WARN, "vgatext: Can't find softstate");
960 960 return (-1);
961 961 }
962 962
963 963 if (!(off >= VGA_MMAP_FB_BASE &&
964 964 off < VGA_MMAP_FB_BASE + softc->fb_size)) {
965 965 cmn_err(CE_WARN, "vgatext: Can't map offset 0x%llx", off);
966 966 return (-1);
967 967 }
968 968
969 969 if (off + len > VGA_MMAP_FB_BASE + softc->fb_size)
970 970 length = VGA_MMAP_FB_BASE + softc->fb_size - off;
971 971 else
972 972 length = len;
973 973
974 974 if ((err = devmap_devmem_setup(dhp, softc->devi, NULL, softc->fb_regno,
975 975 off - VGA_MMAP_FB_BASE,
976 976 length, PROT_ALL, 0, &dev_attr)) < 0) {
977 977 return (err);
978 978 }
979 979
980 980
981 981 *maplen = length;
982 982 return (0);
983 983 }
984 984
985 985
986 986 static int
987 987 vgatext_devinit(struct vgatext_softc *softc, struct vis_devinit *data)
988 988 {
989 989 /* initialize console instance */
990 990 data->version = VIS_CONS_REV;
991 991 data->width = TEXT_COLS;
992 992 data->height = TEXT_ROWS;
993 993 data->linebytes = TEXT_COLS;
994 994 data->depth = 4;
995 995 data->mode = VIS_TEXT;
996 996 data->polledio = &softc->polledio;
997 997
998 998 return (0);
999 999 }
1000 1000
1001 1001 /*
1002 1002 * display a string on the screen at (row, col)
1003 1003 * assume it has been cropped to fit.
1004 1004 */
1005 1005
1006 1006 static void
1007 1007 vgatext_cons_display(struct vgatext_softc *softc, struct vis_consdisplay *da)
1008 1008 {
1009 1009 unsigned char *string;
1010 1010 int i;
1011 1011 unsigned char attr;
1012 1012 struct cgatext {
1013 1013 unsigned char ch;
1014 1014 unsigned char attr;
1015 1015 };
1016 1016 struct cgatext *addr;
1017 1017
1018 1018 /*
1019 1019 * Sanity checks. This is a last-ditch effort to avoid damage
1020 1020 * from brokenness or maliciousness above.
1021 1021 */
1022 1022 if (da->row < 0 || da->row >= TEXT_ROWS ||
1023 1023 da->col < 0 || da->col >= TEXT_COLS ||
1024 1024 da->col + da->width > TEXT_COLS)
1025 1025 return;
1026 1026
1027 1027 /*
1028 1028 * To be fully general, we should copyin the data. This is not
1029 1029 * really relevant for this text-only driver, but a graphical driver
1030 1030 * should support these ioctls from userland to enable simple
1031 1031 * system startup graphics.
1032 1032 */
1033 1033 attr = (solaris_color_to_pc_color[da->bg_color & 0xf] << 4)
1034 1034 | solaris_color_to_pc_color[da->fg_color & 0xf];
1035 1035 string = da->data;
1036 1036 addr = (struct cgatext *)softc->current_base
1037 1037 + (da->row * TEXT_COLS + da->col);
1038 1038 for (i = 0; i < da->width; i++) {
1039 1039 addr->ch = string[i];
1040 1040 addr->attr = attr;
1041 1041 addr++;
1042 1042 }
1043 1043 }
1044 1044
1045 1045 static void
1046 1046 vgatext_polled_display(
1047 1047 struct vis_polledio_arg *arg,
1048 1048 struct vis_consdisplay *da)
1049 1049 {
1050 1050 vgatext_cons_display((struct vgatext_softc *)arg, da);
1051 1051 }
1052 1052
1053 1053 /*
1054 1054 * screen-to-screen copy
1055 1055 */
1056 1056
1057 1057 static void
1058 1058 vgatext_cons_copy(struct vgatext_softc *softc, struct vis_conscopy *ma)
1059 1059 {
1060 1060 unsigned short *from;
1061 1061 unsigned short *to;
1062 1062 int cnt;
1063 1063 screen_size_t chars_per_row;
1064 1064 unsigned short *to_row_start;
1065 1065 unsigned short *from_row_start;
1066 1066 screen_size_t rows_to_move;
1067 1067 unsigned short *base;
1068 1068
1069 1069 /*
1070 1070 * Sanity checks. Note that this is a last-ditch effort to avoid
1071 1071 * damage caused by broken-ness or maliciousness above.
1072 1072 */
1073 1073 if (ma->s_col < 0 || ma->s_col >= TEXT_COLS ||
1074 1074 ma->s_row < 0 || ma->s_row >= TEXT_ROWS ||
1075 1075 ma->e_col < 0 || ma->e_col >= TEXT_COLS ||
1076 1076 ma->e_row < 0 || ma->e_row >= TEXT_ROWS ||
1077 1077 ma->t_col < 0 || ma->t_col >= TEXT_COLS ||
1078 1078 ma->t_row < 0 || ma->t_row >= TEXT_ROWS ||
1079 1079 ma->s_col > ma->e_col ||
1080 1080 ma->s_row > ma->e_row)
1081 1081 return;
1082 1082
1083 1083 /*
1084 1084 * Remember we're going to copy shorts because each
1085 1085 * character/attribute pair is 16 bits.
1086 1086 */
1087 1087 chars_per_row = ma->e_col - ma->s_col + 1;
1088 1088 rows_to_move = ma->e_row - ma->s_row + 1;
1089 1089
1090 1090 /* More sanity checks. */
1091 1091 if (ma->t_row + rows_to_move > TEXT_ROWS ||
1092 1092 ma->t_col + chars_per_row > TEXT_COLS)
1093 1093 return;
1094 1094
1095 1095 base = (unsigned short *)softc->current_base;
1096 1096
1097 1097 to_row_start = base + ((ma->t_row * TEXT_COLS) + ma->t_col);
1098 1098 from_row_start = base + ((ma->s_row * TEXT_COLS) + ma->s_col);
1099 1099
1100 1100 if (to_row_start < from_row_start) {
1101 1101 while (rows_to_move-- > 0) {
1102 1102 to = to_row_start;
1103 1103 from = from_row_start;
1104 1104 to_row_start += TEXT_COLS;
1105 1105 from_row_start += TEXT_COLS;
1106 1106 for (cnt = chars_per_row; cnt-- > 0; )
1107 1107 *to++ = *from++;
1108 1108 }
1109 1109 } else {
1110 1110 /*
1111 1111 * Offset to the end of the region and copy backwards.
1112 1112 */
1113 1113 cnt = rows_to_move * TEXT_COLS + chars_per_row;
1114 1114 to_row_start += cnt;
1115 1115 from_row_start += cnt;
1116 1116
1117 1117 while (rows_to_move-- > 0) {
1118 1118 to_row_start -= TEXT_COLS;
1119 1119 from_row_start -= TEXT_COLS;
1120 1120 to = to_row_start;
1121 1121 from = from_row_start;
1122 1122 for (cnt = chars_per_row; cnt-- > 0; )
1123 1123 *--to = *--from;
1124 1124 }
1125 1125 }
1126 1126 }
1127 1127
1128 1128 static void
1129 1129 vgatext_polled_copy(
1130 1130 struct vis_polledio_arg *arg,
1131 1131 struct vis_conscopy *ca)
1132 1132 {
1133 1133 vgatext_cons_copy((struct vgatext_softc *)arg, ca);
1134 1134 }
1135 1135
1136 1136
1137 1137 static void
1138 1138 vgatext_cons_cursor(struct vgatext_softc *softc, struct vis_conscursor *ca)
1139 1139 {
1140 1140 if (vgatext_silent)
1141 1141 return;
1142 1142
1143 1143 switch (ca->action) {
1144 1144 case VIS_HIDE_CURSOR:
1145 1145 softc->cursor.visible = B_FALSE;
1146 1146 if (softc->current_base == softc->text_base)
1147 1147 vgatext_hide_cursor(softc);
1148 1148 break;
1149 1149 case VIS_DISPLAY_CURSOR:
1150 1150 /*
1151 1151 * Sanity check. This is a last-ditch effort to avoid
1152 1152 * damage from brokenness or maliciousness above.
1153 1153 */
1154 1154 if (ca->col < 0 || ca->col >= TEXT_COLS ||
1155 1155 ca->row < 0 || ca->row >= TEXT_ROWS)
1156 1156 return;
1157 1157
1158 1158 softc->cursor.visible = B_TRUE;
1159 1159 softc->cursor.col = ca->col;
1160 1160 softc->cursor.row = ca->row;
1161 1161 if (softc->current_base == softc->text_base)
1162 1162 vgatext_set_cursor(softc, ca->row, ca->col);
1163 1163 break;
1164 1164 case VIS_GET_CURSOR:
1165 1165 if (softc->current_base == softc->text_base) {
1166 1166 vgatext_get_cursor(softc, &ca->row, &ca->col);
1167 1167 }
1168 1168 break;
1169 1169 }
1170 1170 }
1171 1171
1172 1172 static void
1173 1173 vgatext_polled_cursor(
1174 1174 struct vis_polledio_arg *arg,
1175 1175 struct vis_conscursor *ca)
1176 1176 {
1177 1177 vgatext_cons_cursor((struct vgatext_softc *)arg, ca);
1178 1178 }
1179 1179
1180 1180
1181 1181
1182 1182 /*ARGSUSED*/
1183 1183 static void
1184 1184 vgatext_hide_cursor(struct vgatext_softc *softc)
1185 1185 {
1186 1186 /* Nothing at present */
1187 1187 }
1188 1188
1189 1189 static void
1190 1190 vgatext_set_cursor(struct vgatext_softc *softc, int row, int col)
1191 1191 {
1192 1192 short addr;
1193 1193
1194 1194 if (vgatext_silent)
1195 1195 return;
1196 1196
1197 1197 addr = row * TEXT_COLS + col;
1198 1198
1199 1199 vga_set_crtc(&softc->regs, VGA_CRTC_CLAH, addr >> 8);
1200 1200 vga_set_crtc(&softc->regs, VGA_CRTC_CLAL, addr & 0xff);
1201 1201 }
1202 1202
1203 1203 static int vga_row, vga_col;
1204 1204
1205 1205 static void
1206 1206 vgatext_get_cursor(struct vgatext_softc *softc,
1207 1207 screen_pos_t *row, screen_pos_t *col)
1208 1208 {
1209 1209 short addr;
1210 1210
1211 1211 addr = (vga_get_crtc(&softc->regs, VGA_CRTC_CLAH) << 8) +
1212 1212 vga_get_crtc(&softc->regs, VGA_CRTC_CLAL);
1213 1213
1214 1214 vga_row = *row = addr / TEXT_COLS;
1215 1215 vga_col = *col = addr % TEXT_COLS;
1216 1216 }
1217 1217
1218 1218 /*
1219 1219 * This code is experimental. It's only enabled if console is
1220 1220 * set to graphics, a preliminary implementation of happyface boot.
1221 1221 */
1222 1222 static void
1223 1223 vgatext_set_text(struct vgatext_softc *softc)
1224 1224 {
1225 1225 int i;
1226 1226
1227 1227 if (happyface_boot == 0)
1228 1228 return;
1229 1229
1230 1230 /* we are in graphics mode, set to text 80X25 mode */
1231 1231
1232 1232 /* set misc registers */
1233 1233 vga_set_reg(&softc->regs, VGA_MISC_W, VGA_MISC_TEXT);
1234 1234
1235 1235 /* set sequencer registers */
1236 1236 vga_set_seq(&softc->regs, VGA_SEQ_RST_SYN,
1237 1237 (vga_get_seq(&softc->regs, VGA_SEQ_RST_SYN) &
1238 1238 ~VGA_SEQ_RST_SYN_NO_SYNC_RESET));
1239 1239 for (i = 1; i < NUM_SEQ_REG; i++) {
1240 1240 vga_set_seq(&softc->regs, i, VGA_SEQ_TEXT[i]);
1241 1241 }
1242 1242 vga_set_seq(&softc->regs, VGA_SEQ_RST_SYN,
1243 1243 (vga_get_seq(&softc->regs, VGA_SEQ_RST_SYN) |
1244 1244 VGA_SEQ_RST_SYN_NO_ASYNC_RESET |
1245 1245 VGA_SEQ_RST_SYN_NO_SYNC_RESET));
1246 1246
1247 1247 /* set crt controller registers */
1248 1248 vga_set_crtc(&softc->regs, VGA_CRTC_VRE,
1249 1249 (vga_get_crtc(&softc->regs, VGA_CRTC_VRE) &
1250 1250 ~VGA_CRTC_VRE_LOCK));
1251 1251 for (i = 0; i < NUM_CRTC_REG; i++) {
1252 1252 vga_set_crtc(&softc->regs, i, VGA_CRTC_TEXT[i]);
1253 1253 }
1254 1254
1255 1255 /* set graphics controller registers */
1256 1256 for (i = 0; i < NUM_GRC_REG; i++) {
1257 1257 vga_set_grc(&softc->regs, i, VGA_GRC_TEXT[i]);
1258 1258 }
1259 1259
1260 1260 /* set attribute registers */
1261 1261 for (i = 0; i < NUM_ATR_REG; i++) {
1262 1262 vga_set_atr(&softc->regs, i, VGA_ATR_TEXT[i]);
1263 1263 }
1264 1264
1265 1265 /* set palette */
1266 1266 for (i = 0; i < VGA_TEXT_CMAP_ENTRIES; i++) {
1267 1267 vga_put_cmap(&softc->regs, i, VGA_TEXT_PALETTES[i][0] << 2,
1268 1268 VGA_TEXT_PALETTES[i][1] << 2,
1269 1269 VGA_TEXT_PALETTES[i][2] << 2);
1270 1270 }
1271 1271 for (i = VGA_TEXT_CMAP_ENTRIES; i < VGA8_CMAP_ENTRIES; i++) {
1272 1272 vga_put_cmap(&softc->regs, i, 0, 0, 0);
1273 1273 }
1274 1274
1275 1275 vgatext_save_colormap(softc);
1276 1276 }
1277 1277
1278 1278 static void
1279 1279 vgatext_init(struct vgatext_softc *softc)
1280 1280 {
1281 1281 unsigned char atr_mode;
1282 1282
1283 1283 atr_mode = vga_get_atr(&softc->regs, VGA_ATR_MODE);
1284 1284 if (atr_mode & VGA_ATR_MODE_GRAPH)
1285 1285 vgatext_set_text(softc);
1286 1286 atr_mode = vga_get_atr(&softc->regs, VGA_ATR_MODE);
1287 1287 atr_mode &= ~VGA_ATR_MODE_BLINK;
1288 1288 atr_mode &= ~VGA_ATR_MODE_9WIDE;
1289 1289 vga_set_atr(&softc->regs, VGA_ATR_MODE, atr_mode);
1290 1290 #if defined(USE_BORDERS)
1291 1291 vga_set_atr(&softc->regs, VGA_ATR_BDR_CLR,
1292 1292 vga_get_atr(&softc->regs, VGA_BRIGHT_WHITE));
1293 1293 #else
1294 1294 vga_set_atr(&softc->regs, VGA_ATR_BDR_CLR,
1295 1295 vga_get_atr(&softc->regs, VGA_BLACK));
1296 1296 #endif
1297 1297 vgatext_setfont(softc); /* need selectable font? */
1298 1298 }
1299 1299
1300 1300 #if defined(USE_BORDERS)
1301 1301 static void
1302 1302 vgatext_init_graphics(struct vgatext_softc *softc)
1303 1303 {
1304 1304 vga_set_atr(&softc->regs, VGA_ATR_BDR_CLR,
1305 1305 vga_get_atr(&softc->regs, VGA_BLACK));
1306 1306 }
1307 1307 #endif
1308 1308
1309 1309 static char vga_fontslot = 0;
1310 1310
1311 1311 static void
1312 1312 vgatext_setfont(struct vgatext_softc *softc)
1313 1313 {
1314 1314 static uchar_t fsreg[8] = {0x0, 0x30, 0x5, 0x35, 0xa, 0x3a, 0xf, 0x3f};
1315 1315
1316 1316 extern bitmap_data_t font_data_8x16;
1317 1317 uchar_t *from;
1318 1318 uchar_t volatile *to;
1319 1319 int i, j, s;
1320 1320 int bpc, f_offset;
1321 1321
1322 1322 /* Sync-reset the sequencer registers */
1323 1323 vga_set_seq(&softc->regs, 0x00, 0x01);
1324 1324 /*
1325 1325 * enable write to plane2, since fonts
1326 1326 * could only be loaded into plane2
1327 1327 */
1328 1328 vga_set_seq(&softc->regs, 0x02, 0x04);
1329 1329 /*
1330 1330 * sequentially access data in the bit map being
1331 1331 * selected by MapMask register (index 0x02)
1332 1332 */
1333 1333 vga_set_seq(&softc->regs, 0x04, 0x07);
1334 1334 /* Sync-reset ended, and allow the sequencer to operate */
1335 1335 vga_set_seq(&softc->regs, 0x00, 0x03);
1336 1336
1337 1337 /*
1338 1338 * select plane 2 on Read Mode 0
1339 1339 */
1340 1340 vga_set_grc(&softc->regs, 0x04, 0x02);
1341 1341 /*
1342 1342 * system addresses sequentially access data, follow
1343 1343 * Memory Mode register bit 2 in the sequencer
1344 1344 */
1345 1345 vga_set_grc(&softc->regs, 0x05, 0x00);
1346 1346 /*
1347 1347 * set range of host memory addresses decoded by VGA
1348 1348 * hardware -- A0000h-BFFFFh (128K region)
1349 1349 */
1350 1350 vga_set_grc(&softc->regs, 0x06, 0x00);
1351 1351
1352 1352 /*
1353 1353 * This assumes 8x16 characters, which yield the traditional 80x25
1354 1354 * screen. It really should support other character heights.
1355 1355 */
1356 1356 bpc = 16;
1357 1357 s = vga_fontslot;
1358 1358 f_offset = s * 8 * 1024;
1359 1359 for (i = 0; i < 256; i++) {
1360 1360 from = font_data_8x16.encoding[i];
1361 1361 to = (unsigned char *)softc->fb.addr + f_offset + i * 0x20;
1362 1362 for (j = 0; j < bpc; j++)
1363 1363 *to++ = *from++;
1364 1364 }
1365 1365
1366 1366 /* Sync-reset the sequencer registers */
1367 1367 vga_set_seq(&softc->regs, 0x00, 0x01);
1368 1368 /* enable write to plane 0 and 1 */
1369 1369 vga_set_seq(&softc->regs, 0x02, 0x03);
1370 1370 /*
1371 1371 * enable character map selection
1372 1372 * and odd/even addressing
1373 1373 */
1374 1374 vga_set_seq(&softc->regs, 0x04, 0x03);
1375 1375 /*
1376 1376 * select font map
1377 1377 */
1378 1378 vga_set_seq(&softc->regs, 0x03, fsreg[s]);
1379 1379 /* Sync-reset ended, and allow the sequencer to operate */
1380 1380 vga_set_seq(&softc->regs, 0x00, 0x03);
1381 1381
1382 1382 /* restore graphic registers */
1383 1383
1384 1384 /* select plane 0 */
1385 1385 vga_set_grc(&softc->regs, 0x04, 0x00);
1386 1386 /* enable odd/even addressing mode */
1387 1387 vga_set_grc(&softc->regs, 0x05, 0x10);
1388 1388 /*
1389 1389 * range of host memory addresses decoded by VGA
1390 1390 * hardware -- B8000h-BFFFFh (32K region)
1391 1391 */
1392 1392 vga_set_grc(&softc->regs, 0x06, 0x0e);
1393 1393 /* enable all color plane */
1394 1394 vga_set_atr(&softc->regs, 0x12, 0x0f);
1395 1395
1396 1396 }
1397 1397
1398 1398 static void
1399 1399 vgatext_save_colormap(struct vgatext_softc *softc)
1400 1400 {
1401 1401 int i;
1402 1402
1403 1403 for (i = 0; i < VGA_ATR_NUM_PLT; i++) {
1404 1404 softc->attrib_palette[i] = vga_get_atr(&softc->regs, i);
1405 1405 }
1406 1406 for (i = 0; i < VGA8_CMAP_ENTRIES; i++) {
1407 1407 vga_get_cmap(&softc->regs, i,
1408 1408 &softc->colormap[i].red,
1409 1409 &softc->colormap[i].green,
1410 1410 &softc->colormap[i].blue);
1411 1411 }
1412 1412 }
1413 1413
1414 1414 static void
1415 1415 vgatext_restore_colormap(struct vgatext_softc *softc)
1416 1416 {
1417 1417 int i;
1418 1418
1419 1419 for (i = 0; i < VGA_ATR_NUM_PLT; i++) {
1420 1420 vga_set_atr(&softc->regs, i, softc->attrib_palette[i]);
1421 1421 }
1422 1422 for (i = 0; i < VGA8_CMAP_ENTRIES; i++) {
1423 1423 vga_put_cmap(&softc->regs, i,
1424 1424 softc->colormap[i].red,
1425 1425 softc->colormap[i].green,
1426 1426 softc->colormap[i].blue);
1427 1427 }
1428 1428 }
1429 1429
1430 1430 /*
1431 1431 * search the entries of the "reg" property for one which has the desired
1432 1432 * combination of phys_hi bits and contains the desired address.
1433 1433 *
1434 1434 * This version searches a PCI-style "reg" property. It was prompted by
1435 1435 * issues surrounding the presence or absence of an entry for the ROM:
1436 1436 * (a) a transition problem with PowerPC Virtual Open Firmware
1437 1437 * (b) uncertainty as to whether an entry will be included on a device
1438 1438 * with ROM support (and so an "active" ROM base address register),
1439 1439 * but no ROM actually installed.
1440 1440 *
1441 1441 * See the note below on vgatext_get_isa_reg_index for the reasons for
1442 1442 * returning the offset.
1443 1443 *
1444 1444 * Note that this routine may not be fully general; it is intended for the
1445 1445 * specific purpose of finding a couple of particular VGA reg entries and
1446 1446 * may not be suitable for all reg-searching purposes.
1447 1447 */
1448 1448 static int
1449 1449 vgatext_get_pci_reg_index(
1450 1450 dev_info_t *const devi,
1451 1451 unsigned long himask,
1452 1452 unsigned long hival,
1453 1453 unsigned long addr,
1454 1454 off_t *offset)
1455 1455 {
1456 1456
1457 1457 int length, index;
1458 1458 pci_regspec_t *reg;
1459 1459
1460 1460 if (ddi_getlongprop(DDI_DEV_T_ANY, devi, DDI_PROP_DONTPASS,
1461 1461 "reg", (caddr_t)®, &length) != DDI_PROP_SUCCESS) {
1462 1462 return (-1);
1463 1463 }
1464 1464
1465 1465 for (index = 0; index < length / sizeof (pci_regspec_t); index++) {
1466 1466 if ((reg[index].pci_phys_hi & himask) != hival)
1467 1467 continue;
1468 1468 if (reg[index].pci_size_hi != 0)
1469 1469 continue;
1470 1470 if (reg[index].pci_phys_mid != 0)
1471 1471 continue;
1472 1472 if (reg[index].pci_phys_low > addr)
1473 1473 continue;
1474 1474 if (reg[index].pci_phys_low + reg[index].pci_size_low <= addr)
1475 1475 continue;
1476 1476
1477 1477 *offset = addr - reg[index].pci_phys_low;
1478 1478 kmem_free(reg, (size_t)length);
1479 1479 return (index);
1480 1480 }
1481 1481 kmem_free(reg, (size_t)length);
1482 1482
1483 1483 return (-1);
1484 1484 }
1485 1485
1486 1486 /*
1487 1487 * search the entries of the "reg" property for one which has the desired
1488 1488 * combination of phys_hi bits and contains the desired address.
1489 1489 *
1490 1490 * This version searches a ISA-style "reg" property. It was prompted by
1491 1491 * issues surrounding 8514/A support. By IEEE 1275 compatibility conventions,
1492 1492 * 8514/A registers should have been added after all standard VGA registers.
1493 1493 * Unfortunately, the Solaris/Intel device configuration framework
1494 1494 * (a) lists the 8514/A registers before the video memory, and then
1495 1495 * (b) also sorts the entries so that I/O entries come before memory
1496 1496 * entries.
1497 1497 *
1498 1498 * It returns the "reg" index and offset into that register set.
1499 1499 * The offset is needed because there exist (broken?) BIOSes that
1500 1500 * report larger ranges enclosing the standard ranges. One reports
1501 1501 * 0x3bf for 0x21 instead of 0x3c0 for 0x20, for instance. Using the
1502 1502 * offset adjusts for this difference in the base of the register set.
1503 1503 *
1504 1504 * Note that this routine may not be fully general; it is intended for the
1505 1505 * specific purpose of finding a couple of particular VGA reg entries and
1506 1506 * may not be suitable for all reg-searching purposes.
1507 1507 */
1508 1508 static int
1509 1509 vgatext_get_isa_reg_index(
1510 1510 dev_info_t *const devi,
1511 1511 unsigned long hival,
1512 1512 unsigned long addr,
1513 1513 off_t *offset)
1514 1514 {
1515 1515
1516 1516 int length, index;
1517 1517 struct regspec *reg;
1518 1518
1519 1519 if (ddi_getlongprop(DDI_DEV_T_ANY, devi, DDI_PROP_DONTPASS,
1520 1520 "reg", (caddr_t)®, &length) != DDI_PROP_SUCCESS) {
1521 1521 return (-1);
1522 1522 }
1523 1523
1524 1524 for (index = 0; index < length / sizeof (struct regspec); index++) {
1525 1525 if (reg[index].regspec_bustype != hival)
1526 1526 continue;
1527 1527 if (reg[index].regspec_addr > addr)
1528 1528 continue;
1529 1529 if (reg[index].regspec_addr + reg[index].regspec_size <= addr)
1530 1530 continue;
1531 1531
1532 1532 *offset = addr - reg[index].regspec_addr;
1533 1533 kmem_free(reg, (size_t)length);
1534 1534 return (index);
1535 1535 }
1536 1536 kmem_free(reg, (size_t)length);
1537 1537
1538 1538 return (-1);
1539 1539 }
↓ open down ↓ |
1312 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX