|
|
1.1 root 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 [email protected]
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: * File: pm_misc.c
28: * Author: Alessandro Forin, Carnegie Mellon University
29: * Date: 9/90
30: *
31: * Driver for the VFB01/02 Mono/Color framebuffer (pmax)
32: * Hardware-independent operations, mostly shared with
33: * the CFB driver (see each individual function header),
34: * and possibly others.
35: */
36:
37:
38: #include <platforms.h>
39:
40: #include <fb.h>
41:
42: #if defined(DECSTATION) || defined(FLAMINGO)
43: #include <cfb.h>
44: #include <mfb.h>
45: #include <xcfb.h>
46: #include <sfb.h>
47: #define NPM (NFB+NCFB+NMFB+NXCFB+NSFB)
48: #endif /*DECSTATION*/
49:
50: #ifdef VAXSTATION
51: #define NPM (NFB)
52: #endif /*VAXSTATION*/
53:
54:
55: #if (NPM > 0)
56:
57: #include <mach/vm_param.h> /* PAGE_SIZE */
58: #include <device/device_types.h>
59: #include <vm/vm_map.h> /* kernel_pmap */
60:
61: #include <chips/screen_defs.h>
62: #include <chips/pm_defs.h>
63:
64:
65: #ifdef DECSTATION
66: #define machine_btop mips_btop
67: #define MONO_BM (256*1024)
68: #endif /*DECSTATION*/
69:
70: #ifdef VAXSTATION
71: #define machine_btop vax_btop
72: /*
73: For now we use the last page of the frame for
74: the user_info structure.
75: */
76: #define MONO_BM (256*1024-PAGE_SIZE)
77: #endif /*VAXSTATION*/
78:
79: #ifdef FLAMINGO
80: #define machine_btop alpha_btop
81: #define MONO_BM (256*1024)
82: #define LOG2_SIZEOF_LONG 3 /* 64bit archies */
83: #endif /* FLAMINGO */
84:
85: #ifndef LOG2_SIZEOF_LONG
86: #define LOG2_SIZEOF_LONG 2 /* 32bit archies */
87: #endif
88:
89:
90: /* Hardware state */
91: pm_softc_t pm_softc_data[NPM];
92:
93: pm_softc_t*
94: pm_alloc(
95: int unit,
96: char *cur,
97: unsigned char *fb,
98: unsigned char *pl)
99: {
100: pm_softc_t *pm = &pm_softc_data[unit];
101:
102: pm->cursor_registers = cur;
103: pm->framebuffer = fb;
104: pm->plane_mask = pl;
105: pm->vdac_registers = 0; /* later, if ever */
106:
107: screen_attach(unit, (char *) pm);
108:
109: return pm;
110: }
111:
112:
113: /*
114: * Routine to paint a char on a simple framebuffer.
115: * This is common to the pm, fb and cfb drivers.
116: */
117: pm_char_paint(
118: screen_softc_t sc,
119: int c,
120: int row,
121: int col)
122: {
123: register int incr;
124: int line_size;
125: register unsigned char *font, *bmap;
126: pm_softc_t *pm = (pm_softc_t*)sc->hw_state;
127:
128: /*
129: * Here are the magic numbers that drive the loops below:
130: * incr bytes between scanlines of the glyph
131: * line_size bytes in a row, using the system font
132: *
133: * This code has been optimized to avoid multiplications,
134: * and is therefore much less obvious than it could be.
135: */
136: if (sc->flags & MONO_SCREEN) {
137: /*
138: * B&W screen: 1 bit/pixel
139: * incr --> 1 * BytesPerLine, with possible stride
140: */
141: incr = sc->frame_scanline_width >> 3;
142: } else {
143: /*
144: * Color screen: 8 bits/pixel
145: * incr --> 8 * BytesPerLine, with possible stride
146: */
147: incr = sc->frame_scanline_width;
148: col <<= 3;
149: }
150:
151: /* not all compilers are smart about multiply by 15 */
152: #if (KfontHeight==15)
153: # define TIMES_KfontHeight(w) (((w)<<4)-(w))
154: #else
155: # define TIMES_KfontHeight(w) ((w)*KfontHeight)
156: #endif
157: line_size = TIMES_KfontHeight(incr);
158:
159: bmap = pm->framebuffer + col + (row * line_size);
160: font = &kfont_7x14[ (int)(c - ' ') * 15];
161: if (sc->flags & MONO_SCREEN) {
162: /*
163: * Unroll simple loops, take note of common cases
164: */
165: if (sc->standout) {
166: # define mv() *bmap = ~*font++; bmap += incr;
167: mv();mv();mv();mv();mv();mv();mv();mv();
168: mv();mv();mv();mv();mv();mv();mv();
169: # undef mv
170: } else if (c == ' ') {
171: # define mv() *bmap = 0; bmap += incr;
172: mv();mv();mv();mv();mv();mv();mv();mv();
173: mv();mv();mv();mv();mv();mv();mv();
174: # undef mv
175: } else {
176: # define mv() *bmap = *font++; bmap += incr;
177: mv();mv();mv();mv();mv();mv();mv();mv();
178: mv();mv();mv();mv();mv();mv();mv();
179: # undef mv
180: }
181: } else {
182: /*
183: * 8 bits per pixel --> paint one byte per each font bit.
184: * In order to spread out the 8 bits of a glyph line over
185: * the 64 bits per scanline use a simple vector multiply,
186: * taking 4 bits at a time to get the two resulting words
187: */
188: static unsigned int spread[16] = {
189: 0x00000000, 0x00000001, 0x00000100, 0x00000101,
190: 0x00010000, 0x00010001, 0x00010100, 0x00010101,
191: 0x01000000, 0x01000001, 0x01000100, 0x01000101,
192: 0x01010000, 0x01010001, 0x01010100, 0x01010101,
193: };
194: register int rev_video = sc->standout;
195: register int j;
196: for (j = 0; j < KfontHeight; j++) {
197: register unsigned char c = *font++;
198: if (rev_video) c = ~c;
199: #if (LOG2_SIZEOF_LONG==3)
200: *((long*)bmap) = (long)spread[ c & 0xf ] |
201: ((long)(spread[ (c>>4) & 0xf ]) << 32);
202: #else
203: ((int*)bmap)[0] = spread[ c & 0xf ];
204: ((int*)bmap)[1] = spread[ (c>>4) & 0xf ];
205: #endif
206: bmap += incr;
207: }
208: }
209: }
210:
211: /*
212: * Delete the line at the given row.
213: * This is common to the pm, fb and cfb drivers.
214: */
215: pm_remove_line(
216: screen_softc_t sc,
217: short row)
218: {
219: register long *dest, *src;
220: register long *end;
221: register long temp0,temp1,temp2,temp3;
222: register long i, scaninc, blockcnt;
223: long line_size, incr;
224: unsigned char *framebuffer;
225: pm_softc_t *pm = (pm_softc_t*)sc->hw_state;
226: long CharRows, CharCols;
227:
228: CharRows = sc->up->max_row;
229: CharCols = sc->up->max_col;
230: framebuffer = pm->framebuffer;
231:
232: /* Inner loop works 4 long words at a time (writebuffer deep) */
233: # define BlockSizeShift (2+LOG2_SIZEOF_LONG)
234:
235: /* To copy one (MONO) line, we need to iterate this many times */
236: # define Blocks (CharCols>>BlockSizeShift)
237:
238: /* Skip this many bytes to get to the next line */
239: # define Slop(w) ((w) - (blockcnt<<BlockSizeShift))
240:
241: if (sc->flags & MONO_SCREEN) {
242: blockcnt = Blocks;
243: /* See comments in pm_char_paint() */
244: incr = sc->frame_scanline_width >> 3;
245: } else {
246: blockcnt = Blocks << 3;
247: /* See comments in pm_char_paint() */
248: incr = sc->frame_scanline_width;
249: }
250: line_size = TIMES_KfontHeight(incr);
251:
252: scaninc = (Slop(incr)) >> LOG2_SIZEOF_LONG; /* pointers are long* */
253:
254: dest = (long *)(framebuffer + row * line_size);
255: src = (long *)((char*)dest + line_size);
256: end = (long *)(framebuffer + CharRows * line_size);
257: while (src < end) {
258: i = 0;
259: do {
260: temp0 = src[0];
261: temp1 = src[1];
262: temp2 = src[2];
263: temp3 = src[3];
264: dest[0] = temp0;
265: dest[1] = temp1;
266: dest[2] = temp2;
267: dest[3] = temp3;
268: dest += 4;
269: src += 4;
270: i++;
271: } while (i < blockcnt);
272: src += scaninc;
273: dest += scaninc;
274: }
275:
276: /* Now zero out the last line */
277: bzero(framebuffer + (CharRows - 1) * line_size, line_size);
278:
279: ascii_screen_rem_update(sc, row);
280: }
281:
282:
283: /*
284: * Open a new blank line at the given row.
285: * This is common to the pm, fb and cfb drivers.
286: */
287: pm_insert_line(
288: screen_softc_t sc,
289: short row)
290: {
291: register long *dest, *src;
292: register long *end;
293: register long temp0,temp1,temp2,temp3;
294: register long i, scaninc, blockcnt;
295: long line_size, incr;
296: unsigned char *framebuffer;
297: pm_softc_t *pm = (pm_softc_t*)sc->hw_state;
298: long CharRows, CharCols;
299:
300: CharRows = sc->up->max_row;
301: CharCols = sc->up->max_col;
302:
303: framebuffer = pm->framebuffer;
304:
305: /* See above for comments */
306: if (sc->flags & MONO_SCREEN) {
307: blockcnt = Blocks;
308: /* See comments in pm_char_paint() */
309: incr = sc->frame_scanline_width >> 3;
310: } else {
311: blockcnt = Blocks << 3;
312: /* See comments in pm_char_paint() */
313: incr = sc->frame_scanline_width;
314: }
315: line_size = TIMES_KfontHeight(incr);
316:
317: scaninc = Slop(incr) + ((2 * blockcnt) << BlockSizeShift);
318: scaninc >>= LOG2_SIZEOF_LONG; /* pointers are long* */
319: dest = (long *)(framebuffer + (CharRows - 1) * line_size);
320: src = (long *)((char*)dest - line_size);
321: end = (long *)(framebuffer + row * line_size);
322: while (src >= end) {
323: i = 0;
324: do {
325: temp0 = src[0];
326: temp1 = src[1];
327: temp2 = src[2];
328: temp3 = src[3];
329: dest[0] = temp0;
330: dest[1] = temp1;
331: dest[2] = temp2;
332: dest[3] = temp3;
333: dest += 4;
334: src += 4;
335: i++;
336: } while (i < blockcnt);
337: src -= scaninc;
338: dest -= scaninc;
339: }
340:
341: /* Now zero out the line being opened */
342: bzero(framebuffer + row * line_size, line_size);
343:
344: ascii_screen_ins_update(sc, row);
345: }
346:
347: #undef Slop
348:
349:
350: /*
351: * Initialize screen parameters in the
352: * user-mapped descriptor.
353: * This is common to various drivers.
354: */
355: pm_init_screen_params(
356: screen_softc_t sc,
357: user_info_t *up)
358: {
359: register int vis_x, vis_y;
360:
361: up->frame_scanline_width = sc->frame_scanline_width;
362: up->frame_height = sc->frame_height;
363:
364: vis_x = sc->frame_visible_width;
365: vis_y = sc->frame_visible_height;
366:
367: up->max_x = vis_x;
368: up->max_y = vis_y;
369: up->max_cur_x = vis_x - 1;
370: up->max_cur_y = vis_y - 1;
371: up->min_cur_x = -15;
372: up->min_cur_y = -15;
373: up->max_row = vis_y / KfontHeight;
374: up->max_col = vis_x / KfontWidth;
375:
376: up->version = 11;
377:
378: up->mouse_threshold = 4;
379: up->mouse_scale = 2;
380:
381: up->dev_dep_2.pm.tablet_scale_x = ((vis_x - 1) * 1000) / 2200;
382: up->dev_dep_2.pm.tablet_scale_y = ((vis_y - 1) * 1000) / 2200;
383: }
384:
385: /*
386: * Clear the screen
387: * Used by pm, fb and cfb
388: */
389: pm_clear_bitmap(
390: screen_softc_t sc)
391: {
392: pm_softc_t *pm = (pm_softc_t *) sc->hw_state;
393: unsigned int screen_size;
394:
395: /* Do not touch the non visible part */
396: screen_size = sc->frame_scanline_width * sc->frame_visible_height;
397: blkclr((char *)pm->framebuffer,
398: (sc->flags & MONO_SCREEN) ? (screen_size>>3) : screen_size);
399:
400: /* clear ascii screenmap */
401: ascii_screen_fill(sc, ' ');
402: }
403:
404:
405: /*
406: * Size of the user-mapped structure
407: * Used by both pm and cfb
408: */
409: pm_mem_need()
410: {
411: return USER_INFO_SIZE;
412: }
413:
414: /*
415: * Device-specific get status.
416: * Used by fb and cfb also.
417: */
418: pm_get_status(
419: screen_softc_t sc,
420: dev_flavor_t flavor,
421: dev_status_t status,
422: natural_t *status_count)
423: {
424: if (flavor == SCREEN_GET_OFFSETS) {
425: unsigned *offs = (unsigned *) status;
426:
427: offs[0] = PM_SIZE(sc); /* virtual size */
428: offs[1] = 0; /* offset of user_info_t */
429: *status_count = 2;
430: return D_SUCCESS;
431: } else
432: return D_INVALID_OPERATION;
433: }
434:
435: /*
436: * Driver-specific set status
437: * Only partially used by fb and cfb.
438: */
439: pm_set_status(
440: screen_softc_t sc,
441: dev_flavor_t flavor,
442: dev_status_t status,
443: natural_t status_count)
444: {
445: switch (flavor) {
446: case SCREEN_ADJ_MAPPED_INFO: {
447: unsigned user_addr = *(unsigned *) status;
448: user_info_t *up = sc->up;
449:
450: /* Make it point to the event_queue, in user virtual */
451: up->evque.events = (screen_event_t *)(user_addr +
452: ((char*)up->event_queue - (char*)up));
453:
454: /* Make it point to the point_track, in user virtual */
455: up->evque.track = (screen_timed_point_t *)(user_addr +
456: ((char*)up->point_track - (char*)up));
457:
458: up->dev_dep_1.pm.planemask = (unsigned char *)(user_addr + USER_INFO_SIZE);
459:
460: up->dev_dep_1.pm.bitmap = up->dev_dep_1.pm.planemask + PMASK_SIZE;
461:
462: break;
463: }
464:
465: case SCREEN_LOAD_CURSOR: {
466:
467: sc->flags |= SCREEN_BEING_UPDATED;
468: dc503_load_cursor(sc->hw_state, (unsigned short*)status);
469: sc->flags &= ~SCREEN_BEING_UPDATED;
470:
471: break;
472: }
473:
474: #ifdef DECSTATION
475: case SCREEN_SET_CURSOR_COLOR: {
476: pm_softc_t *pm = (pm_softc_t*) sc->hw_state;
477:
478: sc->flags |= SCREEN_BEING_UPDATED;
479: bt478_cursor_color (pm->vdac_registers, (cursor_color_t*) status);
480: sc->flags &= ~SCREEN_BEING_UPDATED;
481:
482: break;
483: }
484:
485: case SCREEN_SET_CMAP_ENTRY: {
486: pm_softc_t *pm = (pm_softc_t*) sc->hw_state;
487: color_map_entry_t *e = (color_map_entry_t*) status;
488:
489: if (e->index < 256) {
490: sc->flags |= SCREEN_BEING_UPDATED;
491: bt478_load_colormap_entry( pm->vdac_registers, e->index, &e->value);
492: sc->flags &= ~SCREEN_BEING_UPDATED;
493: }
494:
495: break;
496: }
497: #endif /*DECSTATION*/
498: default:
499: return D_INVALID_OPERATION;
500: }
501: return D_SUCCESS;
502: }
503:
504: /*
505: * Map pages to user space
506: */
507: vm_offset_t pm_map_page_empty = (vm_offset_t) 0;
508:
509: integer_t
510: pm_map_page(
511: screen_softc_t sc,
512: vm_offset_t off,
513: int prot)
514: {
515: int bitmapsize;
516: integer_t addr;
517: pm_softc_t *pm = (pm_softc_t *)sc->hw_state;
518: extern vm_offset_t pmap_extract( pmap_t map, vm_offset_t addr);
519:
520: bitmapsize = BITMAP_SIZE(sc);
521:
522: #define OFF0 USER_INFO_SIZE /* user mapped info */
523: #define OFF1 OFF0+PMASK_SIZE /* plane mask register */
524: #define OFF2 OFF1+bitmapsize /* frame buffer mem */
525:
526: if (off < OFF0)
527: #ifdef DECSTATION
528: addr = kvtophys(sc->up);
529: #else
530: addr = (integer_t) pmap_extract(kernel_pmap,
531: (vm_offset_t)sc->up);
532: #endif
533: else
534: if (off < OFF1) {
535: #ifdef VAXSTATION
536: if (pm_map_page_empty == 0) {
537: pm_map_page_empty = vm_page_grab_phys_addr();
538: }
539: addr = (integer_t)pmap_extract(kernel_pmap, pm_map_page_empty);
540: #else
541: addr = (integer_t) pm->plane_mask;
542: #endif
543: off -= OFF0;
544: } else
545: if (off < OFF2) {
546: #ifdef DECSTATION
547: addr = (integer_t)pm->framebuffer;
548: #else
549: addr = (integer_t)pmap_extract(kernel_pmap,
550: (vm_offset_t)pm->framebuffer);
551: #endif
552: off -= OFF1;
553: } else
554: return D_INVALID_SIZE; /* ??? */
555:
556: addr = machine_btop(addr + off);
557: return (addr);
558: }
559:
560:
561: /*
562: *-----------------------------------------------------------
563: * The rest of this file is stricly pmax/pvax-specific
564: *-----------------------------------------------------------
565: */
566: #if (NFB > 0)
567:
568: /*
569: * Do what's needed when the X server exits
570: */
571: pm_soft_reset(
572: screen_softc_t sc)
573: {
574: pm_softc_t *pm = (pm_softc_t*) sc->hw_state;
575: user_info_t *up = sc->up;
576:
577: /*
578: * Restore params in mapped structure
579: */
580: pm_init_screen_params(sc, up);
581: up->row = up->max_row - 2;
582: dc503_init(pm);
583:
584: #ifdef DECSTATION
585: if (sc->flags & MONO_SCREEN)
586: bt478_init_bw_map(pm->vdac_registers, pm->plane_mask);
587: else
588: bt478_init_color_map(pm->vdac_registers, pm->plane_mask);
589: #endif /*DECSTATION*/
590: }
591: #endif /* NFB > 0 */
592:
593:
594: #endif /* NPM > 0 */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.