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