1/*  *********************************************************************
2    *  Broadcom Common Firmware Environment (CFE)
3    *
4    *  PromICE console device			File: dev_promice.c
5    *
6    *  This device driver supports Grammar Engine's PromICE AI2
7    *  serial communications options.  With this console, you can
8    *  communicate with the firmware using only uncached reads in the
9    *  boot ROM space.  See Grammar Engine's PromICE manuals
10    *  for more information at http://www.gei.com
11    *
12    *  Author:  Mitch Lichtenberg (mpl@broadcom.com)
13    *
14    *********************************************************************
15    *
16    *  Copyright 2000,2001,2002,2003
17    *  Broadcom Corporation. All rights reserved.
18    *
19    *  This software is furnished under license and may be used and
20    *  copied only in accordance with the following terms and
21    *  conditions.  Subject to these conditions, you may download,
22    *  copy, install, use, modify and distribute modified or unmodified
23    *  copies of this software in source and/or binary form.  No title
24    *  or ownership is transferred hereby.
25    *
26    *  1) Any source code used, modified or distributed must reproduce
27    *     and retain this copyright notice and list of conditions
28    *     as they appear in the source file.
29    *
30    *  2) No right is granted to use any trade name, trademark, or
31    *     logo of Broadcom Corporation.  The "Broadcom Corporation"
32    *     name may not be used to endorse or promote products derived
33    *     from this software without the prior written permission of
34    *     Broadcom Corporation.
35    *
36    *  3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
37    *     IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
38    *     WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
39    *     PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
40    *     SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
41    *     PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT,
42    *     INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
43    *     (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
44    *     GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
45    *     BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
46    *     OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
47    *     TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF
48    *     THE POSSIBILITY OF SUCH DAMAGE.
49    ********************************************************************* */
50
51
52/*
53 * Example PromICE initialization file:
54 *
55 * -----------------------
56 * output=com1
57 * pponly=lpt1
58 * rom=27040
59 * word=8
60 * file=cfe.srec
61 * ailoc 7FC00,9600
62 * -----------------------
63 *
64 * The offset specified in the 'ailoc' line must be the location where you
65 * will configure the AI2 serial port.  In this example, the ROM is assumed
66 * to be 512KB, and the AI2 serial port is at 511KB, or offset 0x7FC00.
67 * This area is filled with 0xCC to detect AI2's initialization sequence
68 * properly (see the PromICE manual).  You should connect your
69 * PromICE's serial port up to the PC and run a terminal emulator on it.
70 * The parallel port will be used for downloading data to the PromICE.
71 *
72 * If you have connected the write line to the PromICE, then you can
73 * define the _AIDIRT_ symbol to increase performance.
74 */
75
76
77
78#include "lib_types.h"
79#include "lib_malloc.h"
80#include "lib_printf.h"
81#include "lib_string.h"
82#include "cfe_iocb.h"
83#include "cfe_device.h"
84#include "addrspace.h"
85
86#define _AIDIRT_
87
88/*  *********************************************************************
89    *  Prototypes
90    ********************************************************************* */
91
92static void promice_probe(cfe_driver_t *drv,
93			      unsigned long probe_a, unsigned long probe_b,
94			      void *probe_ptr);
95
96
97static int promice_open(cfe_devctx_t *ctx);
98static int promice_read(cfe_devctx_t *ctx,iocb_buffer_t *buffer);
99static int promice_inpstat(cfe_devctx_t *ctx,iocb_inpstat_t *inpstat);
100static int promice_write(cfe_devctx_t *ctx,iocb_buffer_t *buffer);
101static int promice_ioctl(cfe_devctx_t *ctx,iocb_buffer_t *buffer);
102static int promice_close(cfe_devctx_t *ctx);
103
104/*  *********************************************************************
105    *  Device dispatch table
106    ********************************************************************* */
107
108const static cfe_devdisp_t promice_dispatch = {
109    promice_open,
110    promice_read,
111    promice_inpstat,
112    promice_write,
113    promice_ioctl,
114    promice_close,
115    NULL,
116    NULL
117};
118
119/*  *********************************************************************
120    *  Device descriptor
121    ********************************************************************* */
122
123const cfe_driver_t promice_uart = {
124    "PromICE AI2 Serial Port",
125    "promice",
126    CFE_DEV_SERIAL,
127    &promice_dispatch,
128    promice_probe
129};
130
131/*  *********************************************************************
132    *  Local constants and structures
133    ********************************************************************* */
134
135/*
136 * If your PromICE is connected to a 32-bit host (emulating four
137 * flash ROMs) and the SB1250 is set to boot from that host, define
138 * the PROMICE_32BITS symbol to make sure the AI2 interface is
139 * configured correctly.
140 */
141
142/*#define PROMICE_32BITS*/
143
144#ifdef PROMICE_32BITS
145#define WORDSIZE	4
146#define WORDTYPE	uint32_t
147#else
148#define WORDSIZE	1
149#define WORDTYPE	uint8_t
150#endif
151
152
153#define ZERO_OFFSET	(0)
154#define ONE_OFFSET	(1)
155#define DATA_OFFSET	(2)
156#define STATUS_OFFSET	(3)
157
158#define TDA 0x01 	/* Target data available */
159#define HDA 0x02 	/* Host data available */
160#define OVR 0x04 	/* Host data overflow */
161
162typedef struct promice_s {
163    unsigned long ai2_addr;
164    unsigned int ai2_wordsize;
165    volatile WORDTYPE *zero;
166    volatile WORDTYPE *one;
167    volatile WORDTYPE *data;
168    volatile WORDTYPE *status;
169} promice_t;
170
171
172/*  *********************************************************************
173    *  promice_probe(drv,probe_a,probe_b,probe_ptr)
174    *
175    *  Device "Probe" routine.  This routine creates the soft
176    *  context for the device and calls the attach routine.
177    *
178    *  Input parameters:
179    *  	   drv - driver structure
180    *  	   probe_a,probe_b,probe_ptr - probe args
181    *
182    *  Return value:
183    *  	   nothing
184    ********************************************************************* */
185
186
187static void promice_probe(cfe_driver_t *drv,
188			  unsigned long probe_a,
189			  unsigned long probe_b,
190			  void *probe_ptr)
191{
192    promice_t *softc;
193    char descr[80];
194
195    /*
196     * probe_a is the address in the ROM of the AI2 interface
197     * on the PromICE.
198     * probe_b is the word size (1,2,4)
199     */
200
201    softc = (promice_t *) KMALLOC(sizeof(promice_t),0);
202    if (softc) {
203	softc->ai2_addr = probe_a;
204	if (probe_b) softc->ai2_wordsize = probe_b;
205	else softc->ai2_wordsize = WORDSIZE;
206	xsprintf(descr,"%s at 0x%X",drv->drv_description,probe_a);
207	cfe_attach(drv,softc,NULL,descr);
208	}
209}
210
211
212
213/*  *********************************************************************
214    *  promice_open(ctx)
215    *
216    *  Open the device
217    *
218    *  Input parameters:
219    *  	   ctx - device context
220    *
221    *  Return value:
222    *  	   0 if ok, else error code
223    ********************************************************************* */
224static int promice_open(cfe_devctx_t *ctx)
225{
226    promice_t *softc = ctx->dev_softc;
227    uint8_t dummy;
228
229    softc->zero   = (volatile WORDTYPE *)
230	UNCADDR(softc->ai2_addr + (ZERO_OFFSET*softc->ai2_wordsize));
231    softc->one    = (volatile WORDTYPE *)
232	UNCADDR(softc->ai2_addr + (ONE_OFFSET*softc->ai2_wordsize));
233    softc->data   = (volatile WORDTYPE *)
234	UNCADDR(softc->ai2_addr + (DATA_OFFSET*softc->ai2_wordsize));
235    softc->status = (volatile WORDTYPE *)
236	UNCADDR(softc->ai2_addr + (STATUS_OFFSET*softc->ai2_wordsize));
237
238    /*
239     * Wait for bit 3 to clear so we know the interface is ready.
240     */
241
242    while (*(softc->status) == 0xCC) ; 	/* NULL LOOP */
243
244    /*
245     * a dummy read is required to clear out the interface.
246     */
247
248    dummy = *(softc->data);
249
250    return 0;
251}
252
253/*  *********************************************************************
254    *  promice_read(ctx,buffer)
255    *
256    *  Read data from the device
257    *
258    *  Input parameters:
259    *  	   ctx - device context
260    *  	   buffer - I/O buffer descriptor
261    *
262    *  Return value:
263    *  	   number of bytes transferred, or <0 if error
264    ********************************************************************* */
265static int promice_read(cfe_devctx_t *ctx,iocb_buffer_t *buffer)
266{
267    promice_t *softc = ctx->dev_softc;
268    unsigned char *bptr;
269    int blen;
270
271    bptr = buffer->buf_ptr;
272    blen = buffer->buf_length;
273
274    while ((blen > 0) && (*(softc->status) & HDA)) {
275	*bptr++ = *(softc->data);
276	blen--;
277	}
278
279    buffer->buf_retlen = buffer->buf_length - blen;
280    return 0;
281}
282
283/*  *********************************************************************
284    *  promice_inpstat(ctx,inpstat)
285    *
286    *  Determine if read data is available
287    *
288    *  Input parameters:
289    *  	   ctx - device context
290    *  	   inpstat - input status structure
291    *
292    *  Return value:
293    *  	   0
294    ********************************************************************* */
295
296static int promice_inpstat(cfe_devctx_t *ctx,iocb_inpstat_t *inpstat)
297{
298    promice_t *softc = ctx->dev_softc;
299
300    inpstat->inp_status = (*(softc->status) & HDA) ? 1 : 0;
301
302    return 0;
303}
304
305/*  *********************************************************************
306    *  promice_write(ctx,buffer)
307    *
308    *  Write data to the device
309    *
310    *  Input parameters:
311    *  	   ctx - device context
312    *  	   buffer - I/O buffer descriptor
313    *
314    *  Return value:
315    *  	   number of bytes transferred, or <0 if error
316    ********************************************************************* */
317static int promice_write(cfe_devctx_t *ctx,iocb_buffer_t *buffer)
318{
319    promice_t *softc = ctx->dev_softc;
320    unsigned char *bptr;
321    int blen;
322    uint8_t data;
323#ifndef _AIDIRT_
324    uint8_t dummy;
325    int count;
326#endif
327
328    bptr = buffer->buf_ptr;
329    blen = buffer->buf_length;
330
331
332    /*
333     * The AI2 interface requires you to transmit characters
334     * one bit at a time.  First a '1' start bit,
335     * then 8 data bits (lsb first) then another '1' stop bit.
336     *
337     * Just reference the right memory location to transmit a bit.
338     */
339
340    while ((blen > 0) && !(*(softc->status) & TDA)) {
341
342#ifdef _AIDIRT_
343	data = *bptr++;
344	*(softc->zero) = data;
345#else
346	dummy = *(softc->one);		/* send start bit */
347
348	data = *bptr++;
349
350	for (count = 0; count < 8; count++) {
351	    if (data & 1) dummy = *(softc->one);
352	    else dummy = *(softc->zero);
353	    data >>= 1; 		/* shift in next bit */
354	    }
355
356	dummy = *(softc->one);		/* send stop bit */
357#endif
358
359	blen--;
360	}
361
362    buffer->buf_retlen = buffer->buf_length - blen;
363    return 0;
364}
365
366/*  *********************************************************************
367    *  promice_ioctl(ctx,buffer)
368    *
369    *  Do I/O control operations
370    *
371    *  Input parameters:
372    *  	   ctx - device context
373    *  	   buffer - I/O control args
374    *
375    *  Return value:
376    *  	   0 if ok
377    *  	   else error code
378    ********************************************************************* */
379
380static int promice_ioctl(cfe_devctx_t *ctx,iocb_buffer_t *buffer)
381{
382    return -1;
383}
384
385/*  *********************************************************************
386    *  promice_close(ctx)
387    *
388    *  Close the device.
389    *
390    *  Input parameters:
391    *  	   ctx - device context
392    *
393    *  Return value:
394    *  	   0
395    ********************************************************************* */
396
397static int promice_close(cfe_devctx_t *ctx)
398{
399    return 0;
400}
401
402
403