FreeBSD/Linux Kernel Cross Reference
sys/chips/pm_misc.c
1 /*
2 * Mach Operating System
3 * Copyright (c) 1991,1990,1989 Carnegie Mellon University
4 * All Rights Reserved.
5 *
6 * Permission to use, copy, modify and distribute this software and its
7 * documentation is hereby granted, provided that both the copyright
8 * notice and this permission notice appear in all copies of the
9 * software, derivative works or modified versions, and any portions
10 * thereof, and that both notices appear in supporting documentation.
11 *
12 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
13 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
14 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
15 *
16 * Carnegie Mellon requests users of this software to return to
17 *
18 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
19 * School of Computer Science
20 * Carnegie Mellon University
21 * Pittsburgh PA 15213-3890
22 *
23 * any improvements or extensions that they make and grant Carnegie Mellon
24 * the rights to redistribute these changes.
25 */
26 /*
27 * HISTORY
28 * $Log: pm_misc.c,v $
29 * Revision 2.13 93/03/09 10:52:16 danner
30 * Optimized for 64bit machines the inner copy loops.
31 * [93/03/05 af]
32 *
33 * Revision 2.12 93/02/05 08:05:56 danner
34 * Made work on Flamingo. Fixed NPM defines.
35 * Protos.
36 * [93/02/04 01:38:02 af]
37 *
38 * Revision 2.11 92/05/22 15:48:13 jfriedl
39 * Avoid spls and use SCREEN_BEING_UPDATED instead.
40 * [92/05/21 18:55:06 af]
41 *
42 * Cleaned out an empty function.
43 * [92/05/13 20:42:12 af]
44 *
45 * Revision 2.10 92/04/01 15:14:26 rpd
46 * Put spl protection around the user (setstatus) playing
47 * with the cursor and vdac. Never was reported as an
48 * observed problem, but...
49 * [92/03/11 16:02:59 af]
50 *
51 * Revision 2.9 92/03/02 18:33:04 rpd
52 * When first positioning the cursor use the max_row info.
53 * [92/03/02 01:54:40 af]
54 *
55 * Revision 2.8 91/08/24 11:52:44 af
56 * Now we share this with yet another driver. Mods to cope with
57 * arbitrary framebuffer geometries. Did not put pixel sizes in,
58 * maybe should someday. Code seems more understandable, too.
59 * Threw in a couple optims, did not try to avoid copying non-visible
60 * memory when scrolling, will do next time around.
61 * [91/08/02 02:14:16 af]
62 *
63 * Revision 2.7 91/06/25 20:54:36 rpd
64 * Tweaks to make gcc happy.
65 * [91/06/25 rpd]
66 *
67 * Revision 2.6 91/06/20 11:26:39 rvb
68 * X support
69 * [91/06/18 21:36:46 rvb]
70 *
71 * mips->DECSTATION; vax->VAXSTATION
72 * [91/06/12 14:02:05 rvb]
73 *
74 * File moved here from mips/PMAX since it tries to be generic;
75 * it is used on the PMAX and the Vax3100.
76 * [91/06/04 rvb]
77 *
78 * Revision 2.5 91/05/14 17:25:37 mrt
79 * Correcting copyright
80 *
81 * Revision 2.4 91/02/05 17:43:19 mrt
82 * Added author notices
83 * [91/02/04 11:16:01 mrt]
84 *
85 * Changed to use new Mach copyright
86 * [91/02/02 12:14:55 mrt]
87 *
88 * Revision 2.3 90/12/05 23:33:18 af
89 * Cleaned up and tested.
90 * [90/12/03 23:31:05 af]
91 *
92 * Revision 2.1.1.1 90/11/01 03:45:19 af
93 * Created.
94 * [90/09/03 af]
95 */
96 /*
97 * File: pm_misc.c
98 * Author: Alessandro Forin, Carnegie Mellon University
99 * Date: 9/90
100 *
101 * Driver for the VFB01/02 Mono/Color framebuffer (pmax)
102 * Hardware-independent operations, mostly shared with
103 * the CFB driver (see each individual function header),
104 * and possibly others.
105 */
106
107
108 #include <platforms.h>
109
110 #include <fb.h>
111
112 #if defined(DECSTATION) || defined(FLAMINGO)
113 #include <cfb.h>
114 #include <mfb.h>
115 #include <xcfb.h>
116 #include <sfb.h>
117 #define NPM (NFB+NCFB+NMFB+NXCFB+NSFB)
118 #endif /*DECSTATION*/
119
120 #ifdef VAXSTATION
121 #define NPM (NFB)
122 #endif /*VAXSTATION*/
123
124
125 #if (NPM > 0)
126
127 #include <mach/vm_param.h> /* PAGE_SIZE */
128 #include <device/device_types.h>
129 #include <vm/vm_map.h> /* kernel_pmap */
130
131 #include <chips/screen_defs.h>
132 #include <chips/pm_defs.h>
133
134
135 #ifdef DECSTATION
136 #define machine_btop mips_btop
137 #define MONO_BM (256*1024)
138 #endif /*DECSTATION*/
139
140 #ifdef VAXSTATION
141 #define machine_btop vax_btop
142 /*
143 For now we use the last page of the frame for
144 the user_info structure.
145 */
146 #define MONO_BM (256*1024-PAGE_SIZE)
147 #endif /*VAXSTATION*/
148
149 #ifdef FLAMINGO
150 #define machine_btop alpha_btop
151 #define MONO_BM (256*1024)
152 #define LOG2_SIZEOF_LONG 3 /* 64bit archies */
153 #endif /* FLAMINGO */
154
155 #ifndef LOG2_SIZEOF_LONG
156 #define LOG2_SIZEOF_LONG 2 /* 32bit archies */
157 #endif
158
159
160 /* Hardware state */
161 pm_softc_t pm_softc_data[NPM];
162
163 pm_softc_t*
164 pm_alloc(
165 int unit,
166 char *cur,
167 unsigned char *fb,
168 unsigned char *pl)
169 {
170 pm_softc_t *pm = &pm_softc_data[unit];
171
172 pm->cursor_registers = cur;
173 pm->framebuffer = fb;
174 pm->plane_mask = pl;
175 pm->vdac_registers = 0; /* later, if ever */
176
177 screen_attach(unit, (char *) pm);
178
179 return pm;
180 }
181
182
183 /*
184 * Routine to paint a char on a simple framebuffer.
185 * This is common to the pm, fb and cfb drivers.
186 */
187 pm_char_paint(
188 screen_softc_t sc,
189 int c,
190 int row,
191 int col)
192 {
193 register int incr;
194 int line_size;
195 register unsigned char *font, *bmap;
196 pm_softc_t *pm = (pm_softc_t*)sc->hw_state;
197
198 /*
199 * Here are the magic numbers that drive the loops below:
200 * incr bytes between scanlines of the glyph
201 * line_size bytes in a row, using the system font
202 *
203 * This code has been optimized to avoid multiplications,
204 * and is therefore much less obvious than it could be.
205 */
206 if (sc->flags & MONO_SCREEN) {
207 /*
208 * B&W screen: 1 bit/pixel
209 * incr --> 1 * BytesPerLine, with possible stride
210 */
211 incr = sc->frame_scanline_width >> 3;
212 } else {
213 /*
214 * Color screen: 8 bits/pixel
215 * incr --> 8 * BytesPerLine, with possible stride
216 */
217 incr = sc->frame_scanline_width;
218 col <<= 3;
219 }
220
221 /* not all compilers are smart about multiply by 15 */
222 #if (KfontHeight==15)
223 # define TIMES_KfontHeight(w) (((w)<<4)-(w))
224 #else
225 # define TIMES_KfontHeight(w) ((w)*KfontHeight)
226 #endif
227 line_size = TIMES_KfontHeight(incr);
228
229 bmap = pm->framebuffer + col + (row * line_size);
230 font = &kfont_7x14[ (int)(c - ' ') * 15];
231 if (sc->flags & MONO_SCREEN) {
232 /*
233 * Unroll simple loops, take note of common cases
234 */
235 if (sc->standout) {
236 # define mv() *bmap = ~*font++; bmap += incr;
237 mv();mv();mv();mv();mv();mv();mv();mv();
238 mv();mv();mv();mv();mv();mv();mv();
239 # undef mv
240 } else if (c == ' ') {
241 # define mv() *bmap = 0; bmap += incr;
242 mv();mv();mv();mv();mv();mv();mv();mv();
243 mv();mv();mv();mv();mv();mv();mv();
244 # undef mv
245 } else {
246 # define mv() *bmap = *font++; bmap += incr;
247 mv();mv();mv();mv();mv();mv();mv();mv();
248 mv();mv();mv();mv();mv();mv();mv();
249 # undef mv
250 }
251 } else {
252 /*
253 * 8 bits per pixel --> paint one byte per each font bit.
254 * In order to spread out the 8 bits of a glyph line over
255 * the 64 bits per scanline use a simple vector multiply,
256 * taking 4 bits at a time to get the two resulting words
257 */
258 static unsigned int spread[16] = {
259 0x00000000, 0x00000001, 0x00000100, 0x00000101,
260 0x00010000, 0x00010001, 0x00010100, 0x00010101,
261 0x01000000, 0x01000001, 0x01000100, 0x01000101,
262 0x01010000, 0x01010001, 0x01010100, 0x01010101,
263 };
264 register int rev_video = sc->standout;
265 register int j;
266 for (j = 0; j < KfontHeight; j++) {
267 register unsigned char c = *font++;
268 if (rev_video) c = ~c;
269 #if (LOG2_SIZEOF_LONG==3)
270 *((long*)bmap) = (long)spread[ c & 0xf ] |
271 ((long)(spread[ (c>>4) & 0xf ]) << 32);
272 #else
273 ((int*)bmap)[0] = spread[ c & 0xf ];
274 ((int*)bmap)[1] = spread[ (c>>4) & 0xf ];
275 #endif
276 bmap += incr;
277 }
278 }
279 }
280
281 /*
282 * Delete the line at the given row.
283 * This is common to the pm, fb and cfb drivers.
284 */
285 pm_remove_line(
286 screen_softc_t sc,
287 short row)
288 {
289 register long *dest, *src;
290 register long *end;
291 register long temp0,temp1,temp2,temp3;
292 register long i, scaninc, blockcnt;
293 long line_size, incr;
294 unsigned char *framebuffer;
295 pm_softc_t *pm = (pm_softc_t*)sc->hw_state;
296 long CharRows, CharCols;
297
298 CharRows = sc->up->max_row;
299 CharCols = sc->up->max_col;
300 framebuffer = pm->framebuffer;
301
302 /* Inner loop works 4 long words at a time (writebuffer deep) */
303 # define BlockSizeShift (2+LOG2_SIZEOF_LONG)
304
305 /* To copy one (MONO) line, we need to iterate this many times */
306 # define Blocks (CharCols>>BlockSizeShift)
307
308 /* Skip this many bytes to get to the next line */
309 # define Slop(w) ((w) - (blockcnt<<BlockSizeShift))
310
311 if (sc->flags & MONO_SCREEN) {
312 blockcnt = Blocks;
313 /* See comments in pm_char_paint() */
314 incr = sc->frame_scanline_width >> 3;
315 } else {
316 blockcnt = Blocks << 3;
317 /* See comments in pm_char_paint() */
318 incr = sc->frame_scanline_width;
319 }
320 line_size = TIMES_KfontHeight(incr);
321
322 scaninc = (Slop(incr)) >> LOG2_SIZEOF_LONG; /* pointers are long* */
323
324 dest = (long *)(framebuffer + row * line_size);
325 src = (long *)((char*)dest + line_size);
326 end = (long *)(framebuffer + CharRows * line_size);
327 while (src < end) {
328 i = 0;
329 do {
330 temp0 = src[0];
331 temp1 = src[1];
332 temp2 = src[2];
333 temp3 = src[3];
334 dest[0] = temp0;
335 dest[1] = temp1;
336 dest[2] = temp2;
337 dest[3] = temp3;
338 dest += 4;
339 src += 4;
340 i++;
341 } while (i < blockcnt);
342 src += scaninc;
343 dest += scaninc;
344 }
345
346 /* Now zero out the last line */
347 bzero(framebuffer + (CharRows - 1) * line_size, line_size);
348
349 ascii_screen_rem_update(sc, row);
350 }
351
352
353 /*
354 * Open a new blank line at the given row.
355 * This is common to the pm, fb and cfb drivers.
356 */
357 pm_insert_line(
358 screen_softc_t sc,
359 short row)
360 {
361 register long *dest, *src;
362 register long *end;
363 register long temp0,temp1,temp2,temp3;
364 register long i, scaninc, blockcnt;
365 long line_size, incr;
366 unsigned char *framebuffer;
367 pm_softc_t *pm = (pm_softc_t*)sc->hw_state;
368 long CharRows, CharCols;
369
370 CharRows = sc->up->max_row;
371 CharCols = sc->up->max_col;
372
373 framebuffer = pm->framebuffer;
374
375 /* See above for comments */
376 if (sc->flags & MONO_SCREEN) {
377 blockcnt = Blocks;
378 /* See comments in pm_char_paint() */
379 incr = sc->frame_scanline_width >> 3;
380 } else {
381 blockcnt = Blocks << 3;
382 /* See comments in pm_char_paint() */
383 incr = sc->frame_scanline_width;
384 }
385 line_size = TIMES_KfontHeight(incr);
386
387 scaninc = Slop(incr) + ((2 * blockcnt) << BlockSizeShift);
388 scaninc >>= LOG2_SIZEOF_LONG; /* pointers are long* */
389 dest = (long *)(framebuffer + (CharRows - 1) * line_size);
390 src = (long *)((char*)dest - line_size);
391 end = (long *)(framebuffer + row * line_size);
392 while (src >= end) {
393 i = 0;
394 do {
395 temp0 = src[0];
396 temp1 = src[1];
397 temp2 = src[2];
398 temp3 = src[3];
399 dest[0] = temp0;
400 dest[1] = temp1;
401 dest[2] = temp2;
402 dest[3] = temp3;
403 dest += 4;
404 src += 4;
405 i++;
406 } while (i < blockcnt);
407 src -= scaninc;
408 dest -= scaninc;
409 }
410
411 /* Now zero out the line being opened */
412 bzero(framebuffer + row * line_size, line_size);
413
414 ascii_screen_ins_update(sc, row);
415 }
416
417 #undef Slop
418
419
420 /*
421 * Initialize screen parameters in the
422 * user-mapped descriptor.
423 * This is common to various drivers.
424 */
425 pm_init_screen_params(
426 screen_softc_t sc,
427 user_info_t *up)
428 {
429 register int vis_x, vis_y;
430
431 up->frame_scanline_width = sc->frame_scanline_width;
432 up->frame_height = sc->frame_height;
433
434 vis_x = sc->frame_visible_width;
435 vis_y = sc->frame_visible_height;
436
437 up->max_x = vis_x;
438 up->max_y = vis_y;
439 up->max_cur_x = vis_x - 1;
440 up->max_cur_y = vis_y - 1;
441 up->min_cur_x = -15;
442 up->min_cur_y = -15;
443 up->max_row = vis_y / KfontHeight;
444 up->max_col = vis_x / KfontWidth;
445
446 up->version = 11;
447
448 up->mouse_threshold = 4;
449 up->mouse_scale = 2;
450
451 up->dev_dep_2.pm.tablet_scale_x = ((vis_x - 1) * 1000) / 2200;
452 up->dev_dep_2.pm.tablet_scale_y = ((vis_y - 1) * 1000) / 2200;
453 }
454
455 /*
456 * Clear the screen
457 * Used by pm, fb and cfb
458 */
459 pm_clear_bitmap(
460 screen_softc_t sc)
461 {
462 pm_softc_t *pm = (pm_softc_t *) sc->hw_state;
463 unsigned int screen_size;
464
465 /* Do not touch the non visible part */
466 screen_size = sc->frame_scanline_width * sc->frame_visible_height;
467 blkclr((char *)pm->framebuffer,
468 (sc->flags & MONO_SCREEN) ? (screen_size>>3) : screen_size);
469
470 /* clear ascii screenmap */
471 ascii_screen_fill(sc, ' ');
472 }
473
474
475 /*
476 * Size of the user-mapped structure
477 * Used by both pm and cfb
478 */
479 pm_mem_need()
480 {
481 return USER_INFO_SIZE;
482 }
483
484 /*
485 * Device-specific get status.
486 * Used by fb and cfb also.
487 */
488 pm_get_status(
489 screen_softc_t sc,
490 dev_flavor_t flavor,
491 dev_status_t status,
492 natural_t *status_count)
493 {
494 if (flavor == SCREEN_GET_OFFSETS) {
495 unsigned *offs = (unsigned *) status;
496
497 offs[0] = PM_SIZE(sc); /* virtual size */
498 offs[1] = 0; /* offset of user_info_t */
499 *status_count = 2;
500 return D_SUCCESS;
501 } else
502 return D_INVALID_OPERATION;
503 }
504
505 /*
506 * Driver-specific set status
507 * Only partially used by fb and cfb.
508 */
509 pm_set_status(
510 screen_softc_t sc,
511 dev_flavor_t flavor,
512 dev_status_t status,
513 natural_t status_count)
514 {
515 switch (flavor) {
516 case SCREEN_ADJ_MAPPED_INFO: {
517 unsigned user_addr = *(unsigned *) status;
518 user_info_t *up = sc->up;
519
520 /* Make it point to the event_queue, in user virtual */
521 up->evque.events = (screen_event_t *)(user_addr +
522 ((char*)up->event_queue - (char*)up));
523
524 /* Make it point to the point_track, in user virtual */
525 up->evque.track = (screen_timed_point_t *)(user_addr +
526 ((char*)up->point_track - (char*)up));
527
528 up->dev_dep_1.pm.planemask = (unsigned char *)(user_addr + USER_INFO_SIZE);
529
530 up->dev_dep_1.pm.bitmap = up->dev_dep_1.pm.planemask + PMASK_SIZE;
531
532 break;
533 }
534
535 case SCREEN_LOAD_CURSOR: {
536
537 sc->flags |= SCREEN_BEING_UPDATED;
538 dc503_load_cursor(sc->hw_state, (unsigned short*)status);
539 sc->flags &= ~SCREEN_BEING_UPDATED;
540
541 break;
542 }
543
544 #ifdef DECSTATION
545 case SCREEN_SET_CURSOR_COLOR: {
546 pm_softc_t *pm = (pm_softc_t*) sc->hw_state;
547
548 sc->flags |= SCREEN_BEING_UPDATED;
549 bt478_cursor_color (pm->vdac_registers, (cursor_color_t*) status);
550 sc->flags &= ~SCREEN_BEING_UPDATED;
551
552 break;
553 }
554
555 case SCREEN_SET_CMAP_ENTRY: {
556 pm_softc_t *pm = (pm_softc_t*) sc->hw_state;
557 color_map_entry_t *e = (color_map_entry_t*) status;
558
559 if (e->index < 256) {
560 sc->flags |= SCREEN_BEING_UPDATED;
561 bt478_load_colormap_entry( pm->vdac_registers, e->index, &e->value);
562 sc->flags &= ~SCREEN_BEING_UPDATED;
563 }
564
565 break;
566 }
567 #endif /*DECSTATION*/
568 default:
569 return D_INVALID_OPERATION;
570 }
571 return D_SUCCESS;
572 }
573
574 /*
575 * Map pages to user space
576 */
577 vm_offset_t pm_map_page_empty = (vm_offset_t) 0;
578
579 integer_t
580 pm_map_page(
581 screen_softc_t sc,
582 vm_offset_t off,
583 int prot)
584 {
585 int bitmapsize;
586 integer_t addr;
587 pm_softc_t *pm = (pm_softc_t *)sc->hw_state;
588 extern vm_offset_t pmap_extract( pmap_t map, vm_offset_t addr);
589
590 bitmapsize = BITMAP_SIZE(sc);
591
592 #define OFF0 USER_INFO_SIZE /* user mapped info */
593 #define OFF1 OFF0+PMASK_SIZE /* plane mask register */
594 #define OFF2 OFF1+bitmapsize /* frame buffer mem */
595
596 if (off < OFF0)
597 #ifdef DECSTATION
598 addr = kvtophys(sc->up);
599 #else
600 addr = (integer_t) pmap_extract(kernel_pmap,
601 (vm_offset_t)sc->up);
602 #endif
603 else
604 if (off < OFF1) {
605 #ifdef VAXSTATION
606 if (pm_map_page_empty == 0) {
607 pm_map_page_empty = vm_page_grab_phys_addr();
608 }
609 addr = (integer_t)pmap_extract(kernel_pmap, pm_map_page_empty);
610 #else
611 addr = (integer_t) pm->plane_mask;
612 #endif
613 off -= OFF0;
614 } else
615 if (off < OFF2) {
616 #ifdef DECSTATION
617 addr = (integer_t)pm->framebuffer;
618 #else
619 addr = (integer_t)pmap_extract(kernel_pmap,
620 (vm_offset_t)pm->framebuffer);
621 #endif
622 off -= OFF1;
623 } else
624 return D_INVALID_SIZE; /* ??? */
625
626 addr = machine_btop(addr + off);
627 return (addr);
628 }
629
630
631 /*
632 *-----------------------------------------------------------
633 * The rest of this file is stricly pmax/pvax-specific
634 *-----------------------------------------------------------
635 */
636 #if (NFB > 0)
637
638 /*
639 * Do what's needed when the X server exits
640 */
641 pm_soft_reset(
642 screen_softc_t sc)
643 {
644 pm_softc_t *pm = (pm_softc_t*) sc->hw_state;
645 user_info_t *up = sc->up;
646
647 /*
648 * Restore params in mapped structure
649 */
650 pm_init_screen_params(sc, up);
651 up->row = up->max_row - 2;
652 dc503_init(pm);
653
654 #ifdef DECSTATION
655 if (sc->flags & MONO_SCREEN)
656 bt478_init_bw_map(pm->vdac_registers, pm->plane_mask);
657 else
658 bt478_init_color_map(pm->vdac_registers, pm->plane_mask);
659 #endif /*DECSTATION*/
660 }
661 #endif /* NFB > 0 */
662
663
664 #endif /* NPM > 0 */
Cache object: 6dd0578281cfd67c6c037c4e1ad78f0c
|