parent
f8cac651b3
commit
3863585bb1
@ -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, ¢ury) || |
||||
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…
Reference in new issue