1*500856ebSRafal Jaworowski /* 2*500856ebSRafal Jaworowski * (C) Copyright 2007 Semihalf 3*500856ebSRafal Jaworowski * 4*500856ebSRafal Jaworowski * Written by: Rafal Jaworowski <raj@semihalf.com> 5*500856ebSRafal Jaworowski * 6*500856ebSRafal Jaworowski * See file CREDITS for list of people who contributed to this 7*500856ebSRafal Jaworowski * project. 8*500856ebSRafal Jaworowski * 9*500856ebSRafal Jaworowski * This program is free software; you can redistribute it and/or 10*500856ebSRafal Jaworowski * modify it under the terms of the GNU General Public License as 11*500856ebSRafal Jaworowski * published by the Free Software Foundation; either version 2 of 12*500856ebSRafal Jaworowski * the License, or (at your option) any later version. 13*500856ebSRafal Jaworowski * 14*500856ebSRafal Jaworowski * This program is distributed in the hope that it will be useful, 15*500856ebSRafal Jaworowski * but WITHOUT ANY WARRANTY; without even the implied warranty of 16*500856ebSRafal Jaworowski * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17*500856ebSRafal Jaworowski * GNU General Public License for more details. 18*500856ebSRafal Jaworowski * 19*500856ebSRafal Jaworowski * You should have received a copy of the GNU General Public License 20*500856ebSRafal Jaworowski * along with this program; if not, write to the Free Software 21*500856ebSRafal Jaworowski * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 22*500856ebSRafal Jaworowski * MA 02111-1307 USA 23*500856ebSRafal Jaworowski * 24*500856ebSRafal Jaworowski */ 25*500856ebSRafal Jaworowski 26*500856ebSRafal Jaworowski #include <config.h> 27*500856ebSRafal Jaworowski 28*500856ebSRafal Jaworowski #if defined(CONFIG_API) 29*500856ebSRafal Jaworowski 30*500856ebSRafal Jaworowski #include <command.h> 31*500856ebSRafal Jaworowski #include <common.h> 32*500856ebSRafal Jaworowski #include <malloc.h> 33*500856ebSRafal Jaworowski #include <linux/types.h> 34*500856ebSRafal Jaworowski #include <api_public.h> 35*500856ebSRafal Jaworowski 36*500856ebSRafal Jaworowski #include "api_private.h" 37*500856ebSRafal Jaworowski 38*500856ebSRafal Jaworowski #define DEBUG 39*500856ebSRafal Jaworowski #undef DEBUG 40*500856ebSRafal Jaworowski 41*500856ebSRafal Jaworowski /* U-Boot routines needed */ 42*500856ebSRafal Jaworowski extern int do_reset (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]); 43*500856ebSRafal Jaworowski extern uchar (*env_get_char)(int); 44*500856ebSRafal Jaworowski extern uchar *env_get_addr(int); 45*500856ebSRafal Jaworowski 46*500856ebSRafal Jaworowski /***************************************************************************** 47*500856ebSRafal Jaworowski * 48*500856ebSRafal Jaworowski * This is the API core. 49*500856ebSRafal Jaworowski * 50*500856ebSRafal Jaworowski * API_ functions are part of U-Boot code and constitute the lowest level 51*500856ebSRafal Jaworowski * calls: 52*500856ebSRafal Jaworowski * 53*500856ebSRafal Jaworowski * - they know what values they need as arguments 54*500856ebSRafal Jaworowski * - their direct return value pertains to the API_ "shell" itself (0 on 55*500856ebSRafal Jaworowski * success, some error code otherwise) 56*500856ebSRafal Jaworowski * - if the call returns a value it is buried within arguments 57*500856ebSRafal Jaworowski * 58*500856ebSRafal Jaworowski ****************************************************************************/ 59*500856ebSRafal Jaworowski 60*500856ebSRafal Jaworowski #ifdef DEBUG 61*500856ebSRafal Jaworowski #define debugf(fmt, args...) do { printf("%s(): ", __func__); printf(fmt, ##args); } while (0) 62*500856ebSRafal Jaworowski #else 63*500856ebSRafal Jaworowski #define debugf(fmt, args...) 64*500856ebSRafal Jaworowski #endif 65*500856ebSRafal Jaworowski 66*500856ebSRafal Jaworowski typedef int (*cfp_t)(va_list argp); 67*500856ebSRafal Jaworowski 68*500856ebSRafal Jaworowski static int calls_no; 69*500856ebSRafal Jaworowski 70*500856ebSRafal Jaworowski /* 71*500856ebSRafal Jaworowski * pseudo signature: 72*500856ebSRafal Jaworowski * 73*500856ebSRafal Jaworowski * int API_getc(int *c) 74*500856ebSRafal Jaworowski */ 75*500856ebSRafal Jaworowski static int API_getc(va_list ap) 76*500856ebSRafal Jaworowski { 77*500856ebSRafal Jaworowski int *c; 78*500856ebSRafal Jaworowski 79*500856ebSRafal Jaworowski if ((c = (int *)va_arg(ap, u_int32_t)) == NULL) 80*500856ebSRafal Jaworowski return API_EINVAL; 81*500856ebSRafal Jaworowski 82*500856ebSRafal Jaworowski *c = getc(); 83*500856ebSRafal Jaworowski return 0; 84*500856ebSRafal Jaworowski } 85*500856ebSRafal Jaworowski 86*500856ebSRafal Jaworowski /* 87*500856ebSRafal Jaworowski * pseudo signature: 88*500856ebSRafal Jaworowski * 89*500856ebSRafal Jaworowski * int API_tstc(int *c) 90*500856ebSRafal Jaworowski */ 91*500856ebSRafal Jaworowski static int API_tstc(va_list ap) 92*500856ebSRafal Jaworowski { 93*500856ebSRafal Jaworowski int *t; 94*500856ebSRafal Jaworowski 95*500856ebSRafal Jaworowski if ((t = (int *)va_arg(ap, u_int32_t)) == NULL) 96*500856ebSRafal Jaworowski return API_EINVAL; 97*500856ebSRafal Jaworowski 98*500856ebSRafal Jaworowski *t = tstc(); 99*500856ebSRafal Jaworowski return 0; 100*500856ebSRafal Jaworowski } 101*500856ebSRafal Jaworowski 102*500856ebSRafal Jaworowski /* 103*500856ebSRafal Jaworowski * pseudo signature: 104*500856ebSRafal Jaworowski * 105*500856ebSRafal Jaworowski * int API_putc(char *ch) 106*500856ebSRafal Jaworowski */ 107*500856ebSRafal Jaworowski static int API_putc(va_list ap) 108*500856ebSRafal Jaworowski { 109*500856ebSRafal Jaworowski char *c; 110*500856ebSRafal Jaworowski 111*500856ebSRafal Jaworowski if ((c = (char *)va_arg(ap, u_int32_t)) == NULL) 112*500856ebSRafal Jaworowski return API_EINVAL; 113*500856ebSRafal Jaworowski 114*500856ebSRafal Jaworowski putc(*c); 115*500856ebSRafal Jaworowski return 0; 116*500856ebSRafal Jaworowski } 117*500856ebSRafal Jaworowski 118*500856ebSRafal Jaworowski /* 119*500856ebSRafal Jaworowski * pseudo signature: 120*500856ebSRafal Jaworowski * 121*500856ebSRafal Jaworowski * int API_puts(char **s) 122*500856ebSRafal Jaworowski */ 123*500856ebSRafal Jaworowski static int API_puts(va_list ap) 124*500856ebSRafal Jaworowski { 125*500856ebSRafal Jaworowski char *s; 126*500856ebSRafal Jaworowski 127*500856ebSRafal Jaworowski if ((s = (char *)va_arg(ap, u_int32_t)) == NULL) 128*500856ebSRafal Jaworowski return API_EINVAL; 129*500856ebSRafal Jaworowski 130*500856ebSRafal Jaworowski puts(s); 131*500856ebSRafal Jaworowski return 0; 132*500856ebSRafal Jaworowski } 133*500856ebSRafal Jaworowski 134*500856ebSRafal Jaworowski /* 135*500856ebSRafal Jaworowski * pseudo signature: 136*500856ebSRafal Jaworowski * 137*500856ebSRafal Jaworowski * int API_reset(void) 138*500856ebSRafal Jaworowski */ 139*500856ebSRafal Jaworowski static int API_reset(va_list ap) 140*500856ebSRafal Jaworowski { 141*500856ebSRafal Jaworowski do_reset(NULL, 0, 0, NULL); 142*500856ebSRafal Jaworowski 143*500856ebSRafal Jaworowski /* NOT REACHED */ 144*500856ebSRafal Jaworowski return 0; 145*500856ebSRafal Jaworowski } 146*500856ebSRafal Jaworowski 147*500856ebSRafal Jaworowski /* 148*500856ebSRafal Jaworowski * pseudo signature: 149*500856ebSRafal Jaworowski * 150*500856ebSRafal Jaworowski * int API_get_sys_info(struct sys_info *si) 151*500856ebSRafal Jaworowski * 152*500856ebSRafal Jaworowski * fill out the sys_info struct containing selected parameters about the 153*500856ebSRafal Jaworowski * machine 154*500856ebSRafal Jaworowski */ 155*500856ebSRafal Jaworowski static int API_get_sys_info(va_list ap) 156*500856ebSRafal Jaworowski { 157*500856ebSRafal Jaworowski struct sys_info *si; 158*500856ebSRafal Jaworowski 159*500856ebSRafal Jaworowski si = (struct sys_info *)va_arg(ap, u_int32_t); 160*500856ebSRafal Jaworowski if (si == NULL) 161*500856ebSRafal Jaworowski return API_ENOMEM; 162*500856ebSRafal Jaworowski 163*500856ebSRafal Jaworowski return (platform_sys_info(si)) ? 0 : API_ENODEV; 164*500856ebSRafal Jaworowski } 165*500856ebSRafal Jaworowski 166*500856ebSRafal Jaworowski /* 167*500856ebSRafal Jaworowski * pseudo signature: 168*500856ebSRafal Jaworowski * 169*500856ebSRafal Jaworowski * int API_udelay(unsigned long *udelay) 170*500856ebSRafal Jaworowski */ 171*500856ebSRafal Jaworowski static int API_udelay(va_list ap) 172*500856ebSRafal Jaworowski { 173*500856ebSRafal Jaworowski unsigned long *d; 174*500856ebSRafal Jaworowski 175*500856ebSRafal Jaworowski if ((d = (unsigned long *)va_arg(ap, u_int32_t)) == NULL) 176*500856ebSRafal Jaworowski return API_EINVAL; 177*500856ebSRafal Jaworowski 178*500856ebSRafal Jaworowski udelay(*d); 179*500856ebSRafal Jaworowski return 0; 180*500856ebSRafal Jaworowski } 181*500856ebSRafal Jaworowski 182*500856ebSRafal Jaworowski /* 183*500856ebSRafal Jaworowski * pseudo signature: 184*500856ebSRafal Jaworowski * 185*500856ebSRafal Jaworowski * int API_get_timer(unsigned long *current, unsigned long *base) 186*500856ebSRafal Jaworowski */ 187*500856ebSRafal Jaworowski static int API_get_timer(va_list ap) 188*500856ebSRafal Jaworowski { 189*500856ebSRafal Jaworowski unsigned long *base, *cur; 190*500856ebSRafal Jaworowski 191*500856ebSRafal Jaworowski cur = (unsigned long *)va_arg(ap, u_int32_t); 192*500856ebSRafal Jaworowski if (cur == NULL) 193*500856ebSRafal Jaworowski return API_EINVAL; 194*500856ebSRafal Jaworowski 195*500856ebSRafal Jaworowski base = (unsigned long *)va_arg(ap, u_int32_t); 196*500856ebSRafal Jaworowski if (base == NULL) 197*500856ebSRafal Jaworowski return API_EINVAL; 198*500856ebSRafal Jaworowski 199*500856ebSRafal Jaworowski *cur = get_timer(*base); 200*500856ebSRafal Jaworowski return 0; 201*500856ebSRafal Jaworowski } 202*500856ebSRafal Jaworowski 203*500856ebSRafal Jaworowski 204*500856ebSRafal Jaworowski /***************************************************************************** 205*500856ebSRafal Jaworowski * 206*500856ebSRafal Jaworowski * pseudo signature: 207*500856ebSRafal Jaworowski * 208*500856ebSRafal Jaworowski * int API_dev_enum(struct device_info *) 209*500856ebSRafal Jaworowski * 210*500856ebSRafal Jaworowski * 211*500856ebSRafal Jaworowski * cookies uniqely identify the previously enumerated device instance and 212*500856ebSRafal Jaworowski * provide a hint for what to inspect in current enum iteration: 213*500856ebSRafal Jaworowski * 214*500856ebSRafal Jaworowski * - net: ð_device struct address from list pointed to by eth_devices 215*500856ebSRafal Jaworowski * 216*500856ebSRafal Jaworowski * - storage: block_dev_desc_t struct address from &ide_dev_desc[n], 217*500856ebSRafal Jaworowski * &scsi_dev_desc[n] and similar tables 218*500856ebSRafal Jaworowski * 219*500856ebSRafal Jaworowski ****************************************************************************/ 220*500856ebSRafal Jaworowski 221*500856ebSRafal Jaworowski static int API_dev_enum(va_list ap) 222*500856ebSRafal Jaworowski { 223*500856ebSRafal Jaworowski struct device_info *di; 224*500856ebSRafal Jaworowski 225*500856ebSRafal Jaworowski /* arg is ptr to the device_info struct we are going to fill out */ 226*500856ebSRafal Jaworowski di = (struct device_info *)va_arg(ap, u_int32_t); 227*500856ebSRafal Jaworowski if (di == NULL) 228*500856ebSRafal Jaworowski return API_EINVAL; 229*500856ebSRafal Jaworowski 230*500856ebSRafal Jaworowski if (di->cookie == NULL) { 231*500856ebSRafal Jaworowski /* start over - clean up enumeration */ 232*500856ebSRafal Jaworowski dev_enum_reset(); /* XXX shouldn't the name contain 'stor'? */ 233*500856ebSRafal Jaworowski debugf("RESTART ENUM\n"); 234*500856ebSRafal Jaworowski 235*500856ebSRafal Jaworowski /* net device enumeration first */ 236*500856ebSRafal Jaworowski if (dev_enum_net(di)) 237*500856ebSRafal Jaworowski return 0; 238*500856ebSRafal Jaworowski } 239*500856ebSRafal Jaworowski 240*500856ebSRafal Jaworowski /* 241*500856ebSRafal Jaworowski * The hidden assumption is there can only be one active network 242*500856ebSRafal Jaworowski * device and it is identified upon enumeration (re)start, so there's 243*500856ebSRafal Jaworowski * no point in trying to find network devices in other cases than the 244*500856ebSRafal Jaworowski * (re)start and hence the 'next' device can only be storage 245*500856ebSRafal Jaworowski */ 246*500856ebSRafal Jaworowski if (!dev_enum_storage(di)) 247*500856ebSRafal Jaworowski /* make sure we mark there are no more devices */ 248*500856ebSRafal Jaworowski di->cookie = NULL; 249*500856ebSRafal Jaworowski 250*500856ebSRafal Jaworowski return 0; 251*500856ebSRafal Jaworowski } 252*500856ebSRafal Jaworowski 253*500856ebSRafal Jaworowski 254*500856ebSRafal Jaworowski static int API_dev_open(va_list ap) 255*500856ebSRafal Jaworowski { 256*500856ebSRafal Jaworowski struct device_info *di; 257*500856ebSRafal Jaworowski int err = 0; 258*500856ebSRafal Jaworowski 259*500856ebSRafal Jaworowski /* arg is ptr to the device_info struct */ 260*500856ebSRafal Jaworowski di = (struct device_info *)va_arg(ap, u_int32_t); 261*500856ebSRafal Jaworowski if (di == NULL) 262*500856ebSRafal Jaworowski return API_EINVAL; 263*500856ebSRafal Jaworowski 264*500856ebSRafal Jaworowski /* Allow only one consumer of the device at a time */ 265*500856ebSRafal Jaworowski if (di->state == DEV_STA_OPEN) 266*500856ebSRafal Jaworowski return API_EBUSY; 267*500856ebSRafal Jaworowski 268*500856ebSRafal Jaworowski if (di->cookie == NULL) 269*500856ebSRafal Jaworowski return API_ENODEV; 270*500856ebSRafal Jaworowski 271*500856ebSRafal Jaworowski if (di->type & DEV_TYP_STOR) 272*500856ebSRafal Jaworowski err = dev_open_stor(di->cookie); 273*500856ebSRafal Jaworowski 274*500856ebSRafal Jaworowski else if (di->type & DEV_TYP_NET) 275*500856ebSRafal Jaworowski err = dev_open_net(di->cookie); 276*500856ebSRafal Jaworowski else 277*500856ebSRafal Jaworowski err = API_ENODEV; 278*500856ebSRafal Jaworowski 279*500856ebSRafal Jaworowski if (!err) 280*500856ebSRafal Jaworowski di->state = DEV_STA_OPEN; 281*500856ebSRafal Jaworowski 282*500856ebSRafal Jaworowski return err; 283*500856ebSRafal Jaworowski } 284*500856ebSRafal Jaworowski 285*500856ebSRafal Jaworowski 286*500856ebSRafal Jaworowski static int API_dev_close(va_list ap) 287*500856ebSRafal Jaworowski { 288*500856ebSRafal Jaworowski struct device_info *di; 289*500856ebSRafal Jaworowski int err = 0; 290*500856ebSRafal Jaworowski 291*500856ebSRafal Jaworowski /* arg is ptr to the device_info struct */ 292*500856ebSRafal Jaworowski di = (struct device_info *)va_arg(ap, u_int32_t); 293*500856ebSRafal Jaworowski if (di == NULL) 294*500856ebSRafal Jaworowski return API_EINVAL; 295*500856ebSRafal Jaworowski 296*500856ebSRafal Jaworowski if (di->state == DEV_STA_CLOSED) 297*500856ebSRafal Jaworowski return 0; 298*500856ebSRafal Jaworowski 299*500856ebSRafal Jaworowski if (di->cookie == NULL) 300*500856ebSRafal Jaworowski return API_ENODEV; 301*500856ebSRafal Jaworowski 302*500856ebSRafal Jaworowski if (di->type & DEV_TYP_STOR) 303*500856ebSRafal Jaworowski err = dev_close_stor(di->cookie); 304*500856ebSRafal Jaworowski 305*500856ebSRafal Jaworowski else if (di->type & DEV_TYP_NET) 306*500856ebSRafal Jaworowski err = dev_close_net(di->cookie); 307*500856ebSRafal Jaworowski else 308*500856ebSRafal Jaworowski /* 309*500856ebSRafal Jaworowski * In case of unknown device we cannot change its state, so 310*500856ebSRafal Jaworowski * only return error code 311*500856ebSRafal Jaworowski */ 312*500856ebSRafal Jaworowski err = API_ENODEV; 313*500856ebSRafal Jaworowski 314*500856ebSRafal Jaworowski if (!err) 315*500856ebSRafal Jaworowski di->state = DEV_STA_CLOSED; 316*500856ebSRafal Jaworowski 317*500856ebSRafal Jaworowski return err; 318*500856ebSRafal Jaworowski } 319*500856ebSRafal Jaworowski 320*500856ebSRafal Jaworowski 321*500856ebSRafal Jaworowski /* 322*500856ebSRafal Jaworowski * Notice: this is for sending network packets only, as U-Boot does not 323*500856ebSRafal Jaworowski * support writing to storage at the moment (12.2007) 324*500856ebSRafal Jaworowski * 325*500856ebSRafal Jaworowski * pseudo signature: 326*500856ebSRafal Jaworowski * 327*500856ebSRafal Jaworowski * int API_dev_write( 328*500856ebSRafal Jaworowski * struct device_info *di, 329*500856ebSRafal Jaworowski * void *buf, 330*500856ebSRafal Jaworowski * int *len 331*500856ebSRafal Jaworowski * ) 332*500856ebSRafal Jaworowski * 333*500856ebSRafal Jaworowski * buf: ptr to buffer from where to get the data to send 334*500856ebSRafal Jaworowski * 335*500856ebSRafal Jaworowski * len: length of packet to be sent (in bytes) 336*500856ebSRafal Jaworowski * 337*500856ebSRafal Jaworowski */ 338*500856ebSRafal Jaworowski static int API_dev_write(va_list ap) 339*500856ebSRafal Jaworowski { 340*500856ebSRafal Jaworowski struct device_info *di; 341*500856ebSRafal Jaworowski void *buf; 342*500856ebSRafal Jaworowski int *len; 343*500856ebSRafal Jaworowski int err = 0; 344*500856ebSRafal Jaworowski 345*500856ebSRafal Jaworowski /* 1. arg is ptr to the device_info struct */ 346*500856ebSRafal Jaworowski di = (struct device_info *)va_arg(ap, u_int32_t); 347*500856ebSRafal Jaworowski if (di == NULL) 348*500856ebSRafal Jaworowski return API_EINVAL; 349*500856ebSRafal Jaworowski 350*500856ebSRafal Jaworowski /* XXX should we check if device is open? i.e. the ->state ? */ 351*500856ebSRafal Jaworowski 352*500856ebSRafal Jaworowski if (di->cookie == NULL) 353*500856ebSRafal Jaworowski return API_ENODEV; 354*500856ebSRafal Jaworowski 355*500856ebSRafal Jaworowski /* 2. arg is ptr to buffer from where to get data to write */ 356*500856ebSRafal Jaworowski buf = (void *)va_arg(ap, u_int32_t); 357*500856ebSRafal Jaworowski if (buf == NULL) 358*500856ebSRafal Jaworowski return API_EINVAL; 359*500856ebSRafal Jaworowski 360*500856ebSRafal Jaworowski /* 3. arg is length of buffer */ 361*500856ebSRafal Jaworowski len = (int *)va_arg(ap, u_int32_t); 362*500856ebSRafal Jaworowski if (len == NULL) 363*500856ebSRafal Jaworowski return API_EINVAL; 364*500856ebSRafal Jaworowski if (*len <= 0) 365*500856ebSRafal Jaworowski return API_EINVAL; 366*500856ebSRafal Jaworowski 367*500856ebSRafal Jaworowski if (di->type & DEV_TYP_STOR) 368*500856ebSRafal Jaworowski /* 369*500856ebSRafal Jaworowski * write to storage is currently not supported by U-Boot: 370*500856ebSRafal Jaworowski * no storage device implements block_write() method 371*500856ebSRafal Jaworowski */ 372*500856ebSRafal Jaworowski return API_ENODEV; 373*500856ebSRafal Jaworowski 374*500856ebSRafal Jaworowski else if (di->type & DEV_TYP_NET) 375*500856ebSRafal Jaworowski err = dev_write_net(di->cookie, buf, *len); 376*500856ebSRafal Jaworowski else 377*500856ebSRafal Jaworowski err = API_ENODEV; 378*500856ebSRafal Jaworowski 379*500856ebSRafal Jaworowski return err; 380*500856ebSRafal Jaworowski } 381*500856ebSRafal Jaworowski 382*500856ebSRafal Jaworowski 383*500856ebSRafal Jaworowski /* 384*500856ebSRafal Jaworowski * pseudo signature: 385*500856ebSRafal Jaworowski * 386*500856ebSRafal Jaworowski * int API_dev_read( 387*500856ebSRafal Jaworowski * struct device_info *di, 388*500856ebSRafal Jaworowski * void *buf, 389*500856ebSRafal Jaworowski * size_t *len, 390*500856ebSRafal Jaworowski * unsigned long *start 391*500856ebSRafal Jaworowski * size_t *act_len 392*500856ebSRafal Jaworowski * ) 393*500856ebSRafal Jaworowski * 394*500856ebSRafal Jaworowski * buf: ptr to buffer where to put the read data 395*500856ebSRafal Jaworowski * 396*500856ebSRafal Jaworowski * len: ptr to length to be read 397*500856ebSRafal Jaworowski * - network: len of packet to read (in bytes) 398*500856ebSRafal Jaworowski * - storage: # of blocks to read (can vary in size depending on define) 399*500856ebSRafal Jaworowski * 400*500856ebSRafal Jaworowski * start: ptr to start block (only used for storage devices, ignored for 401*500856ebSRafal Jaworowski * network) 402*500856ebSRafal Jaworowski * 403*500856ebSRafal Jaworowski * act_len: ptr to where to put the len actually read 404*500856ebSRafal Jaworowski */ 405*500856ebSRafal Jaworowski static int API_dev_read(va_list ap) 406*500856ebSRafal Jaworowski { 407*500856ebSRafal Jaworowski struct device_info *di; 408*500856ebSRafal Jaworowski void *buf; 409*500856ebSRafal Jaworowski lbasize_t *len_stor, *act_len_stor; 410*500856ebSRafal Jaworowski lbastart_t *start; 411*500856ebSRafal Jaworowski int *len_net, *act_len_net; 412*500856ebSRafal Jaworowski 413*500856ebSRafal Jaworowski /* 1. arg is ptr to the device_info struct */ 414*500856ebSRafal Jaworowski di = (struct device_info *)va_arg(ap, u_int32_t); 415*500856ebSRafal Jaworowski if (di == NULL) 416*500856ebSRafal Jaworowski return API_EINVAL; 417*500856ebSRafal Jaworowski 418*500856ebSRafal Jaworowski /* XXX should we check if device is open? i.e. the ->state ? */ 419*500856ebSRafal Jaworowski 420*500856ebSRafal Jaworowski if (di->cookie == NULL) 421*500856ebSRafal Jaworowski return API_ENODEV; 422*500856ebSRafal Jaworowski 423*500856ebSRafal Jaworowski /* 2. arg is ptr to buffer from where to put the read data */ 424*500856ebSRafal Jaworowski buf = (void *)va_arg(ap, u_int32_t); 425*500856ebSRafal Jaworowski if (buf == NULL) 426*500856ebSRafal Jaworowski return API_EINVAL; 427*500856ebSRafal Jaworowski 428*500856ebSRafal Jaworowski if (di->type & DEV_TYP_STOR) { 429*500856ebSRafal Jaworowski /* 3. arg - ptr to var with # of blocks to read */ 430*500856ebSRafal Jaworowski len_stor = (lbasize_t *)va_arg(ap, u_int32_t); 431*500856ebSRafal Jaworowski if (!len_stor) 432*500856ebSRafal Jaworowski return API_EINVAL; 433*500856ebSRafal Jaworowski if (*len_stor <= 0) 434*500856ebSRafal Jaworowski return API_EINVAL; 435*500856ebSRafal Jaworowski 436*500856ebSRafal Jaworowski /* 4. arg - ptr to var with start block */ 437*500856ebSRafal Jaworowski start = (lbastart_t *)va_arg(ap, u_int32_t); 438*500856ebSRafal Jaworowski 439*500856ebSRafal Jaworowski /* 5. arg - ptr to var where to put the len actually read */ 440*500856ebSRafal Jaworowski act_len_stor = (lbasize_t *)va_arg(ap, u_int32_t); 441*500856ebSRafal Jaworowski if (!act_len_stor) 442*500856ebSRafal Jaworowski return API_EINVAL; 443*500856ebSRafal Jaworowski 444*500856ebSRafal Jaworowski *act_len_stor = dev_read_stor(di->cookie, buf, *len_stor, *start); 445*500856ebSRafal Jaworowski 446*500856ebSRafal Jaworowski } else if (di->type & DEV_TYP_NET) { 447*500856ebSRafal Jaworowski 448*500856ebSRafal Jaworowski /* 3. arg points to the var with length of packet to read */ 449*500856ebSRafal Jaworowski len_net = (int *)va_arg(ap, u_int32_t); 450*500856ebSRafal Jaworowski if (!len_net) 451*500856ebSRafal Jaworowski return API_EINVAL; 452*500856ebSRafal Jaworowski if (*len_net <= 0) 453*500856ebSRafal Jaworowski return API_EINVAL; 454*500856ebSRafal Jaworowski 455*500856ebSRafal Jaworowski /* 4. - ptr to var where to put the len actually read */ 456*500856ebSRafal Jaworowski act_len_net = (int *)va_arg(ap, u_int32_t); 457*500856ebSRafal Jaworowski if (!act_len_net) 458*500856ebSRafal Jaworowski return API_EINVAL; 459*500856ebSRafal Jaworowski 460*500856ebSRafal Jaworowski *act_len_net = dev_read_net(di->cookie, buf, *len_net); 461*500856ebSRafal Jaworowski 462*500856ebSRafal Jaworowski } else 463*500856ebSRafal Jaworowski return API_ENODEV; 464*500856ebSRafal Jaworowski 465*500856ebSRafal Jaworowski return 0; 466*500856ebSRafal Jaworowski } 467*500856ebSRafal Jaworowski 468*500856ebSRafal Jaworowski 469*500856ebSRafal Jaworowski /* 470*500856ebSRafal Jaworowski * pseudo signature: 471*500856ebSRafal Jaworowski * 472*500856ebSRafal Jaworowski * int API_env_get(const char *name, char **value) 473*500856ebSRafal Jaworowski * 474*500856ebSRafal Jaworowski * name: ptr to name of env var 475*500856ebSRafal Jaworowski */ 476*500856ebSRafal Jaworowski static int API_env_get(va_list ap) 477*500856ebSRafal Jaworowski { 478*500856ebSRafal Jaworowski char *name, **value; 479*500856ebSRafal Jaworowski 480*500856ebSRafal Jaworowski if ((name = (char *)va_arg(ap, u_int32_t)) == NULL) 481*500856ebSRafal Jaworowski return API_EINVAL; 482*500856ebSRafal Jaworowski if ((value = (char **)va_arg(ap, u_int32_t)) == NULL) 483*500856ebSRafal Jaworowski return API_EINVAL; 484*500856ebSRafal Jaworowski 485*500856ebSRafal Jaworowski *value = getenv(name); 486*500856ebSRafal Jaworowski 487*500856ebSRafal Jaworowski return 0; 488*500856ebSRafal Jaworowski } 489*500856ebSRafal Jaworowski 490*500856ebSRafal Jaworowski /* 491*500856ebSRafal Jaworowski * pseudo signature: 492*500856ebSRafal Jaworowski * 493*500856ebSRafal Jaworowski * int API_env_set(const char *name, const char *value) 494*500856ebSRafal Jaworowski * 495*500856ebSRafal Jaworowski * name: ptr to name of env var 496*500856ebSRafal Jaworowski * 497*500856ebSRafal Jaworowski * value: ptr to value to be set 498*500856ebSRafal Jaworowski */ 499*500856ebSRafal Jaworowski static int API_env_set(va_list ap) 500*500856ebSRafal Jaworowski { 501*500856ebSRafal Jaworowski char *name, *value; 502*500856ebSRafal Jaworowski 503*500856ebSRafal Jaworowski if ((name = (char *)va_arg(ap, u_int32_t)) == NULL) 504*500856ebSRafal Jaworowski return API_EINVAL; 505*500856ebSRafal Jaworowski if ((value = (char *)va_arg(ap, u_int32_t)) == NULL) 506*500856ebSRafal Jaworowski return API_EINVAL; 507*500856ebSRafal Jaworowski 508*500856ebSRafal Jaworowski setenv(name, value); 509*500856ebSRafal Jaworowski 510*500856ebSRafal Jaworowski return 0; 511*500856ebSRafal Jaworowski } 512*500856ebSRafal Jaworowski 513*500856ebSRafal Jaworowski /* 514*500856ebSRafal Jaworowski * pseudo signature: 515*500856ebSRafal Jaworowski * 516*500856ebSRafal Jaworowski * int API_env_enum(const char *last, char **next) 517*500856ebSRafal Jaworowski * 518*500856ebSRafal Jaworowski * last: ptr to name of env var found in last iteration 519*500856ebSRafal Jaworowski */ 520*500856ebSRafal Jaworowski static int API_env_enum(va_list ap) 521*500856ebSRafal Jaworowski { 522*500856ebSRafal Jaworowski int i, n; 523*500856ebSRafal Jaworowski char *last, **next; 524*500856ebSRafal Jaworowski 525*500856ebSRafal Jaworowski last = (char *)va_arg(ap, u_int32_t); 526*500856ebSRafal Jaworowski 527*500856ebSRafal Jaworowski if ((next = (char **)va_arg(ap, u_int32_t)) == NULL) 528*500856ebSRafal Jaworowski return API_EINVAL; 529*500856ebSRafal Jaworowski 530*500856ebSRafal Jaworowski if (last == NULL) 531*500856ebSRafal Jaworowski /* start over */ 532*500856ebSRafal Jaworowski *next = ((char *)env_get_addr(0)); 533*500856ebSRafal Jaworowski else { 534*500856ebSRafal Jaworowski *next = last; 535*500856ebSRafal Jaworowski 536*500856ebSRafal Jaworowski for (i = 0; env_get_char(i) != '\0'; i = n + 1) { 537*500856ebSRafal Jaworowski for (n = i; env_get_char(n) != '\0'; ++n) { 538*500856ebSRafal Jaworowski if (n >= CFG_ENV_SIZE) { 539*500856ebSRafal Jaworowski /* XXX shouldn't we set *next = NULL?? */ 540*500856ebSRafal Jaworowski return 0; 541*500856ebSRafal Jaworowski } 542*500856ebSRafal Jaworowski } 543*500856ebSRafal Jaworowski 544*500856ebSRafal Jaworowski if (envmatch((uchar *)last, i) < 0) 545*500856ebSRafal Jaworowski continue; 546*500856ebSRafal Jaworowski 547*500856ebSRafal Jaworowski /* try to get next name */ 548*500856ebSRafal Jaworowski i = n + 1; 549*500856ebSRafal Jaworowski if (env_get_char(i) == '\0') { 550*500856ebSRafal Jaworowski /* no more left */ 551*500856ebSRafal Jaworowski *next = NULL; 552*500856ebSRafal Jaworowski return 0; 553*500856ebSRafal Jaworowski } 554*500856ebSRafal Jaworowski 555*500856ebSRafal Jaworowski *next = ((char *)env_get_addr(i)); 556*500856ebSRafal Jaworowski return 0; 557*500856ebSRafal Jaworowski } 558*500856ebSRafal Jaworowski } 559*500856ebSRafal Jaworowski 560*500856ebSRafal Jaworowski return 0; 561*500856ebSRafal Jaworowski } 562*500856ebSRafal Jaworowski 563*500856ebSRafal Jaworowski static cfp_t calls_table[API_MAXCALL] = { NULL, }; 564*500856ebSRafal Jaworowski 565*500856ebSRafal Jaworowski /* 566*500856ebSRafal Jaworowski * The main syscall entry point - this is not reentrant, only one call is 567*500856ebSRafal Jaworowski * serviced until finished. 568*500856ebSRafal Jaworowski * 569*500856ebSRafal Jaworowski * e.g. syscall(1, int *, u_int32_t, u_int32_t, u_int32_t, u_int32_t); 570*500856ebSRafal Jaworowski * 571*500856ebSRafal Jaworowski * call: syscall number 572*500856ebSRafal Jaworowski * 573*500856ebSRafal Jaworowski * retval: points to the return value placeholder, this is the place the 574*500856ebSRafal Jaworowski * syscall puts its return value, if NULL the caller does not 575*500856ebSRafal Jaworowski * expect a return value 576*500856ebSRafal Jaworowski * 577*500856ebSRafal Jaworowski * ... syscall arguments (variable number) 578*500856ebSRafal Jaworowski * 579*500856ebSRafal Jaworowski * returns: 0 if the call not found, 1 if serviced 580*500856ebSRafal Jaworowski */ 581*500856ebSRafal Jaworowski int syscall(int call, int *retval, ...) 582*500856ebSRafal Jaworowski { 583*500856ebSRafal Jaworowski va_list ap; 584*500856ebSRafal Jaworowski int rv; 585*500856ebSRafal Jaworowski 586*500856ebSRafal Jaworowski if (call < 0 || call >= calls_no || calls_table[call] == NULL) { 587*500856ebSRafal Jaworowski debugf("invalid call #%d\n", call); 588*500856ebSRafal Jaworowski return 0; 589*500856ebSRafal Jaworowski } 590*500856ebSRafal Jaworowski 591*500856ebSRafal Jaworowski if (calls_table[call] == NULL) { 592*500856ebSRafal Jaworowski debugf("syscall #%d does not have a handler\n", call); 593*500856ebSRafal Jaworowski return 0; 594*500856ebSRafal Jaworowski } 595*500856ebSRafal Jaworowski 596*500856ebSRafal Jaworowski va_start(ap, retval); 597*500856ebSRafal Jaworowski rv = calls_table[call](ap); 598*500856ebSRafal Jaworowski if (retval != NULL) 599*500856ebSRafal Jaworowski *retval = rv; 600*500856ebSRafal Jaworowski 601*500856ebSRafal Jaworowski return 1; 602*500856ebSRafal Jaworowski } 603*500856ebSRafal Jaworowski 604*500856ebSRafal Jaworowski void api_init(void) 605*500856ebSRafal Jaworowski { 606*500856ebSRafal Jaworowski struct api_signature *sig = NULL; 607*500856ebSRafal Jaworowski 608*500856ebSRafal Jaworowski /* TODO put this into linker set one day... */ 609*500856ebSRafal Jaworowski calls_table[API_RSVD] = NULL; 610*500856ebSRafal Jaworowski calls_table[API_GETC] = &API_getc; 611*500856ebSRafal Jaworowski calls_table[API_PUTC] = &API_putc; 612*500856ebSRafal Jaworowski calls_table[API_TSTC] = &API_tstc; 613*500856ebSRafal Jaworowski calls_table[API_PUTS] = &API_puts; 614*500856ebSRafal Jaworowski calls_table[API_RESET] = &API_reset; 615*500856ebSRafal Jaworowski calls_table[API_GET_SYS_INFO] = &API_get_sys_info; 616*500856ebSRafal Jaworowski calls_table[API_UDELAY] = &API_udelay; 617*500856ebSRafal Jaworowski calls_table[API_GET_TIMER] = &API_get_timer; 618*500856ebSRafal Jaworowski calls_table[API_DEV_ENUM] = &API_dev_enum; 619*500856ebSRafal Jaworowski calls_table[API_DEV_OPEN] = &API_dev_open; 620*500856ebSRafal Jaworowski calls_table[API_DEV_CLOSE] = &API_dev_close; 621*500856ebSRafal Jaworowski calls_table[API_DEV_READ] = &API_dev_read; 622*500856ebSRafal Jaworowski calls_table[API_DEV_WRITE] = &API_dev_write; 623*500856ebSRafal Jaworowski calls_table[API_ENV_GET] = &API_env_get; 624*500856ebSRafal Jaworowski calls_table[API_ENV_SET] = &API_env_set; 625*500856ebSRafal Jaworowski calls_table[API_ENV_ENUM] = &API_env_enum; 626*500856ebSRafal Jaworowski calls_no = API_MAXCALL; 627*500856ebSRafal Jaworowski 628*500856ebSRafal Jaworowski debugf("API initialized with %d calls\n", calls_no); 629*500856ebSRafal Jaworowski 630*500856ebSRafal Jaworowski dev_stor_init(); 631*500856ebSRafal Jaworowski 632*500856ebSRafal Jaworowski /* 633*500856ebSRafal Jaworowski * Produce the signature so the API consumers can find it 634*500856ebSRafal Jaworowski */ 635*500856ebSRafal Jaworowski sig = malloc(sizeof(struct api_signature)); 636*500856ebSRafal Jaworowski if (sig == NULL) { 637*500856ebSRafal Jaworowski printf("API: could not allocate memory for the signature!\n"); 638*500856ebSRafal Jaworowski return; 639*500856ebSRafal Jaworowski } 640*500856ebSRafal Jaworowski 641*500856ebSRafal Jaworowski debugf("API sig @ 0x%08x\n", sig); 642*500856ebSRafal Jaworowski memcpy(sig->magic, API_SIG_MAGIC, 8); 643*500856ebSRafal Jaworowski sig->version = API_SIG_VERSION; 644*500856ebSRafal Jaworowski sig->syscall = &syscall; 645*500856ebSRafal Jaworowski sig->checksum = 0; 646*500856ebSRafal Jaworowski sig->checksum = crc32(0, (unsigned char *)sig, 647*500856ebSRafal Jaworowski sizeof(struct api_signature)); 648*500856ebSRafal Jaworowski debugf("syscall entry: 0x%08x\n", sig->syscall); 649*500856ebSRafal Jaworowski } 650*500856ebSRafal Jaworowski 651*500856ebSRafal Jaworowski void platform_set_mr(struct sys_info *si, unsigned long start, unsigned long size, 652*500856ebSRafal Jaworowski int flags) 653*500856ebSRafal Jaworowski { 654*500856ebSRafal Jaworowski int i; 655*500856ebSRafal Jaworowski 656*500856ebSRafal Jaworowski if (!si->mr || !size || (flags == 0)) 657*500856ebSRafal Jaworowski return; 658*500856ebSRafal Jaworowski 659*500856ebSRafal Jaworowski /* find free slot */ 660*500856ebSRafal Jaworowski for (i = 0; i < si->mr_no; i++) 661*500856ebSRafal Jaworowski if (si->mr[i].flags == 0) { 662*500856ebSRafal Jaworowski /* insert new mem region */ 663*500856ebSRafal Jaworowski si->mr[i].start = start; 664*500856ebSRafal Jaworowski si->mr[i].size = size; 665*500856ebSRafal Jaworowski si->mr[i].flags = flags; 666*500856ebSRafal Jaworowski return; 667*500856ebSRafal Jaworowski } 668*500856ebSRafal Jaworowski } 669*500856ebSRafal Jaworowski 670*500856ebSRafal Jaworowski #endif /* CONFIG_API */ 671