diff options
Diffstat (limited to 'cfe/cfe/dev/dev_promice.c')
-rw-r--r-- | cfe/cfe/dev/dev_promice.c | 402 |
1 files changed, 402 insertions, 0 deletions
diff --git a/cfe/cfe/dev/dev_promice.c b/cfe/cfe/dev/dev_promice.c new file mode 100644 index 0000000..fe79086 --- /dev/null +++ b/cfe/cfe/dev/dev_promice.c @@ -0,0 +1,402 @@ +/* ********************************************************************* + * Broadcom Common Firmware Environment (CFE) + * + * PromICE console device File: dev_promice.c + * + * This device driver supports Grammar Engine's PromICE AI2 + * serial communications options. With this console, you can + * communicate with the firmware using only uncached reads in the + * boot ROM space. See Grammar Engine's PromICE manuals + * for more information at http://www.gei.com + * + * Author: Mitch Lichtenberg (mpl@broadcom.com) + * + ********************************************************************* + * + * Copyright 2000,2001,2002,2003 + * Broadcom Corporation. All rights reserved. + * + * This software is furnished under license and may be used and + * copied only in accordance with the following terms and + * conditions. Subject to these conditions, you may download, + * copy, install, use, modify and distribute modified or unmodified + * copies of this software in source and/or binary form. No title + * or ownership is transferred hereby. + * + * 1) Any source code used, modified or distributed must reproduce + * and retain this copyright notice and list of conditions + * as they appear in the source file. + * + * 2) No right is granted to use any trade name, trademark, or + * logo of Broadcom Corporation. The "Broadcom Corporation" + * name may not be used to endorse or promote products derived + * from this software without the prior written permission of + * Broadcom Corporation. + * + * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED + * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR + * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT + * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN + * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + * TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + ********************************************************************* */ + + +/* + * Example PromICE initialization file: + * + * ----------------------- + * output=com1 + * pponly=lpt1 + * rom=27040 + * word=8 + * file=cfe.srec + * ailoc 7FC00,9600 + * ----------------------- + * + * The offset specified in the 'ailoc' line must be the location where you + * will configure the AI2 serial port. In this example, the ROM is assumed + * to be 512KB, and the AI2 serial port is at 511KB, or offset 0x7FC00. + * This area is filled with 0xCC to detect AI2's initialization sequence + * properly (see the PromICE manual). You should connect your + * PromICE's serial port up to the PC and run a terminal emulator on it. + * The parallel port will be used for downloading data to the PromICE. + * + * If you have connected the write line to the PromICE, then you can + * define the _AIDIRT_ symbol to increase performance. + */ + + + +#include "lib_types.h" +#include "lib_malloc.h" +#include "lib_printf.h" +#include "lib_string.h" +#include "cfe_iocb.h" +#include "cfe_device.h" +#include "addrspace.h" + +#define _AIDIRT_ + +/* ********************************************************************* + * Prototypes + ********************************************************************* */ + +static void promice_probe(cfe_driver_t *drv, + unsigned long probe_a, unsigned long probe_b, + void *probe_ptr); + + +static int promice_open(cfe_devctx_t *ctx); +static int promice_read(cfe_devctx_t *ctx,iocb_buffer_t *buffer); +static int promice_inpstat(cfe_devctx_t *ctx,iocb_inpstat_t *inpstat); +static int promice_write(cfe_devctx_t *ctx,iocb_buffer_t *buffer); +static int promice_ioctl(cfe_devctx_t *ctx,iocb_buffer_t *buffer); +static int promice_close(cfe_devctx_t *ctx); + +/* ********************************************************************* + * Device dispatch table + ********************************************************************* */ + +const static cfe_devdisp_t promice_dispatch = { + promice_open, + promice_read, + promice_inpstat, + promice_write, + promice_ioctl, + promice_close, + NULL, + NULL +}; + +/* ********************************************************************* + * Device descriptor + ********************************************************************* */ + +const cfe_driver_t promice_uart = { + "PromICE AI2 Serial Port", + "promice", + CFE_DEV_SERIAL, + &promice_dispatch, + promice_probe +}; + +/* ********************************************************************* + * Local constants and structures + ********************************************************************* */ + +/* + * If your PromICE is connected to a 32-bit host (emulating four + * flash ROMs) and the SB1250 is set to boot from that host, define + * the PROMICE_32BITS symbol to make sure the AI2 interface is + * configured correctly. + */ + +/*#define PROMICE_32BITS*/ + +#ifdef PROMICE_32BITS +#define WORDSIZE 4 +#define WORDTYPE uint32_t +#else +#define WORDSIZE 1 +#define WORDTYPE uint8_t +#endif + + +#define ZERO_OFFSET (0) +#define ONE_OFFSET (1) +#define DATA_OFFSET (2) +#define STATUS_OFFSET (3) + +#define TDA 0x01 /* Target data available */ +#define HDA 0x02 /* Host data available */ +#define OVR 0x04 /* Host data overflow */ + +typedef struct promice_s { + unsigned long ai2_addr; + unsigned int ai2_wordsize; + volatile WORDTYPE *zero; + volatile WORDTYPE *one; + volatile WORDTYPE *data; + volatile WORDTYPE *status; +} promice_t; + + +/* ********************************************************************* + * promice_probe(drv,probe_a,probe_b,probe_ptr) + * + * Device "Probe" routine. This routine creates the soft + * context for the device and calls the attach routine. + * + * Input parameters: + * drv - driver structure + * probe_a,probe_b,probe_ptr - probe args + * + * Return value: + * nothing + ********************************************************************* */ + + +static void promice_probe(cfe_driver_t *drv, + unsigned long probe_a, + unsigned long probe_b, + void *probe_ptr) +{ + promice_t *softc; + char descr[80]; + + /* + * probe_a is the address in the ROM of the AI2 interface + * on the PromICE. + * probe_b is the word size (1,2,4) + */ + + softc = (promice_t *) KMALLOC(sizeof(promice_t),0); + if (softc) { + softc->ai2_addr = probe_a; + if (probe_b) softc->ai2_wordsize = probe_b; + else softc->ai2_wordsize = WORDSIZE; + xsprintf(descr,"%s at 0x%X",drv->drv_description,probe_a); + cfe_attach(drv,softc,NULL,descr); + } +} + + + +/* ********************************************************************* + * promice_open(ctx) + * + * Open the device + * + * Input parameters: + * ctx - device context + * + * Return value: + * 0 if ok, else error code + ********************************************************************* */ +static int promice_open(cfe_devctx_t *ctx) +{ + promice_t *softc = ctx->dev_softc; + uint8_t dummy; + + softc->zero = (volatile WORDTYPE *) + UNCADDR(softc->ai2_addr + (ZERO_OFFSET*softc->ai2_wordsize)); + softc->one = (volatile WORDTYPE *) + UNCADDR(softc->ai2_addr + (ONE_OFFSET*softc->ai2_wordsize)); + softc->data = (volatile WORDTYPE *) + UNCADDR(softc->ai2_addr + (DATA_OFFSET*softc->ai2_wordsize)); + softc->status = (volatile WORDTYPE *) + UNCADDR(softc->ai2_addr + (STATUS_OFFSET*softc->ai2_wordsize)); + + /* + * Wait for bit 3 to clear so we know the interface is ready. + */ + + while (*(softc->status) == 0xCC) ; /* NULL LOOP */ + + /* + * a dummy read is required to clear out the interface. + */ + + dummy = *(softc->data); + + return 0; +} + +/* ********************************************************************* + * promice_read(ctx,buffer) + * + * Read data from the device + * + * Input parameters: + * ctx - device context + * buffer - I/O buffer descriptor + * + * Return value: + * number of bytes transferred, or <0 if error + ********************************************************************* */ +static int promice_read(cfe_devctx_t *ctx,iocb_buffer_t *buffer) +{ + promice_t *softc = ctx->dev_softc; + unsigned char *bptr; + int blen; + + bptr = buffer->buf_ptr; + blen = buffer->buf_length; + + while ((blen > 0) && (*(softc->status) & HDA)) { + *bptr++ = *(softc->data); + blen--; + } + + buffer->buf_retlen = buffer->buf_length - blen; + return 0; +} + +/* ********************************************************************* + * promice_inpstat(ctx,inpstat) + * + * Determine if read data is available + * + * Input parameters: + * ctx - device context + * inpstat - input status structure + * + * Return value: + * 0 + ********************************************************************* */ + +static int promice_inpstat(cfe_devctx_t *ctx,iocb_inpstat_t *inpstat) +{ + promice_t *softc = ctx->dev_softc; + + inpstat->inp_status = (*(softc->status) & HDA) ? 1 : 0; + + return 0; +} + +/* ********************************************************************* + * promice_write(ctx,buffer) + * + * Write data to the device + * + * Input parameters: + * ctx - device context + * buffer - I/O buffer descriptor + * + * Return value: + * number of bytes transferred, or <0 if error + ********************************************************************* */ +static int promice_write(cfe_devctx_t *ctx,iocb_buffer_t *buffer) +{ + promice_t *softc = ctx->dev_softc; + unsigned char *bptr; + int blen; + uint8_t data; +#ifndef _AIDIRT_ + uint8_t dummy; + int count; +#endif + + bptr = buffer->buf_ptr; + blen = buffer->buf_length; + + + /* + * The AI2 interface requires you to transmit characters + * one bit at a time. First a '1' start bit, + * then 8 data bits (lsb first) then another '1' stop bit. + * + * Just reference the right memory location to transmit a bit. + */ + + while ((blen > 0) && !(*(softc->status) & TDA)) { + +#ifdef _AIDIRT_ + data = *bptr++; + *(softc->zero) = data; +#else + dummy = *(softc->one); /* send start bit */ + + data = *bptr++; + + for (count = 0; count < 8; count++) { + if (data & 1) dummy = *(softc->one); + else dummy = *(softc->zero); + data >>= 1; /* shift in next bit */ + } + + dummy = *(softc->one); /* send stop bit */ +#endif + + blen--; + } + + buffer->buf_retlen = buffer->buf_length - blen; + return 0; +} + +/* ********************************************************************* + * promice_ioctl(ctx,buffer) + * + * Do I/O control operations + * + * Input parameters: + * ctx - device context + * buffer - I/O control args + * + * Return value: + * 0 if ok + * else error code + ********************************************************************* */ + +static int promice_ioctl(cfe_devctx_t *ctx,iocb_buffer_t *buffer) +{ + return -1; +} + +/* ********************************************************************* + * promice_close(ctx) + * + * Close the device. + * + * Input parameters: + * ctx - device context + * + * Return value: + * 0 + ********************************************************************* */ + +static int promice_close(cfe_devctx_t *ctx) +{ + return 0; +} + + |