1/*  *********************************************************************
2    *  Broadcom Common Firmware Environment (CFE)
3    *
4    *  VGA "teletype" routines			File: VGA_SUBR.C
5    *
6    *  These routines implement a simple "glass tty" interface
7    *  to a vga monitor.
8    *
9    *  Author:  Mitch Lichtenberg
10    *
11    *********************************************************************
12    *
13    *  Copyright 2000,2001,2002,2003
14    *  Broadcom Corporation. All rights reserved.
15    *
16    *  This software is furnished under license and may be used and
17    *  copied only in accordance with the following terms and
18    *  conditions.  Subject to these conditions, you may download,
19    *  copy, install, use, modify and distribute modified or unmodified
20    *  copies of this software in source and/or binary form.  No title
21    *  or ownership is transferred hereby.
22    *
23    *  1) Any source code used, modified or distributed must reproduce
24    *     and retain this copyright notice and list of conditions
25    *     as they appear in the source file.
26    *
27    *  2) No right is granted to use any trade name, trademark, or
28    *     logo of Broadcom Corporation.  The "Broadcom Corporation"
29    *     name may not be used to endorse or promote products derived
30    *     from this software without the prior written permission of
31    *     Broadcom Corporation.
32    *
33    *  3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
34    *     IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
35    *     WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
36    *     PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
37    *     SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
38    *     PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT,
39    *     INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
40    *     (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
41    *     GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
42    *     BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
43    *     OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
44    *     TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF
45    *     THE POSSIBILITY OF SUCH DAMAGE.
46    ********************************************************************* */
47
48
49#include "cpu_config.h"
50#include "lib_types.h"
51#include "lib_string.h"
52#include "lib_printf.h"
53#include "lib_malloc.h"
54#include "lib_hssubr.h"
55
56#include "lib_physio.h"
57
58#include "vga_subr.h"
59#include "vga.h"
60
61
62/*  *********************************************************************
63    *  Macros
64    ********************************************************************* */
65
66#define OUTB(vga,port,val) (*((vga)->vga_outb))(port,val)
67
68#ifdef __MIPSEB
69#define VGA_SPACE_CHAR 0x2007		/* belongs somewhere else */
70#else
71#define VGA_SPACE_CHAR 0x0720
72#endif
73
74/*  *********************************************************************
75    *  Data
76    ********************************************************************* */
77
78
79/*  *********************************************************************
80    *  VGA_CLEAR(vga)
81    *
82    *  Clear the VGA screen
83    *
84    *  Input parameters:
85    *  	   vga - VGA object
86    *
87    *  Return value:
88    *  	   nothing
89    ********************************************************************* */
90
91void vga_clear(vga_term_t *vga)
92{
93    int idx;
94
95    /* Clear the frame buffer */
96
97    for (idx = 0; idx < VGA_TEXTBUF_SIZE; idx+=2) {
98	phys_write16(vga->vga_buffer+idx,VGA_SPACE_CHAR);
99	}
100}
101
102
103/*  *********************************************************************
104    *  VGA_SETCURSOR(vga,x,y)
105    *
106    *  Set the hardware cursor position
107    *
108    *  Input parameters:
109    *  	   vga - VGA object
110    *  	   x,y - cursor location
111    *
112    *  Return value:
113    *  	   nothing
114    ********************************************************************* */
115
116void vga_setcursor(vga_term_t *vga,int x,int y)
117{
118    unsigned int loc = y*vga->vga_ncols + x;
119
120    OUTB(vga,VGA_CRTC_INDEX,CRTC_CURSOR_HIGH);
121    OUTB(vga,VGA_CRTC_DATA,(loc >> 8) & 0xFF);
122    OUTB(vga,VGA_CRTC_INDEX,CRTC_CURSOR_LOW);
123    OUTB(vga,VGA_CRTC_DATA,(loc >> 0) & 0xFF);
124
125    vga->vga_cursorX = x;
126    vga->vga_cursorY = y;
127}
128
129/*  *********************************************************************
130    *  VGA_SCROLL(vga)
131    *
132    *  Scroll the display up one line
133    *
134    *  Input parameters:
135    *  	   vga - VGA object
136    *
137    *  Return value:
138    *  	   nothing
139    ********************************************************************* */
140
141static void vga_scroll(vga_term_t *vga)
142{
143    int idx;
144    int count;
145    int rowsize;
146    uint32_t t;
147
148    rowsize = vga->vga_ncols * 2;
149    count = (vga->vga_nrows-1) * rowsize;
150
151    for (idx = 0; idx < count; idx+=4) {
152	t = phys_read32(vga->vga_buffer+idx+rowsize);
153	phys_write32(vga->vga_buffer+idx,t);
154	}
155
156    for (idx = 0; idx < rowsize; idx += 2) {
157	phys_write16(vga->vga_buffer+(vga->vga_nrows-1)*rowsize+idx,VGA_SPACE_CHAR);
158	}
159
160    vga_setcursor(vga,0,vga->vga_nrows-1);
161}
162
163/*  *********************************************************************
164    *  VGA_WRITECHAR(vga,ch,attr)
165    *
166    *  Write a character to the display.  This routine also
167    *  interprets some rudimentary control characters, such
168    *  as tab, backspace, linefeed, and carriage return.
169    *
170    *  Input parameters:
171    *  	   vga - VGA object
172    *  	   ch - character to write
173    *  	   attr - attribute byte for new character
174    *
175    *  Return value:
176    *  	   nothing
177    ********************************************************************* */
178
179void vga_writechar(vga_term_t *vga,uint8_t ch,uint8_t attr)
180{
181    physaddr_t addr;
182
183    switch (ch) {
184	case 0x07:
185	    break;
186	case 0x09:
187	    vga_writechar(vga,' ',attr);
188	    while (vga->vga_cursorX % 8) vga_writechar(vga,' ',attr);
189	    break;
190	case 0x0A:
191	    vga->vga_cursorY++;
192	    if (vga->vga_cursorY > (vga->vga_nrows-1)) {
193		vga_scroll(vga);
194		}
195	    break;
196	case 0x08:
197	    if (vga->vga_cursorX) {
198		vga->vga_cursorX--;
199		addr = vga->vga_buffer + (vga->vga_cursorX*2+vga->vga_cursorY*vga->vga_ncols*2);
200		phys_write8(addr,' ');
201		}
202	    break;
203	case 0x0D:
204	    vga->vga_cursorX = 0;
205	    break;
206	default:
207	    addr = vga->vga_buffer + (vga->vga_cursorX*2+vga->vga_cursorY*vga->vga_ncols*2);
208	    phys_write8(addr,ch);
209	    phys_write8(addr+1,attr);
210	    vga->vga_cursorX++;
211	    if (vga->vga_cursorX > (vga->vga_ncols-1)) {
212		vga->vga_cursorX = 0;
213		vga->vga_cursorY++;
214		if (vga->vga_cursorY > (vga->vga_nrows-1)) {
215		    vga_scroll(vga);
216		    }
217		}
218	    break;
219	}
220
221    vga_setcursor(vga,vga->vga_cursorX,vga->vga_cursorY);
222}
223
224/*  *********************************************************************
225    *  VGA_WRITESTR(vga,str,attr,len)
226    *
227    *  Write a string of characters to the VGA
228    *
229    *  Input parameters:
230    *  	   vga - VGA object
231    *  	   str - pointer to buffer
232    *  	   attr - attribute byte for characters we're writing
233    *  	   len - number of characters to write
234    *
235    *  Return value:
236    *  	   nothing
237    ********************************************************************* */
238
239void vga_writestr(vga_term_t *vga,hsaddr_t str,uint8_t attr,int len)
240{
241    while (len) {
242	vga_writechar(vga,hs_read8(str),attr);
243	str++;
244	len--;
245	}
246}
247
248/*  *********************************************************************
249    *  VGA_RESET(vga)
250    *
251    *  (mostly unused) - reset the VGA
252    *
253    *  Input parameters:
254    *  	   vga - vga object
255    *
256    *  Return value:
257    *  	   nothing
258    ********************************************************************* */
259
260void vga_reset(vga_term_t *vga)
261{
262    vga_clear(vga);
263}
264
265/*  *********************************************************************
266    *  VGA_INIT(vga,buffer,outfunc)
267    *
268    *  Initialize a VGA object
269    *
270    *  Input parameters:
271    *  	   vga - VGA object
272    *  	   buffer - pointer to VGA-style frame buffer (physical addr)
273    *  	   outfunc - pointer to function to write ISA I/O ports
274    *
275    *  Return value:
276    *  	   nothing
277    ********************************************************************* */
278
279void vga_init(vga_term_t *vga,physaddr_t buffer,void (*outfunc)(unsigned int port,uint8_t val))
280{
281    vga->vga_buffer =  buffer;
282    vga->vga_cursorX = 0;
283    vga->vga_cursorY = 0;
284    vga->vga_nrows = VGA_TEXTMODE_ROWS;
285    vga->vga_ncols = VGA_TEXTMODE_COLS;
286    vga->vga_outb = outfunc;
287}
288