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