linux/arch/mips/fw/cfe/cfe_api.c
<<
>>
Prefs
   1/*
   2 * Copyright (C) 2000, 2001, 2002 Broadcom Corporation
   3 *
   4 * This program is free software; you can redistribute it and/or
   5 * modify it under the terms of the GNU General Public License
   6 * as published by the Free Software Foundation; either version 2
   7 * of the License, or (at your option) any later version.
   8 *
   9 * This program is distributed in the hope that it will be useful,
  10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12 * GNU General Public License for more details.
  13 *
  14 * You should have received a copy of the GNU General Public License
  15 * along with this program; if not, write to the Free Software
  16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  17 */
  18
  19/*
  20 *
  21 * Broadcom Common Firmware Environment (CFE)
  22 *
  23 * This module contains device function stubs (small routines to
  24 * call the standard "iocb" interface entry point to CFE).
  25 * There should be one routine here per iocb function call.
  26 *
  27 * Authors:  Mitch Lichtenberg, Chris Demetriou
  28 */
  29
  30#include <asm/fw/cfe/cfe_api.h>
  31#include "cfe_api_int.h"
  32
  33/* Cast from a native pointer to a cfe_xptr_t and back.  */
  34#define XPTR_FROM_NATIVE(n)     ((cfe_xptr_t) (intptr_t) (n))
  35#define NATIVE_FROM_XPTR(x)     ((void *) (intptr_t) (x))
  36
  37int cfe_iocb_dispatch(struct cfe_xiocb *xiocb);
  38
  39/*
  40 * Declare the dispatch function with args of "intptr_t".
  41 * This makes sure whatever model we're compiling in
  42 * puts the pointers in a single register.  For example,
  43 * combining -mlong64 and -mips1 or -mips2 would lead to
  44 * trouble, since the handle and IOCB pointer will be
  45 * passed in two registers each, and CFE expects one.
  46 */
  47
  48static int (*cfe_dispfunc) (intptr_t handle, intptr_t xiocb);
  49static u64 cfe_handle;
  50
  51int cfe_init(u64 handle, u64 ept)
  52{
  53        cfe_dispfunc = NATIVE_FROM_XPTR(ept);
  54        cfe_handle = handle;
  55        return 0;
  56}
  57
  58int cfe_iocb_dispatch(struct cfe_xiocb * xiocb)
  59{
  60        if (!cfe_dispfunc)
  61                return -1;
  62        return (*cfe_dispfunc) ((intptr_t) cfe_handle, (intptr_t) xiocb);
  63}
  64
  65int cfe_close(int handle)
  66{
  67        struct cfe_xiocb xiocb;
  68
  69        xiocb.xiocb_fcode = CFE_CMD_DEV_CLOSE;
  70        xiocb.xiocb_status = 0;
  71        xiocb.xiocb_handle = handle;
  72        xiocb.xiocb_flags = 0;
  73        xiocb.xiocb_psize = 0;
  74
  75        cfe_iocb_dispatch(&xiocb);
  76
  77        return xiocb.xiocb_status;
  78
  79}
  80
  81int cfe_cpu_start(int cpu, void (*fn) (void), long sp, long gp, long a1)
  82{
  83        struct cfe_xiocb xiocb;
  84
  85        xiocb.xiocb_fcode = CFE_CMD_FW_CPUCTL;
  86        xiocb.xiocb_status = 0;
  87        xiocb.xiocb_handle = 0;
  88        xiocb.xiocb_flags = 0;
  89        xiocb.xiocb_psize = sizeof(struct xiocb_cpuctl);
  90        xiocb.plist.xiocb_cpuctl.cpu_number = cpu;
  91        xiocb.plist.xiocb_cpuctl.cpu_command = CFE_CPU_CMD_START;
  92        xiocb.plist.xiocb_cpuctl.gp_val = gp;
  93        xiocb.plist.xiocb_cpuctl.sp_val = sp;
  94        xiocb.plist.xiocb_cpuctl.a1_val = a1;
  95        xiocb.plist.xiocb_cpuctl.start_addr = (long) fn;
  96
  97        cfe_iocb_dispatch(&xiocb);
  98
  99        return xiocb.xiocb_status;
 100}
 101
 102int cfe_cpu_stop(int cpu)
 103{
 104        struct cfe_xiocb xiocb;
 105
 106        xiocb.xiocb_fcode = CFE_CMD_FW_CPUCTL;
 107        xiocb.xiocb_status = 0;
 108        xiocb.xiocb_handle = 0;
 109        xiocb.xiocb_flags = 0;
 110        xiocb.xiocb_psize = sizeof(struct xiocb_cpuctl);
 111        xiocb.plist.xiocb_cpuctl.cpu_number = cpu;
 112        xiocb.plist.xiocb_cpuctl.cpu_command = CFE_CPU_CMD_STOP;
 113
 114        cfe_iocb_dispatch(&xiocb);
 115
 116        return xiocb.xiocb_status;
 117}
 118
 119int cfe_enumenv(int idx, char *name, int namelen, char *val, int vallen)
 120{
 121        struct cfe_xiocb xiocb;
 122
 123        xiocb.xiocb_fcode = CFE_CMD_ENV_SET;
 124        xiocb.xiocb_status = 0;
 125        xiocb.xiocb_handle = 0;
 126        xiocb.xiocb_flags = 0;
 127        xiocb.xiocb_psize = sizeof(struct xiocb_envbuf);
 128        xiocb.plist.xiocb_envbuf.enum_idx = idx;
 129        xiocb.plist.xiocb_envbuf.name_ptr = XPTR_FROM_NATIVE(name);
 130        xiocb.plist.xiocb_envbuf.name_length = namelen;
 131        xiocb.plist.xiocb_envbuf.val_ptr = XPTR_FROM_NATIVE(val);
 132        xiocb.plist.xiocb_envbuf.val_length = vallen;
 133
 134        cfe_iocb_dispatch(&xiocb);
 135
 136        return xiocb.xiocb_status;
 137}
 138
 139int
 140cfe_enummem(int idx, int flags, u64 *start, u64 *length, u64 *type)
 141{
 142        struct cfe_xiocb xiocb;
 143
 144        xiocb.xiocb_fcode = CFE_CMD_FW_MEMENUM;
 145        xiocb.xiocb_status = 0;
 146        xiocb.xiocb_handle = 0;
 147        xiocb.xiocb_flags = flags;
 148        xiocb.xiocb_psize = sizeof(struct xiocb_meminfo);
 149        xiocb.plist.xiocb_meminfo.mi_idx = idx;
 150
 151        cfe_iocb_dispatch(&xiocb);
 152
 153        if (xiocb.xiocb_status < 0)
 154                return xiocb.xiocb_status;
 155
 156        *start = xiocb.plist.xiocb_meminfo.mi_addr;
 157        *length = xiocb.plist.xiocb_meminfo.mi_size;
 158        *type = xiocb.plist.xiocb_meminfo.mi_type;
 159
 160        return 0;
 161}
 162
 163int cfe_exit(int warm, int status)
 164{
 165        struct cfe_xiocb xiocb;
 166
 167        xiocb.xiocb_fcode = CFE_CMD_FW_RESTART;
 168        xiocb.xiocb_status = 0;
 169        xiocb.xiocb_handle = 0;
 170        xiocb.xiocb_flags = warm ? CFE_FLG_WARMSTART : 0;
 171        xiocb.xiocb_psize = sizeof(struct xiocb_exitstat);
 172        xiocb.plist.xiocb_exitstat.status = status;
 173
 174        cfe_iocb_dispatch(&xiocb);
 175
 176        return xiocb.xiocb_status;
 177}
 178
 179int cfe_flushcache(int flg)
 180{
 181        struct cfe_xiocb xiocb;
 182
 183        xiocb.xiocb_fcode = CFE_CMD_FW_FLUSHCACHE;
 184        xiocb.xiocb_status = 0;
 185        xiocb.xiocb_handle = 0;
 186        xiocb.xiocb_flags = flg;
 187        xiocb.xiocb_psize = 0;
 188
 189        cfe_iocb_dispatch(&xiocb);
 190
 191        return xiocb.xiocb_status;
 192}
 193
 194int cfe_getdevinfo(char *name)
 195{
 196        struct cfe_xiocb xiocb;
 197
 198        xiocb.xiocb_fcode = CFE_CMD_DEV_GETINFO;
 199        xiocb.xiocb_status = 0;
 200        xiocb.xiocb_handle = 0;
 201        xiocb.xiocb_flags = 0;
 202        xiocb.xiocb_psize = sizeof(struct xiocb_buffer);
 203        xiocb.plist.xiocb_buffer.buf_offset = 0;
 204        xiocb.plist.xiocb_buffer.buf_ptr = XPTR_FROM_NATIVE(name);
 205        xiocb.plist.xiocb_buffer.buf_length = strlen(name);
 206
 207        cfe_iocb_dispatch(&xiocb);
 208
 209        if (xiocb.xiocb_status < 0)
 210                return xiocb.xiocb_status;
 211        return xiocb.plist.xiocb_buffer.buf_ioctlcmd;
 212}
 213
 214int cfe_getenv(char *name, char *dest, int destlen)
 215{
 216        struct cfe_xiocb xiocb;
 217
 218        *dest = 0;
 219
 220        xiocb.xiocb_fcode = CFE_CMD_ENV_GET;
 221        xiocb.xiocb_status = 0;
 222        xiocb.xiocb_handle = 0;
 223        xiocb.xiocb_flags = 0;
 224        xiocb.xiocb_psize = sizeof(struct xiocb_envbuf);
 225        xiocb.plist.xiocb_envbuf.enum_idx = 0;
 226        xiocb.plist.xiocb_envbuf.name_ptr = XPTR_FROM_NATIVE(name);
 227        xiocb.plist.xiocb_envbuf.name_length = strlen(name);
 228        xiocb.plist.xiocb_envbuf.val_ptr = XPTR_FROM_NATIVE(dest);
 229        xiocb.plist.xiocb_envbuf.val_length = destlen;
 230
 231        cfe_iocb_dispatch(&xiocb);
 232
 233        return xiocb.xiocb_status;
 234}
 235
 236int cfe_getfwinfo(cfe_fwinfo_t * info)
 237{
 238        struct cfe_xiocb xiocb;
 239
 240        xiocb.xiocb_fcode = CFE_CMD_FW_GETINFO;
 241        xiocb.xiocb_status = 0;
 242        xiocb.xiocb_handle = 0;
 243        xiocb.xiocb_flags = 0;
 244        xiocb.xiocb_psize = sizeof(struct xiocb_fwinfo);
 245
 246        cfe_iocb_dispatch(&xiocb);
 247
 248        if (xiocb.xiocb_status < 0)
 249                return xiocb.xiocb_status;
 250
 251        info->fwi_version = xiocb.plist.xiocb_fwinfo.fwi_version;
 252        info->fwi_totalmem = xiocb.plist.xiocb_fwinfo.fwi_totalmem;
 253        info->fwi_flags = xiocb.plist.xiocb_fwinfo.fwi_flags;
 254        info->fwi_boardid = xiocb.plist.xiocb_fwinfo.fwi_boardid;
 255        info->fwi_bootarea_va = xiocb.plist.xiocb_fwinfo.fwi_bootarea_va;
 256        info->fwi_bootarea_pa = xiocb.plist.xiocb_fwinfo.fwi_bootarea_pa;
 257        info->fwi_bootarea_size =
 258            xiocb.plist.xiocb_fwinfo.fwi_bootarea_size;
 259#if 0
 260        info->fwi_reserved1 = xiocb.plist.xiocb_fwinfo.fwi_reserved1;
 261        info->fwi_reserved2 = xiocb.plist.xiocb_fwinfo.fwi_reserved2;
 262        info->fwi_reserved3 = xiocb.plist.xiocb_fwinfo.fwi_reserved3;
 263#endif
 264
 265        return 0;
 266}
 267
 268int cfe_getstdhandle(int flg)
 269{
 270        struct cfe_xiocb xiocb;
 271
 272        xiocb.xiocb_fcode = CFE_CMD_DEV_GETHANDLE;
 273        xiocb.xiocb_status = 0;
 274        xiocb.xiocb_handle = 0;
 275        xiocb.xiocb_flags = flg;
 276        xiocb.xiocb_psize = 0;
 277
 278        cfe_iocb_dispatch(&xiocb);
 279
 280        if (xiocb.xiocb_status < 0)
 281                return xiocb.xiocb_status;
 282        return xiocb.xiocb_handle;
 283}
 284
 285int64_t
 286cfe_getticks(void)
 287{
 288        struct cfe_xiocb xiocb;
 289
 290        xiocb.xiocb_fcode = CFE_CMD_FW_GETTIME;
 291        xiocb.xiocb_status = 0;
 292        xiocb.xiocb_handle = 0;
 293        xiocb.xiocb_flags = 0;
 294        xiocb.xiocb_psize = sizeof(struct xiocb_time);
 295        xiocb.plist.xiocb_time.ticks = 0;
 296
 297        cfe_iocb_dispatch(&xiocb);
 298
 299        return xiocb.plist.xiocb_time.ticks;
 300
 301}
 302
 303int cfe_inpstat(int handle)
 304{
 305        struct cfe_xiocb xiocb;
 306
 307        xiocb.xiocb_fcode = CFE_CMD_DEV_INPSTAT;
 308        xiocb.xiocb_status = 0;
 309        xiocb.xiocb_handle = handle;
 310        xiocb.xiocb_flags = 0;
 311        xiocb.xiocb_psize = sizeof(struct xiocb_inpstat);
 312        xiocb.plist.xiocb_inpstat.inp_status = 0;
 313
 314        cfe_iocb_dispatch(&xiocb);
 315
 316        if (xiocb.xiocb_status < 0)
 317                return xiocb.xiocb_status;
 318        return xiocb.plist.xiocb_inpstat.inp_status;
 319}
 320
 321int
 322cfe_ioctl(int handle, unsigned int ioctlnum, unsigned char *buffer,
 323          int length, int *retlen, u64 offset)
 324{
 325        struct cfe_xiocb xiocb;
 326
 327        xiocb.xiocb_fcode = CFE_CMD_DEV_IOCTL;
 328        xiocb.xiocb_status = 0;
 329        xiocb.xiocb_handle = handle;
 330        xiocb.xiocb_flags = 0;
 331        xiocb.xiocb_psize = sizeof(struct xiocb_buffer);
 332        xiocb.plist.xiocb_buffer.buf_offset = offset;
 333        xiocb.plist.xiocb_buffer.buf_ioctlcmd = ioctlnum;
 334        xiocb.plist.xiocb_buffer.buf_ptr = XPTR_FROM_NATIVE(buffer);
 335        xiocb.plist.xiocb_buffer.buf_length = length;
 336
 337        cfe_iocb_dispatch(&xiocb);
 338
 339        if (retlen)
 340                *retlen = xiocb.plist.xiocb_buffer.buf_retlen;
 341        return xiocb.xiocb_status;
 342}
 343
 344int cfe_open(char *name)
 345{
 346        struct cfe_xiocb xiocb;
 347
 348        xiocb.xiocb_fcode = CFE_CMD_DEV_OPEN;
 349        xiocb.xiocb_status = 0;
 350        xiocb.xiocb_handle = 0;
 351        xiocb.xiocb_flags = 0;
 352        xiocb.xiocb_psize = sizeof(struct xiocb_buffer);
 353        xiocb.plist.xiocb_buffer.buf_offset = 0;
 354        xiocb.plist.xiocb_buffer.buf_ptr = XPTR_FROM_NATIVE(name);
 355        xiocb.plist.xiocb_buffer.buf_length = strlen(name);
 356
 357        cfe_iocb_dispatch(&xiocb);
 358
 359        if (xiocb.xiocb_status < 0)
 360                return xiocb.xiocb_status;
 361        return xiocb.xiocb_handle;
 362}
 363
 364int cfe_read(int handle, unsigned char *buffer, int length)
 365{
 366        return cfe_readblk(handle, 0, buffer, length);
 367}
 368
 369int cfe_readblk(int handle, s64 offset, unsigned char *buffer, int length)
 370{
 371        struct cfe_xiocb xiocb;
 372
 373        xiocb.xiocb_fcode = CFE_CMD_DEV_READ;
 374        xiocb.xiocb_status = 0;
 375        xiocb.xiocb_handle = handle;
 376        xiocb.xiocb_flags = 0;
 377        xiocb.xiocb_psize = sizeof(struct xiocb_buffer);
 378        xiocb.plist.xiocb_buffer.buf_offset = offset;
 379        xiocb.plist.xiocb_buffer.buf_ptr = XPTR_FROM_NATIVE(buffer);
 380        xiocb.plist.xiocb_buffer.buf_length = length;
 381
 382        cfe_iocb_dispatch(&xiocb);
 383
 384        if (xiocb.xiocb_status < 0)
 385                return xiocb.xiocb_status;
 386        return xiocb.plist.xiocb_buffer.buf_retlen;
 387}
 388
 389int cfe_setenv(char *name, char *val)
 390{
 391        struct cfe_xiocb xiocb;
 392
 393        xiocb.xiocb_fcode = CFE_CMD_ENV_SET;
 394        xiocb.xiocb_status = 0;
 395        xiocb.xiocb_handle = 0;
 396        xiocb.xiocb_flags = 0;
 397        xiocb.xiocb_psize = sizeof(struct xiocb_envbuf);
 398        xiocb.plist.xiocb_envbuf.enum_idx = 0;
 399        xiocb.plist.xiocb_envbuf.name_ptr = XPTR_FROM_NATIVE(name);
 400        xiocb.plist.xiocb_envbuf.name_length = strlen(name);
 401        xiocb.plist.xiocb_envbuf.val_ptr = XPTR_FROM_NATIVE(val);
 402        xiocb.plist.xiocb_envbuf.val_length = strlen(val);
 403
 404        cfe_iocb_dispatch(&xiocb);
 405
 406        return xiocb.xiocb_status;
 407}
 408
 409int cfe_write(int handle, unsigned char *buffer, int length)
 410{
 411        return cfe_writeblk(handle, 0, buffer, length);
 412}
 413
 414int cfe_writeblk(int handle, s64 offset, unsigned char *buffer, int length)
 415{
 416        struct cfe_xiocb xiocb;
 417
 418        xiocb.xiocb_fcode = CFE_CMD_DEV_WRITE;
 419        xiocb.xiocb_status = 0;
 420        xiocb.xiocb_handle = handle;
 421        xiocb.xiocb_flags = 0;
 422        xiocb.xiocb_psize = sizeof(struct xiocb_buffer);
 423        xiocb.plist.xiocb_buffer.buf_offset = offset;
 424        xiocb.plist.xiocb_buffer.buf_ptr = XPTR_FROM_NATIVE(buffer);
 425        xiocb.plist.xiocb_buffer.buf_length = length;
 426
 427        cfe_iocb_dispatch(&xiocb);
 428
 429        if (xiocb.xiocb_status < 0)
 430                return xiocb.xiocb_status;
 431        return xiocb.plist.xiocb_buffer.buf_retlen;
 432}
 433