1500856ebSRafal Jaworowski /* 2500856ebSRafal Jaworowski * (C) Copyright 2007 Semihalf 3500856ebSRafal Jaworowski * 4500856ebSRafal Jaworowski * Written by: Rafal Jaworowski <raj@semihalf.com> 5500856ebSRafal Jaworowski * 6500856ebSRafal Jaworowski * See file CREDITS for list of people who contributed to this 7500856ebSRafal Jaworowski * project. 8500856ebSRafal Jaworowski * 9500856ebSRafal Jaworowski * This program is free software; you can redistribute it and/or 10500856ebSRafal Jaworowski * modify it under the terms of the GNU General Public License as 11500856ebSRafal Jaworowski * published by the Free Software Foundation; either version 2 of 12500856ebSRafal Jaworowski * the License, or (at your option) any later version. 13500856ebSRafal Jaworowski * 14500856ebSRafal Jaworowski * This program is distributed in the hope that it will be useful, 15500856ebSRafal Jaworowski * but WITHOUT ANY WARRANTY; without even the implied warranty of 16500856ebSRafal Jaworowski * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17500856ebSRafal Jaworowski * GNU General Public License for more details. 18500856ebSRafal Jaworowski * 19500856ebSRafal Jaworowski * You should have received a copy of the GNU General Public License 20500856ebSRafal Jaworowski * along with this program; if not, write to the Free Software 21500856ebSRafal Jaworowski * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 22500856ebSRafal Jaworowski * MA 02111-1307 USA 23500856ebSRafal Jaworowski * 24500856ebSRafal Jaworowski */ 25500856ebSRafal Jaworowski 26500856ebSRafal Jaworowski #include <config.h> 27500856ebSRafal Jaworowski #include <command.h> 28500856ebSRafal Jaworowski #include <common.h> 29500856ebSRafal Jaworowski #include <malloc.h> 30a8409f4fSWolfgang Denk #include <environment.h> 31500856ebSRafal Jaworowski #include <linux/types.h> 32500856ebSRafal Jaworowski #include <api_public.h> 33500856ebSRafal Jaworowski 34500856ebSRafal Jaworowski #include "api_private.h" 35500856ebSRafal Jaworowski 36500856ebSRafal Jaworowski #define DEBUG 37500856ebSRafal Jaworowski #undef DEBUG 38500856ebSRafal Jaworowski 39500856ebSRafal Jaworowski /***************************************************************************** 40500856ebSRafal Jaworowski * 41500856ebSRafal Jaworowski * This is the API core. 42500856ebSRafal Jaworowski * 43500856ebSRafal Jaworowski * API_ functions are part of U-Boot code and constitute the lowest level 44500856ebSRafal Jaworowski * calls: 45500856ebSRafal Jaworowski * 46500856ebSRafal Jaworowski * - they know what values they need as arguments 47500856ebSRafal Jaworowski * - their direct return value pertains to the API_ "shell" itself (0 on 48500856ebSRafal Jaworowski * success, some error code otherwise) 49500856ebSRafal Jaworowski * - if the call returns a value it is buried within arguments 50500856ebSRafal Jaworowski * 51500856ebSRafal Jaworowski ****************************************************************************/ 52500856ebSRafal Jaworowski 53500856ebSRafal Jaworowski #ifdef DEBUG 54500856ebSRafal Jaworowski #define debugf(fmt, args...) do { printf("%s(): ", __func__); printf(fmt, ##args); } while (0) 55500856ebSRafal Jaworowski #else 56500856ebSRafal Jaworowski #define debugf(fmt, args...) 57500856ebSRafal Jaworowski #endif 58500856ebSRafal Jaworowski 59500856ebSRafal Jaworowski typedef int (*cfp_t)(va_list argp); 60500856ebSRafal Jaworowski 61500856ebSRafal Jaworowski static int calls_no; 62500856ebSRafal Jaworowski 63500856ebSRafal Jaworowski /* 64500856ebSRafal Jaworowski * pseudo signature: 65500856ebSRafal Jaworowski * 66500856ebSRafal Jaworowski * int API_getc(int *c) 67500856ebSRafal Jaworowski */ 68500856ebSRafal Jaworowski static int API_getc(va_list ap) 69500856ebSRafal Jaworowski { 70500856ebSRafal Jaworowski int *c; 71500856ebSRafal Jaworowski 72500856ebSRafal Jaworowski if ((c = (int *)va_arg(ap, u_int32_t)) == NULL) 73500856ebSRafal Jaworowski return API_EINVAL; 74500856ebSRafal Jaworowski 75500856ebSRafal Jaworowski *c = getc(); 76500856ebSRafal Jaworowski return 0; 77500856ebSRafal Jaworowski } 78500856ebSRafal Jaworowski 79500856ebSRafal Jaworowski /* 80500856ebSRafal Jaworowski * pseudo signature: 81500856ebSRafal Jaworowski * 82500856ebSRafal Jaworowski * int API_tstc(int *c) 83500856ebSRafal Jaworowski */ 84500856ebSRafal Jaworowski static int API_tstc(va_list ap) 85500856ebSRafal Jaworowski { 86500856ebSRafal Jaworowski int *t; 87500856ebSRafal Jaworowski 88500856ebSRafal Jaworowski if ((t = (int *)va_arg(ap, u_int32_t)) == NULL) 89500856ebSRafal Jaworowski return API_EINVAL; 90500856ebSRafal Jaworowski 91500856ebSRafal Jaworowski *t = tstc(); 92500856ebSRafal Jaworowski return 0; 93500856ebSRafal Jaworowski } 94500856ebSRafal Jaworowski 95500856ebSRafal Jaworowski /* 96500856ebSRafal Jaworowski * pseudo signature: 97500856ebSRafal Jaworowski * 98500856ebSRafal Jaworowski * int API_putc(char *ch) 99500856ebSRafal Jaworowski */ 100500856ebSRafal Jaworowski static int API_putc(va_list ap) 101500856ebSRafal Jaworowski { 102500856ebSRafal Jaworowski char *c; 103500856ebSRafal Jaworowski 104500856ebSRafal Jaworowski if ((c = (char *)va_arg(ap, u_int32_t)) == NULL) 105500856ebSRafal Jaworowski return API_EINVAL; 106500856ebSRafal Jaworowski 107500856ebSRafal Jaworowski putc(*c); 108500856ebSRafal Jaworowski return 0; 109500856ebSRafal Jaworowski } 110500856ebSRafal Jaworowski 111500856ebSRafal Jaworowski /* 112500856ebSRafal Jaworowski * pseudo signature: 113500856ebSRafal Jaworowski * 114500856ebSRafal Jaworowski * int API_puts(char **s) 115500856ebSRafal Jaworowski */ 116500856ebSRafal Jaworowski static int API_puts(va_list ap) 117500856ebSRafal Jaworowski { 118500856ebSRafal Jaworowski char *s; 119500856ebSRafal Jaworowski 120500856ebSRafal Jaworowski if ((s = (char *)va_arg(ap, u_int32_t)) == NULL) 121500856ebSRafal Jaworowski return API_EINVAL; 122500856ebSRafal Jaworowski 123500856ebSRafal Jaworowski puts(s); 124500856ebSRafal Jaworowski return 0; 125500856ebSRafal Jaworowski } 126500856ebSRafal Jaworowski 127500856ebSRafal Jaworowski /* 128500856ebSRafal Jaworowski * pseudo signature: 129500856ebSRafal Jaworowski * 130500856ebSRafal Jaworowski * int API_reset(void) 131500856ebSRafal Jaworowski */ 132500856ebSRafal Jaworowski static int API_reset(va_list ap) 133500856ebSRafal Jaworowski { 134500856ebSRafal Jaworowski do_reset(NULL, 0, 0, NULL); 135500856ebSRafal Jaworowski 136500856ebSRafal Jaworowski /* NOT REACHED */ 137500856ebSRafal Jaworowski return 0; 138500856ebSRafal Jaworowski } 139500856ebSRafal Jaworowski 140500856ebSRafal Jaworowski /* 141500856ebSRafal Jaworowski * pseudo signature: 142500856ebSRafal Jaworowski * 143500856ebSRafal Jaworowski * int API_get_sys_info(struct sys_info *si) 144500856ebSRafal Jaworowski * 145500856ebSRafal Jaworowski * fill out the sys_info struct containing selected parameters about the 146500856ebSRafal Jaworowski * machine 147500856ebSRafal Jaworowski */ 148500856ebSRafal Jaworowski static int API_get_sys_info(va_list ap) 149500856ebSRafal Jaworowski { 150500856ebSRafal Jaworowski struct sys_info *si; 151500856ebSRafal Jaworowski 152500856ebSRafal Jaworowski si = (struct sys_info *)va_arg(ap, u_int32_t); 153500856ebSRafal Jaworowski if (si == NULL) 154500856ebSRafal Jaworowski return API_ENOMEM; 155500856ebSRafal Jaworowski 156500856ebSRafal Jaworowski return (platform_sys_info(si)) ? 0 : API_ENODEV; 157500856ebSRafal Jaworowski } 158500856ebSRafal Jaworowski 159500856ebSRafal Jaworowski /* 160500856ebSRafal Jaworowski * pseudo signature: 161500856ebSRafal Jaworowski * 162500856ebSRafal Jaworowski * int API_udelay(unsigned long *udelay) 163500856ebSRafal Jaworowski */ 164500856ebSRafal Jaworowski static int API_udelay(va_list ap) 165500856ebSRafal Jaworowski { 166500856ebSRafal Jaworowski unsigned long *d; 167500856ebSRafal Jaworowski 168500856ebSRafal Jaworowski if ((d = (unsigned long *)va_arg(ap, u_int32_t)) == NULL) 169500856ebSRafal Jaworowski return API_EINVAL; 170500856ebSRafal Jaworowski 171500856ebSRafal Jaworowski udelay(*d); 172500856ebSRafal Jaworowski return 0; 173500856ebSRafal Jaworowski } 174500856ebSRafal Jaworowski 175500856ebSRafal Jaworowski /* 176500856ebSRafal Jaworowski * pseudo signature: 177500856ebSRafal Jaworowski * 178500856ebSRafal Jaworowski * int API_get_timer(unsigned long *current, unsigned long *base) 179500856ebSRafal Jaworowski */ 180500856ebSRafal Jaworowski static int API_get_timer(va_list ap) 181500856ebSRafal Jaworowski { 182500856ebSRafal Jaworowski unsigned long *base, *cur; 183500856ebSRafal Jaworowski 184500856ebSRafal Jaworowski cur = (unsigned long *)va_arg(ap, u_int32_t); 185500856ebSRafal Jaworowski if (cur == NULL) 186500856ebSRafal Jaworowski return API_EINVAL; 187500856ebSRafal Jaworowski 188500856ebSRafal Jaworowski base = (unsigned long *)va_arg(ap, u_int32_t); 189500856ebSRafal Jaworowski if (base == NULL) 190500856ebSRafal Jaworowski return API_EINVAL; 191500856ebSRafal Jaworowski 192500856ebSRafal Jaworowski *cur = get_timer(*base); 193500856ebSRafal Jaworowski return 0; 194500856ebSRafal Jaworowski } 195500856ebSRafal Jaworowski 196500856ebSRafal Jaworowski 197500856ebSRafal Jaworowski /***************************************************************************** 198500856ebSRafal Jaworowski * 199500856ebSRafal Jaworowski * pseudo signature: 200500856ebSRafal Jaworowski * 201500856ebSRafal Jaworowski * int API_dev_enum(struct device_info *) 202500856ebSRafal Jaworowski * 203500856ebSRafal Jaworowski * 204500856ebSRafal Jaworowski * cookies uniqely identify the previously enumerated device instance and 205500856ebSRafal Jaworowski * provide a hint for what to inspect in current enum iteration: 206500856ebSRafal Jaworowski * 207500856ebSRafal Jaworowski * - net: ð_device struct address from list pointed to by eth_devices 208500856ebSRafal Jaworowski * 209500856ebSRafal Jaworowski * - storage: block_dev_desc_t struct address from &ide_dev_desc[n], 210500856ebSRafal Jaworowski * &scsi_dev_desc[n] and similar tables 211500856ebSRafal Jaworowski * 212500856ebSRafal Jaworowski ****************************************************************************/ 213500856ebSRafal Jaworowski 214500856ebSRafal Jaworowski static int API_dev_enum(va_list ap) 215500856ebSRafal Jaworowski { 216500856ebSRafal Jaworowski struct device_info *di; 217500856ebSRafal Jaworowski 218500856ebSRafal Jaworowski /* arg is ptr to the device_info struct we are going to fill out */ 219500856ebSRafal Jaworowski di = (struct device_info *)va_arg(ap, u_int32_t); 220500856ebSRafal Jaworowski if (di == NULL) 221500856ebSRafal Jaworowski return API_EINVAL; 222500856ebSRafal Jaworowski 223500856ebSRafal Jaworowski if (di->cookie == NULL) { 224500856ebSRafal Jaworowski /* start over - clean up enumeration */ 225500856ebSRafal Jaworowski dev_enum_reset(); /* XXX shouldn't the name contain 'stor'? */ 226500856ebSRafal Jaworowski debugf("RESTART ENUM\n"); 227500856ebSRafal Jaworowski 228500856ebSRafal Jaworowski /* net device enumeration first */ 229500856ebSRafal Jaworowski if (dev_enum_net(di)) 230500856ebSRafal Jaworowski return 0; 231500856ebSRafal Jaworowski } 232500856ebSRafal Jaworowski 233500856ebSRafal Jaworowski /* 234500856ebSRafal Jaworowski * The hidden assumption is there can only be one active network 235500856ebSRafal Jaworowski * device and it is identified upon enumeration (re)start, so there's 236500856ebSRafal Jaworowski * no point in trying to find network devices in other cases than the 237500856ebSRafal Jaworowski * (re)start and hence the 'next' device can only be storage 238500856ebSRafal Jaworowski */ 239500856ebSRafal Jaworowski if (!dev_enum_storage(di)) 240500856ebSRafal Jaworowski /* make sure we mark there are no more devices */ 241500856ebSRafal Jaworowski di->cookie = NULL; 242500856ebSRafal Jaworowski 243500856ebSRafal Jaworowski return 0; 244500856ebSRafal Jaworowski } 245500856ebSRafal Jaworowski 246500856ebSRafal Jaworowski 247500856ebSRafal Jaworowski static int API_dev_open(va_list ap) 248500856ebSRafal Jaworowski { 249500856ebSRafal Jaworowski struct device_info *di; 250500856ebSRafal Jaworowski int err = 0; 251500856ebSRafal Jaworowski 252500856ebSRafal Jaworowski /* arg is ptr to the device_info struct */ 253500856ebSRafal Jaworowski di = (struct device_info *)va_arg(ap, u_int32_t); 254500856ebSRafal Jaworowski if (di == NULL) 255500856ebSRafal Jaworowski return API_EINVAL; 256500856ebSRafal Jaworowski 257500856ebSRafal Jaworowski /* Allow only one consumer of the device at a time */ 258500856ebSRafal Jaworowski if (di->state == DEV_STA_OPEN) 259500856ebSRafal Jaworowski return API_EBUSY; 260500856ebSRafal Jaworowski 261500856ebSRafal Jaworowski if (di->cookie == NULL) 262500856ebSRafal Jaworowski return API_ENODEV; 263500856ebSRafal Jaworowski 264500856ebSRafal Jaworowski if (di->type & DEV_TYP_STOR) 265500856ebSRafal Jaworowski err = dev_open_stor(di->cookie); 266500856ebSRafal Jaworowski 267500856ebSRafal Jaworowski else if (di->type & DEV_TYP_NET) 268500856ebSRafal Jaworowski err = dev_open_net(di->cookie); 269500856ebSRafal Jaworowski else 270500856ebSRafal Jaworowski err = API_ENODEV; 271500856ebSRafal Jaworowski 272500856ebSRafal Jaworowski if (!err) 273500856ebSRafal Jaworowski di->state = DEV_STA_OPEN; 274500856ebSRafal Jaworowski 275500856ebSRafal Jaworowski return err; 276500856ebSRafal Jaworowski } 277500856ebSRafal Jaworowski 278500856ebSRafal Jaworowski 279500856ebSRafal Jaworowski static int API_dev_close(va_list ap) 280500856ebSRafal Jaworowski { 281500856ebSRafal Jaworowski struct device_info *di; 282500856ebSRafal Jaworowski int err = 0; 283500856ebSRafal Jaworowski 284500856ebSRafal Jaworowski /* arg is ptr to the device_info struct */ 285500856ebSRafal Jaworowski di = (struct device_info *)va_arg(ap, u_int32_t); 286500856ebSRafal Jaworowski if (di == NULL) 287500856ebSRafal Jaworowski return API_EINVAL; 288500856ebSRafal Jaworowski 289500856ebSRafal Jaworowski if (di->state == DEV_STA_CLOSED) 290500856ebSRafal Jaworowski return 0; 291500856ebSRafal Jaworowski 292500856ebSRafal Jaworowski if (di->cookie == NULL) 293500856ebSRafal Jaworowski return API_ENODEV; 294500856ebSRafal Jaworowski 295500856ebSRafal Jaworowski if (di->type & DEV_TYP_STOR) 296500856ebSRafal Jaworowski err = dev_close_stor(di->cookie); 297500856ebSRafal Jaworowski 298500856ebSRafal Jaworowski else if (di->type & DEV_TYP_NET) 299500856ebSRafal Jaworowski err = dev_close_net(di->cookie); 300500856ebSRafal Jaworowski else 301500856ebSRafal Jaworowski /* 302500856ebSRafal Jaworowski * In case of unknown device we cannot change its state, so 303500856ebSRafal Jaworowski * only return error code 304500856ebSRafal Jaworowski */ 305500856ebSRafal Jaworowski err = API_ENODEV; 306500856ebSRafal Jaworowski 307500856ebSRafal Jaworowski if (!err) 308500856ebSRafal Jaworowski di->state = DEV_STA_CLOSED; 309500856ebSRafal Jaworowski 310500856ebSRafal Jaworowski return err; 311500856ebSRafal Jaworowski } 312500856ebSRafal Jaworowski 313500856ebSRafal Jaworowski 314500856ebSRafal Jaworowski /* 315500856ebSRafal Jaworowski * Notice: this is for sending network packets only, as U-Boot does not 316500856ebSRafal Jaworowski * support writing to storage at the moment (12.2007) 317500856ebSRafal Jaworowski * 318500856ebSRafal Jaworowski * pseudo signature: 319500856ebSRafal Jaworowski * 320500856ebSRafal Jaworowski * int API_dev_write( 321500856ebSRafal Jaworowski * struct device_info *di, 322500856ebSRafal Jaworowski * void *buf, 323500856ebSRafal Jaworowski * int *len 324500856ebSRafal Jaworowski * ) 325500856ebSRafal Jaworowski * 326500856ebSRafal Jaworowski * buf: ptr to buffer from where to get the data to send 327500856ebSRafal Jaworowski * 328500856ebSRafal Jaworowski * len: length of packet to be sent (in bytes) 329500856ebSRafal Jaworowski * 330500856ebSRafal Jaworowski */ 331500856ebSRafal Jaworowski static int API_dev_write(va_list ap) 332500856ebSRafal Jaworowski { 333500856ebSRafal Jaworowski struct device_info *di; 334500856ebSRafal Jaworowski void *buf; 335500856ebSRafal Jaworowski int *len; 336500856ebSRafal Jaworowski int err = 0; 337500856ebSRafal Jaworowski 338500856ebSRafal Jaworowski /* 1. arg is ptr to the device_info struct */ 339500856ebSRafal Jaworowski di = (struct device_info *)va_arg(ap, u_int32_t); 340500856ebSRafal Jaworowski if (di == NULL) 341500856ebSRafal Jaworowski return API_EINVAL; 342500856ebSRafal Jaworowski 343500856ebSRafal Jaworowski /* XXX should we check if device is open? i.e. the ->state ? */ 344500856ebSRafal Jaworowski 345500856ebSRafal Jaworowski if (di->cookie == NULL) 346500856ebSRafal Jaworowski return API_ENODEV; 347500856ebSRafal Jaworowski 348500856ebSRafal Jaworowski /* 2. arg is ptr to buffer from where to get data to write */ 349500856ebSRafal Jaworowski buf = (void *)va_arg(ap, u_int32_t); 350500856ebSRafal Jaworowski if (buf == NULL) 351500856ebSRafal Jaworowski return API_EINVAL; 352500856ebSRafal Jaworowski 353500856ebSRafal Jaworowski /* 3. arg is length of buffer */ 354500856ebSRafal Jaworowski len = (int *)va_arg(ap, u_int32_t); 355500856ebSRafal Jaworowski if (len == NULL) 356500856ebSRafal Jaworowski return API_EINVAL; 357500856ebSRafal Jaworowski if (*len <= 0) 358500856ebSRafal Jaworowski return API_EINVAL; 359500856ebSRafal Jaworowski 360500856ebSRafal Jaworowski if (di->type & DEV_TYP_STOR) 361500856ebSRafal Jaworowski /* 362500856ebSRafal Jaworowski * write to storage is currently not supported by U-Boot: 363500856ebSRafal Jaworowski * no storage device implements block_write() method 364500856ebSRafal Jaworowski */ 365500856ebSRafal Jaworowski return API_ENODEV; 366500856ebSRafal Jaworowski 367500856ebSRafal Jaworowski else if (di->type & DEV_TYP_NET) 368500856ebSRafal Jaworowski err = dev_write_net(di->cookie, buf, *len); 369500856ebSRafal Jaworowski else 370500856ebSRafal Jaworowski err = API_ENODEV; 371500856ebSRafal Jaworowski 372500856ebSRafal Jaworowski return err; 373500856ebSRafal Jaworowski } 374500856ebSRafal Jaworowski 375500856ebSRafal Jaworowski 376500856ebSRafal Jaworowski /* 377500856ebSRafal Jaworowski * pseudo signature: 378500856ebSRafal Jaworowski * 379500856ebSRafal Jaworowski * int API_dev_read( 380500856ebSRafal Jaworowski * struct device_info *di, 381500856ebSRafal Jaworowski * void *buf, 382500856ebSRafal Jaworowski * size_t *len, 383500856ebSRafal Jaworowski * unsigned long *start 384500856ebSRafal Jaworowski * size_t *act_len 385500856ebSRafal Jaworowski * ) 386500856ebSRafal Jaworowski * 387500856ebSRafal Jaworowski * buf: ptr to buffer where to put the read data 388500856ebSRafal Jaworowski * 389500856ebSRafal Jaworowski * len: ptr to length to be read 390500856ebSRafal Jaworowski * - network: len of packet to read (in bytes) 391500856ebSRafal Jaworowski * - storage: # of blocks to read (can vary in size depending on define) 392500856ebSRafal Jaworowski * 393500856ebSRafal Jaworowski * start: ptr to start block (only used for storage devices, ignored for 394500856ebSRafal Jaworowski * network) 395500856ebSRafal Jaworowski * 396500856ebSRafal Jaworowski * act_len: ptr to where to put the len actually read 397500856ebSRafal Jaworowski */ 398500856ebSRafal Jaworowski static int API_dev_read(va_list ap) 399500856ebSRafal Jaworowski { 400500856ebSRafal Jaworowski struct device_info *di; 401500856ebSRafal Jaworowski void *buf; 402500856ebSRafal Jaworowski lbasize_t *len_stor, *act_len_stor; 403500856ebSRafal Jaworowski lbastart_t *start; 404500856ebSRafal Jaworowski int *len_net, *act_len_net; 405500856ebSRafal Jaworowski 406500856ebSRafal Jaworowski /* 1. arg is ptr to the device_info struct */ 407500856ebSRafal Jaworowski di = (struct device_info *)va_arg(ap, u_int32_t); 408500856ebSRafal Jaworowski if (di == NULL) 409500856ebSRafal Jaworowski return API_EINVAL; 410500856ebSRafal Jaworowski 411500856ebSRafal Jaworowski /* XXX should we check if device is open? i.e. the ->state ? */ 412500856ebSRafal Jaworowski 413500856ebSRafal Jaworowski if (di->cookie == NULL) 414500856ebSRafal Jaworowski return API_ENODEV; 415500856ebSRafal Jaworowski 416500856ebSRafal Jaworowski /* 2. arg is ptr to buffer from where to put the read data */ 417500856ebSRafal Jaworowski buf = (void *)va_arg(ap, u_int32_t); 418500856ebSRafal Jaworowski if (buf == NULL) 419500856ebSRafal Jaworowski return API_EINVAL; 420500856ebSRafal Jaworowski 421500856ebSRafal Jaworowski if (di->type & DEV_TYP_STOR) { 422500856ebSRafal Jaworowski /* 3. arg - ptr to var with # of blocks to read */ 423500856ebSRafal Jaworowski len_stor = (lbasize_t *)va_arg(ap, u_int32_t); 424500856ebSRafal Jaworowski if (!len_stor) 425500856ebSRafal Jaworowski return API_EINVAL; 426500856ebSRafal Jaworowski if (*len_stor <= 0) 427500856ebSRafal Jaworowski return API_EINVAL; 428500856ebSRafal Jaworowski 429500856ebSRafal Jaworowski /* 4. arg - ptr to var with start block */ 430500856ebSRafal Jaworowski start = (lbastart_t *)va_arg(ap, u_int32_t); 431500856ebSRafal Jaworowski 432500856ebSRafal Jaworowski /* 5. arg - ptr to var where to put the len actually read */ 433500856ebSRafal Jaworowski act_len_stor = (lbasize_t *)va_arg(ap, u_int32_t); 434500856ebSRafal Jaworowski if (!act_len_stor) 435500856ebSRafal Jaworowski return API_EINVAL; 436500856ebSRafal Jaworowski 437500856ebSRafal Jaworowski *act_len_stor = dev_read_stor(di->cookie, buf, *len_stor, *start); 438500856ebSRafal Jaworowski 439500856ebSRafal Jaworowski } else if (di->type & DEV_TYP_NET) { 440500856ebSRafal Jaworowski 441500856ebSRafal Jaworowski /* 3. arg points to the var with length of packet to read */ 442500856ebSRafal Jaworowski len_net = (int *)va_arg(ap, u_int32_t); 443500856ebSRafal Jaworowski if (!len_net) 444500856ebSRafal Jaworowski return API_EINVAL; 445500856ebSRafal Jaworowski if (*len_net <= 0) 446500856ebSRafal Jaworowski return API_EINVAL; 447500856ebSRafal Jaworowski 448500856ebSRafal Jaworowski /* 4. - ptr to var where to put the len actually read */ 449500856ebSRafal Jaworowski act_len_net = (int *)va_arg(ap, u_int32_t); 450500856ebSRafal Jaworowski if (!act_len_net) 451500856ebSRafal Jaworowski return API_EINVAL; 452500856ebSRafal Jaworowski 453500856ebSRafal Jaworowski *act_len_net = dev_read_net(di->cookie, buf, *len_net); 454500856ebSRafal Jaworowski 455500856ebSRafal Jaworowski } else 456500856ebSRafal Jaworowski return API_ENODEV; 457500856ebSRafal Jaworowski 458500856ebSRafal Jaworowski return 0; 459500856ebSRafal Jaworowski } 460500856ebSRafal Jaworowski 461500856ebSRafal Jaworowski 462500856ebSRafal Jaworowski /* 463500856ebSRafal Jaworowski * pseudo signature: 464500856ebSRafal Jaworowski * 465500856ebSRafal Jaworowski * int API_env_get(const char *name, char **value) 466500856ebSRafal Jaworowski * 467500856ebSRafal Jaworowski * name: ptr to name of env var 468500856ebSRafal Jaworowski */ 469500856ebSRafal Jaworowski static int API_env_get(va_list ap) 470500856ebSRafal Jaworowski { 471500856ebSRafal Jaworowski char *name, **value; 472500856ebSRafal Jaworowski 473500856ebSRafal Jaworowski if ((name = (char *)va_arg(ap, u_int32_t)) == NULL) 474500856ebSRafal Jaworowski return API_EINVAL; 475500856ebSRafal Jaworowski if ((value = (char **)va_arg(ap, u_int32_t)) == NULL) 476500856ebSRafal Jaworowski return API_EINVAL; 477500856ebSRafal Jaworowski 478500856ebSRafal Jaworowski *value = getenv(name); 479500856ebSRafal Jaworowski 480500856ebSRafal Jaworowski return 0; 481500856ebSRafal Jaworowski } 482500856ebSRafal Jaworowski 483500856ebSRafal Jaworowski /* 484500856ebSRafal Jaworowski * pseudo signature: 485500856ebSRafal Jaworowski * 486500856ebSRafal Jaworowski * int API_env_set(const char *name, const char *value) 487500856ebSRafal Jaworowski * 488500856ebSRafal Jaworowski * name: ptr to name of env var 489500856ebSRafal Jaworowski * 490500856ebSRafal Jaworowski * value: ptr to value to be set 491500856ebSRafal Jaworowski */ 492500856ebSRafal Jaworowski static int API_env_set(va_list ap) 493500856ebSRafal Jaworowski { 494500856ebSRafal Jaworowski char *name, *value; 495500856ebSRafal Jaworowski 496500856ebSRafal Jaworowski if ((name = (char *)va_arg(ap, u_int32_t)) == NULL) 497500856ebSRafal Jaworowski return API_EINVAL; 498500856ebSRafal Jaworowski if ((value = (char *)va_arg(ap, u_int32_t)) == NULL) 499500856ebSRafal Jaworowski return API_EINVAL; 500500856ebSRafal Jaworowski 501500856ebSRafal Jaworowski setenv(name, value); 502500856ebSRafal Jaworowski 503500856ebSRafal Jaworowski return 0; 504500856ebSRafal Jaworowski } 505500856ebSRafal Jaworowski 506500856ebSRafal Jaworowski /* 507500856ebSRafal Jaworowski * pseudo signature: 508500856ebSRafal Jaworowski * 509500856ebSRafal Jaworowski * int API_env_enum(const char *last, char **next) 510500856ebSRafal Jaworowski * 511500856ebSRafal Jaworowski * last: ptr to name of env var found in last iteration 512500856ebSRafal Jaworowski */ 513500856ebSRafal Jaworowski static int API_env_enum(va_list ap) 514500856ebSRafal Jaworowski { 515500856ebSRafal Jaworowski int i, n; 516500856ebSRafal Jaworowski char *last, **next; 517500856ebSRafal Jaworowski 518500856ebSRafal Jaworowski last = (char *)va_arg(ap, u_int32_t); 519500856ebSRafal Jaworowski 520500856ebSRafal Jaworowski if ((next = (char **)va_arg(ap, u_int32_t)) == NULL) 521500856ebSRafal Jaworowski return API_EINVAL; 522500856ebSRafal Jaworowski 523500856ebSRafal Jaworowski if (last == NULL) 524500856ebSRafal Jaworowski /* start over */ 525500856ebSRafal Jaworowski *next = ((char *)env_get_addr(0)); 526500856ebSRafal Jaworowski else { 527500856ebSRafal Jaworowski *next = last; 528500856ebSRafal Jaworowski 529500856ebSRafal Jaworowski for (i = 0; env_get_char(i) != '\0'; i = n + 1) { 530500856ebSRafal Jaworowski for (n = i; env_get_char(n) != '\0'; ++n) { 5310e8d1586SJean-Christophe PLAGNIOL-VILLARD if (n >= CONFIG_ENV_SIZE) { 532500856ebSRafal Jaworowski /* XXX shouldn't we set *next = NULL?? */ 533500856ebSRafal Jaworowski return 0; 534500856ebSRafal Jaworowski } 535500856ebSRafal Jaworowski } 536500856ebSRafal Jaworowski 537500856ebSRafal Jaworowski if (envmatch((uchar *)last, i) < 0) 538500856ebSRafal Jaworowski continue; 539500856ebSRafal Jaworowski 540500856ebSRafal Jaworowski /* try to get next name */ 541500856ebSRafal Jaworowski i = n + 1; 542500856ebSRafal Jaworowski if (env_get_char(i) == '\0') { 543500856ebSRafal Jaworowski /* no more left */ 544500856ebSRafal Jaworowski *next = NULL; 545500856ebSRafal Jaworowski return 0; 546500856ebSRafal Jaworowski } 547500856ebSRafal Jaworowski 548500856ebSRafal Jaworowski *next = ((char *)env_get_addr(i)); 549500856ebSRafal Jaworowski return 0; 550500856ebSRafal Jaworowski } 551500856ebSRafal Jaworowski } 552500856ebSRafal Jaworowski 553500856ebSRafal Jaworowski return 0; 554500856ebSRafal Jaworowski } 555500856ebSRafal Jaworowski 556*a2a5729fSChe-Liang Chiou /* 557*a2a5729fSChe-Liang Chiou * pseudo signature: 558*a2a5729fSChe-Liang Chiou * 559*a2a5729fSChe-Liang Chiou * int API_display_get_info(int type, struct display_info *di) 560*a2a5729fSChe-Liang Chiou */ 561*a2a5729fSChe-Liang Chiou static int API_display_get_info(va_list ap) 562*a2a5729fSChe-Liang Chiou { 563*a2a5729fSChe-Liang Chiou int type; 564*a2a5729fSChe-Liang Chiou struct display_info *di; 565*a2a5729fSChe-Liang Chiou 566*a2a5729fSChe-Liang Chiou type = va_arg(ap, int); 567*a2a5729fSChe-Liang Chiou di = va_arg(ap, struct display_info *); 568*a2a5729fSChe-Liang Chiou 569*a2a5729fSChe-Liang Chiou return display_get_info(type, di); 570*a2a5729fSChe-Liang Chiou } 571*a2a5729fSChe-Liang Chiou 572*a2a5729fSChe-Liang Chiou /* 573*a2a5729fSChe-Liang Chiou * pseudo signature: 574*a2a5729fSChe-Liang Chiou * 575*a2a5729fSChe-Liang Chiou * int API_display_draw_bitmap(ulong bitmap, int x, int y) 576*a2a5729fSChe-Liang Chiou */ 577*a2a5729fSChe-Liang Chiou static int API_display_draw_bitmap(va_list ap) 578*a2a5729fSChe-Liang Chiou { 579*a2a5729fSChe-Liang Chiou ulong bitmap; 580*a2a5729fSChe-Liang Chiou int x, y; 581*a2a5729fSChe-Liang Chiou 582*a2a5729fSChe-Liang Chiou bitmap = va_arg(ap, ulong); 583*a2a5729fSChe-Liang Chiou x = va_arg(ap, int); 584*a2a5729fSChe-Liang Chiou y = va_arg(ap, int); 585*a2a5729fSChe-Liang Chiou 586*a2a5729fSChe-Liang Chiou return display_draw_bitmap(bitmap, x, y); 587*a2a5729fSChe-Liang Chiou } 588*a2a5729fSChe-Liang Chiou 589*a2a5729fSChe-Liang Chiou /* 590*a2a5729fSChe-Liang Chiou * pseudo signature: 591*a2a5729fSChe-Liang Chiou * 592*a2a5729fSChe-Liang Chiou * void API_display_clear(void) 593*a2a5729fSChe-Liang Chiou */ 594*a2a5729fSChe-Liang Chiou static int API_display_clear(va_list ap) 595*a2a5729fSChe-Liang Chiou { 596*a2a5729fSChe-Liang Chiou display_clear(); 597*a2a5729fSChe-Liang Chiou return 0; 598*a2a5729fSChe-Liang Chiou } 599*a2a5729fSChe-Liang Chiou 600500856ebSRafal Jaworowski static cfp_t calls_table[API_MAXCALL] = { NULL, }; 601500856ebSRafal Jaworowski 602500856ebSRafal Jaworowski /* 603500856ebSRafal Jaworowski * The main syscall entry point - this is not reentrant, only one call is 604500856ebSRafal Jaworowski * serviced until finished. 605500856ebSRafal Jaworowski * 606500856ebSRafal Jaworowski * e.g. syscall(1, int *, u_int32_t, u_int32_t, u_int32_t, u_int32_t); 607500856ebSRafal Jaworowski * 608500856ebSRafal Jaworowski * call: syscall number 609500856ebSRafal Jaworowski * 610500856ebSRafal Jaworowski * retval: points to the return value placeholder, this is the place the 611500856ebSRafal Jaworowski * syscall puts its return value, if NULL the caller does not 612500856ebSRafal Jaworowski * expect a return value 613500856ebSRafal Jaworowski * 614500856ebSRafal Jaworowski * ... syscall arguments (variable number) 615500856ebSRafal Jaworowski * 616500856ebSRafal Jaworowski * returns: 0 if the call not found, 1 if serviced 617500856ebSRafal Jaworowski */ 618500856ebSRafal Jaworowski int syscall(int call, int *retval, ...) 619500856ebSRafal Jaworowski { 620500856ebSRafal Jaworowski va_list ap; 621500856ebSRafal Jaworowski int rv; 622500856ebSRafal Jaworowski 62320e5ed13SJean-Christophe PLAGNIOL-VILLARD if (call < 0 || call >= calls_no) { 624500856ebSRafal Jaworowski debugf("invalid call #%d\n", call); 625500856ebSRafal Jaworowski return 0; 626500856ebSRafal Jaworowski } 627500856ebSRafal Jaworowski 628500856ebSRafal Jaworowski if (calls_table[call] == NULL) { 629500856ebSRafal Jaworowski debugf("syscall #%d does not have a handler\n", call); 630500856ebSRafal Jaworowski return 0; 631500856ebSRafal Jaworowski } 632500856ebSRafal Jaworowski 633500856ebSRafal Jaworowski va_start(ap, retval); 634500856ebSRafal Jaworowski rv = calls_table[call](ap); 635500856ebSRafal Jaworowski if (retval != NULL) 636500856ebSRafal Jaworowski *retval = rv; 637500856ebSRafal Jaworowski 638500856ebSRafal Jaworowski return 1; 639500856ebSRafal Jaworowski } 640500856ebSRafal Jaworowski 641500856ebSRafal Jaworowski void api_init(void) 642500856ebSRafal Jaworowski { 643500856ebSRafal Jaworowski struct api_signature *sig = NULL; 644500856ebSRafal Jaworowski 645500856ebSRafal Jaworowski /* TODO put this into linker set one day... */ 646500856ebSRafal Jaworowski calls_table[API_RSVD] = NULL; 647500856ebSRafal Jaworowski calls_table[API_GETC] = &API_getc; 648500856ebSRafal Jaworowski calls_table[API_PUTC] = &API_putc; 649500856ebSRafal Jaworowski calls_table[API_TSTC] = &API_tstc; 650500856ebSRafal Jaworowski calls_table[API_PUTS] = &API_puts; 651500856ebSRafal Jaworowski calls_table[API_RESET] = &API_reset; 652500856ebSRafal Jaworowski calls_table[API_GET_SYS_INFO] = &API_get_sys_info; 653500856ebSRafal Jaworowski calls_table[API_UDELAY] = &API_udelay; 654500856ebSRafal Jaworowski calls_table[API_GET_TIMER] = &API_get_timer; 655500856ebSRafal Jaworowski calls_table[API_DEV_ENUM] = &API_dev_enum; 656500856ebSRafal Jaworowski calls_table[API_DEV_OPEN] = &API_dev_open; 657500856ebSRafal Jaworowski calls_table[API_DEV_CLOSE] = &API_dev_close; 658500856ebSRafal Jaworowski calls_table[API_DEV_READ] = &API_dev_read; 659500856ebSRafal Jaworowski calls_table[API_DEV_WRITE] = &API_dev_write; 660500856ebSRafal Jaworowski calls_table[API_ENV_GET] = &API_env_get; 661500856ebSRafal Jaworowski calls_table[API_ENV_SET] = &API_env_set; 662500856ebSRafal Jaworowski calls_table[API_ENV_ENUM] = &API_env_enum; 663*a2a5729fSChe-Liang Chiou calls_table[API_DISPLAY_GET_INFO] = &API_display_get_info; 664*a2a5729fSChe-Liang Chiou calls_table[API_DISPLAY_DRAW_BITMAP] = &API_display_draw_bitmap; 665*a2a5729fSChe-Liang Chiou calls_table[API_DISPLAY_CLEAR] = &API_display_clear; 666500856ebSRafal Jaworowski calls_no = API_MAXCALL; 667500856ebSRafal Jaworowski 668500856ebSRafal Jaworowski debugf("API initialized with %d calls\n", calls_no); 669500856ebSRafal Jaworowski 670500856ebSRafal Jaworowski dev_stor_init(); 671500856ebSRafal Jaworowski 672500856ebSRafal Jaworowski /* 673500856ebSRafal Jaworowski * Produce the signature so the API consumers can find it 674500856ebSRafal Jaworowski */ 675500856ebSRafal Jaworowski sig = malloc(sizeof(struct api_signature)); 676500856ebSRafal Jaworowski if (sig == NULL) { 677500856ebSRafal Jaworowski printf("API: could not allocate memory for the signature!\n"); 678500856ebSRafal Jaworowski return; 679500856ebSRafal Jaworowski } 680500856ebSRafal Jaworowski 681500856ebSRafal Jaworowski debugf("API sig @ 0x%08x\n", sig); 682500856ebSRafal Jaworowski memcpy(sig->magic, API_SIG_MAGIC, 8); 683500856ebSRafal Jaworowski sig->version = API_SIG_VERSION; 684500856ebSRafal Jaworowski sig->syscall = &syscall; 685500856ebSRafal Jaworowski sig->checksum = 0; 686500856ebSRafal Jaworowski sig->checksum = crc32(0, (unsigned char *)sig, 687500856ebSRafal Jaworowski sizeof(struct api_signature)); 688500856ebSRafal Jaworowski debugf("syscall entry: 0x%08x\n", sig->syscall); 689500856ebSRafal Jaworowski } 690500856ebSRafal Jaworowski 691500856ebSRafal Jaworowski void platform_set_mr(struct sys_info *si, unsigned long start, unsigned long size, 692500856ebSRafal Jaworowski int flags) 693500856ebSRafal Jaworowski { 694500856ebSRafal Jaworowski int i; 695500856ebSRafal Jaworowski 696500856ebSRafal Jaworowski if (!si->mr || !size || (flags == 0)) 697500856ebSRafal Jaworowski return; 698500856ebSRafal Jaworowski 699500856ebSRafal Jaworowski /* find free slot */ 700500856ebSRafal Jaworowski for (i = 0; i < si->mr_no; i++) 701500856ebSRafal Jaworowski if (si->mr[i].flags == 0) { 702500856ebSRafal Jaworowski /* insert new mem region */ 703500856ebSRafal Jaworowski si->mr[i].start = start; 704500856ebSRafal Jaworowski si->mr[i].size = size; 705500856ebSRafal Jaworowski si->mr[i].flags = flags; 706500856ebSRafal Jaworowski return; 707500856ebSRafal Jaworowski } 708500856ebSRafal Jaworowski } 709