1/*  *********************************************************************
2    *  Broadcom Common Firmware Environment (CFE)
3    *
4    *  PC Console driver			File: dev_pcconsole.c
5    *
6    *  A console driver for a PC-style keyboard and mouse
7    *
8    *  Author:  Mitch Lichtenberg
9    *
10    *********************************************************************
11    *
12    *  Copyright 2000,2001,2002,2003
13    *  Broadcom Corporation. All rights reserved.
14    *
15    *  This software is furnished under license and may be used and
16    *  copied only in accordance with the following terms and
17    *  conditions.  Subject to these conditions, you may download,
18    *  copy, install, use, modify and distribute modified or unmodified
19    *  copies of this software in source and/or binary form.  No title
20    *  or ownership is transferred hereby.
21    *
22    *  1) Any source code used, modified or distributed must reproduce
23    *     and retain this copyright notice and list of conditions
24    *     as they appear in the source file.
25    *
26    *  2) No right is granted to use any trade name, trademark, or
27    *     logo of Broadcom Corporation.  The "Broadcom Corporation"
28    *     name may not be used to endorse or promote products derived
29    *     from this software without the prior written permission of
30    *     Broadcom Corporation.
31    *
32    *  3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
33    *     IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
34    *     WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
35    *     PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
36    *     SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
37    *     PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT,
38    *     INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
39    *     (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
40    *     GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
41    *     BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
42    *     OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
43    *     TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF
44    *     THE POSSIBILITY OF SUCH DAMAGE.
45    ********************************************************************* */
46
47
48
49#include "cfe.h"
50#include "sbmips.h"
51
52#include "lib_physio.h"
53
54#include "kbd_subr.h"
55#include "vga_subr.h"
56
57#include "pcireg.h"
58#include "pcivar.h"
59
60
61/*  *********************************************************************
62    *  Constants
63    ********************************************************************* */
64
65#define KBD_RXFULL		1		/* bit set if kb has data */
66#define KBD_TXFULL		2		/* bit set if we can send cmd */
67#define VGA_TEXTBUF_COLOR	0xB8000		/* VGA frame buffer */
68
69#if defined(_P5064_) || defined(_P6064_)
70  #define PCI_MEM_SPACE	0x10000000	/* 128MB: s/w configurable */
71  #define __ISAaddr(addr) ((physaddr_t)(PCI_MEM_SPACE+(addr)))
72#else
73  #define __ISAaddr(addr) ((physaddr_t)0x40000000+(addr))
74#endif
75
76#define cpu_isamap(x,y) __ISAaddr(x)
77
78/*  *********************************************************************
79    *  Forward references
80    ********************************************************************* */
81
82static void pcconsole_probe(cfe_driver_t *drv,
83			      unsigned long probe_a, unsigned long probe_b,
84			      void *probe_ptr);
85
86
87static int pcconsole_open(cfe_devctx_t *ctx);
88static int pcconsole_read(cfe_devctx_t *ctx,iocb_buffer_t *buffer);
89static int pcconsole_inpstat(cfe_devctx_t *ctx,iocb_inpstat_t *inpstat);
90static int pcconsole_write(cfe_devctx_t *ctx,iocb_buffer_t *buffer);
91static int pcconsole_ioctl(cfe_devctx_t *ctx,iocb_buffer_t *buffer);
92static int pcconsole_close(cfe_devctx_t *ctx);
93static void pcconsole_poll(cfe_devctx_t *ctx,int64_t ticks);
94
95const static cfe_devdisp_t pcconsole_dispatch = {
96    pcconsole_open,
97    pcconsole_read,
98    pcconsole_inpstat,
99    pcconsole_write,
100    pcconsole_ioctl,
101    pcconsole_close,
102    pcconsole_poll,
103    NULL
104};
105
106const cfe_driver_t pcconsole = {
107    "PC Console",
108    "pcconsole",
109    CFE_DEV_SERIAL,
110    &pcconsole_dispatch,
111    pcconsole_probe
112};
113
114
115/*  *********************************************************************
116    *  Structures
117    ********************************************************************* */
118
119
120typedef struct pcconsole_s {
121    vga_term_t vga;
122    keystate_t ks;
123    uint32_t kbd_status;
124    uint32_t kbd_data;
125} pcconsole_t;
126
127
128/*  *********************************************************************
129    *  pcconsole_poll(ctx,ticks)
130    *
131    *  Poll routine - check for new keyboard events
132    *
133    *  Input parameters:
134    *  	   ctx - device context
135    *  	   ticks - current time
136    *
137    *  Return value:
138    *  	   nothing
139    ********************************************************************* */
140
141
142static void pcconsole_poll(cfe_devctx_t *ctx,int64_t ticks)
143{
144    pcconsole_t *softc = ctx->dev_softc;
145    uint8_t status;
146    uint8_t b;
147
148    status = inb(softc->kbd_status);
149
150    if (status & KBD_RXFULL) {
151	b = inb(softc->kbd_data);
152	kbd_doscan(&(softc->ks),b);
153	}
154}
155
156/*  *********************************************************************
157    *  pcconsole_waitcmdready(softc)
158    *
159    *  Wait for the keyboard to be ready to accept a command
160    *
161    *  Input parameters:
162    *  	   softc - console structure
163    *
164    *  Return value:
165    *  	   nothing
166    ********************************************************************* */
167
168static void pcconsole_waitcmdready(pcconsole_t *softc)
169{
170    uint8_t status;
171    uint8_t data;
172
173    for (;;) {
174	status = inb(softc->kbd_status);	/* read status */
175	if (status & KBD_RXFULL) {
176	    data = inb(softc->kbd_data);	/* get data */
177	    kbd_doscan(&(softc->ks),data);	/* process scan codes */
178	    }
179	if (!(status & KBD_TXFULL)) break;	/* stop when kbd ready */
180	}
181}
182
183
184/*  *********************************************************************
185    *  pcconsole_setleds(ks,leds)
186    *
187    *  Callback from the keyboard routines for setting the LEDS
188    *
189    *  Input parameters:
190    *  	   ks - keyboard state
191    *  	   leds - new LED state
192    *
193    *  Return value:
194    *  	   0
195    ********************************************************************* */
196
197static int pcconsole_setleds(keystate_t *ks,int leds)
198{
199    pcconsole_t *softc = kbd_getref(ks);
200
201    pcconsole_waitcmdready(softc);
202    outb(softc->kbd_data,KBDCMD_SETLEDS);
203    pcconsole_waitcmdready(softc);
204    outb(softc->kbd_data,(leds & 7));
205
206    return 0;
207}
208
209
210/*  *********************************************************************
211    *  pcconsole_probe(drv,probe_a,probe_b,probe_ptr)
212    *
213    *  Probe routine.  This routine sets up the pcconsole device
214    *
215    *  Input parameters:
216    *  	   drv - driver structure
217    *  	   probe_a
218    *  	   probe_b
219    *  	   probe_ptr
220    *
221    *  Return value:
222    *  	   nothing
223    ********************************************************************* */
224
225static void pcconsole_probe(cfe_driver_t *drv,
226			      unsigned long probe_a, unsigned long probe_b,
227			      void *probe_ptr)
228{
229    pcconsole_t *softc;
230    char descr[80];
231    volatile uint8_t *isamem;
232
233    /*
234     * probe_a is
235     * probe_b is
236     * probe_ptr is
237     */
238
239    softc = (pcconsole_t *) KMALLOC(sizeof(pcconsole_t),0);
240    if (softc) {
241	/*
242	 * XXX This should not be hardwired.
243	 */
244	softc->kbd_status = 0x64;
245	softc->kbd_data =   0x60;
246	kbd_init(&(softc->ks),pcconsole_setleds,softc);
247
248	/*
249	 * XXX this should not be hardwired
250	 */
251	isamem = (volatile uint8_t *) ((uintptr_t)cpu_isamap(0,1024*1024));
252	vga_init(&(softc->vga),__ISAaddr(VGA_TEXTBUF_COLOR),outb);
253
254	xsprintf(descr,"%s",drv->drv_description,probe_a,probe_b);
255	cfe_attach(drv,softc,NULL,descr);
256	}
257
258}
259
260
261static int pcconsole_open(cfe_devctx_t *ctx)
262{
263    pcconsole_t *softc = ctx->dev_softc;
264
265    outb(softc->kbd_data,KBDCMD_RESET);		/* reset keyboard */
266    kbd_init(&(softc->ks),pcconsole_setleds,softc);
267    vga_clear(&(softc->vga));
268    vga_setcursor(&(softc->vga),0,0);
269
270    return 0;
271}
272
273static int pcconsole_read(cfe_devctx_t *ctx,iocb_buffer_t *buffer)
274{
275    pcconsole_t *softc = ctx->dev_softc;
276    hsaddr_t bptr;
277    uint8_t b;
278    int blen;
279
280    pcconsole_poll(ctx,0);
281
282    bptr = buffer->buf_ptr;
283    blen = buffer->buf_length;
284
285    while ((blen > 0) && (kbd_inpstat(&(softc->ks)))) {
286	b = (kbd_read(&(softc->ks)) & 0xFF);
287	hs_write8(bptr,b);
288	bptr++;
289	blen--;
290	}
291
292    buffer->buf_retlen = buffer->buf_length - blen;
293    return 0;
294}
295
296static int pcconsole_inpstat(cfe_devctx_t *ctx,iocb_inpstat_t *inpstat)
297{
298    pcconsole_t *softc = ctx->dev_softc;
299
300    pcconsole_poll(ctx,0);
301
302    inpstat->inp_status = kbd_inpstat(&(softc->ks)) ? 1 : 0;
303
304    return 0;
305}
306
307static int pcconsole_write(cfe_devctx_t *ctx,iocb_buffer_t *buffer)
308{
309    pcconsole_t *softc = ctx->dev_softc;
310    hsaddr_t bptr;
311    int blen;
312
313    bptr = buffer->buf_ptr;
314    blen = buffer->buf_length;
315
316    vga_writestr(&(softc->vga),bptr,7,blen);
317
318    buffer->buf_retlen = buffer->buf_length;
319    return 0;
320}
321
322static int pcconsole_ioctl(cfe_devctx_t *ctx,iocb_buffer_t *buffer)
323{
324/*    pcconsole_t *softc = ctx->dev_softc;*/
325
326    return -1;
327}
328
329static int pcconsole_close(cfe_devctx_t *ctx)
330{
331/*    pcconsole_t *softc = ctx->dev_softc;*/
332
333    return 0;
334}
335
336
337