upstream u-boot with additional patches for our devices/boards: https://lists.denx.de/pipermail/u-boot/2017-March/282789.html (AXP crashes) ; Gbit ethernet patch for some LIME2 revisions ; with SPI flash support
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
u-boot/common/cmd_ide.c

2071 lines
51 KiB

22 years ago
/*
* (C) Copyright 2000-2011
22 years ago
* 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
*
*/
/*
* IDE support
*/
22 years ago
#include <common.h>
#include <config.h>
#include <watchdog.h>
#include <command.h>
#include <image.h>
#include <asm/byteorder.h>
#include <asm/io.h>
22 years ago
#if defined(CONFIG_IDE_8xx_DIRECT) || defined(CONFIG_IDE_PCMCIA)
# include <pcmcia.h>
#endif
22 years ago
#ifdef CONFIG_8xx
# include <mpc8xx.h>
#endif
#ifdef CONFIG_MPC5xxx
#include <mpc5xxx.h>
#endif
22 years ago
#include <ide.h>
#include <ata.h>
22 years ago
#ifdef CONFIG_STATUS_LED
# include <status_led.h>
#endif
#ifdef CONFIG_IDE_8xx_DIRECT
DECLARE_GLOBAL_DATA_PTR;
#endif
#ifdef __PPC__
# define EIEIO __asm__ volatile ("eieio")
# define SYNC __asm__ volatile ("sync")
#else
# define EIEIO /* nothing */
# define SYNC /* nothing */
22 years ago
#endif
#ifdef CONFIG_IDE_8xx_DIRECT
22 years ago
/* Timings for IDE Interface
*
* SETUP / LENGTH / HOLD - cycles valid for 50 MHz clk
* 70 165 30 PIO-Mode 0, [ns]
* 4 9 2 [Cycles]
* 50 125 20 PIO-Mode 1, [ns]
* 3 7 2 [Cycles]
* 30 100 15 PIO-Mode 2, [ns]
* 2 6 1 [Cycles]
* 30 80 10 PIO-Mode 3, [ns]
* 2 5 1 [Cycles]
* 25 70 10 PIO-Mode 4, [ns]
* 2 4 1 [Cycles]
*/
const static pio_config_t pio_config_ns [IDE_MAX_PIO_MODE+1] =
{
/* Setup Length Hold */
{ 70, 165, 30 }, /* PIO-Mode 0, [ns] */
{ 50, 125, 20 }, /* PIO-Mode 1, [ns] */
{ 30, 101, 15 }, /* PIO-Mode 2, [ns] */
{ 30, 80, 10 }, /* PIO-Mode 3, [ns] */
{ 25, 70, 10 }, /* PIO-Mode 4, [ns] */
};
static pio_config_t pio_config_clk [IDE_MAX_PIO_MODE+1];
#ifndef CONFIG_SYS_PIO_MODE
#define CONFIG_SYS_PIO_MODE 0 /* use a relaxed default */
22 years ago
#endif
static int pio_mode = CONFIG_SYS_PIO_MODE;
22 years ago
/* Make clock cycles and always round up */
#define PCMCIA_MK_CLKS( t, T ) (( (t) * (T) + 999U ) / 1000U )
#endif /* CONFIG_IDE_8xx_DIRECT */
22 years ago
/* ------------------------------------------------------------------------- */
/* Current I/O Device */
static int curr_device = -1;
/* Current offset for IDE0 / IDE1 bus access */
ulong ide_bus_offset[CONFIG_SYS_IDE_MAXBUS] = {
#if defined(CONFIG_SYS_ATA_IDE0_OFFSET)
CONFIG_SYS_ATA_IDE0_OFFSET,
22 years ago
#endif
#if defined(CONFIG_SYS_ATA_IDE1_OFFSET) && (CONFIG_SYS_IDE_MAXBUS > 1)
CONFIG_SYS_ATA_IDE1_OFFSET,
22 years ago
#endif
};
static int ide_bus_ok[CONFIG_SYS_IDE_MAXBUS];
22 years ago
block_dev_desc_t ide_dev_desc[CONFIG_SYS_IDE_MAXDEVICE];
22 years ago
/* ------------------------------------------------------------------------- */
#ifdef CONFIG_IDE_LED
# if !defined(CONFIG_BMS2003) && \
!defined(CONFIG_CPC45) && \
!defined(CONFIG_KUP4K) && \
!defined(CONFIG_KUP4X)
22 years ago
static void ide_led (uchar led, uchar status);
#else
extern void ide_led (uchar led, uchar status);
#endif
#else
22 years ago
#define ide_led(a,b) /* dummy */
#endif
#ifdef CONFIG_IDE_RESET
static void ide_reset (void);
#else
#define ide_reset() /* dummy */
#endif
static void ide_ident (block_dev_desc_t *dev_desc);
static uchar ide_wait (int dev, ulong t);
#define IDE_TIME_OUT 2000 /* 2 sec timeout */
#define ATAPI_TIME_OUT 7000 /* 7 sec timeout (5 sec seems to work...) */
#define IDE_SPIN_UP_TIME_OUT 5000 /* 5 sec spin-up timeout */
static void input_data(int dev, ulong *sect_buf, int words);
static void output_data(int dev, const ulong *sect_buf, int words);
22 years ago
static void ident_cpy (unsigned char *dest, unsigned char *src, unsigned int len);
#ifndef CONFIG_SYS_ATA_PORT_ADDR
#define CONFIG_SYS_ATA_PORT_ADDR(port) (port)
#endif
22 years ago
#ifdef CONFIG_ATAPI
static void atapi_inquiry(block_dev_desc_t *dev_desc);
ulong atapi_read (int device, lbaint_t blknr, ulong blkcnt, void *buffer);
22 years ago
#endif
#ifdef CONFIG_IDE_8xx_DIRECT
static void set_pcmcia_timing (int pmode);
#endif
/* ------------------------------------------------------------------------- */
int do_ide(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
22 years ago
{
int rcode = 0;
switch (argc) {
case 0:
case 1:
return CMD_RET_USAGE;
case 2:
if (strncmp(argv[1], "res", 3) == 0) {
puts("\nReset IDE"
22 years ago
#ifdef CONFIG_IDE_8xx_DIRECT
" on PCMCIA " PCMCIA_SLOT_MSG
22 years ago
#endif
": ");
22 years ago
ide_init();
return 0;
} else if (strncmp(argv[1], "inf", 3) == 0) {
int i;
22 years ago
putc('\n');
22 years ago
for (i = 0; i < CONFIG_SYS_IDE_MAXDEVICE; ++i) {
if (ide_dev_desc[i].type == DEV_TYPE_UNKNOWN)
continue; /* list only known devices */
printf("IDE device %d: ", i);
dev_print(&ide_dev_desc[i]);
}
return 0;
22 years ago
} else if (strncmp(argv[1], "dev", 3) == 0) {
if ((curr_device < 0)
|| (curr_device >= CONFIG_SYS_IDE_MAXDEVICE)) {
puts("\nno IDE devices available\n");
return 1;
22 years ago
}
printf("\nIDE device %d: ", curr_device);
dev_print(&ide_dev_desc[curr_device]);
return 0;
} else if (strncmp(argv[1], "part", 4) == 0) {
int dev, ok;
for (ok = 0, dev = 0;
dev < CONFIG_SYS_IDE_MAXDEVICE;
++dev) {
if (ide_dev_desc[dev].part_type !=
PART_TYPE_UNKNOWN) {
++ok;
if (dev)
putc('\n');
print_part(&ide_dev_desc[dev]);
}
}
if (!ok) {
puts("\nno IDE devices available\n");
rcode++;
}
return rcode;
22 years ago
}
return CMD_RET_USAGE;
case 3:
if (strncmp(argv[1], "dev", 3) == 0) {
int dev = (int) simple_strtoul(argv[2], NULL, 10);
22 years ago
printf("\nIDE device %d: ", dev);
if (dev >= CONFIG_SYS_IDE_MAXDEVICE) {
puts("unknown device\n");
return 1;
}
dev_print(&ide_dev_desc[dev]);
/*ide_print (dev); */
22 years ago
if (ide_dev_desc[dev].type == DEV_TYPE_UNKNOWN)
return 1;
22 years ago
curr_device = dev;
22 years ago
puts("... is now current device\n");
return 0;
} else if (strncmp(argv[1], "part", 4) == 0) {
int dev = (int) simple_strtoul(argv[2], NULL, 10);
22 years ago
if (ide_dev_desc[dev].part_type != PART_TYPE_UNKNOWN) {
22 years ago
print_part(&ide_dev_desc[dev]);
} else {
printf("\nIDE device %d not available\n",
dev);
rcode = 1;
}
return rcode;
22 years ago
}
return CMD_RET_USAGE;
default:
/* at least 4 args */
22 years ago
if (strcmp(argv[1], "read") == 0) {
ulong addr = simple_strtoul(argv[2], NULL, 16);
ulong cnt = simple_strtoul(argv[4], NULL, 16);
ulong n;
22 years ago
#ifdef CONFIG_SYS_64BIT_LBA
lbaint_t blk = simple_strtoull(argv[3], NULL, 16);
22 years ago
printf("\nIDE read: device %d block # %lld, count %ld ... ",
curr_device, blk, cnt);
#else
lbaint_t blk = simple_strtoul(argv[3], NULL, 16);
printf("\nIDE read: device %d block # %ld, count %ld ... ",
curr_device, blk, cnt);
#endif
n = ide_dev_desc[curr_device].block_read(curr_device,
blk, cnt,
(ulong *)addr);
/* flush cache after read */
flush_cache(addr,
cnt * ide_dev_desc[curr_device].blksz);
printf("%ld blocks read: %s\n",
n, (n == cnt) ? "OK" : "ERROR");
if (n == cnt)
return 0;
else
return 1;
} else if (strcmp(argv[1], "write") == 0) {
ulong addr = simple_strtoul(argv[2], NULL, 16);
ulong cnt = simple_strtoul(argv[4], NULL, 16);
ulong n;
22 years ago
#ifdef CONFIG_SYS_64BIT_LBA
lbaint_t blk = simple_strtoull(argv[3], NULL, 16);
22 years ago
printf("\nIDE write: device %d block # %lld, count %ld ... ",
curr_device, blk, cnt);
#else
lbaint_t blk = simple_strtoul(argv[3], NULL, 16);
printf("\nIDE write: device %d block # %ld, count %ld ... ",
curr_device, blk, cnt);
#endif
n = ide_write(curr_device, blk, cnt, (ulong *) addr);
22 years ago
printf("%ld blocks written: %s\n",
n, (n == cnt) ? "OK" : "ERROR");
if (n == cnt)
return 0;
else
return 1;
} else {
return CMD_RET_USAGE;
}
22 years ago
return rcode;
22 years ago
}
}
int do_diskboot(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
22 years ago
{
char *boot_device = NULL;
char *ep;
int dev, part = 0;
ulong addr, cnt;
22 years ago
disk_partition_t info;
image_header_t *hdr;
#if defined(CONFIG_FIT)
const void *fit_hdr = NULL;
#endif
22 years ago
bootstage_mark(BOOTSTAGE_ID_IDE_START);
22 years ago
switch (argc) {
case 1:
addr = CONFIG_SYS_LOAD_ADDR;
boot_device = getenv("bootdevice");
22 years ago
break;
case 2:
addr = simple_strtoul(argv[1], NULL, 16);
boot_device = getenv("bootdevice");
22 years ago
break;
case 3:
addr = simple_strtoul(argv[1], NULL, 16);
boot_device = argv[2];
break;
default:
bootstage_error(BOOTSTAGE_ID_IDE_ADDR);
return CMD_RET_USAGE;
22 years ago
}
bootstage_mark(BOOTSTAGE_ID_IDE_ADDR);
22 years ago
if (!boot_device) {
puts("\n** No boot device **\n");
bootstage_error(BOOTSTAGE_ID_IDE_BOOT_DEVICE);
22 years ago
return 1;
}
bootstage_mark(BOOTSTAGE_ID_IDE_BOOT_DEVICE);
22 years ago
dev = simple_strtoul(boot_device, &ep, 16);
if (ide_dev_desc[dev].type == DEV_TYPE_UNKNOWN) {
printf("\n** Device %d not available\n", dev);
bootstage_error(BOOTSTAGE_ID_IDE_TYPE);
22 years ago
return 1;
}
bootstage_mark(BOOTSTAGE_ID_IDE_TYPE);
22 years ago
if (*ep) {
if (*ep != ':') {
puts("\n** Invalid boot device, use `dev[:part]' **\n");
bootstage_error(BOOTSTAGE_ID_IDE_PART);
22 years ago
return 1;
}
part = simple_strtoul(++ep, NULL, 16);
}
bootstage_mark(BOOTSTAGE_ID_IDE_PART);
if (get_partition_info(&ide_dev_desc[dev], part, &info)) {
bootstage_error(BOOTSTAGE_ID_IDE_PART_INFO);
22 years ago
return 1;
}
bootstage_mark(BOOTSTAGE_ID_IDE_PART_INFO);
if ((strncmp((char *)info.type, BOOT_PART_TYPE, sizeof(info.type)) != 0)
&&
(strncmp((char *)info.type, BOOT_PART_COMP, sizeof(info.type)) != 0)
) {
printf("\n** Invalid partition type \"%.32s\"" " (expect \""
BOOT_PART_TYPE "\")\n",
22 years ago
info.type);
bootstage_error(BOOTSTAGE_ID_IDE_PART_TYPE);
22 years ago
return 1;
}
bootstage_mark(BOOTSTAGE_ID_IDE_PART_TYPE);
22 years ago
printf("\nLoading from IDE device %d, partition %d: "
"Name: %.32s Type: %.32s\n", dev, part, info.name, info.type);
22 years ago
debug("First Block: %ld, # of blocks: %ld, Block Size: %ld\n",
info.start, info.size, info.blksz);
22 years ago
if (ide_dev_desc[dev].
block_read(dev, info.start, 1, (ulong *) addr) != 1) {
printf("** Read error on %d:%d\n", dev, part);
bootstage_error(BOOTSTAGE_ID_IDE_PART_READ);
22 years ago
return 1;
}
bootstage_mark(BOOTSTAGE_ID_IDE_PART_READ);
22 years ago
switch (genimg_get_format((void *) addr)) {
case IMAGE_FORMAT_LEGACY:
hdr = (image_header_t *) addr;
22 years ago
bootstage_mark(BOOTSTAGE_ID_IDE_FORMAT);
if (!image_check_hcrc(hdr)) {
puts("\n** Bad Header Checksum **\n");
bootstage_error(BOOTSTAGE_ID_IDE_CHECKSUM);
return 1;
}
bootstage_mark(BOOTSTAGE_ID_IDE_CHECKSUM);
22 years ago
image_print_contents(hdr);
cnt = image_get_image_size(hdr);
break;
#if defined(CONFIG_FIT)
case IMAGE_FORMAT_FIT:
fit_hdr = (const void *) addr;
puts("Fit image detected...\n");
cnt = fit_get_size(fit_hdr);
break;
#endif
default:
bootstage_error(BOOTSTAGE_ID_IDE_FORMAT);
puts("** Unknown image type\n");
return 1;
}
cnt += info.blksz - 1;
cnt /= info.blksz;
cnt -= 1;
if (ide_dev_desc[dev].block_read(dev, info.start + 1, cnt,
(ulong *)(addr + info.blksz)) != cnt) {
printf("** Read error on %d:%d\n", dev, part);
bootstage_error(BOOTSTAGE_ID_IDE_READ);
22 years ago
return 1;
}
bootstage_mark(BOOTSTAGE_ID_IDE_READ);
22 years ago
#if defined(CONFIG_FIT)
/* This cannot be done earlier, we need complete FIT image in RAM first */
if (genimg_get_format((void *) addr) == IMAGE_FORMAT_FIT) {
if (!fit_check_format(fit_hdr)) {
bootstage_error(BOOTSTAGE_ID_IDE_FIT_READ);
puts("** Bad FIT image format\n");
return 1;
}
bootstage_mark(BOOTSTAGE_ID_IDE_FIT_READ_OK);
fit_print_contents(fit_hdr);
}
#endif
22 years ago
/* Loading ok, update default load address */
load_addr = addr;
return bootm_maybe_autostart(cmdtp, argv[0]);
22 years ago
}
/* ------------------------------------------------------------------------- */
inline void __ide_outb(int dev, int port, unsigned char val)
{
debug("ide_outb (dev= %d, port= 0x%x, val= 0x%02x) : @ 0x%08lx\n",
dev, port, val,
(ATA_CURR_BASE(dev) + CONFIG_SYS_ATA_PORT_ADDR(port)));
#if defined(CONFIG_IDE_AHB)
if (port) {
/* write command */
ide_write_register(dev, port, val);
} else {
/* write data */
outb(val, (ATA_CURR_BASE(dev)));
}
#else
outb(val, (ATA_CURR_BASE(dev) + CONFIG_SYS_ATA_PORT_ADDR(port)));
#endif
}
void ide_outb(int dev, int port, unsigned char val)
__attribute__ ((weak, alias("__ide_outb")));
inline unsigned char __ide_inb(int dev, int port)
{
uchar val;
#if defined(CONFIG_IDE_AHB)
val = ide_read_register(dev, port);
#else
val = inb((ATA_CURR_BASE(dev) + CONFIG_SYS_ATA_PORT_ADDR(port)));
#endif
debug("ide_inb (dev= %d, port= 0x%x) : @ 0x%08lx -> 0x%02x\n",
dev, port,
(ATA_CURR_BASE(dev) + CONFIG_SYS_ATA_PORT_ADDR(port)), val);
return val;
}
unsigned char ide_inb(int dev, int port)
__attribute__ ((weak, alias("__ide_inb")));
#ifdef CONFIG_TUNE_PIO
inline int __ide_set_piomode(int pio_mode)
{
return 0;
}
inline int ide_set_piomode(int pio_mode)
__attribute__ ((weak, alias("__ide_set_piomode")));
#endif
void ide_init(void)
22 years ago
{
#ifdef CONFIG_IDE_8xx_DIRECT
volatile immap_t *immr = (immap_t *) CONFIG_SYS_IMMR;
22 years ago
volatile pcmconf8xx_t *pcmp = &(immr->im_pcmcia);
#endif
unsigned char c;
int i, bus;
#if defined(CONFIG_SC3)
unsigned int ata_reset_time = ATA_RESET_TIME;
#endif
#ifdef CONFIG_IDE_8xx_PCCARD
extern int pcmcia_on(void);
extern int ide_devices_found; /* Initialized in check_ide_device() */
#endif /* CONFIG_IDE_8xx_PCCARD */
#ifdef CONFIG_IDE_PREINIT
extern int ide_preinit(void);
WATCHDOG_RESET();
if (ide_preinit()) {
puts("ide_preinit failed\n");
return;
}
#endif /* CONFIG_IDE_PREINIT */
22 years ago
#ifdef CONFIG_IDE_8xx_PCCARD
extern int pcmcia_on(void);
extern int ide_devices_found; /* Initialized in check_ide_device() */
22 years ago
WATCHDOG_RESET();
ide_devices_found = 0;
22 years ago
/* initialize the PCMCIA IDE adapter card */
pcmcia_on();
if (!ide_devices_found)
22 years ago
return;
udelay(1000000); /* 1 s */
#endif /* CONFIG_IDE_8xx_PCCARD */
22 years ago
WATCHDOG_RESET();
#ifdef CONFIG_IDE_8xx_DIRECT
22 years ago
/* Initialize PIO timing tables */
for (i = 0; i <= IDE_MAX_PIO_MODE; ++i) {
pio_config_clk[i].t_setup =
PCMCIA_MK_CLKS(pio_config_ns[i].t_setup, gd->bus_clk);
pio_config_clk[i].t_length =
PCMCIA_MK_CLKS(pio_config_ns[i].t_length,
gd->bus_clk);
pio_config_clk[i].t_hold =
PCMCIA_MK_CLKS(pio_config_ns[i].t_hold, gd->bus_clk);
debug("PIO Mode %d: setup=%2d ns/%d clk" " len=%3d ns/%d clk"
" hold=%2d ns/%d clk\n", i, pio_config_ns[i].t_setup,
pio_config_clk[i].t_setup, pio_config_ns[i].t_length,
pio_config_clk[i].t_length, pio_config_ns[i].t_hold,
pio_config_clk[i].t_hold);
22 years ago
}
#endif /* CONFIG_IDE_8xx_DIRECT */
22 years ago
/*
* Reset the IDE just to be sure.
22 years ago
* Light LED's to show
*/
ide_led((LED_IDE1 | LED_IDE2), 1); /* LED's on */
/* ATAPI Drives seems to need a proper IDE Reset */
ide_reset();
22 years ago
#ifdef CONFIG_IDE_8xx_DIRECT
/* PCMCIA / IDE initialization for common mem space */
pcmp->pcmc_pgcrb = 0;
/* start in PIO mode 0 - most relaxed timings */
pio_mode = 0;
set_pcmcia_timing(pio_mode);
#endif /* CONFIG_IDE_8xx_DIRECT */
22 years ago
/*
* Wait for IDE to get ready.
* According to spec, this can take up to 31 seconds!
*/
for (bus = 0; bus < CONFIG_SYS_IDE_MAXBUS; ++bus) {
int dev =
bus * (CONFIG_SYS_IDE_MAXDEVICE /
CONFIG_SYS_IDE_MAXBUS);
22 years ago
#ifdef CONFIG_IDE_8xx_PCCARD
/* Skip non-ide devices from probing */
if ((ide_devices_found & (1 << bus)) == 0) {
ide_led((LED_IDE1 | LED_IDE2), 0); /* LED's off */
continue;
}
#endif
printf("Bus %d: ", bus);
22 years ago
ide_bus_ok[bus] = 0;
/* Select device
*/
udelay(100000); /* 100 ms */
ide_outb(dev, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(dev));
udelay(100000); /* 100 ms */
22 years ago
i = 0;
do {
udelay(10000); /* 10 ms */
22 years ago
c = ide_inb(dev, ATA_STATUS);
22 years ago
i++;
#if defined(CONFIG_SC3)
if (i > (ata_reset_time * 100)) {
#else
22 years ago
if (i > (ATA_RESET_TIME * 100)) {
#endif
puts("** Timeout **\n");
/* LED's off */
ide_led((LED_IDE1 | LED_IDE2), 0);
22 years ago
return;
}
if ((i >= 100) && ((i % 100) == 0))
putc('.');
22 years ago
} while (c & ATA_STAT_BUSY);
if (c & (ATA_STAT_BUSY | ATA_STAT_FAULT)) {
puts("not available ");
debug("Status = 0x%02X ", c);
#ifndef CONFIG_ATAPI /* ATAPI Devices do not set DRDY */
} else if ((c & ATA_STAT_READY) == 0) {
puts("not available ");
debug("Status = 0x%02X ", c);
22 years ago
#endif
} else {
puts("OK ");
22 years ago
ide_bus_ok[bus] = 1;
}
WATCHDOG_RESET();
}
putc('\n');
22 years ago
ide_led((LED_IDE1 | LED_IDE2), 0); /* LED's off */
22 years ago
curr_device = -1;
for (i = 0; i < CONFIG_SYS_IDE_MAXDEVICE; ++i) {
22 years ago
#ifdef CONFIG_IDE_LED
int led = (IDE_BUS(i) == 0) ? LED_IDE1 : LED_IDE2;
#endif
ide_dev_desc[i].type = DEV_TYPE_UNKNOWN;
ide_dev_desc[i].if_type = IF_TYPE_IDE;
ide_dev_desc[i].dev = i;
ide_dev_desc[i].part_type = PART_TYPE_UNKNOWN;
ide_dev_desc[i].blksz = 0;
ide_dev_desc[i].lba = 0;
ide_dev_desc[i].block_read = ide_read;
ide_dev_desc[i].block_write = ide_write;
22 years ago
if (!ide_bus_ok[IDE_BUS(i)])
continue;
ide_led(led, 1); /* LED on */
22 years ago
ide_ident(&ide_dev_desc[i]);
ide_led(led, 0); /* LED off */
22 years ago
dev_print(&ide_dev_desc[i]);
22 years ago
if ((ide_dev_desc[i].lba > 0) && (ide_dev_desc[i].blksz > 0)) {
/* initialize partition type */
init_part(&ide_dev_desc[i]);
22 years ago
if (curr_device < 0)
curr_device = i;
}
}
WATCHDOG_RESET();
}
/* ------------------------------------------------------------------------- */
#ifdef CONFIG_PARTITIONS
block_dev_desc_t *ide_get_dev(int dev)
22 years ago
{
return (dev < CONFIG_SYS_IDE_MAXDEVICE) ? &ide_dev_desc[dev] : NULL;
22 years ago
}
#endif
22 years ago
#ifdef CONFIG_IDE_8xx_DIRECT
static void set_pcmcia_timing(int pmode)
22 years ago
{
volatile immap_t *immr = (immap_t *) CONFIG_SYS_IMMR;
22 years ago
volatile pcmconf8xx_t *pcmp = &(immr->im_pcmcia);
ulong timings;
debug("Set timing for PIO Mode %d\n", pmode);
22 years ago
timings = PCMCIA_SHT(pio_config_clk[pmode].t_hold)
| PCMCIA_SST(pio_config_clk[pmode].t_setup)
| PCMCIA_SL(pio_config_clk[pmode].t_length);
22 years ago
/*
* IDE 0
22 years ago
*/
pcmp->pcmc_pbr0 = CONFIG_SYS_PCMCIA_PBR0;
pcmp->pcmc_por0 = CONFIG_SYS_PCMCIA_POR0
#if (CONFIG_SYS_PCMCIA_POR0 != 0)
| timings
22 years ago
#endif
;
debug("PBR0: %08x POR0: %08x\n", pcmp->pcmc_pbr0, pcmp->pcmc_por0);
22 years ago
pcmp->pcmc_pbr1 = CONFIG_SYS_PCMCIA_PBR1;
pcmp->pcmc_por1 = CONFIG_SYS_PCMCIA_POR1
#if (CONFIG_SYS_PCMCIA_POR1 != 0)
| timings
22 years ago
#endif
;
debug("PBR1: %08x POR1: %08x\n", pcmp->pcmc_pbr1, pcmp->pcmc_por1);
22 years ago
pcmp->pcmc_pbr2 = CONFIG_SYS_PCMCIA_PBR2;
pcmp->pcmc_por2 = CONFIG_SYS_PCMCIA_POR2
#if (CONFIG_SYS_PCMCIA_POR2 != 0)
| timings
22 years ago
#endif
;
debug("PBR2: %08x POR2: %08x\n", pcmp->pcmc_pbr2, pcmp->pcmc_por2);
22 years ago
pcmp->pcmc_pbr3 = CONFIG_SYS_PCMCIA_PBR3;
pcmp->pcmc_por3 = CONFIG_SYS_PCMCIA_POR3
#if (CONFIG_SYS_PCMCIA_POR3 != 0)
| timings
22 years ago
#endif
;
debug("PBR3: %08x POR3: %08x\n", pcmp->pcmc_pbr3, pcmp->pcmc_por3);
22 years ago
/*
* IDE 1
22 years ago
*/
pcmp->pcmc_pbr4 = CONFIG_SYS_PCMCIA_PBR4;
pcmp->pcmc_por4 = CONFIG_SYS_PCMCIA_POR4
#if (CONFIG_SYS_PCMCIA_POR4 != 0)
| timings
22 years ago
#endif
;
debug("PBR4: %08x POR4: %08x\n", pcmp->pcmc_pbr4, pcmp->pcmc_por4);
22 years ago
pcmp->pcmc_pbr5 = CONFIG_SYS_PCMCIA_PBR5;
pcmp->pcmc_por5 = CONFIG_SYS_PCMCIA_POR5
#if (CONFIG_SYS_PCMCIA_POR5 != 0)
| timings
22 years ago
#endif
;
debug("PBR5: %08x POR5: %08x\n", pcmp->pcmc_pbr5, pcmp->pcmc_por5);
22 years ago
pcmp->pcmc_pbr6 = CONFIG_SYS_PCMCIA_PBR6;
pcmp->pcmc_por6 = CONFIG_SYS_PCMCIA_POR6
#if (CONFIG_SYS_PCMCIA_POR6 != 0)
| timings
22 years ago
#endif
;
debug("PBR6: %08x POR6: %08x\n", pcmp->pcmc_pbr6, pcmp->pcmc_por6);
22 years ago
pcmp->pcmc_pbr7 = CONFIG_SYS_PCMCIA_PBR7;
pcmp->pcmc_por7 = CONFIG_SYS_PCMCIA_POR7
#if (CONFIG_SYS_PCMCIA_POR7 != 0)
| timings
22 years ago
#endif
;
debug("PBR7: %08x POR7: %08x\n", pcmp->pcmc_pbr7, pcmp->pcmc_por7);
22 years ago
}
#endif /* CONFIG_IDE_8xx_DIRECT */
22 years ago
/* ------------------------------------------------------------------------- */
/* We only need to swap data if we are running on a big endian cpu. */
/* But Au1x00 cpu:s already swaps data in big endian mode! */
#if defined(__LITTLE_ENDIAN) || \
(defined(CONFIG_SOC_AU1X00) && !defined(CONFIG_GTH2))
#define input_swap_data(x,y,z) input_data(x,y,z)
#else
static void input_swap_data(int dev, ulong *sect_buf, int words)
22 years ago
{
Remove HMI10 board support Recent changes caused that the HMI10 board now is included in the boards built by MAKEALL, which revealed that compilation for this board has been broken for a long time: ps2ser.c: In function 'ps2ser_init': ps2ser.c:155: error: 'UART_LCR' undeclared (first use in this function) ps2ser.c:155: error: (Each undeclared identifier is reported only once ps2ser.c:155: error: for each function it appears in.) ps2ser.c:156: error: 'UART_DLL' undeclared (first use in this function) ps2ser.c:157: error: 'UART_DLM' undeclared (first use in this function) ps2ser.c:159: error: 'UART_IER' undeclared (first use in this function) ps2ser.c:160: error: 'UART_MCR' undeclared (first use in this function) ps2ser.c:161: error: 'UART_FCR' undeclared (first use in this function) ps2ser.c:162: error: 'UART_FCR_ENABLE_FIFO' undeclared (first use in this function) ps2ser.c:166: error: 'UART_LSR' undeclared (first use in this function) ps2ser.c: In function 'ps2ser_putc': ps2ser.c:198: error: 'UART_LSR' undeclared (first use in this function) ps2ser.c:200: error: 'UART_TX' undeclared (first use in this function) ps2ser.c: In function 'ps2ser_getc_hw': ps2ser.c:224: error: 'UART_LSR' undeclared (first use in this function) ps2ser.c:225: error: 'UART_RX' undeclared (first use in this function) ps2ser.c: In function 'ps2ser_interrupt': ps2ser.c:293: error: 'UART_IIR' undeclared (first use in this function) The board is orphaned, and AFAICT has reached EOL. Drop support for it. Signed-off-by: Wolfgang Denk <wd@denx.de>
14 years ago
#if defined(CONFIG_CPC45)
uchar i;
volatile uchar *pbuf_even =
(uchar *) (ATA_CURR_BASE(dev) + ATA_DATA_EVEN);
volatile uchar *pbuf_odd =
(uchar *) (ATA_CURR_BASE(dev) + ATA_DATA_ODD);
ushort *dbuf = (ushort *) sect_buf;
while (words--) {
for (i = 0; i < 2; i++) {
*(((uchar *) (dbuf)) + 1) = *pbuf_even;
*(uchar *) dbuf = *pbuf_odd;
dbuf += 1;
}
}
#else
volatile ushort *pbuf =
(ushort *) (ATA_CURR_BASE(dev) + ATA_DATA_REG);
ushort *dbuf = (ushort *) sect_buf;
debug("in input swap data base for read is %lx\n",
(unsigned long) pbuf);
while (words--) {
#ifdef __MIPS__
*dbuf++ = swab16p((u16 *) pbuf);
*dbuf++ = swab16p((u16 *) pbuf);
#elif defined(CONFIG_PCS440EP)
*dbuf++ = *pbuf;
*dbuf++ = *pbuf;
#else
*dbuf++ = ld_le16(pbuf);
*dbuf++ = ld_le16(pbuf);
#endif /* !MIPS */
}
#endif
22 years ago
}
#endif /* __LITTLE_ENDIAN || CONFIG_AU1X00 */
#if defined(CONFIG_IDE_SWAP_IO)
static void output_data(int dev, const ulong *sect_buf, int words)
22 years ago
{
Remove HMI10 board support Recent changes caused that the HMI10 board now is included in the boards built by MAKEALL, which revealed that compilation for this board has been broken for a long time: ps2ser.c: In function 'ps2ser_init': ps2ser.c:155: error: 'UART_LCR' undeclared (first use in this function) ps2ser.c:155: error: (Each undeclared identifier is reported only once ps2ser.c:155: error: for each function it appears in.) ps2ser.c:156: error: 'UART_DLL' undeclared (first use in this function) ps2ser.c:157: error: 'UART_DLM' undeclared (first use in this function) ps2ser.c:159: error: 'UART_IER' undeclared (first use in this function) ps2ser.c:160: error: 'UART_MCR' undeclared (first use in this function) ps2ser.c:161: error: 'UART_FCR' undeclared (first use in this function) ps2ser.c:162: error: 'UART_FCR_ENABLE_FIFO' undeclared (first use in this function) ps2ser.c:166: error: 'UART_LSR' undeclared (first use in this function) ps2ser.c: In function 'ps2ser_putc': ps2ser.c:198: error: 'UART_LSR' undeclared (first use in this function) ps2ser.c:200: error: 'UART_TX' undeclared (first use in this function) ps2ser.c: In function 'ps2ser_getc_hw': ps2ser.c:224: error: 'UART_LSR' undeclared (first use in this function) ps2ser.c:225: error: 'UART_RX' undeclared (first use in this function) ps2ser.c: In function 'ps2ser_interrupt': ps2ser.c:293: error: 'UART_IIR' undeclared (first use in this function) The board is orphaned, and AFAICT has reached EOL. Drop support for it. Signed-off-by: Wolfgang Denk <wd@denx.de>
14 years ago
#if defined(CONFIG_CPC45)
uchar *dbuf;
volatile uchar *pbuf_even;
volatile uchar *pbuf_odd;
pbuf_even = (uchar *) (ATA_CURR_BASE(dev) + ATA_DATA_EVEN);
pbuf_odd = (uchar *) (ATA_CURR_BASE(dev) + ATA_DATA_ODD);
dbuf = (uchar *) sect_buf;
while (words--) {
EIEIO;
*pbuf_even = *dbuf++;
EIEIO;
*pbuf_odd = *dbuf++;
EIEIO;
*pbuf_even = *dbuf++;
EIEIO;
*pbuf_odd = *dbuf++;
}
#else
ushort *dbuf;
volatile ushort *pbuf;
pbuf = (ushort *) (ATA_CURR_BASE(dev) + ATA_DATA_REG);
dbuf = (ushort *) sect_buf;
while (words--) {
#if defined(CONFIG_PCS440EP)
/* not tested, because CF was write protected */
EIEIO;
*pbuf = ld_le16(dbuf++);
EIEIO;
*pbuf = ld_le16(dbuf++);
#else
EIEIO;
*pbuf = *dbuf++;
EIEIO;
*pbuf = *dbuf++;
#endif
}
#endif
22 years ago
}
#else /* ! CONFIG_IDE_SWAP_IO */
static void output_data(int dev, const ulong *sect_buf, int words)
{
#if defined(CONFIG_IDE_AHB)
ide_write_data(dev, sect_buf, words);
#else
outsw(ATA_CURR_BASE(dev) + ATA_DATA_REG, sect_buf, words << 1);
#endif
}
#endif /* CONFIG_IDE_SWAP_IO */
22 years ago
#if defined(CONFIG_IDE_SWAP_IO)
static void input_data(int dev, ulong *sect_buf, int words)
22 years ago
{
Remove HMI10 board support Recent changes caused that the HMI10 board now is included in the boards built by MAKEALL, which revealed that compilation for this board has been broken for a long time: ps2ser.c: In function 'ps2ser_init': ps2ser.c:155: error: 'UART_LCR' undeclared (first use in this function) ps2ser.c:155: error: (Each undeclared identifier is reported only once ps2ser.c:155: error: for each function it appears in.) ps2ser.c:156: error: 'UART_DLL' undeclared (first use in this function) ps2ser.c:157: error: 'UART_DLM' undeclared (first use in this function) ps2ser.c:159: error: 'UART_IER' undeclared (first use in this function) ps2ser.c:160: error: 'UART_MCR' undeclared (first use in this function) ps2ser.c:161: error: 'UART_FCR' undeclared (first use in this function) ps2ser.c:162: error: 'UART_FCR_ENABLE_FIFO' undeclared (first use in this function) ps2ser.c:166: error: 'UART_LSR' undeclared (first use in this function) ps2ser.c: In function 'ps2ser_putc': ps2ser.c:198: error: 'UART_LSR' undeclared (first use in this function) ps2ser.c:200: error: 'UART_TX' undeclared (first use in this function) ps2ser.c: In function 'ps2ser_getc_hw': ps2ser.c:224: error: 'UART_LSR' undeclared (first use in this function) ps2ser.c:225: error: 'UART_RX' undeclared (first use in this function) ps2ser.c: In function 'ps2ser_interrupt': ps2ser.c:293: error: 'UART_IIR' undeclared (first use in this function) The board is orphaned, and AFAICT has reached EOL. Drop support for it. Signed-off-by: Wolfgang Denk <wd@denx.de>
14 years ago
#if defined(CONFIG_CPC45)
uchar *dbuf;
volatile uchar *pbuf_even;
volatile uchar *pbuf_odd;
pbuf_even = (uchar *) (ATA_CURR_BASE(dev) + ATA_DATA_EVEN);
pbuf_odd = (uchar *) (ATA_CURR_BASE(dev) + ATA_DATA_ODD);
dbuf = (uchar *) sect_buf;
while (words--) {
*dbuf++ = *pbuf_even;
EIEIO;
SYNC;
*dbuf++ = *pbuf_odd;
EIEIO;
SYNC;
*dbuf++ = *pbuf_even;
EIEIO;
SYNC;
*dbuf++ = *pbuf_odd;
EIEIO;
SYNC;
}
#else
ushort *dbuf;
volatile ushort *pbuf;
pbuf = (ushort *) (ATA_CURR_BASE(dev) + ATA_DATA_REG);
dbuf = (ushort *) sect_buf;
debug("in input data base for read is %lx\n", (unsigned long) pbuf);
while (words--) {
#if defined(CONFIG_PCS440EP)
EIEIO;
*dbuf++ = ld_le16(pbuf);
EIEIO;
*dbuf++ = ld_le16(pbuf);
#else
EIEIO;
*dbuf++ = *pbuf;
EIEIO;
*dbuf++ = *pbuf;
#endif
}
#endif
22 years ago
}
#else /* ! CONFIG_IDE_SWAP_IO */
static void input_data(int dev, ulong *sect_buf, int words)
{
#if defined(CONFIG_IDE_AHB)
ide_read_data(dev, sect_buf, words);
#else
insw(ATA_CURR_BASE(dev) + ATA_DATA_REG, sect_buf, words << 1);
#endif
}
#endif /* CONFIG_IDE_SWAP_IO */
22 years ago
/* -------------------------------------------------------------------------
*/
static void ide_ident(block_dev_desc_t *dev_desc)
22 years ago
{
unsigned char c;
hd_driveid_t iop;
22 years ago
#ifdef CONFIG_ATAPI
int retries = 0;
#endif
#ifdef CONFIG_TUNE_PIO
int pio_mode;
#endif
22 years ago
#if 0
int mode, cycle_time;
#endif
int device;
device = dev_desc->dev;
printf(" Device %d: ", device);
ide_led(DEVICE_LED(device), 1); /* LED on */
22 years ago
/* Select device
*/
ide_outb(device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device));
dev_desc->if_type = IF_TYPE_IDE;
22 years ago
#ifdef CONFIG_ATAPI
retries = 0;
/* Warning: This will be tricky to read */
while (retries <= 1) {
/* check signature */
if ((ide_inb(device, ATA_SECT_CNT) == 0x01) &&
(ide_inb(device, ATA_SECT_NUM) == 0x01) &&
(ide_inb(device, ATA_CYL_LOW) == 0x14) &&
(ide_inb(device, ATA_CYL_HIGH) == 0xEB)) {
/* ATAPI Signature found */
dev_desc->if_type = IF_TYPE_ATAPI;
/*
* Start Ident Command
*/
ide_outb(device, ATA_COMMAND, ATAPI_CMD_IDENT);
/*
* Wait for completion - ATAPI devices need more time
* to become ready
*/
c = ide_wait(device, ATAPI_TIME_OUT);
} else
22 years ago
#endif
{
/*
* Start Ident Command
*/
ide_outb(device, ATA_COMMAND, ATA_CMD_IDENT);
/*
* Wait for completion
*/
c = ide_wait(device, IDE_TIME_OUT);
}
ide_led(DEVICE_LED(device), 0); /* LED off */
if (((c & ATA_STAT_DRQ) == 0) ||
((c & (ATA_STAT_FAULT | ATA_STAT_ERR)) != 0)) {
#ifdef CONFIG_ATAPI
{
/*
* Need to soft reset the device
* in case it's an ATAPI...
*/
debug("Retrying...\n");
ide_outb(device, ATA_DEV_HD,
ATA_LBA | ATA_DEVICE(device));
udelay(100000);
ide_outb(device, ATA_COMMAND, 0x08);
udelay(500000); /* 500 ms */
}
/*
* Select device
*/
ide_outb(device, ATA_DEV_HD,
ATA_LBA | ATA_DEVICE(device));
retries++;
#else
return;
#endif
}
#ifdef CONFIG_ATAPI
else
break;
} /* see above - ugly to read */
if (retries == 2) /* Not found */
return;
#endif
22 years ago
input_swap_data(device, (ulong *)&iop, ATA_SECTORWORDS);
22 years ago
ident_cpy((unsigned char *) dev_desc->revision, iop.fw_rev,
sizeof(dev_desc->revision));
ident_cpy((unsigned char *) dev_desc->vendor, iop.model,
sizeof(dev_desc->vendor));
ident_cpy((unsigned char *) dev_desc->product, iop.serial_no,
sizeof(dev_desc->product));
#ifdef __LITTLE_ENDIAN
/*
* firmware revision, model, and serial number have Big Endian Byte
* order in Word. Convert all three to little endian.
*
* See CF+ and CompactFlash Specification Revision 2.0:
* 6.2.1.6: Identify Drive, Table 39 for more details
*/
strswab(dev_desc->revision);
strswab(dev_desc->vendor);
strswab(dev_desc->product);
#endif /* __LITTLE_ENDIAN */
22 years ago
if ((iop.config & 0x0080) == 0x0080)
22 years ago
dev_desc->removable = 1;
else
dev_desc->removable = 0;
#ifdef CONFIG_TUNE_PIO
/* Mode 0 - 2 only, are directly determined by word 51. */
pio_mode = iop.tPIO;
if (pio_mode > 2) {
printf("WARNING: Invalid PIO (word 51 = %d).\n", pio_mode);
/* Force it to dead slow, and hope for the best... */
pio_mode = 0;
}
/* Any CompactFlash Storage Card that supports PIO mode 3 or above
* shall set bit 1 of word 53 to one and support the fields contained
* in words 64 through 70.
*/
if (iop.field_valid & 0x02) {
/*
* Mode 3 and above are possible. Check in order from slow
* to fast, so we wind up with the highest mode allowed.
*/
if (iop.eide_pio_modes & 0x01)
pio_mode = 3;
if (iop.eide_pio_modes & 0x02)
pio_mode = 4;
if (ata_id_is_cfa((u16 *)&iop)) {
if ((iop.cf_advanced_caps & 0x07) == 0x01)
pio_mode = 5;
if ((iop.cf_advanced_caps & 0x07) == 0x02)
pio_mode = 6;
}
}
/* System-specific, depends on bus speeds, etc. */
ide_set_piomode(pio_mode);
#endif /* CONFIG_TUNE_PIO */
22 years ago
#if 0
/*
* Drive PIO mode autoselection
*/
mode = iop.tPIO;
22 years ago
printf("tPIO = 0x%02x = %d\n", mode, mode);
22 years ago
if (mode > 2) { /* 2 is maximum allowed tPIO value */
mode = 2;
debug("Override tPIO -> 2\n");
22 years ago
}
if (iop.field_valid & 2) { /* drive implements ATA2? */
debug("Drive implements ATA2\n");
if (iop.capability & 8) { /* drive supports use_iordy? */
cycle_time = iop.eide_pio_iordy;
22 years ago
} else {
cycle_time = iop.eide_pio;
22 years ago
}
debug("cycle time = %d\n", cycle_time);
22 years ago
mode = 4;
if (cycle_time > 120)
mode = 3; /* 120 ns for PIO mode 4 */
if (cycle_time > 180)
mode = 2; /* 180 ns for PIO mode 3 */
if (cycle_time > 240)
mode = 1; /* 240 ns for PIO mode 4 */
if (cycle_time > 383)
mode = 0; /* 383 ns for PIO mode 4 */
22 years ago
}
printf("PIO mode to use: PIO %d\n", mode);
22 years ago
#endif /* 0 */
#ifdef CONFIG_ATAPI
if (dev_desc->if_type == IF_TYPE_ATAPI) {
22 years ago
atapi_inquiry(dev_desc);
return;
}
#endif /* CONFIG_ATAPI */
#ifdef __BIG_ENDIAN
22 years ago
/* swap shorts */
dev_desc->lba = (iop.lba_capacity << 16) | (iop.lba_capacity >> 16);
#else /* ! __BIG_ENDIAN */
/*
* do not swap shorts on little endian
*
* See CF+ and CompactFlash Specification Revision 2.0:
* 6.2.1.6: Identfy Drive, Table 39, Word Address 57-58 for details.
*/
dev_desc->lba = iop.lba_capacity;
#endif /* __BIG_ENDIAN */
#ifdef CONFIG_LBA48
if (iop.command_set_2 & 0x0400) { /* LBA 48 support */
dev_desc->lba48 = 1;
dev_desc->lba = (unsigned long long) iop.lba48_capacity[0] |
((unsigned long long) iop.lba48_capacity[1] << 16) |
((unsigned long long) iop.lba48_capacity[2] << 32) |
((unsigned long long) iop.lba48_capacity[3] << 48);
} else {
dev_desc->lba48 = 0;
}
#endif /* CONFIG_LBA48 */
22 years ago
/* assuming HD */
dev_desc->type = DEV_TYPE_HARDDISK;
dev_desc->blksz = ATA_BLOCKSIZE;
dev_desc->lun = 0; /* just to fill something in... */
#if 0 /* only used to test the powersaving mode,
* if enabled, the drive goes after 5 sec
* in standby mode */
ide_outb(device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device));
c = ide_wait(device, IDE_TIME_OUT);
ide_outb(device, ATA_SECT_CNT, 1);
ide_outb(device, ATA_LBA_LOW, 0);
ide_outb(device, ATA_LBA_MID, 0);
ide_outb(device, ATA_LBA_HIGH, 0);
ide_outb(device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device));
ide_outb(device, ATA_COMMAND, 0xe3);
udelay(50);
c = ide_wait(device, IDE_TIME_OUT); /* can't take over 500 ms */
22 years ago
#endif
}
/* ------------------------------------------------------------------------- */
ulong ide_read(int device, lbaint_t blknr, ulong blkcnt, void *buffer)
22 years ago
{
ulong n = 0;
unsigned char c;
unsigned char pwrsave = 0; /* power save */
#ifdef CONFIG_LBA48
unsigned char lba48 = 0;
22 years ago
if (blknr & 0x0000fffff0000000ULL) {
/* more than 28 bits used, use 48bit mode */
lba48 = 1;
}
#endif
debug("ide_read dev %d start %lX, blocks %lX buffer at %lX\n",
device, blknr, blkcnt, (ulong) buffer);
22 years ago
ide_led(DEVICE_LED(device), 1); /* LED on */
22 years ago
/* Select device
*/
ide_outb(device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device));
c = ide_wait(device, IDE_TIME_OUT);
22 years ago
if (c & ATA_STAT_BUSY) {
printf("IDE read: device %d not ready\n", device);
22 years ago
goto IDE_READ_E;
}
/* first check if the drive is in Powersaving mode, if yes,
* increase the timeout value */
ide_outb(device, ATA_COMMAND, ATA_CMD_CHK_PWR);
udelay(50);
22 years ago
c = ide_wait(device, IDE_TIME_OUT); /* can't take over 500 ms */
22 years ago
if (c & ATA_STAT_BUSY) {
printf("IDE read: device %d not ready\n", device);
22 years ago
goto IDE_READ_E;
}
if ((c & ATA_STAT_ERR) == ATA_STAT_ERR) {
printf("No Powersaving mode %X\n", c);
22 years ago
} else {
c = ide_inb(device, ATA_SECT_CNT);
debug("Powersaving %02X\n", c);
if (c == 0)
pwrsave = 1;
22 years ago
}
while (blkcnt-- > 0) {
c = ide_wait(device, IDE_TIME_OUT);
22 years ago
if (c & ATA_STAT_BUSY) {
printf("IDE read: device %d not ready\n", device);
22 years ago
break;
}
#ifdef CONFIG_LBA48
if (lba48) {
/* write high bits */
ide_outb(device, ATA_SECT_CNT, 0);
ide_outb(device, ATA_LBA_LOW, (blknr >> 24) & 0xFF);
#ifdef CONFIG_SYS_64BIT_LBA
ide_outb(device, ATA_LBA_MID, (blknr >> 32) & 0xFF);
ide_outb(device, ATA_LBA_HIGH, (blknr >> 40) & 0xFF);
#else
ide_outb(device, ATA_LBA_MID, 0);
ide_outb(device, ATA_LBA_HIGH, 0);
#endif
}
#endif
ide_outb(device, ATA_SECT_CNT, 1);
ide_outb(device, ATA_LBA_LOW, (blknr >> 0) & 0xFF);
ide_outb(device, ATA_LBA_MID, (blknr >> 8) & 0xFF);
ide_outb(device, ATA_LBA_HIGH, (blknr >> 16) & 0xFF);
#ifdef CONFIG_LBA48
if (lba48) {
ide_outb(device, ATA_DEV_HD,
ATA_LBA | ATA_DEVICE(device));
ide_outb(device, ATA_COMMAND, ATA_CMD_READ_EXT);
} else
#endif
{
ide_outb(device, ATA_DEV_HD, ATA_LBA |
ATA_DEVICE(device) | ((blknr >> 24) & 0xF));
ide_outb(device, ATA_COMMAND, ATA_CMD_READ);
}
22 years ago
udelay(50);
22 years ago
if (pwrsave) {
/* may take up to 4 sec */
c = ide_wait(device, IDE_SPIN_UP_TIME_OUT);
pwrsave = 0;
22 years ago
} else {
/* can't take over 500 ms */
c = ide_wait(device, IDE_TIME_OUT);
22 years ago
}
if ((c & (ATA_STAT_DRQ | ATA_STAT_BUSY | ATA_STAT_ERR)) !=
ATA_STAT_DRQ) {
#if defined(CONFIG_SYS_64BIT_LBA)
printf("Error (no IRQ) dev %d blk %lld: status 0x%02x\n",
22 years ago
device, blknr, c);
#else
printf("Error (no IRQ) dev %d blk %ld: status 0x%02x\n",
device, (ulong) blknr, c);
#endif
22 years ago
break;
}
input_data(device, buffer, ATA_SECTORWORDS);
(void) ide_inb(device, ATA_STATUS); /* clear IRQ */
22 years ago
++n;
++blknr;
buffer += ATA_BLOCKSIZE;
22 years ago
}
IDE_READ_E:
ide_led(DEVICE_LED(device), 0); /* LED off */
22 years ago
return (n);
}
/* ------------------------------------------------------------------------- */
ulong ide_write(int device, lbaint_t blknr, ulong blkcnt, const void *buffer)
22 years ago
{
ulong n = 0;
unsigned char c;
#ifdef CONFIG_LBA48
unsigned char lba48 = 0;
if (blknr & 0x0000fffff0000000ULL) {
/* more than 28 bits used, use 48bit mode */
lba48 = 1;
}
#endif
22 years ago
ide_led(DEVICE_LED(device), 1); /* LED on */
22 years ago
/* Select device
*/
ide_outb(device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device));
22 years ago
while (blkcnt-- > 0) {
c = ide_wait(device, IDE_TIME_OUT);
22 years ago
if (c & ATA_STAT_BUSY) {
printf("IDE read: device %d not ready\n", device);
22 years ago
goto WR_OUT;
}
#ifdef CONFIG_LBA48
if (lba48) {
/* write high bits */
ide_outb(device, ATA_SECT_CNT, 0);
ide_outb(device, ATA_LBA_LOW, (blknr >> 24) & 0xFF);
#ifdef CONFIG_SYS_64BIT_LBA
ide_outb(device, ATA_LBA_MID, (blknr >> 32) & 0xFF);
ide_outb(device, ATA_LBA_HIGH, (blknr >> 40) & 0xFF);
#else
ide_outb(device, ATA_LBA_MID, 0);
ide_outb(device, ATA_LBA_HIGH, 0);
#endif
}
#endif
ide_outb(device, ATA_SECT_CNT, 1);
ide_outb(device, ATA_LBA_LOW, (blknr >> 0) & 0xFF);
ide_outb(device, ATA_LBA_MID, (blknr >> 8) & 0xFF);
ide_outb(device, ATA_LBA_HIGH, (blknr >> 16) & 0xFF);
#ifdef CONFIG_LBA48
if (lba48) {
ide_outb(device, ATA_DEV_HD,
ATA_LBA | ATA_DEVICE(device));
ide_outb(device, ATA_COMMAND, ATA_CMD_WRITE_EXT);
} else
#endif
{
ide_outb(device, ATA_DEV_HD, ATA_LBA |
ATA_DEVICE(device) | ((blknr >> 24) & 0xF));
ide_outb(device, ATA_COMMAND, ATA_CMD_WRITE);
}
22 years ago
udelay(50);
22 years ago
/* can't take over 500 ms */
c = ide_wait(device, IDE_TIME_OUT);
22 years ago
if ((c & (ATA_STAT_DRQ | ATA_STAT_BUSY | ATA_STAT_ERR)) !=
ATA_STAT_DRQ) {
#if defined(CONFIG_SYS_64BIT_LBA)
printf("Error (no IRQ) dev %d blk %lld: status 0x%02x\n",
22 years ago
device, blknr, c);
#else
printf("Error (no IRQ) dev %d blk %ld: status 0x%02x\n",
device, (ulong) blknr, c);
#endif
22 years ago
goto WR_OUT;
}
output_data(device, buffer, ATA_SECTORWORDS);
c = ide_inb(device, ATA_STATUS); /* clear IRQ */
22 years ago
++n;
++blknr;
buffer += ATA_BLOCKSIZE;
22 years ago
}
WR_OUT:
ide_led(DEVICE_LED(device), 0); /* LED off */
22 years ago
return (n);
}
/* ------------------------------------------------------------------------- */
/*
* copy src to dest, skipping leading and trailing blanks and null
* terminate the string
* "len" is the size of available memory including the terminating '\0'
22 years ago
*/
static void ident_cpy(unsigned char *dst, unsigned char *src,
unsigned int len)
22 years ago
{
unsigned char *end, *last;
last = dst;
end = src + len - 1;
/* reserve space for '\0' */
if (len < 2)
goto OUT;
/* skip leading white space */
while ((*src) && (src < end) && (*src == ' '))
++src;
/* copy string, omitting trailing white space */
while ((*src) && (src < end)) {
*dst++ = *src;
if (*src++ != ' ')
last = dst;
22 years ago
}
OUT:
*last = '\0';
22 years ago
}
/* ------------------------------------------------------------------------- */
/*
* Wait until Busy bit is off, or timeout (in ms)
* Return last status
*/
static uchar ide_wait(int dev, ulong t)
22 years ago
{
ulong delay = 10 * t; /* poll every 100 us */
22 years ago
uchar c;
while ((c = ide_inb(dev, ATA_STATUS)) & ATA_STAT_BUSY) {
udelay(100);
if (delay-- == 0)
22 years ago
break;
}
return (c);
}
/* ------------------------------------------------------------------------- */
#ifdef CONFIG_IDE_RESET
extern void ide_set_reset(int idereset);
static void ide_reset(void)
22 years ago
{
#if defined(CONFIG_SYS_PB_12V_ENABLE) || defined(CONFIG_SYS_PB_IDE_MOTOR)
volatile immap_t *immr = (immap_t *) CONFIG_SYS_IMMR;
22 years ago
#endif
int i;
curr_device = -1;
for (i = 0; i < CONFIG_SYS_IDE_MAXBUS; ++i)
22 years ago
ide_bus_ok[i] = 0;
for (i = 0; i < CONFIG_SYS_IDE_MAXDEVICE; ++i)
22 years ago
ide_dev_desc[i].type = DEV_TYPE_UNKNOWN;
ide_set_reset(1); /* assert reset */
22 years ago
/* the reset signal shall be asserted for et least 25 us */
udelay(25);
22 years ago
WATCHDOG_RESET();
#ifdef CONFIG_SYS_PB_12V_ENABLE
/* 12V Enable output OFF */
immr->im_cpm.cp_pbdat &= ~(CONFIG_SYS_PB_12V_ENABLE);
immr->im_cpm.cp_pbpar &= ~(CONFIG_SYS_PB_12V_ENABLE);
immr->im_cpm.cp_pbodr &= ~(CONFIG_SYS_PB_12V_ENABLE);
immr->im_cpm.cp_pbdir |= CONFIG_SYS_PB_12V_ENABLE;
22 years ago
/* wait 500 ms for the voltage to stabilize */
for (i = 0; i < 500; ++i)
udelay(1000);
22 years ago
/* 12V Enable output ON */
immr->im_cpm.cp_pbdat |= CONFIG_SYS_PB_12V_ENABLE;
#endif /* CONFIG_SYS_PB_12V_ENABLE */
22 years ago
#ifdef CONFIG_SYS_PB_IDE_MOTOR
22 years ago
/* configure IDE Motor voltage monitor pin as input */
immr->im_cpm.cp_pbpar &= ~(CONFIG_SYS_PB_IDE_MOTOR);
immr->im_cpm.cp_pbodr &= ~(CONFIG_SYS_PB_IDE_MOTOR);
immr->im_cpm.cp_pbdir &= ~(CONFIG_SYS_PB_IDE_MOTOR);
22 years ago
/* wait up to 1 s for the motor voltage to stabilize */
for (i = 0; i < 1000; ++i) {
if ((immr->im_cpm.cp_pbdat & CONFIG_SYS_PB_IDE_MOTOR) != 0) {
22 years ago
break;
}
udelay(1000);
22 years ago
}
if (i == 1000) { /* Timeout */
printf("\nWarning: 5V for IDE Motor missing\n");
#ifdef CONFIG_STATUS_LED
#ifdef STATUS_LED_YELLOW
status_led_set(STATUS_LED_YELLOW, STATUS_LED_ON);
#endif
#ifdef STATUS_LED_GREEN
status_led_set(STATUS_LED_GREEN, STATUS_LED_OFF);
#endif
#endif /* CONFIG_STATUS_LED */
22 years ago
}
#endif /* CONFIG_SYS_PB_IDE_MOTOR */
22 years ago
WATCHDOG_RESET();
/* de-assert RESET signal */
ide_set_reset(0);
/* wait 250 ms */
for (i = 0; i < 250; ++i)
udelay(1000);
22 years ago
}
#endif /* CONFIG_IDE_RESET */
22 years ago
/* ------------------------------------------------------------------------- */
#if defined(CONFIG_IDE_LED) && \
!defined(CONFIG_CPC45) && \
!defined(CONFIG_KUP4K) && \
!defined(CONFIG_KUP4X)
22 years ago
static uchar led_buffer; /* Buffer for current LED status */
22 years ago
static void ide_led(uchar led, uchar status)
22 years ago
{
uchar *led_port = LED_PORT;
if (status) /* switch LED on */
led_buffer |= led;
else /* switch LED off */
22 years ago
led_buffer &= ~led;
*led_port = led_buffer;
}
#endif /* CONFIG_IDE_LED */
22 years ago
#if defined(CONFIG_OF_IDE_FIXUP)
int ide_device_present(int dev)
{
if (dev >= CONFIG_SYS_IDE_MAXBUS)
return 0;
return (ide_dev_desc[dev].type == DEV_TYPE_UNKNOWN ? 0 : 1);
}
#endif
22 years ago
/* ------------------------------------------------------------------------- */
#ifdef CONFIG_ATAPI
/****************************************************************************
* ATAPI Support
*/
#if defined(CONFIG_IDE_SWAP_IO)
22 years ago
/* since ATAPI may use commands with not 4 bytes alligned length
* we have our own transfer functions, 2 bytes alligned */
static void output_data_shorts(int dev, ushort *sect_buf, int shorts)
22 years ago
{
Remove HMI10 board support Recent changes caused that the HMI10 board now is included in the boards built by MAKEALL, which revealed that compilation for this board has been broken for a long time: ps2ser.c: In function 'ps2ser_init': ps2ser.c:155: error: 'UART_LCR' undeclared (first use in this function) ps2ser.c:155: error: (Each undeclared identifier is reported only once ps2ser.c:155: error: for each function it appears in.) ps2ser.c:156: error: 'UART_DLL' undeclared (first use in this function) ps2ser.c:157: error: 'UART_DLM' undeclared (first use in this function) ps2ser.c:159: error: 'UART_IER' undeclared (first use in this function) ps2ser.c:160: error: 'UART_MCR' undeclared (first use in this function) ps2ser.c:161: error: 'UART_FCR' undeclared (first use in this function) ps2ser.c:162: error: 'UART_FCR_ENABLE_FIFO' undeclared (first use in this function) ps2ser.c:166: error: 'UART_LSR' undeclared (first use in this function) ps2ser.c: In function 'ps2ser_putc': ps2ser.c:198: error: 'UART_LSR' undeclared (first use in this function) ps2ser.c:200: error: 'UART_TX' undeclared (first use in this function) ps2ser.c: In function 'ps2ser_getc_hw': ps2ser.c:224: error: 'UART_LSR' undeclared (first use in this function) ps2ser.c:225: error: 'UART_RX' undeclared (first use in this function) ps2ser.c: In function 'ps2ser_interrupt': ps2ser.c:293: error: 'UART_IIR' undeclared (first use in this function) The board is orphaned, and AFAICT has reached EOL. Drop support for it. Signed-off-by: Wolfgang Denk <wd@denx.de>
14 years ago
#if defined(CONFIG_CPC45)
uchar *dbuf;
volatile uchar *pbuf_even;
volatile uchar *pbuf_odd;
pbuf_even = (uchar *) (ATA_CURR_BASE(dev) + ATA_DATA_EVEN);
pbuf_odd = (uchar *) (ATA_CURR_BASE(dev) + ATA_DATA_ODD);
while (shorts--) {
EIEIO;
*pbuf_even = *dbuf++;
EIEIO;
*pbuf_odd = *dbuf++;
}
#else
ushort *dbuf;
volatile ushort *pbuf;
22 years ago
pbuf = (ushort *) (ATA_CURR_BASE(dev) + ATA_DATA_REG);
dbuf = (ushort *) sect_buf;
debug("in output data shorts base for read is %lx\n",
(unsigned long) pbuf);
22 years ago
while (shorts--) {
EIEIO;
*pbuf = *dbuf++;
22 years ago
}
#endif
}
static void input_data_shorts(int dev, ushort *sect_buf, int shorts)
{
Remove HMI10 board support Recent changes caused that the HMI10 board now is included in the boards built by MAKEALL, which revealed that compilation for this board has been broken for a long time: ps2ser.c: In function 'ps2ser_init': ps2ser.c:155: error: 'UART_LCR' undeclared (first use in this function) ps2ser.c:155: error: (Each undeclared identifier is reported only once ps2ser.c:155: error: for each function it appears in.) ps2ser.c:156: error: 'UART_DLL' undeclared (first use in this function) ps2ser.c:157: error: 'UART_DLM' undeclared (first use in this function) ps2ser.c:159: error: 'UART_IER' undeclared (first use in this function) ps2ser.c:160: error: 'UART_MCR' undeclared (first use in this function) ps2ser.c:161: error: 'UART_FCR' undeclared (first use in this function) ps2ser.c:162: error: 'UART_FCR_ENABLE_FIFO' undeclared (first use in this function) ps2ser.c:166: error: 'UART_LSR' undeclared (first use in this function) ps2ser.c: In function 'ps2ser_putc': ps2ser.c:198: error: 'UART_LSR' undeclared (first use in this function) ps2ser.c:200: error: 'UART_TX' undeclared (first use in this function) ps2ser.c: In function 'ps2ser_getc_hw': ps2ser.c:224: error: 'UART_LSR' undeclared (first use in this function) ps2ser.c:225: error: 'UART_RX' undeclared (first use in this function) ps2ser.c: In function 'ps2ser_interrupt': ps2ser.c:293: error: 'UART_IIR' undeclared (first use in this function) The board is orphaned, and AFAICT has reached EOL. Drop support for it. Signed-off-by: Wolfgang Denk <wd@denx.de>
14 years ago
#if defined(CONFIG_CPC45)
uchar *dbuf;
volatile uchar *pbuf_even;
volatile uchar *pbuf_odd;
pbuf_even = (uchar *) (ATA_CURR_BASE(dev) + ATA_DATA_EVEN);
pbuf_odd = (uchar *) (ATA_CURR_BASE(dev) + ATA_DATA_ODD);
while (shorts--) {
EIEIO;
*dbuf++ = *pbuf_even;
EIEIO;
*dbuf++ = *pbuf_odd;
}
#else
ushort *dbuf;
volatile ushort *pbuf;
pbuf = (ushort *) (ATA_CURR_BASE(dev) + ATA_DATA_REG);
dbuf = (ushort *) sect_buf;
debug("in input data shorts base for read is %lx\n",
(unsigned long) pbuf);
while (shorts--) {
EIEIO;
*dbuf++ = *pbuf;
}
#endif
22 years ago
}
#else /* ! CONFIG_IDE_SWAP_IO */
static void output_data_shorts(int dev, ushort *sect_buf, int shorts)
{
outsw(ATA_CURR_BASE(dev) + ATA_DATA_REG, sect_buf, shorts);
}
static void input_data_shorts(int dev, ushort *sect_buf, int shorts)
{
insw(ATA_CURR_BASE(dev) + ATA_DATA_REG, sect_buf, shorts);
}
#endif /* CONFIG_IDE_SWAP_IO */
22 years ago
/*
* Wait until (Status & mask) == res, or timeout (in ms)
* Return last status
* This is used since some ATAPI CD ROMs clears their Busy Bit first
* and then they set their DRQ Bit
*/
static uchar atapi_wait_mask(int dev, ulong t, uchar mask, uchar res)
22 years ago
{
ulong delay = 10 * t; /* poll every 100 us */
22 years ago
uchar c;
/* prevents to read the status before valid */
c = ide_inb(dev, ATA_DEV_CTL);
while (((c = ide_inb(dev, ATA_STATUS)) & mask) != res) {
22 years ago
/* break if error occurs (doesn't make sense to wait more) */
if ((c & ATA_STAT_ERR) == ATA_STAT_ERR)
22 years ago
break;
udelay(100);
if (delay-- == 0)
22 years ago
break;
}
return (c);
}
/*
* issue an atapi command
*/
unsigned char atapi_issue(int device, unsigned char *ccb, int ccblen,
unsigned char *buffer, int buflen)
22 years ago
{
unsigned char c, err, mask, res;
22 years ago
int n;
ide_led(DEVICE_LED(device), 1); /* LED on */
22 years ago
/* Select device
*/
mask = ATA_STAT_BUSY | ATA_STAT_DRQ;
22 years ago
res = 0;
ide_outb(device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device));
c = atapi_wait_mask(device, ATAPI_TIME_OUT, mask, res);
22 years ago
if ((c & mask) != res) {
printf("ATAPI_ISSUE: device %d not ready status %X\n", device,
c);
err = 0xFF;
22 years ago
goto AI_OUT;
}
/* write taskfile */
ide_outb(device, ATA_ERROR_REG, 0); /* no DMA, no overlaped */
ide_outb(device, ATA_SECT_CNT, 0);
ide_outb(device, ATA_SECT_NUM, 0);
ide_outb(device, ATA_CYL_LOW, (unsigned char) (buflen & 0xFF));
ide_outb(device, ATA_CYL_HIGH,
(unsigned char) ((buflen >> 8) & 0xFF));
ide_outb(device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device));
ide_outb(device, ATA_COMMAND, ATAPI_CMD_PACKET);
udelay(50);
mask = ATA_STAT_DRQ | ATA_STAT_BUSY | ATA_STAT_ERR;
22 years ago
res = ATA_STAT_DRQ;
c = atapi_wait_mask(device, ATAPI_TIME_OUT, mask, res);
22 years ago
if ((c & mask) != res) { /* DRQ must be 1, BSY 0 */
printf("ATAPI_ISSUE: Error (no IRQ) before sending ccb dev %d status 0x%02x\n",
device, c);
err = 0xFF;
22 years ago
goto AI_OUT;
}
/* write command block */
output_data_shorts(device, (unsigned short *) ccb, ccblen / 2);
/* ATAPI Command written wait for completition */
udelay(5000); /* device must set bsy */
22 years ago
mask = ATA_STAT_DRQ | ATA_STAT_BUSY | ATA_STAT_ERR;
/*
* if no data wait for DRQ = 0 BSY = 0
* if data wait for DRQ = 1 BSY = 0
*/
res = 0;
if (buflen)
22 years ago
res = ATA_STAT_DRQ;
c = atapi_wait_mask(device, ATAPI_TIME_OUT, mask, res);
if ((c & mask) != res) {
22 years ago
if (c & ATA_STAT_ERR) {
err = (ide_inb(device, ATA_ERROR_REG)) >> 4;
debug("atapi_issue 1 returned sense key %X status %02X\n",
err, c);
22 years ago
} else {
printf("ATAPI_ISSUE: (no DRQ) after sending ccb (%x) status 0x%02x\n",
ccb[0], c);
err = 0xFF;
22 years ago
}
goto AI_OUT;
}
n = ide_inb(device, ATA_CYL_HIGH);
n <<= 8;
n += ide_inb(device, ATA_CYL_LOW);
if (n > buflen) {
printf("ERROR, transfer bytes %d requested only %d\n", n,
buflen);
err = 0xff;
22 years ago
goto AI_OUT;
}
if ((n == 0) && (buflen < 0)) {
printf("ERROR, transfer bytes %d requested %d\n", n, buflen);
err = 0xff;
22 years ago
goto AI_OUT;
}
if (n != buflen) {
debug("WARNING, transfer bytes %d not equal with requested %d\n",
n, buflen);
22 years ago
}
if (n != 0) { /* data transfer */
debug("ATAPI_ISSUE: %d Bytes to transfer\n", n);
/* we transfer shorts */
n >>= 1;
22 years ago
/* ok now decide if it is an in or output */
if ((ide_inb(device, ATA_SECT_CNT) & 0x02) == 0) {
debug("Write to device\n");
output_data_shorts(device, (unsigned short *) buffer,
n);
22 years ago
} else {
debug("Read from device @ %p shorts %d\n", buffer, n);
input_data_shorts(device, (unsigned short *) buffer,
n);
22 years ago
}
}
udelay(5000); /* seems that some CD ROMs need this... */
mask = ATA_STAT_BUSY | ATA_STAT_ERR;
res = 0;
c = atapi_wait_mask(device, ATAPI_TIME_OUT, mask, res);
22 years ago
if ((c & ATA_STAT_ERR) == ATA_STAT_ERR) {
err = (ide_inb(device, ATA_ERROR_REG) >> 4);
debug("atapi_issue 2 returned sense key %X status %X\n", err,
c);
22 years ago
} else {
err = 0;
}
AI_OUT:
ide_led(DEVICE_LED(device), 0); /* LED off */
22 years ago
return (err);
}
/*
* sending the command to atapi_issue. If an status other than good
* returns, an request_sense will be issued
*/
#define ATAPI_DRIVE_NOT_READY 100
22 years ago
#define ATAPI_UNIT_ATTN 10
unsigned char atapi_issue_autoreq(int device,
unsigned char *ccb,
int ccblen,
unsigned char *buffer, int buflen)
22 years ago
{
unsigned char sense_data[18], sense_ccb[12];
unsigned char res, key, asc, ascq;
int notready, unitattn;
22 years ago
unitattn = ATAPI_UNIT_ATTN;
notready = ATAPI_DRIVE_NOT_READY;
22 years ago
retry:
res = atapi_issue(device, ccb, ccblen, buffer, buflen);
if (res == 0)
return 0; /* Ok */
if (res == 0xFF)
return 0xFF; /* error */
debug("(auto_req)atapi_issue returned sense key %X\n", res);
memset(sense_ccb, 0, sizeof(sense_ccb));
memset(sense_data, 0, sizeof(sense_data));
sense_ccb[0] = ATAPI_CMD_REQ_SENSE;
sense_ccb[4] = 18; /* allocation Length */
res = atapi_issue(device, sense_ccb, 12, sense_data, 18);
key = (sense_data[2] & 0xF);
asc = (sense_data[12]);
ascq = (sense_data[13]);
debug("ATAPI_CMD_REQ_SENSE returned %x\n", res);
debug(" Sense page: %02X key %02X ASC %02X ASCQ %02X\n",
sense_data[0], key, asc, ascq);
if ((key == 0))
return 0; /* ok device ready */
if ((key == 6) || (asc == 0x29) || (asc == 0x28)) { /* Unit Attention */
if (unitattn-- > 0) {
udelay(200 * 1000);
22 years ago
goto retry;
}
printf("Unit Attention, tried %d\n", ATAPI_UNIT_ATTN);
22 years ago
goto error;
}
if ((asc == 0x4) && (ascq == 0x1)) {
/* not ready, but will be ready soon */
if (notready-- > 0) {
udelay(200 * 1000);
22 years ago
goto retry;
}
printf("Drive not ready, tried %d times\n",
ATAPI_DRIVE_NOT_READY);
22 years ago
goto error;
}
if (asc == 0x3a) {
debug("Media not present\n");
22 years ago
goto error;
}
printf("ERROR: Unknown Sense key %02X ASC %02X ASCQ %02X\n", key, asc,
ascq);
22 years ago
error:
debug("ERROR Sense key %02X ASC %02X ASCQ %02X\n", key, asc, ascq);
22 years ago
return (0xFF);
}
static void atapi_inquiry(block_dev_desc_t *dev_desc)
22 years ago
{
unsigned char ccb[12]; /* Command descriptor block */
unsigned char iobuf[64]; /* temp buf */
22 years ago
unsigned char c;
int device;
device = dev_desc->dev;
dev_desc->type = DEV_TYPE_UNKNOWN; /* not yet valid */
dev_desc->block_read = atapi_read;
22 years ago
memset(ccb, 0, sizeof(ccb));
memset(iobuf, 0, sizeof(iobuf));
22 years ago
ccb[0] = ATAPI_CMD_INQUIRY;
ccb[4] = 40; /* allocation Legnth */
c = atapi_issue_autoreq(device, ccb, 12, (unsigned char *) iobuf, 40);
22 years ago
debug("ATAPI_CMD_INQUIRY returned %x\n", c);
if (c != 0)
22 years ago
return;
/* copy device ident strings */
ident_cpy((unsigned char *) dev_desc->vendor, &iobuf[8], 8);
ident_cpy((unsigned char *) dev_desc->product, &iobuf[16], 16);
ident_cpy((unsigned char *) dev_desc->revision, &iobuf[32], 5);
22 years ago
dev_desc->lun = 0;
dev_desc->lba = 0;
dev_desc->blksz = 0;
dev_desc->type = iobuf[0] & 0x1f;
22 years ago
if ((iobuf[1] & 0x80) == 0x80)
22 years ago
dev_desc->removable = 1;
else
dev_desc->removable = 0;
memset(ccb, 0, sizeof(ccb));
memset(iobuf, 0, sizeof(iobuf));
ccb[0] = ATAPI_CMD_START_STOP;
ccb[4] = 0x03; /* start */
22 years ago
c = atapi_issue_autoreq(device, ccb, 12, (unsigned char *) iobuf, 0);
22 years ago
debug("ATAPI_CMD_START_STOP returned %x\n", c);
if (c != 0)
22 years ago
return;
memset(ccb, 0, sizeof(ccb));
memset(iobuf, 0, sizeof(iobuf));
c = atapi_issue_autoreq(device, ccb, 12, (unsigned char *) iobuf, 0);
22 years ago
debug("ATAPI_CMD_UNIT_TEST_READY returned %x\n", c);
if (c != 0)
22 years ago
return;
memset(ccb, 0, sizeof(ccb));
memset(iobuf, 0, sizeof(iobuf));
ccb[0] = ATAPI_CMD_READ_CAP;
c = atapi_issue_autoreq(device, ccb, 12, (unsigned char *) iobuf, 8);
debug("ATAPI_CMD_READ_CAP returned %x\n", c);
if (c != 0)
22 years ago
return;
debug("Read Cap: LBA %02X%02X%02X%02X blksize %02X%02X%02X%02X\n",
iobuf[0], iobuf[1], iobuf[2], iobuf[3],
iobuf[4], iobuf[5], iobuf[6], iobuf[7]);
dev_desc->lba = ((unsigned long) iobuf[0] << 24) +
((unsigned long) iobuf[1] << 16) +
((unsigned long) iobuf[2] << 8) + ((unsigned long) iobuf[3]);
dev_desc->blksz = ((unsigned long) iobuf[4] << 24) +
((unsigned long) iobuf[5] << 16) +
((unsigned long) iobuf[6] << 8) + ((unsigned long) iobuf[7]);
#ifdef CONFIG_LBA48
/* ATAPI devices cannot use 48bit addressing (ATA/ATAPI v7) */
dev_desc->lba48 = 0;
#endif
22 years ago
return;
}
/*
* atapi_read:
* we transfer only one block per command, since the multiple DRQ per
* command is not yet implemented
*/
#define ATAPI_READ_MAX_BYTES 2048 /* we read max 2kbytes */
#define ATAPI_READ_BLOCK_SIZE 2048 /* assuming CD part */
#define ATAPI_READ_MAX_BLOCK (ATAPI_READ_MAX_BYTES/ATAPI_READ_BLOCK_SIZE)
22 years ago
ulong atapi_read(int device, lbaint_t blknr, ulong blkcnt, void *buffer)
22 years ago
{
ulong n = 0;
unsigned char ccb[12]; /* Command descriptor block */
22 years ago
ulong cnt;
debug("atapi_read dev %d start %lX, blocks %lX buffer at %lX\n",
device, blknr, blkcnt, (ulong) buffer);
22 years ago
do {
if (blkcnt > ATAPI_READ_MAX_BLOCK)
cnt = ATAPI_READ_MAX_BLOCK;
else
cnt = blkcnt;
ccb[0] = ATAPI_CMD_READ_12;
ccb[1] = 0; /* reserved */
ccb[2] = (unsigned char) (blknr >> 24) & 0xFF; /* MSB Block */
ccb[3] = (unsigned char) (blknr >> 16) & 0xFF; /* */
ccb[4] = (unsigned char) (blknr >> 8) & 0xFF;
ccb[5] = (unsigned char) blknr & 0xFF; /* LSB Block */
ccb[6] = (unsigned char) (cnt >> 24) & 0xFF; /* MSB Block cnt */
ccb[7] = (unsigned char) (cnt >> 16) & 0xFF;
ccb[8] = (unsigned char) (cnt >> 8) & 0xFF;
ccb[9] = (unsigned char) cnt & 0xFF; /* LSB Block */
ccb[10] = 0; /* reserved */
ccb[11] = 0; /* reserved */
if (atapi_issue_autoreq(device, ccb, 12,
(unsigned char *) buffer,
cnt * ATAPI_READ_BLOCK_SIZE)
== 0xFF) {
22 years ago
return (n);
}
n += cnt;
blkcnt -= cnt;
blknr += cnt;
buffer += (cnt * ATAPI_READ_BLOCK_SIZE);
22 years ago
} while (blkcnt > 0);
return (n);
}
/* ------------------------------------------------------------------------- */
#endif /* CONFIG_ATAPI */
U_BOOT_CMD(ide, 5, 1, do_ide,
"IDE sub-system",
"reset - reset IDE controller\n"
"ide info - show available IDE devices\n"
"ide device [dev] - show or set current device\n"
"ide part [dev] - print partition table of one or all IDE devices\n"
"ide read addr blk# cnt\n"
"ide write addr blk# cnt - read/write `cnt'"
" blocks starting at block `blk#'\n"
" to/from memory address `addr'");
U_BOOT_CMD(diskboot, 3, 1, do_diskboot,
"boot from IDE device", "loadAddr dev:part");