Initial revision

master
wdenk 23 years ago
parent f8cac651b3
commit 3863585bb1
  1. 98
      common/cmd_cache.c
  2. 61
      common/cmd_console.c
  3. 189
      common/cmd_date.c
  4. 103
      common/cmd_dcr.c
  5. 49
      common/cmd_dtt.c
  6. 353
      common/cmd_eeprom.c
  7. 735
      common/cmd_fdc.c
  8. 850
      common/cmd_mem.c
  9. 56
      common/cmd_misc.c
  10. 164
      common/cmd_net.c

@ -0,0 +1,98 @@
/*
* (C) Copyright 2000
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
*
* See file CREDITS for list of people who contributed to this
* project.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*/
/*
* Cache support: switch on or off, get status
*/
#include <common.h>
#include <command.h>
#include <cmd_cache.h>
#if (CONFIG_COMMANDS & CFG_CMD_CACHE)
static int on_off (const char *);
int do_icache ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
{
switch (argc) {
case 2: /* on / off */
switch (on_off(argv[1])) {
#if 0 /* prevented by varargs handling; FALLTROUGH is harmless, too */
default: printf ("Usage:\n%s\n", cmdtp->usage);
return;
#endif
case 0: icache_disable();
break;
case 1: icache_enable ();
break;
}
/* FALL TROUGH */
case 1: /* get status */
printf ("Instruction Cache is %s\n",
icache_status() ? "ON" : "OFF");
return 0;
default:
printf ("Usage:\n%s\n", cmdtp->usage);
return 1;
}
return 0;
}
int do_dcache ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
{
switch (argc) {
case 2: /* on / off */
switch (on_off(argv[1])) {
#if 0 /* prevented by varargs handling; FALLTROUGH is harmless, too */
default: printf ("Usage:\n%s\n", cmdtp->usage);
return;
#endif
case 0: dcache_disable();
break;
case 1: dcache_enable ();
break;
}
/* FALL TROUGH */
case 1: /* get status */
printf ("Data (writethrough) Cache is %s\n",
dcache_status() ? "ON" : "OFF");
return 0;
default:
printf ("Usage:\n%s\n", cmdtp->usage);
return 1;
}
return 0;
}
static int on_off (const char *s)
{
if (strcmp(s, "on") == 0) {
return (1);
} else if (strcmp(s, "off") == 0) {
return (0);
}
return (-1);
}
#endif /* CFG_CMD_CACHE */

@ -0,0 +1,61 @@
/*
* (C) Copyright 2000
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
*
* See file CREDITS for list of people who contributed to this
* project.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*/
/*
* Boot support
*/
#include <common.h>
#include <command.h>
#include <devices.h>
#if (CONFIG_COMMANDS & CFG_CMD_CONSOLE)
extern void _do_coninfo (void);
int do_coninfo (cmd_tbl_t * cmd, int flag, int argc, char *argv[])
{
int i, l;
/* Scan for valid output and input devices */
printf ("List of available devices:\n");
for (i = 1; i <= ListNumItems (devlist); i++) {
device_t *dev = ListGetPtrToItem (devlist, i);
printf ("%-8s %08x %c%c%c ",
dev->name,
dev->flags,
(dev->flags & DEV_FLAGS_SYSTEM) ? 'S' : '.',
(dev->flags & DEV_FLAGS_INPUT) ? 'I' : '.',
(dev->flags & DEV_FLAGS_OUTPUT) ? 'O' : '.');
for (l = 0; l < MAX_FILES; l++) {
if (stdio_devices[l] == dev) {
printf ("%s ", stdio_names[l]);
}
}
putc ('\n');
}
return 0;
}
#endif /* CFG_CMD_CONSOLE */

@ -0,0 +1,189 @@
/*
* (C) Copyright 2001
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
*
* See file CREDITS for list of people who contributed to this
* project.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*/
/*
* RTC, Date & Time support: get and set date & time
*/
#include <common.h>
#include <command.h>
#include <rtc.h>
#if (CONFIG_COMMANDS & CFG_CMD_DATE)
const char *weekdays[] = {
"Sun", "Mon", "Tues", "Wednes", "Thurs", "Fri", "Satur",
};
int mk_date (char *, struct rtc_time *);
int do_date (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
{
struct rtc_time tm;
int rcode = 0;
switch (argc) {
case 2: /* set date & time */
if (strcmp(argv[1],"reset") == 0) {
printf ("Reset RTC...\n");
rtc_reset ();
} else {
/* initialize tm with current time */
rtc_get (&tm);
/* insert new date & time */
if (mk_date (argv[1], &tm) != 0) {
printf ("## Bad date format\n");
return 1;
}
/* and write to RTC */
rtc_set (&tm);
}
/* FALL TROUGH */
case 1: /* get date & time */
rtc_get (&tm);
printf ("Date: %4d-%02d-%02d (%sday) Time: %2d:%02d:%02d\n",
tm.tm_year, tm.tm_mon, tm.tm_mday,
(tm.tm_wday<0 || tm.tm_wday>6) ?
"unknown " : weekdays[tm.tm_wday],
tm.tm_hour, tm.tm_min, tm.tm_sec);
return 0;
default:
printf ("Usage:\n%s\n", cmdtp->usage);
rcode = 1;
}
return rcode;
}
/*
* simple conversion of two-digit string with error checking
*/
static int cnvrt2 (char *str, int *valp)
{
int val;
if ((*str < '0') || (*str > '9'))
return (-1);
val = *str - '0';
++str;
if ((*str < '0') || (*str > '9'))
return (-1);
*valp = 10 * val + (*str - '0');
return (0);
}
/*
* Convert date string: MMDDhhmm[[CC]YY][.ss]
*
* Some basic checking for valid values is done, but this will not catch
* all possible error conditions.
*/
int mk_date (char *datestr, struct rtc_time *tmp)
{
int len, val;
char *ptr;
ptr = strchr (datestr,'.');
len = strlen (datestr);
/* Set seconds */
if (ptr) {
int sec;
*ptr++ = '\0';
if ((len - (ptr - datestr)) != 2)
return (-1);
len = strlen (datestr);
if (cnvrt2 (ptr, &sec))
return (-1);
tmp->tm_sec = sec;
} else {
tmp->tm_sec = 0;
}
if (len == 12) { /* MMDDhhmmCCYY */
int year, century;
if (cnvrt2 (datestr+ 8, &century) ||
cnvrt2 (datestr+10, &year) ) {
return (-1);
}
tmp->tm_year = 100 * century + year;
} else if (len == 10) { /* MMDDhhmmYY */
int year, century;
century = tmp->tm_year / 100;
if (cnvrt2 (datestr+ 8, &year))
return (-1);
tmp->tm_year = 100 * century + year;
}
switch (len) {
case 8: /* MMDDhhmm */
/* fall thru */
case 10: /* MMDDhhmmYY */
/* fall thru */
case 12: /* MMDDhhmmCCYY */
if (cnvrt2 (datestr+0, &val) ||
val > 12) {
break;
}
tmp->tm_mon = val;
if (cnvrt2 (datestr+2, &val) ||
val > ((tmp->tm_mon==2) ? 29 : 31)) {
break;
}
tmp->tm_mday = val;
if (cnvrt2 (datestr+4, &val) ||
val > 23) {
break;
}
tmp->tm_hour = val;
if (cnvrt2 (datestr+6, &val) ||
val > 59) {
break;
}
tmp->tm_min = val;
/* calculate day of week */
GregorianDay (tmp);
return (0);
default:
break;
}
return (-1);
}
#endif /* CFG_CMD_DATE */

@ -0,0 +1,103 @@
/*
* (C) Copyright 2001
* Erik Theisen, Wave 7 Optics, etheisen@mindspring.com.
*
* See file CREDITS for list of people who contributed to this
* project.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*/
/*
* IBM 4XX DCR Functions
*/
#include <common.h>
#include <config.h>
#include <command.h>
#include <cmd_dcr.h>
#if defined(CONFIG_4xx) && defined(CFG_CMD_SETGETDCR)
/* ======================================================================
* Interpreter command to retrieve an IBM PPC 4xx Device Control Register
* ======================================================================
*/
int do_getdcr ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[] )
{
unsigned short dcrn; /* Device Control Register Num */
unsigned long value; /* DCR's value */
/* Validate arguments */
if (argc < 2) {
printf("Usage:\n%s\n", cmdtp->usage);
return 1;
}
/* Get a DCR */
dcrn = (unsigned short)simple_strtoul(argv[ 1 ], NULL, 16);
value = get_dcr(dcrn);
printf("%04x: %08lx\n", dcrn, value);
return 0;
} /* do_getdcr */
/* ======================================================================
* Interpreter command to set an IBM PPC 4xx Device Control Register
* ======================================================================
*/
int do_setdcr ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
{
unsigned short dcrn; /* Device Control Register Num */
unsigned long value; /* DCR's value */
int nbytes;
extern char console_buffer[];
/* Validate arguments */
if (argc < 2) {
printf("Usage:\n%s\n", cmdtp->usage);
return 1;
}
/* Set a DCR */
dcrn = (unsigned short)simple_strtoul(argv[1], NULL, 16);
do {
value = get_dcr(dcrn);
printf("%04x: %08lx", dcrn, value);
nbytes = readline(" ? ");
if (nbytes == 0) {
/*
* <CR> pressed as only input, don't modify current
* location and exit command.
*/
nbytes = 1;
return 0;
} else {
unsigned long i;
char *endp;
i = simple_strtoul(console_buffer, &endp, 16);
nbytes = endp - console_buffer;
if (nbytes)
set_dcr(dcrn, i);
}
} while (nbytes);
return 0;
} /* do_setdcr */
#endif /* CONFIG_4xx & CFG_CMD_SETGETDCR */

@ -0,0 +1,49 @@
/*
* (C) Copyright 2001
* Erik Theisen, Wave 7 Optics, etheisen@mindspring.com
*
* See file CREDITS for list of people who contributed to this
* project.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*/
#include <common.h>
#include <config.h>
#include <command.h>
#include <cmd_dtt.h>
#if (CONFIG_COMMANDS & CFG_CMD_DTT)
#include <dtt.h>
int do_dtt (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
{
int i;
unsigned char sensors[] = CONFIG_DTT_SENSORS;
/*
* Loop through sensors, read
* temperature, and output it.
*/
for (i = 0; i < sizeof (sensors); i++) {
printf ("DTT%d: %i C\n", i + 1, dtt_get_temp (sensors[i]));
}
return 0;
} /* do_dtt() */
#endif /* CONFIG_COMMANDS & CFG_CMD_DTT */

@ -0,0 +1,353 @@
/*
* (C) Copyright 2000, 2001
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
*
* See file CREDITS for list of people who contributed to this
* project.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*
*/
#include <common.h>
#include <config.h>
#include <command.h>
#include <i2c.h>
#if (CONFIG_COMMANDS & CFG_CMD_EEPROM) || defined(CFG_ENV_IS_IN_EEPROM)
extern void eeprom_init (void);
extern int eeprom_read (unsigned dev_addr, unsigned offset,
uchar *buffer, unsigned cnt);
extern int eeprom_write (unsigned dev_addr, unsigned offset,
uchar *buffer, unsigned cnt);
#endif
#if defined(CFG_EEPROM_X40430)
/* Maximum number of times to poll for acknowledge after write */
#define MAX_ACKNOWLEDGE_POLLS 10
#endif
/* ------------------------------------------------------------------------- */
#if (CONFIG_COMMANDS & CFG_CMD_EEPROM)
int do_eeprom ( cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
{
const char *const fmt =
"\nEEPROM @0x%lX %s: addr %08lx off %04lx count %ld ... ";
#if defined(CFG_I2C_MULTI_EEPROMS)
if (argc == 6) {
ulong dev_addr = simple_strtoul (argv[2], NULL, 16);
ulong addr = simple_strtoul (argv[3], NULL, 16);
ulong off = simple_strtoul (argv[4], NULL, 16);
ulong cnt = simple_strtoul (argv[5], NULL, 16);
#else
if (argc == 5) {
ulong dev_addr = CFG_DEF_EEPROM_ADDR;
ulong addr = simple_strtoul (argv[2], NULL, 16);
ulong off = simple_strtoul (argv[3], NULL, 16);
ulong cnt = simple_strtoul (argv[4], NULL, 16);
#endif /* CFG_I2C_MULTI_EEPROMS */
# ifndef CONFIG_SPI
eeprom_init ();
# endif /* !CONFIG_SPI */
if (strcmp (argv[1], "read") == 0) {
int rcode;
printf (fmt, dev_addr, argv[1], addr, off, cnt);
rcode = eeprom_read (dev_addr, off, (uchar *) addr, cnt);
printf ("done\n");
return rcode;
} else if (strcmp (argv[1], "write") == 0) {
int rcode;
printf (fmt, dev_addr, argv[1], addr, off, cnt);
rcode = eeprom_write (dev_addr, off, (uchar *) addr, cnt);
printf ("done\n");
return rcode;
}
}
printf ("Usage:\n%s\n", cmdtp->usage);
return 1;
}
#endif /* CFG_CMD_EEPROM */
/*-----------------------------------------------------------------------
*
* for CFG_I2C_EEPROM_ADDR_LEN == 2 (16-bit EEPROM address) offset is
* 0x000nxxxx for EEPROM address selectors at n, offset xxxx in EEPROM.
*
* for CFG_I2C_EEPROM_ADDR_LEN == 1 (8-bit EEPROM page address) offset is
* 0x00000nxx for EEPROM address selectors and page number at n.
*/
#if (CONFIG_COMMANDS & CFG_CMD_EEPROM) || defined(CFG_ENV_IS_IN_EEPROM)
#ifndef CONFIG_SPI
#if !defined(CFG_I2C_EEPROM_ADDR_LEN) || CFG_I2C_EEPROM_ADDR_LEN < 1 || CFG_I2C_EEPROM_ADDR_LEN > 2
#error CFG_I2C_EEPROM_ADDR_LEN must be 1 or 2
#endif
#endif
int eeprom_read (unsigned dev_addr, unsigned offset, uchar *buffer, unsigned cnt)
{
unsigned end = offset + cnt;
unsigned blk_off;
int rcode = 0;
/* Read data until done or would cross a page boundary.
* We must write the address again when changing pages
* because the next page may be in a different device.
*/
while (offset < end) {
unsigned alen, len, maxlen;
#if CFG_I2C_EEPROM_ADDR_LEN == 1 && !defined(CONFIG_SPI_X)
uchar addr[2];
blk_off = offset & 0xFF; /* block offset */
addr[0] = offset >> 8; /* block number */
addr[1] = blk_off; /* block offset */
alen = 2;
#else
uchar addr[3];
blk_off = offset & 0xFF; /* block offset */
addr[0] = offset >> 16; /* block number */
addr[1] = offset >> 8; /* upper address octet */
addr[2] = blk_off; /* lower address octet */
alen = 3;
#endif /* CFG_I2C_EEPROM_ADDR_LEN, CONFIG_SPI_X */
addr[0] |= dev_addr; /* insert device address */
maxlen = 0x100 - blk_off;
if (maxlen > I2C_RXTX_LEN)
maxlen = I2C_RXTX_LEN;
len = end - offset;
if (len > maxlen)
len = maxlen;
#ifdef CONFIG_SPI
spi_read (addr, alen, buffer, len);
#else
if (i2c_read (addr[0], offset, alen-1, buffer, len) != 0)
rcode = 1;
#endif
buffer += len;
offset += len;
}
return rcode;
}
/*-----------------------------------------------------------------------
*
* for CFG_I2C_EEPROM_ADDR_LEN == 2 (16-bit EEPROM address) offset is
* 0x000nxxxx for EEPROM address selectors at n, offset xxxx in EEPROM.
*
* for CFG_I2C_EEPROM_ADDR_LEN == 1 (8-bit EEPROM page address) offset is
* 0x00000nxx for EEPROM address selectors and page number at n.
*/
int eeprom_write (unsigned dev_addr, unsigned offset, uchar *buffer, unsigned cnt)
{
unsigned end = offset + cnt;
unsigned blk_off;
int rcode = 0;
#if defined(CFG_EEPROM_X40430)
uchar contr_r_addr[2];
uchar addr_void[2];
uchar contr_reg[2];
uchar ctrl_reg_v;
int i;
#endif
/* Write data until done or would cross a write page boundary.
* We must write the address again when changing pages
* because the address counter only increments within a page.
*/
while (offset < end) {
unsigned alen, len, maxlen;
#if CFG_I2C_EEPROM_ADDR_LEN == 1 && !defined(CONFIG_SPI_X)
uchar addr[2];
blk_off = offset & 0xFF; /* block offset */
addr[0] = offset >> 8; /* block number */
addr[1] = blk_off; /* block offset */
alen = 2;
#else
uchar addr[3];
blk_off = offset & 0xFF; /* block offset */
addr[0] = offset >> 16; /* block number */
addr[1] = offset >> 8; /* upper address octet */
addr[2] = blk_off; /* lower address octet */
alen = 3;
#endif /* CFG_I2C_EEPROM_ADDR_LEN, CONFIG_SPI_X */
addr[0] |= dev_addr; /* insert device address */
#if defined(CFG_EEPROM_PAGE_WRITE_BITS)
#define EEPROM_PAGE_SIZE (1 << CFG_EEPROM_PAGE_WRITE_BITS)
#define EEPROM_PAGE_OFFSET(x) ((x) & (EEPROM_PAGE_SIZE - 1))
maxlen = EEPROM_PAGE_SIZE - EEPROM_PAGE_OFFSET(blk_off);
#else
maxlen = 0x100 - blk_off;
#endif
if (maxlen > I2C_RXTX_LEN)
maxlen = I2C_RXTX_LEN;
len = end - offset;
if (len > maxlen)
len = maxlen;
#ifdef CONFIG_SPI
spi_write (addr, alen, buffer, len);
#else
#if defined(CFG_EEPROM_X40430)
/* Get the value of the control register.
* Set current address (internal pointer in the x40430)
* to 0x1ff.
*/
contr_r_addr[0] = 9;
contr_r_addr[1] = 0xff;
addr_void[0] = 0;
addr_void[1] = addr[1];
#ifdef CFG_I2C_EEPROM_ADDR
contr_r_addr[0] |= CFG_I2C_EEPROM_ADDR;
addr_void[0] |= CFG_I2C_EEPROM_ADDR;
#endif
contr_reg[0] = 0xff;
if (i2c_read (contr_r_addr[0], contr_r_addr[1], 1, contr_reg, 1) != 0) {
rcode = 1;
}
ctrl_reg_v = contr_reg[0];
/* Are any of the eeprom blocks write protected?
*/
if (ctrl_reg_v & 0x18) {
ctrl_reg_v &= ~0x18; /* reset block protect bits */
ctrl_reg_v |= 0x02; /* set write enable latch */
ctrl_reg_v &= ~0x04; /* clear RWEL */
/* Set write enable latch.
*/
contr_reg[0] = 0x02;
if (i2c_write (contr_r_addr[0], 0xff, 1, contr_reg, 1) != 0) {
rcode = 1;
}
/* Set register write enable latch.
*/
contr_reg[0] = 0x06;
if (i2c_write (contr_r_addr[0], 0xFF, 1, contr_reg, 1) != 0) {
rcode = 1;
}
/* Modify ctrl register.
*/
contr_reg[0] = ctrl_reg_v;
if (i2c_write (contr_r_addr[0], 0xFF, 1, contr_reg, 1) != 0) {
rcode = 1;
}
/* The write (above) is an operation on NV memory.
* These can take some time (~5ms), and the device
* will not respond to further I2C messages till
* it's completed the write.
* So poll device for an I2C acknowledge.
* When we get one we know we can continue with other
* operations.
*/
contr_reg[0] = 0;
for (i = 0; i < MAX_ACKNOWLEDGE_POLLS; i++) {
if (i2c_read (addr_void[0], addr_void[1], 1, contr_reg, 1) == 1)
break; /* got ack */
#if defined(CFG_EEPROM_PAGE_WRITE_DELAY_MS)
udelay(CFG_EEPROM_PAGE_WRITE_DELAY_MS * 1000);
#endif
}
if (i == MAX_ACKNOWLEDGE_POLLS) {
printf("EEPROM poll acknowledge failed\n");
rcode = 1;
}
}
/* Is the write enable latch on?.
*/
else if (!(ctrl_reg_v & 0x02)) {
/* Set write enable latch.
*/
contr_reg[0] = 0x02;
if (i2c_write (contr_r_addr[0], 0xFF, 1, contr_reg, 1) != 0) {
rcode = 1;
}
}
/* Write is enabled ... now write eeprom value.
*/
#endif
if (i2c_write (addr[0], offset, alen-1, buffer, len) != 0)
rcode = 1;
#endif
buffer += len;
offset += len;
#if defined(CFG_EEPROM_PAGE_WRITE_DELAY_MS)
udelay(CFG_EEPROM_PAGE_WRITE_DELAY_MS * 1000);
#endif
}
return rcode;
}
/*-----------------------------------------------------------------------
* Set default values
*/
#ifndef CFG_I2C_SPEED
#define CFG_I2C_SPEED 50000
#endif
#ifndef CFG_I2C_SLAVE
#define CFG_I2C_SLAVE 0xFE
#endif
void eeprom_init (void)
{
#if defined(CONFIG_SPI)
spi_init_f ();
#endif
#if defined(CONFIG_HARD_I2C) || \
defined(CONFIG_SOFT_I2C)
i2c_init (CFG_I2C_SPEED, CFG_I2C_SLAVE);
#endif
}
/*-----------------------------------------------------------------------
*/
#endif /* CFG_CMD_EEPROM */

@ -0,0 +1,735 @@
/*
* (C) Copyright 2001
* Denis Peter, MPL AG, d.peter@mpl.ch.
*
* See file CREDITS for list of people who contributed to this
* project.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*
*/
/*
* Floppy Disk support
*/
#include <common.h>
#include <config.h>
#include <command.h>
#include <image.h>
#undef FDC_DEBUG
#ifdef FDC_DEBUG
#define PRINTF(fmt,args...) printf (fmt ,##args)
#else
#define PRINTF(fmt,args...)
#endif
#ifndef TRUE
#define TRUE 1
#endif
#ifndef FALSE
#define FALSE 0
#endif
#if (CONFIG_COMMANDS & CFG_CMD_DATE)
#include <rtc.h>
#endif
#if (CONFIG_COMMANDS & CFG_CMD_FDC)
typedef struct {
int flags; /* connected drives ect */
unsigned long blnr; /* Logical block nr */
uchar drive; /* drive no */
uchar cmdlen; /* cmd length */
uchar cmd[16]; /* cmd desc */
uchar dma; /* if > 0 dma enabled */
uchar result[11];/* status information */
uchar resultlen; /* lenght of result */
} FDC_COMMAND_STRUCT;
/* flags: only the lower 8bit used:
* bit 0 if set drive 0 is present
* bit 1 if set drive 1 is present
* bit 2 if set drive 2 is present
* bit 3 if set drive 3 is present
* bit 4 if set disk in drive 0 is inserted
* bit 5 if set disk in drive 1 is inserted
* bit 6 if set disk in drive 2 is inserted
* bit 7 if set disk in drive 4 is inserted
*/
/* cmd indexes */
#define COMMAND 0
#define DRIVE 1
#define CONFIG0 1
#define SPEC_HUTSRT 1
#define TRACK 2
#define CONFIG1 2
#define SPEC_HLT 2
#define HEAD 3
#define CONFIG2 3
#define SECTOR 4
#define SECTOR_SIZE 5
#define LAST_TRACK 6
#define GAP 7
#define DTL 8
/* result indexes */
#define STATUS_0 0
#define STATUS_PCN 1
#define STATUS_1 1
#define STATUS_2 2
#define STATUS_TRACK 3
#define STATUS_HEAD 4
#define STATUS_SECT 5
#define STATUS_SECT_SIZE 6
/* Register addresses */
#define FDC_BASE 0x3F0
#define FDC_SRA FDC_BASE + 0 /* Status Register A */
#define FDC_SRB FDC_BASE + 1 /* Status Register B */
#define FDC_DOR FDC_BASE + 2 /* Digital Output Register */
#define FDC_TDR FDC_BASE + 3 /* Tape Drive Register */
#define FDC_DSR FDC_BASE + 4 /* Data rate Register */
#define FDC_MSR FDC_BASE + 4 /* Main Status Register */
#define FDC_FIFO FDC_BASE + 5 /* FIFO */
#define FDC_DIR FDC_BASE + 6 /* Digital Input Register */
#define FDC_CCR FDC_BASE + 7 /* Configuration Control */
/* Commands */
#define FDC_CMD_SENSE_INT 0x08
#define FDC_CMD_CONFIGURE 0x13
#define FDC_CMD_SPECIFY 0x03
#define FDC_CMD_RECALIBRATE 0x07
#define FDC_CMD_READ 0x06
#define FDC_CMD_READ_TRACK 0x02
#define FDC_CMD_READ_ID 0x0A
#define FDC_CMD_DUMP_REG 0x0E
#define FDC_CMD_SEEK 0x0F
#define FDC_CMD_SENSE_INT_LEN 0x01
#define FDC_CMD_CONFIGURE_LEN 0x04
#define FDC_CMD_SPECIFY_LEN 0x03
#define FDC_CMD_RECALIBRATE_LEN 0x02
#define FDC_CMD_READ_LEN 0x09
#define FDC_CMD_READ_TRACK_LEN 0x09
#define FDC_CMD_READ_ID_LEN 0x02
#define FDC_CMD_DUMP_REG_LEN 0x01
#define FDC_CMD_SEEK_LEN 0x03
#define FDC_FIFO_THR 0x0C
#define FDC_FIFO_DIS 0x00
#define FDC_IMPLIED_SEEK 0x01
#define FDC_POLL_DIS 0x00
#define FDC_PRE_TRK 0x00
#define FDC_CONFIGURE FDC_FIFO_THR | (FDC_POLL_DIS<<4) | (FDC_FIFO_DIS<<5) | (FDC_IMPLIED_SEEK << 6)
#define FDC_MFM_MODE 0x01 /* MFM enable */
#define FDC_SKIP_MODE 0x00 /* skip enable */
#define FDC_TIME_OUT 100000 /* time out */
#define FDC_RW_RETRIES 3 /* read write retries */
#define FDC_CAL_RETRIES 3 /* calibration and seek retries */
/* Disk structure */
typedef struct {
unsigned int size; /* nr of sectors total */
unsigned int sect; /* sectors per track */
unsigned int head; /* nr of heads */
unsigned int track; /* nr of tracks */
unsigned int stretch; /* !=0 means double track steps */
unsigned char gap; /* gap1 size */
unsigned char rate; /* data rate. |= 0x40 for perpendicular */
unsigned char spec1; /* stepping rate, head unload time */
unsigned char fmt_gap; /* gap2 size */
unsigned char hlt; /* head load time */
unsigned char sect_code; /* Sector Size code */
const char * name; /* used only for predefined formats */
} FD_GEO_STRUCT;
/* supported Floppy types (currently only one) */
const static FD_GEO_STRUCT floppy_type[2] = {
{ 2880,18,2,80,0,0x1B,0x00,0xCF,0x6C,16,2,"H1440" }, /* 7 1.44MB 3.5" */
{ 0, 0,0, 0,0,0x00,0x00,0x00,0x00, 0,0,NULL }, /* end of table */
};
static FDC_COMMAND_STRUCT cmd; /* global command struct */
/* Supporting Functions */
/* reads a Register of the FDC */
unsigned char read_fdc_reg(unsigned int addr)
{
volatile unsigned char *val = (volatile unsigned char *)(CFG_ISA_IO_BASE_ADDRESS | addr);
return val[0];
}
/* writes a Register of the FDC */
void write_fdc_reg(unsigned int addr, unsigned char val)
{
volatile unsigned char *tmp = (volatile unsigned char *)(CFG_ISA_IO_BASE_ADDRESS | addr);
tmp[0]=val;
}
/* waits for an interrupt (polling) */
int wait_for_fdc_int(void)
{
unsigned long timeout;
timeout = FDC_TIME_OUT;
while((read_fdc_reg(FDC_SRA)&0x80)==0) {
timeout--;
udelay(10);
if(timeout==0) /* timeout occured */
return FALSE;
}
return TRUE;
}
/* reads a byte from the FIFO of the FDC and checks direction and RQM bit
of the MSR. returns -1 if timeout, or byte if ok */
int read_fdc_byte(void)
{
unsigned long timeout;
timeout = FDC_TIME_OUT;
while((read_fdc_reg(FDC_MSR)&0xC0)!=0xC0) {
/* direction out and ready */
udelay(10);
timeout--;
if(timeout==0) /* timeout occured */
return -1;
}
return read_fdc_reg(FDC_FIFO);
}
/* if the direction of the FIFO is wrong, this routine is used to
empty the FIFO. Should _not_ be used */
int fdc_need_more_output(void)
{
unsigned char c;
while((read_fdc_reg(FDC_MSR)&0xC0)==0xC0) {
c=(unsigned char)read_fdc_byte();
printf("Error: more output: %x\n",c);
}
return TRUE;
}
/* writes a byte to the FIFO of the FDC and checks direction and RQM bit
of the MSR */
int write_fdc_byte(unsigned char val)
{
unsigned long timeout;
timeout = FDC_TIME_OUT;
while((read_fdc_reg(FDC_MSR)&0xC0)!=0x80) {
/* direction in and ready for byte */
timeout--;
udelay(10);
fdc_need_more_output();
if(timeout==0) /* timeout occured */
return FALSE;
}
write_fdc_reg(FDC_FIFO,val);
return TRUE;
}
/* sets up all FDC commands and issues it to the FDC. If
the command causes direct results (no Execution Phase)
the result is be read as well. */
int fdc_issue_cmd(FDC_COMMAND_STRUCT *pCMD,FD_GEO_STRUCT *pFG)
{
int i;
unsigned long head,track,sect,timeout;
track = pCMD->blnr / (pFG->sect * pFG->head); /* track nr */
sect = pCMD->blnr % (pFG->sect * pFG->head); /* remaining blocks */
head = sect / pFG->sect; /* head nr */
sect = sect % pFG->sect; /* remaining blocks */
sect++; /* sectors are 1 based */
PRINTF("Track %ld, Head %ld, Sector %ld, Drive %d (blnr %ld)\n",track,head,sect,pCMD->drive,pCMD->blnr);
if(head|=0) { /* max heads = 2 */
pCMD->cmd[DRIVE]=pCMD->drive | 0x04; /* head 1 */
pCMD->cmd[HEAD]=(unsigned char) head; /* head register */
}
else {
pCMD->cmd[DRIVE]=pCMD->drive; /* head 0 */
pCMD->cmd[HEAD]=(unsigned char) head; /* head register */
}
pCMD->cmd[TRACK]=(unsigned char) track; /* track */
switch (pCMD->cmd[COMMAND]) {
case FDC_CMD_READ:
pCMD->cmd[SECTOR]=(unsigned char) sect; /* sector */
pCMD->cmd[SECTOR_SIZE]=pFG->sect_code; /* sector size code */
pCMD->cmd[LAST_TRACK]=pFG->sect; /* End of track */
pCMD->cmd[GAP]=pFG->gap; /* gap */
pCMD->cmd[DTL]=0xFF; /* DTL */
pCMD->cmdlen=FDC_CMD_READ_LEN;
pCMD->cmd[COMMAND]|=(FDC_MFM_MODE<<6); /* set MFM bit */
pCMD->cmd[COMMAND]|=(FDC_SKIP_MODE<<5); /* set Skip bit */
pCMD->resultlen=0; /* result only after execution */
break;
case FDC_CMD_SEEK:
pCMD->cmdlen=FDC_CMD_SEEK_LEN;
pCMD->resultlen=0; /* no result */
break;
case FDC_CMD_CONFIGURE:
pCMD->cmd[CONFIG0]=0;
pCMD->cmd[CONFIG1]=FDC_CONFIGURE; /* FIFO Threshold, Poll, Enable FIFO */
pCMD->cmd[CONFIG2]=FDC_PRE_TRK; /* Precompensation Track */
pCMD->cmdlen=FDC_CMD_CONFIGURE_LEN;
pCMD->resultlen=0; /* no result */
break;
case FDC_CMD_SPECIFY:
pCMD->cmd[SPEC_HUTSRT]=pFG->spec1;
pCMD->cmd[SPEC_HLT]=(pFG->hlt)<<1; /* head load time */
if(pCMD->dma==0)
pCMD->cmd[SPEC_HLT]|=0x1; /* no dma */
pCMD->cmdlen=FDC_CMD_SPECIFY_LEN;
pCMD->resultlen=0; /* no result */
break;
case FDC_CMD_DUMP_REG:
pCMD->cmdlen=FDC_CMD_DUMP_REG_LEN;
pCMD->resultlen=10; /* 10 byte result */
break;
case FDC_CMD_READ_ID:
pCMD->cmd[COMMAND]|=(FDC_MFM_MODE<<6); /* set MFM bit */
pCMD->cmdlen=FDC_CMD_READ_ID_LEN;
pCMD->resultlen=7; /* 7 byte result */
break;
case FDC_CMD_RECALIBRATE:
pCMD->cmd[DRIVE]&=0x03; /* don't set the head bit */
pCMD->cmdlen=FDC_CMD_RECALIBRATE_LEN;
pCMD->resultlen=0; /* no result */
break;
break;
case FDC_CMD_SENSE_INT:
pCMD->cmdlen=FDC_CMD_SENSE_INT_LEN;
pCMD->resultlen=2;
break;
}
for(i=0;i<pCMD->cmdlen;i++) {
/* PRINTF("write cmd%d = 0x%02X\n",i,pCMD->cmd[i]); */
if(write_fdc_byte(pCMD->cmd[i])==FALSE) {
PRINTF("Error: timeout while issue cmd%d\n",i);
return FALSE;
}
}
timeout=FDC_TIME_OUT;
for(i=0;i<pCMD->resultlen;i++) {
while((read_fdc_reg(FDC_MSR)&0xC0)!=0xC0) {
timeout--;
if(timeout==0) {
PRINTF(" timeout while reading result%d MSR=0x%02X\n",i,read_fdc_reg(FDC_MSR));
return FALSE;
}
}
pCMD->result[i]=(unsigned char)read_fdc_byte();
}
return TRUE;
}
/* selects the drive assigned in the cmd structur and
switches on the Motor */
void select_fdc_drive(FDC_COMMAND_STRUCT *pCMD)
{
unsigned char val;
val=(1<<(4+pCMD->drive))|pCMD->drive|0xC; /* set reset, dma gate and motor bits */
if((read_fdc_reg(FDC_DOR)&val)!=val) {
write_fdc_reg(FDC_DOR,val);
for(val=0;val<255;val++)
udelay(500); /* wait some time to start motor */
}
}
/* switches off the Motor of the specified drive */
void stop_fdc_drive(FDC_COMMAND_STRUCT *pCMD)
{
unsigned char val;
val=(1<<(4+pCMD->drive))|pCMD->drive; /* sets motor bits */
write_fdc_reg(FDC_DOR,(read_fdc_reg(FDC_DOR)&~val));
}
/* issues a recalibrate command, waits for interrupt and
* issues a sense_interrupt */
int fdc_recalibrate(FDC_COMMAND_STRUCT *pCMD,FD_GEO_STRUCT *pFG)
{
pCMD->cmd[COMMAND]=FDC_CMD_RECALIBRATE;
if(fdc_issue_cmd(pCMD,pFG)==FALSE)
return FALSE;
while(wait_for_fdc_int()!=TRUE);
pCMD->cmd[COMMAND]=FDC_CMD_SENSE_INT;
return(fdc_issue_cmd(pCMD,pFG));
}
/* issues a recalibrate command, waits for interrupt and
* issues a sense_interrupt */
int fdc_seek(FDC_COMMAND_STRUCT *pCMD,FD_GEO_STRUCT *pFG)
{
pCMD->cmd[COMMAND]=FDC_CMD_SEEK;
if(fdc_issue_cmd(pCMD,pFG)==FALSE)
return FALSE;
while(wait_for_fdc_int()!=TRUE);
pCMD->cmd[COMMAND]=FDC_CMD_SENSE_INT;
return(fdc_issue_cmd(pCMD,pFG));
}
/* terminates current command, by not servicing the FIFO
* waits for interrupt and fills in the result bytes */
int fdc_terminate(FDC_COMMAND_STRUCT *pCMD)
{
int i;
for(i=0;i<100;i++)
udelay(500); /* wait 500usec for fifo overrun */
while((read_fdc_reg(FDC_SRA)&0x80)==0x00); /* wait as long as no int has occured */
for(i=0;i<7;i++) {
pCMD->result[i]=(unsigned char)read_fdc_byte();
}
return TRUE;
}
/* reads data from FDC, seek commands are issued automatic */
int fdc_read_data(unsigned char *buffer, unsigned long blocks,FDC_COMMAND_STRUCT *pCMD, FD_GEO_STRUCT *pFG)
{
/* first seek to start address */
unsigned long len,lastblk,readblk,i,timeout,ii,offset;
unsigned char pcn,c,retriesrw,retriescal;
unsigned char *bufferw; /* working buffer */
int sect_size;
int flags;
flags=disable_interrupts(); /* switch off all Interrupts */
select_fdc_drive(pCMD); /* switch on drive */
sect_size=0x080<<pFG->sect_code;
retriesrw=0;
retriescal=0;
offset=0;
if(fdc_seek(pCMD,pFG)==FALSE) {
stop_fdc_drive(pCMD);
enable_interrupts();
return FALSE;
}
if((pCMD->result[STATUS_0]&0x20)!=0x20) {
printf("Seek error Status: %02X\n",pCMD->result[STATUS_0]);
stop_fdc_drive(pCMD);
enable_interrupts();
return FALSE;
}
pcn=pCMD->result[STATUS_PCN]; /* current track */
/* now determine the next seek point */
lastblk=pCMD->blnr + blocks;
/* readblk=(pFG->head*pFG->sect)-(pCMD->blnr%(pFG->head*pFG->sect)); */
readblk=pFG->sect-(pCMD->blnr%pFG->sect);
PRINTF("1st nr of block possible read %ld start %ld\n",readblk,pCMD->blnr);
if(readblk>blocks) /* is end within 1st track */
readblk=blocks; /* yes, correct it */
PRINTF("we read %ld blocks start %ld\n",readblk,pCMD->blnr);
bufferw=&buffer[0]; /* setup working buffer */
do {
retryrw:
len=sect_size * readblk;
pCMD->cmd[COMMAND]=FDC_CMD_READ;
if(fdc_issue_cmd(pCMD,pFG)==FALSE) {
stop_fdc_drive(pCMD);
enable_interrupts();
return FALSE;
}
for (i=0;i<len;i++) {
timeout=FDC_TIME_OUT;
do {
c=read_fdc_reg(FDC_MSR);
if((c&0xC0)==0xC0) {
bufferw[i]=read_fdc_reg(FDC_FIFO);
break;
}
if((c&0xC0)==0x80) { /* output */
PRINTF("Transfer error transfered: at %ld, MSR=%02X\n",i,c);
if(i>6) {
for(ii=0;ii<7;ii++) {
pCMD->result[ii]=bufferw[(i-7+ii)];
} /* for */
}
if(retriesrw++>FDC_RW_RETRIES) {
if (retriescal++>FDC_CAL_RETRIES) {
stop_fdc_drive(pCMD);
enable_interrupts();
return FALSE;
}
else {
PRINTF(" trying to recalibrate Try %d\n",retriescal);
if(fdc_recalibrate(pCMD,pFG)==FALSE) {
stop_fdc_drive(pCMD);
enable_interrupts();
return FALSE;
}
retriesrw=0;
goto retrycal;
} /* else >FDC_CAL_RETRIES */
}
else {
PRINTF("Read retry %d\n",retriesrw);
goto retryrw;
} /* else >FDC_RW_RETRIES */
}/* if output */
timeout--;
}while(TRUE);
} /* for len */
/* the last sector of a track or all data has been read,
* we need to get the results */
fdc_terminate(pCMD);
offset+=(sect_size*readblk); /* set up buffer pointer */
bufferw=&buffer[offset];
pCMD->blnr+=readblk; /* update current block nr */
blocks-=readblk; /* update blocks */
if(blocks==0)
break; /* we are finish */
/* setup new read blocks */
/* readblk=pFG->head*pFG->sect; */
readblk=pFG->sect;
if(readblk>blocks)
readblk=blocks;
retrycal:
/* a seek is necessary */
if(fdc_seek(pCMD,pFG)==FALSE) {
stop_fdc_drive(pCMD);
enable_interrupts();
return FALSE;
}
if((pCMD->result[STATUS_0]&0x20)!=0x20) {
PRINTF("Seek error Status: %02X\n",pCMD->result[STATUS_0]);
stop_fdc_drive(pCMD);
return FALSE;
}
pcn=pCMD->result[STATUS_PCN]; /* current track */
}while(TRUE); /* start over */
stop_fdc_drive(pCMD); /* switch off drive */
enable_interrupts();
return TRUE;
}
/* Scan all drives and check if drive is present and disk is inserted */
int fdc_check_drive(FDC_COMMAND_STRUCT *pCMD, FD_GEO_STRUCT *pFG)
{
int i,drives,state;
/* OK procedure of data book is satisfied.
* trying to get some information over the drives */
state=0; /* no drives, no disks */
for(drives=0;drives<4;drives++) {
pCMD->drive=drives;
select_fdc_drive(pCMD);
pCMD->blnr=0; /* set to the 1st block */
if(fdc_recalibrate(pCMD,pFG)==FALSE)
break;
if((pCMD->result[STATUS_0]&0x10)==0x10)
break;
/* ok drive connected check for disk */
state|=(1<<drives);
pCMD->blnr=pFG->size; /* set to the last block */
if(fdc_seek(pCMD,pFG)==FALSE)
break;
pCMD->blnr=0; /* set to the 1st block */
if(fdc_recalibrate(pCMD,pFG)==FALSE)
break;
pCMD->cmd[COMMAND]=FDC_CMD_READ_ID;
if(fdc_issue_cmd(pCMD,pFG)==FALSE)
break;
state|=(0x10<<drives);
}
stop_fdc_drive(pCMD);
for(i=0;i<4;i++) {
PRINTF("Floppy Drive %d %sconnected %sDisk inserted %s\n",i,
((state&(1<<i))==(1<<i)) ? "":"not ",
((state&(0x10<<i))==(0x10<<i)) ? "":"no ",
((state&(0x10<<i))==(0x10<<i)) ? pFG->name : "");
}
pCMD->flags=state;
return TRUE;
}
/**************************************************************************
* int fdc_setup
* setup the fdc according the datasheet
* assuming in PS2 Mode
*/
int fdc_setup(FDC_COMMAND_STRUCT *pCMD, FD_GEO_STRUCT *pFG)
{
int i;
/* first, we reset the FDC via the DOR */
write_fdc_reg(FDC_DOR,0x00);
for(i=0; i<255; i++) /* then we wait some time */
udelay(500);
/* then, we clear the reset in the DOR */
pCMD->drive=0;
select_fdc_drive(pCMD);
/* initialize the CCR */
write_fdc_reg(FDC_CCR,pFG->rate);
/* then initialize the DSR */
write_fdc_reg(FDC_DSR,pFG->rate);
if(wait_for_fdc_int()==FALSE) {
PRINTF("Time Out after writing CCR\n");
return FALSE;
}
/* now issue sense Interrupt and status command
* assuming only one drive present (drive 0) */
pCMD->dma=0; /* we don't use any dma at all */
for(i=0;i<4;i++) {
/* issue sense interrupt for all 4 possible drives */
pCMD->cmd[COMMAND]=FDC_CMD_SENSE_INT;
if(fdc_issue_cmd(pCMD,pFG)==FALSE) {
PRINTF("Sense Interrupt for drive %d failed\n",i);
}
}
/* assuming drive 0 for rest of configuration
* issue the configure command */
pCMD->drive=0;
select_fdc_drive(pCMD);
pCMD->cmd[COMMAND]=FDC_CMD_CONFIGURE;
if(fdc_issue_cmd(pCMD,pFG)==FALSE) {
PRINTF(" configure timeout\n");
stop_fdc_drive(pCMD);
return FALSE;
}
/* issue specify command */
pCMD->cmd[COMMAND]=FDC_CMD_SPECIFY;
if(fdc_issue_cmd(pCMD,pFG)==FALSE) {
PRINTF(" specify timeout\n");
stop_fdc_drive(pCMD);
return FALSE;
}
/* then, we clear the reset in the DOR */
/* fdc_check_drive(pCMD,pFG); */
/* write_fdc_reg(FDC_DOR,0x04); */
return TRUE;
}
/****************************************************************************
* main routine do_fdcboot
*/
int do_fdcboot (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
{
FD_GEO_STRUCT *pFG = (FD_GEO_STRUCT *)floppy_type;
FDC_COMMAND_STRUCT *pCMD = &cmd;
unsigned long addr,imsize;
image_header_t *hdr; /* used for fdc boot */
unsigned char boot_drive;
int i,nrofblk;
char *ep;
int rcode = 0;
switch (argc) {
case 1:
addr = CFG_LOAD_ADDR;
boot_drive=0; /* default boot from drive 0 */
break;
case 2:
addr = simple_strtoul(argv[1], NULL, 16);
boot_drive=0; /* default boot from drive 0 */
break;
case 3:
addr = simple_strtoul(argv[1], NULL, 16);
boot_drive=simple_strtoul(argv[2], NULL, 10);
break;
default:
printf ("Usage:\n%s\n", cmdtp->usage);
return 1;
}
/* setup FDC and scan for drives */
if(fdc_setup(pCMD,pFG)==FALSE) {
printf("\n** Error in setup FDC **\n");
return 1;
}
if(fdc_check_drive(pCMD,pFG)==FALSE) {
printf("\n** Error in check_drives **\n");
return 1;
}
if((pCMD->flags&(1<<boot_drive))==0) {
/* drive not available */
printf("\n** Drive %d not availabe **\n",boot_drive);
return 1;
}
if((pCMD->flags&(0x10<<boot_drive))==0) {
/* no disk inserted */
printf("\n** No disk inserted in drive %d **\n",boot_drive);
return 1;
}
/* ok, we have a valid source */
pCMD->drive=boot_drive;
/* read first block */
pCMD->blnr=0;
if(fdc_read_data((unsigned char *)addr,1,pCMD,pFG)==FALSE) {
printf("\nRead error:");
for(i=0;i<7;i++)
printf("result%d: 0x%02X\n",i,pCMD->result[i]);
return 1;
}
hdr = (image_header_t *)addr;
if (hdr->ih_magic != IH_MAGIC) {
printf ("Bad Magic Number\n");
return 1;
}
print_image_hdr(hdr);
imsize= hdr->ih_size+sizeof(image_header_t);
nrofblk=imsize/512;
if((imsize%512)>0)
nrofblk++;
printf("Loading %ld Bytes (%d blocks) at 0x%08lx..\n",imsize,nrofblk,addr);
pCMD->blnr=0;
if(fdc_read_data((unsigned char *)addr,nrofblk,pCMD,pFG)==FALSE) {
/* read image block */
printf("\nRead error:");
for(i=0;i<7;i++)
printf("result%d: 0x%02X\n",i,pCMD->result[i]);
return 1;
}
printf("OK %ld Bytes loaded.\n",imsize);
flush_cache (addr, imsize);
/* Loading ok, update default load address */
load_addr = addr;
if(hdr->ih_type == IH_TYPE_KERNEL) {
/* Check if we should attempt an auto-start */
if (((ep = getenv("autostart")) != NULL) && (strcmp(ep,"yes") == 0)) {
char *local_args[2];
extern int do_bootm (cmd_tbl_t *, int, int, char *[]);
local_args[0] = argv[0];
local_args[1] = NULL;
printf ("Automatic boot of image at addr 0x%08lX ...\n", addr);
do_bootm (cmdtp, 0, 1, local_args);
rcode ++;
}
}
return rcode;
}
#endif /* CONFIG_COMMANDS & CFG_CMD_FDC */

@ -0,0 +1,850 @@
/*
* (C) Copyright 2000
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
*
* See file CREDITS for list of people who contributed to this
* project.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*/
/*
* Memory Functions
*
* Copied from FADS ROM, Dan Malek (dmalek@jlc.net)
*/
#include <common.h>
#include <command.h>
#include <cmd_mem.h>
#if (CONFIG_COMMANDS & (CFG_CMD_MEMORY | CFG_CMD_PCI | CFG_CMD_I2C))
int cmd_get_data_size(char* arg, int default_size)
{
/* Check for a size specification .b, .w or .l.
*/
int len = strlen(arg);
if (len > 2 && arg[len-2] == '.') {
switch(arg[len-1]) {
case 'b':
return 1;
case 'w':
return 2;
case 'l':
return 4;
}
}
return default_size;
}
#endif
#if (CONFIG_COMMANDS & CFG_CMD_MEMORY)
#ifdef CMD_MEM_DEBUG
#define PRINTF(fmt,args...) printf (fmt ,##args)
#else
#define PRINTF(fmt,args...)
#endif
static int mod_mem(cmd_tbl_t *, int, int, int, char *[]);
/* Display values from last command.
* Memory modify remembered values are different from display memory.
*/
uint dp_last_addr, dp_last_size;
uint dp_last_length = 0x40;
uint mm_last_addr, mm_last_size;
static ulong base_address = 0;
/* Memory Display
*
* Syntax:
* md{.b, .w, .l} {addr} {len}
*/
#define DISP_LINE_LEN 16
int do_mem_md ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
{
ulong addr, size, length;
ulong i, nbytes, linebytes;
u_char *cp;
int rc = 0;
/* We use the last specified parameters, unless new ones are
* entered.
*/
addr = dp_last_addr;
size = dp_last_size;
length = dp_last_length;
if (argc < 2) {
printf ("Usage:\n%s\n", cmdtp->usage);
return 1;
}
if ((flag & CMD_FLAG_REPEAT) == 0) {
/* New command specified. Check for a size specification.
* Defaults to long if no or incorrect specification.
*/
size = cmd_get_data_size(argv[0], 4);
/* Address is specified since argc > 1
*/
addr = simple_strtoul(argv[1], NULL, 16);
addr += base_address;
/* If another parameter, it is the length to display.
* Length is the number of objects, not number of bytes.
*/
if (argc > 2)
length = simple_strtoul(argv[2], NULL, 16);
}
/* Print the lines.
*
* We buffer all read data, so we can make sure data is read only
* once, and all accesses are with the specified bus width.
*/
nbytes = length * size;
do {
char linebuf[DISP_LINE_LEN];
uint *uip = (uint *)linebuf;
ushort *usp = (ushort *)linebuf;
u_char *ucp = (u_char *)linebuf;
printf("%08lx:", addr);
linebytes = (nbytes>DISP_LINE_LEN)?DISP_LINE_LEN:nbytes;
for (i=0; i<linebytes; i+= size) {
if (size == 4) {
printf(" %08x", (*uip++ = *((uint *)addr)));
} else if (size == 2) {
printf(" %04x", (*usp++ = *((ushort *)addr)));
} else {
printf(" %02x", (*ucp++ = *((u_char *)addr)));
}
addr += size;
}
printf(" ");
cp = linebuf;
for (i=0; i<linebytes; i++) {
if ((*cp < 0x20) || (*cp > 0x7e))
printf(".");
else
printf("%c", *cp);
cp++;
}
printf("\n");
nbytes -= linebytes;
if (ctrlc()) {
rc = 1;
break;
}
} while (nbytes > 0);
dp_last_addr = addr;
dp_last_length = length;
dp_last_size = size;
return (rc);
}
int do_mem_mm ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
{
return mod_mem (cmdtp, 1, flag, argc, argv);
}
int do_mem_nm ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
{
return mod_mem (cmdtp, 0, flag, argc, argv);
}
int do_mem_mw ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
{
ulong addr, size, writeval, count;
if ((argc < 3) || (argc > 4)) {
printf ("Usage:\n%s\n", cmdtp->usage);
return 1;
}
/* Check for size specification.
*/
size = cmd_get_data_size(argv[0], 4);
/* Address is specified since argc > 1
*/
addr = simple_strtoul(argv[1], NULL, 16);
addr += base_address;
/* Get the value to write.
*/
writeval = simple_strtoul(argv[2], NULL, 16);
/* Count ? */
if (argc == 4) {
count = simple_strtoul(argv[3], NULL, 16);
} else {
count = 1;
}
while (count-- > 0) {
if (size == 4)
*((ulong *)addr) = (ulong )writeval;
else if (size == 2)
*((ushort *)addr) = (ushort)writeval;
else
*((u_char *)addr) = (u_char)writeval;
addr += size;
}
return 0;
}
int do_mem_cmp (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
{
ulong size, addr1, addr2, count, ngood;
int rcode = 0;
if (argc != 4) {
printf ("Usage:\n%s\n", cmdtp->usage);
return 1;
}
/* Check for size specification.
*/
size = cmd_get_data_size(argv[0], 4);
addr1 = simple_strtoul(argv[1], NULL, 16);
addr1 += base_address;
addr2 = simple_strtoul(argv[2], NULL, 16);
addr2 += base_address;
count = simple_strtoul(argv[3], NULL, 16);
ngood = 0;
while (count-- > 0) {
if (size == 4) {
ulong word1 = *(ulong *)addr1;
ulong word2 = *(ulong *)addr2;
if (word1 != word2) {
printf("word at 0x%08lx (0x%08lx) "
"!= word at 0x%08lx (0x%08lx)\n",
addr1, word1, addr2, word2);
rcode = 1;
break;
}
}
else if (size == 2) {
ushort hword1 = *(ushort *)addr1;
ushort hword2 = *(ushort *)addr2;
if (hword1 != hword2) {
printf("halfword at 0x%08lx (0x%04x) "
"!= halfword at 0x%08lx (0x%04x)\n",
addr1, hword1, addr2, hword2);
rcode = 1;
break;
}
}
else {
u_char byte1 = *(u_char *)addr1;
u_char byte2 = *(u_char *)addr2;
if (byte1 != byte2) {
printf("byte at 0x%08lx (0x%02x) "
"!= byte at 0x%08lx (0x%02x)\n",
addr1, byte1, addr2, byte2);
rcode = 1;
break;
}
}
ngood++;
addr1 += size;
addr2 += size;
}
printf("Total of %ld %s%s were the same\n",
ngood, size == 4 ? "word" : size == 2 ? "halfword" : "byte",
ngood == 1 ? "" : "s");
return rcode;
}
int do_mem_cp ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
{
ulong addr, size, dest, count;
if (argc != 4) {
printf ("Usage:\n%s\n", cmdtp->usage);
return 1;
}
/* Check for size specification.
*/
size = cmd_get_data_size(argv[0], 4);
addr = simple_strtoul(argv[1], NULL, 16);
addr += base_address;
dest = simple_strtoul(argv[2], NULL, 16);
dest += base_address;
count = simple_strtoul(argv[3], NULL, 16);
if (count == 0) {
puts ("Zero length ???\n");
return 1;
}
#ifndef CFG_NO_FLASH
/* check if we are copying to Flash */
if (addr2info(dest) != NULL) {
int rc;
printf ("Copy to Flash... ");
rc = flash_write ((uchar *)addr, dest, count*size);
if (rc != 0) {
flash_perror (rc);
return (1);
}
puts ("done\n");
return 0;
}
#endif
while (count-- > 0) {
if (size == 4)
*((ulong *)dest) = *((ulong *)addr);
else if (size == 2)
*((ushort *)dest) = *((ushort *)addr);
else
*((u_char *)dest) = *((u_char *)addr);
addr += size;
dest += size;
}
return 0;
}
int do_mem_base (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
{
if (argc > 1) {
/* Set new base address.
*/
base_address = simple_strtoul(argv[1], NULL, 16);
}
/* Print the current base address.
*/
printf("Base Address: 0x%08lx\n", base_address);
return 0;
}
int do_mem_loop (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
{
ulong addr, size, length, i, junk;
volatile uint *longp;
volatile ushort *shortp;
volatile u_char *cp;
if (argc < 3) {
printf ("Usage:\n%s\n", cmdtp->usage);
return 1;
}
/* Check for a size spefication.
* Defaults to long if no or incorrect specification.
*/
size = cmd_get_data_size(argv[0], 4);
/* Address is always specified.
*/
addr = simple_strtoul(argv[1], NULL, 16);
/* Length is the number of objects, not number of bytes.
*/
length = simple_strtoul(argv[2], NULL, 16);
/* We want to optimize the loops to run as fast as possible.
* If we have only one object, just run infinite loops.
*/
if (length == 1) {
if (size == 4) {
longp = (uint *)addr;
for (;;)
i = *longp;
}
if (size == 2) {
shortp = (ushort *)addr;
for (;;)
i = *shortp;
}
cp = (u_char *)addr;
for (;;)
i = *cp;
}
if (size == 4) {
for (;;) {
longp = (uint *)addr;
i = length;
while (i-- > 0)
junk = *longp++;
}
}
if (size == 2) {
for (;;) {
shortp = (ushort *)addr;
i = length;
while (i-- > 0)
junk = *shortp++;
}
}
for (;;) {
cp = (u_char *)addr;
i = length;
while (i-- > 0)
junk = *cp++;
}
}
/*
* Perform a memory test. A more complete alternative test can be
* configured using CFG_ALT_MEMTEST. The complete test loops until
* interrupted by ctrl-c or by a failure of one of the sub-tests.
*/
int do_mem_mtest (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
{
vu_long *addr, *start, *end;
ulong val;
ulong readback;
#if defined(CFG_ALT_MEMTEST)
vu_long addr_mask;
vu_long offset;
vu_long test_offset;
vu_long pattern;
vu_long temp;
vu_long anti_pattern;
vu_long num_words;
vu_long *dummy = NULL;
int j;
int iterations = 1;
static const ulong bitpattern[] = {
0x00000001, /* single bit */
0x00000003, /* two adjacent bits */
0x00000007, /* three adjacent bits */
0x0000000F, /* four adjacent bits */
0x00000005, /* two non-adjacent bits */
0x00000015, /* three non-adjacent bits */
0x00000055, /* four non-adjacent bits */
0xaaaaaaaa, /* alternating 1/0 */
};
#else
ulong incr;
ulong pattern;
int rcode = 0;
#endif
if (argc > 1) {
start = (ulong *)simple_strtoul(argv[1], NULL, 16);
} else {
start = (ulong *)CFG_MEMTEST_START;
}
if (argc > 2) {
end = (ulong *)simple_strtoul(argv[2], NULL, 16);
} else {
end = (ulong *)(CFG_MEMTEST_END);
}
if (argc > 3) {
pattern = (ulong)simple_strtoul(argv[3], NULL, 16);
} else {
pattern = 0;
}
#if defined(CFG_ALT_MEMTEST)
printf ("Testing %08x ... %08x:\n", (uint)start, (uint)end);
PRINTF("%s:%d: start 0x%p end 0x%p\n",
__FUNCTION__, __LINE__, start, end);
for (;;) {
if (ctrlc()) {
putc ('\n');
return 1;
}
printf("Iteration: %6d\r", iterations);
PRINTF("Iteration: %6d\n", iterations);
iterations++;
/*
* Data line test: write a pattern to the first
* location, write the 1's complement to a 'parking'
* address (changes the state of the data bus so a
* floating bus doen't give a false OK), and then
* read the value back. Note that we read it back
* into a variable because the next time we read it,
* it might be right (been there, tough to explain to
* the quality guys why it prints a failure when the
* "is" and "should be" are obviously the same in the
* error message).
*
* Rather than exhaustively testing, we test some
* patterns by shifting '1' bits through a field of
* '0's and '0' bits through a field of '1's (i.e.
* pattern and ~pattern).
*/
addr = start;
for (j = 0; j < sizeof(bitpattern)/sizeof(bitpattern[0]); j++) {
val = bitpattern[j];
for(; val != 0; val <<= 1) {
*addr = val;
*dummy = ~val; /* clear the test data off of the bus */
readback = *addr;
if(readback != val) {
printf ("FAILURE (data line): "
"expected %08lx, actual %08lx\n",
val, readback);
}
*addr = ~val;
*dummy = val;
readback = *addr;
if(readback != ~val) {
printf ("FAILURE (data line): "
"Is %08lx, should be %08lx\n",
val, readback);
}
}
}
/*
* Based on code whose Original Author and Copyright
* information follows: Copyright (c) 1998 by Michael
* Barr. This software is placed into the public
* domain and may be used for any purpose. However,
* this notice must not be changed or removed and no
* warranty is either expressed or implied by its
* publication or distribution.
*/
/*
* Address line test
*
* Description: Test the address bus wiring in a
* memory region by performing a walking
* 1's test on the relevant bits of the
* address and checking for aliasing.
* This test will find single-bit
* address failures such as stuck -high,
* stuck-low, and shorted pins. The base
* address and size of the region are
* selected by the caller.
*
* Notes: For best results, the selected base
* address should have enough LSB 0's to
* guarantee single address bit changes.
* For example, to test a 64-Kbyte
* region, select a base address on a
* 64-Kbyte boundary. Also, select the
* region size as a power-of-two if at
* all possible.
*
* Returns: 0 if the test succeeds, 1 if the test fails.
*
* ## NOTE ## Be sure to specify start and end
* addresses such that addr_mask has
* lots of bits set. For example an
* address range of 01000000 02000000 is
* bad while a range of 01000000
* 01ffffff is perfect.
*/
addr_mask = ((ulong)end - (ulong)start)/sizeof(vu_long);
pattern = (vu_long) 0xaaaaaaaa;
anti_pattern = (vu_long) 0x55555555;
PRINTF("%s:%d: addr mask = 0x%.8lx\n",
__FUNCTION__, __LINE__,
addr_mask);
/*
* Write the default pattern at each of the
* power-of-two offsets.
*/
for (offset = 1; (offset & addr_mask) != 0; offset <<= 1) {
start[offset] = pattern;
}
/*
* Check for address bits stuck high.
*/
test_offset = 0;
start[test_offset] = anti_pattern;
for (offset = 1; (offset & addr_mask) != 0; offset <<= 1) {
temp = start[offset];
if (temp != pattern) {
printf ("\nFAILURE: Address bit stuck high @ 0x%.8lx:"
" expected 0x%.8lx, actual 0x%.8lx\n",
(ulong)&start[offset], pattern, temp);
return 1;
}
}
start[test_offset] = pattern;
/*
* Check for addr bits stuck low or shorted.
*/
for (test_offset = 1; (test_offset & addr_mask) != 0; test_offset <<= 1) {
start[test_offset] = anti_pattern;
for (offset = 1; (offset & addr_mask) != 0; offset <<= 1) {
temp = start[offset];
if ((temp != pattern) && (offset != test_offset)) {
printf ("\nFAILURE: Address bit stuck low or shorted @"
" 0x%.8lx: expected 0x%.8lx, actual 0x%.8lx\n",
(ulong)&start[offset], pattern, temp);
return 1;
}
}
start[test_offset] = pattern;
}
/*
* Description: Test the integrity of a physical
* memory device by performing an
* increment/decrement test over the
* entire region. In the process every
* storage bit in the device is tested
* as a zero and a one. The base address
* and the size of the region are
* selected by the caller.
*
* Returns: 0 if the test succeeds, 1 if the test fails.
*/
num_words = ((ulong)end - (ulong)start)/sizeof(vu_long) + 1;
/*
* Fill memory with a known pattern.
*/
for (pattern = 1, offset = 0; offset < num_words; pattern++, offset++) {
start[offset] = pattern;
}
/*
* Check each location and invert it for the second pass.
*/
for (pattern = 1, offset = 0; offset < num_words; pattern++, offset++) {
temp = start[offset];
if (temp != pattern) {
printf ("\nFAILURE (read/write) @ 0x%.8lx:"
" expected 0x%.8lx, actual 0x%.8lx)\n",
(ulong)&start[offset], pattern, temp);
return 1;
}
anti_pattern = ~pattern;
start[offset] = anti_pattern;
}
/*
* Check each location for the inverted pattern and zero it.
*/
for (pattern = 1, offset = 0; offset < num_words; pattern++, offset++) {
anti_pattern = ~pattern;
temp = start[offset];
if (temp != anti_pattern) {
printf ("\nFAILURE (read/write): @ 0x%.8lx:"
" expected 0x%.8lx, actual 0x%.8lx)\n",
(ulong)&start[offset], anti_pattern, temp);
return 1;
}
start[offset] = 0;
}
}
#else /* The original, quickie test */
incr = 1;
for (;;) {
if (ctrlc()) {
putc ('\n');
return 1;
}
printf ("\rPattern %08lX Writing..."
"%12s"
"\b\b\b\b\b\b\b\b\b\b",
pattern, "");
for (addr=start,val=pattern; addr<end; addr++) {
*addr = val;
val += incr;
}
printf("Reading...");
for (addr=start,val=pattern; addr<end; addr++) {
readback = *addr;
if (readback != val) {
printf ("\nMem error @ 0x%08X: "
"found %08lX, expected %08lX\n",
(uint)addr, readback, val);
rcode = 1;
}
val += incr;
}
/*
* Flip the pattern each time to make lots of zeros and
* then, the next time, lots of ones. We decrement
* the "negative" patterns and increment the "positive"
* patterns to preserve this feature.
*/
if(pattern & 0x80000000) {
pattern = -pattern; /* complement & increment */
}
else {
pattern = ~pattern;
}
incr = -incr;
}
return rcode;
#endif
}
/* Modify memory.
*
* Syntax:
* mm{.b, .w, .l} {addr}
* nm{.b, .w, .l} {addr}
*/
static int
mod_mem(cmd_tbl_t *cmdtp, int incrflag, int flag, int argc, char *argv[])
{
ulong addr, size, i;
int nbytes;
extern char console_buffer[];
if (argc != 2) {
printf ("Usage:\n%s\n", cmdtp->usage);
return 1;
}
#ifdef CONFIG_BOOT_RETRY_TIME
reset_cmd_timeout(); /* got a good command to get here */
#endif
/* We use the last specified parameters, unless new ones are
* entered.
*/
addr = mm_last_addr;
size = mm_last_size;
if ((flag & CMD_FLAG_REPEAT) == 0) {
/* New command specified. Check for a size specification.
* Defaults to long if no or incorrect specification.
*/
size = cmd_get_data_size(argv[0], 4);
/* Address is specified since argc > 1
*/
addr = simple_strtoul(argv[1], NULL, 16);
addr += base_address;
}
/* Print the address, followed by value. Then accept input for
* the next value. A non-converted value exits.
*/
do {
printf("%08lx:", addr);
if (size == 4)
printf(" %08x", *((uint *)addr));
else if (size == 2)
printf(" %04x", *((ushort *)addr));
else
printf(" %02x", *((u_char *)addr));
nbytes = readline (" ? ");
if (nbytes == 0 || (nbytes == 1 && console_buffer[0] == '-')) {
/* <CR> pressed as only input, don't modify current
* location and move to next. "-" pressed will go back.
*/
if (incrflag)
addr += nbytes ? -size : size;
nbytes = 1;
#ifdef CONFIG_BOOT_RETRY_TIME
reset_cmd_timeout(); /* good enough to not time out */
#endif
}
#ifdef CONFIG_BOOT_RETRY_TIME
else if (nbytes == -2) {
break; /* timed out, exit the command */
}
#endif
else {
char *endp;
i = simple_strtoul(console_buffer, &endp, 16);
nbytes = endp - console_buffer;
if (nbytes) {
#ifdef CONFIG_BOOT_RETRY_TIME
/* good enough to not time out
*/
reset_cmd_timeout();
#endif
if (size == 4)
*((uint *)addr) = i;
else if (size == 2)
*((ushort *)addr) = i;
else
*((u_char *)addr) = i;
if (incrflag)
addr += size;
}
}
} while (nbytes);
mm_last_addr = addr;
mm_last_size = size;
return 0;
}
int do_mem_crc (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
{
ulong addr, length;
ulong crc;
ulong *ptr;
if (argc < 3) {
printf ("Usage:\n%s\n", cmdtp->usage);
return 1;
}
addr = simple_strtoul(argv[1], NULL, 16);
addr += base_address;
length = simple_strtoul(argv[2], NULL, 16);
crc = crc32 (0, (const uchar *)addr, length);
printf ("CRC32 for %08lx ... %08lx ==> %08lx\n",
addr, addr + length -1, crc);
if (argc > 3)
{
ptr = (ulong *)simple_strtoul(argv[3], NULL, 16);
*ptr = crc;
}
return 0;
}
#endif /* CFG_CMD_MEMORY */

@ -0,0 +1,56 @@
/*
* (C) Copyright 2001
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
*
* See file CREDITS for list of people who contributed to this
* project.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*/
/*
* Misc functions
*/
#include <common.h>
#include <command.h>
#if (CONFIG_COMMANDS & CFG_CMD_MISC)
int do_sleep (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
{
ulong delay;
if (argc != 2) {
printf ("Usage:\n%s\n", cmdtp->usage);
return 1;
}
delay = simple_strtoul(argv[1], NULL, 10);
while (delay) {
int i;
for (i=0; i<1000; ++i) {
if (ctrlc ()) {
return (-1);
}
udelay (1000);
}
--delay;
}
return 0;
}
#endif /* CFG_CMD_MISC */

@ -0,0 +1,164 @@
/*
* (C) Copyright 2000
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
*
* See file CREDITS for list of people who contributed to this
* project.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*/
/*
* Boot support
*/
#include <common.h>
#include <command.h>
#include <cmd_net.h>
#include <net.h>
#if (CONFIG_COMMANDS & CFG_CMD_NET)
# if (CONFIG_COMMANDS & CFG_CMD_AUTOSCRIPT)
# include <cmd_autoscript.h>
# endif
extern int do_bootm (cmd_tbl_t *, int, int, char *[]);
static int netboot_common (int, cmd_tbl_t *, int , char *[]);
int do_bootp (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
{
return netboot_common (BOOTP, cmdtp, argc, argv);
}
int do_tftpb (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
{
return netboot_common (TFTP, cmdtp, argc, argv);
}
int do_rarpb (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
{
return netboot_common (RARP, cmdtp, argc, argv);
}
#if (CONFIG_COMMANDS & CFG_CMD_DHCP)
int do_dhcp (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
{
return netboot_common(DHCP, cmdtp, argc, argv);
}
#endif /* CFG_CMD_DHCP */
static void netboot_update_env(void)
{
char tmp[16] ;
if (NetOurGatewayIP) {
ip_to_string (NetOurGatewayIP, tmp);
setenv("gatewayip", tmp);
}
if (NetOurSubnetMask) {
ip_to_string (NetOurSubnetMask, tmp);
setenv("netmask", tmp);
}
if (NetOurHostName[0])
setenv("hostname", NetOurHostName);
if (NetOurRootPath[0])
setenv("rootpath", NetOurRootPath);
if (NetOurIP) {
ip_to_string (NetOurIP, tmp);
setenv("ipaddr", tmp);
}
if (NetServerIP) {
ip_to_string (NetServerIP, tmp);
setenv("serverip", tmp);
}
if (NetOurDNSIP) {
ip_to_string (NetOurDNSIP, tmp);
setenv("dnsip", tmp);
}
}
static int
netboot_common (int proto, cmd_tbl_t *cmdtp, int argc, char *argv[])
{
char *s;
int rcode = 0;
int size;
/* pre-set load_addr */
if ((s = getenv("loadaddr")) != NULL) {
load_addr = simple_strtoul(s, NULL, 16);
}
switch (argc) {
case 1:
break;
case 2: /* only one arg - accept two forms:
* just load address, or just boot file name.
* The latter form must be written "filename" here.
*/
if (argv[1][0] == '"') { /* just boot filename */
copy_filename (BootFile, argv[1], sizeof(BootFile));
} else { /* load address */
load_addr = simple_strtoul(argv[1], NULL, 16);
}
break;
case 3: load_addr = simple_strtoul(argv[1], NULL, 16);
copy_filename (BootFile, argv[2], sizeof(BootFile));
break;
default: printf ("Usage:\n%s\n", cmdtp->usage);
return 1;
}
if ((size = NetLoop(proto)) == 0)
return 1;
/* NetLoop ok, update environment */
netboot_update_env();
/* flush cache */
flush_cache(load_addr, size);
/* Loading ok, check if we should attempt an auto-start */
if (((s = getenv("autostart")) != NULL) && (strcmp(s,"yes") == 0)) {
char *local_args[2];
local_args[0] = argv[0];
local_args[1] = NULL;
printf ("Automatic boot of image at addr 0x%08lX ...\n",
load_addr);
rcode = do_bootm (cmdtp, 0, 1, local_args);
}
#ifdef CONFIG_AUTOSCRIPT
if (((s = getenv("autoscript")) != NULL) && (strcmp(s,"yes") == 0)) {
printf("Running autoscript at addr 0x%08lX ...\n", load_addr);
rcode = autoscript (load_addr);
}
#endif
return rcode;
}
#endif /* CFG_CMD_NET */
Loading…
Cancel
Save