X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=common%2Fcmd_ide.c;h=a4155029a7b8ddb7755619056af7c5c29a1e0ef7;hb=0dc018ece13effc689e47479ea9ebf1c98a507f5;hp=f1b24be684f5f58769dcfa5727b2ea1af4f3670f;hpb=cceb871fff195f2981b4cbedbcfa8e3c7bbe5c7b;p=u-boot diff --git a/common/cmd_ide.c b/common/cmd_ide.c index f1b24be684..a4155029a7 100644 --- a/common/cmd_ide.c +++ b/common/cmd_ide.c @@ -1,5 +1,5 @@ /* - * (C) Copyright 2000-2002 + * (C) Copyright 2000-2005 * Wolfgang Denk, DENX Software Engineering, wd@denx.de. * * See file CREDITS for list of people who contributed to this @@ -37,15 +37,20 @@ #ifdef CONFIG_8xx # include #endif +#ifdef CONFIG_MPC5xxx +#include +#endif #include #include -#include -#include #ifdef CONFIG_STATUS_LED # include #endif -#ifdef __I386__ +#ifndef __PPC__ #include +#ifdef __MIPS__ +/* Macros depend on this variable */ +unsigned long mips_io_port_base = 0; +#endif #endif #ifdef CONFIG_SHOW_BOOT_PROGRESS @@ -55,18 +60,21 @@ # define SHOW_BOOT_PROGRESS(arg) #endif +#ifdef CONFIG_IDE_8xx_DIRECT +DECLARE_GLOBAL_DATA_PTR; +#endif -#undef IDE_DEBUG - - -#ifdef IDE_DEBUG -#define PRINTF(fmt,args...) printf (fmt ,##args) +#ifdef __PPC__ +# define EIEIO __asm__ volatile ("eieio") +# define SYNC __asm__ volatile ("sync") #else -#define PRINTF(fmt,args...) +# define EIEIO /* nothing */ +# define SYNC /* nothing */ #endif #if (CONFIG_COMMANDS & CFG_CMD_IDE) +#ifdef CONFIG_IDE_8xx_DIRECT /* Timings for IDE Interface * * SETUP / LENGTH / HOLD - cycles valid for 50 MHz clk @@ -103,6 +111,8 @@ static int pio_mode = CFG_PIO_MODE; #define PCMCIA_MK_CLKS( t, T ) (( (t) * (T) + 999U ) / 1000U ) +#endif /* CONFIG_IDE_8xx_DIRECT */ + /* ------------------------------------------------------------------------- */ /* Current I/O Device */ @@ -118,21 +128,20 @@ ulong ide_bus_offset[CFG_IDE_MAXBUS] = { #endif }; -#ifdef __PPC__ + #define ATA_CURR_BASE(dev) (CFG_ATA_BASE_ADDR+ide_bus_offset[IDE_BUS(dev)]) -#endif #ifndef CONFIG_AMIGAONEG3SE -static int ide_bus_ok[CFG_IDE_MAXBUS]; +static int ide_bus_ok[CFG_IDE_MAXBUS]; #else -static int ide_bus_ok[CFG_IDE_MAXBUS] = {0,}; +static int ide_bus_ok[CFG_IDE_MAXBUS] = {0,}; #endif -static block_dev_desc_t ide_dev_desc[CFG_IDE_MAXDEVICE]; +block_dev_desc_t ide_dev_desc[CFG_IDE_MAXDEVICE]; /* ------------------------------------------------------------------------- */ #ifdef CONFIG_IDE_LED -#ifndef CONFIG_KUP4K +#if !defined(CONFIG_KUP4K) && !defined(CONFIG_KUP4X) &&!defined(CONFIG_BMS2003) &&!defined(CONFIG_CPC45) static void ide_led (uchar led, uchar status); #else extern void ide_led (uchar led, uchar status); @@ -166,9 +175,6 @@ static uchar ide_wait (int dev, ulong t); static void __inline__ ide_outb(int dev, int port, unsigned char val); static unsigned char __inline__ ide_inb(int dev, int port); -#ifdef __PPC__ -static void input_swap_data(int dev, ulong *sect_buf, int words); -#endif static void input_data(int dev, ulong *sect_buf, int words); static void output_data(int dev, ulong *sect_buf, int words); static void ident_cpy (unsigned char *dest, unsigned char *src, unsigned int len); @@ -176,14 +182,12 @@ static void ident_cpy (unsigned char *dest, unsigned char *src, unsigned int len #ifdef CONFIG_ATAPI static void atapi_inquiry(block_dev_desc_t *dev_desc); -ulong atapi_read (int device, ulong blknr, ulong blkcnt, ulong *buffer); +ulong atapi_read (int device, lbaint_t blknr, ulong blkcnt, ulong *buffer); #endif #ifdef CONFIG_IDE_8xx_DIRECT static void set_pcmcia_timing (int pmode); -#else -#define set_pcmcia_timing(a) /* dummy */ #endif /* ------------------------------------------------------------------------- */ @@ -301,12 +305,19 @@ int do_ide (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) if (strcmp(argv[1],"read") == 0) { ulong addr = simple_strtoul(argv[2], NULL, 16); - ulong blk = simple_strtoul(argv[3], NULL, 16); ulong cnt = simple_strtoul(argv[4], NULL, 16); ulong n; +#ifdef CFG_64BIT_STRTOUL + lbaint_t blk = simple_strtoull(argv[3], NULL, 16); + + printf ("\nIDE read: device %d block # %qd, 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, @@ -323,12 +334,19 @@ int do_ide (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) } } else if (strcmp(argv[1],"write") == 0) { ulong addr = simple_strtoul(argv[2], NULL, 16); - ulong blk = simple_strtoul(argv[3], NULL, 16); ulong cnt = simple_strtoul(argv[4], NULL, 16); ulong n; +#ifdef CFG_64BIT_STRTOUL + lbaint_t blk = simple_strtoull(argv[3], NULL, 16); + + printf ("\nIDE write: device %d block # %qd, 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); @@ -353,8 +371,7 @@ int do_diskboot (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) char *boot_device = NULL; char *ep; int dev, part = 0; - ulong cnt; - ulong addr; + ulong addr, cnt, checksum; disk_partition_t info; image_header_t *hdr; int rcode = 0; @@ -400,12 +417,12 @@ int do_diskboot (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) } part = simple_strtoul(++ep, NULL, 16); } - if (get_partition_info (&ide_dev_desc[dev], part, &info)) { + if (get_partition_info (ide_dev_desc, part, &info)) { SHOW_BOOT_PROGRESS (-1); return 1; } - if ((strncmp(info.type, BOOT_PART_TYPE, sizeof(info.type)) != 0) && - (strncmp(info.type, BOOT_PART_COMP, sizeof(info.type)) != 0)) { + 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", info.type); @@ -417,7 +434,7 @@ int do_diskboot (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) "Name: %.32s Type: %.32s\n", dev, part, info.name, info.type); - PRINTF ("First Block: %ld, # of blocks: %ld, Block Size: %ld\n", + debug ("First Block: %ld, # of blocks: %ld, Block Size: %ld\n", info.start, info.size, info.blksz); if (ide_dev_desc[dev].block_read (dev, info.start, 1, (ulong *)addr) != 1) { @@ -428,20 +445,29 @@ int do_diskboot (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) hdr = (image_header_t *)addr; - if (ntohl(hdr->ih_magic) == IH_MAGIC) { - - print_image_hdr (hdr); - - cnt = (ntohl(hdr->ih_size) + sizeof(image_header_t)); - cnt += info.blksz - 1; - cnt /= info.blksz; - cnt -= 1; - } else { + if (ntohl(hdr->ih_magic) != IH_MAGIC) { printf("\n** Bad Magic Number **\n"); SHOW_BOOT_PROGRESS (-1); return 1; } + checksum = ntohl(hdr->ih_hcrc); + hdr->ih_hcrc = 0; + + if (crc32 (0, (uchar *)hdr, sizeof(image_header_t)) != checksum) { + puts ("\n** Bad Header Checksum **\n"); + SHOW_BOOT_PROGRESS (-2); + return 1; + } + hdr->ih_hcrc = htonl(checksum); /* restore checksum for later use */ + + print_image_hdr (hdr); + + cnt = (ntohl(hdr->ih_size) + sizeof(image_header_t)); + 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); @@ -474,7 +500,6 @@ int do_diskboot (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) void ide_init (void) { - DECLARE_GLOBAL_DATA_PTR; #ifdef CONFIG_IDE_8xx_DIRECT volatile immap_t *immr = (immap_t *)CFG_IMMR; @@ -487,6 +512,20 @@ void ide_init (void) unsigned int ata_reset_time; char *s; #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 */ #ifdef CONFIG_IDE_8xx_PCCARD extern int pcmcia_on (void); @@ -504,22 +543,24 @@ void ide_init (void) WATCHDOG_RESET(); +#ifdef CONFIG_IDE_8xx_DIRECT /* 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); - PRINTF ("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); + 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); } +#endif /* CONFIG_IDE_8xx_DIRECT */ /* Reset the IDE just to be sure. * Light LED's to show @@ -530,11 +571,11 @@ void ide_init (void) #ifdef CONFIG_IDE_8xx_DIRECT /* PCMCIA / IDE initialization for common mem space */ pcmp->pcmc_pgcrb = 0; -#endif /* start in PIO mode 0 - most relaxed timings */ pio_mode = 0; set_pcmcia_timing (pio_mode); +#endif /* CONFIG_IDE_8xx_DIRECT */ /* * Wait for IDE to get ready. @@ -546,9 +587,9 @@ void ide_init (void) #else s = getenv("ide_maxbus"); if (s) - max_bus_scan = simple_strtol(s, NULL, 10); + max_bus_scan = simple_strtol(s, NULL, 10); else - max_bus_scan = CFG_IDE_MAXBUS; + max_bus_scan = CFG_IDE_MAXBUS; for (bus=0; busim_pcmcia); ulong timings; - PRINTF ("Set timing for PIO Mode %d\n", pmode); + debug ("Set timing for PIO Mode %d\n", pmode); timings = PCMCIA_SHT(pio_config_clk[pmode].t_hold) | PCMCIA_SST(pio_config_clk[pmode].t_setup) @@ -684,7 +725,7 @@ set_pcmcia_timing (int pmode) | timings #endif ; - PRINTF ("PBR0: %08x POR0: %08x\n", pcmp->pcmc_pbr0, pcmp->pcmc_por0); + debug ("PBR0: %08x POR0: %08x\n", pcmp->pcmc_pbr0, pcmp->pcmc_por0); pcmp->pcmc_pbr1 = CFG_PCMCIA_PBR1; pcmp->pcmc_por1 = CFG_PCMCIA_POR1 @@ -692,7 +733,7 @@ set_pcmcia_timing (int pmode) | timings #endif ; - PRINTF ("PBR1: %08x POR1: %08x\n", pcmp->pcmc_pbr1, pcmp->pcmc_por1); + debug ("PBR1: %08x POR1: %08x\n", pcmp->pcmc_pbr1, pcmp->pcmc_por1); pcmp->pcmc_pbr2 = CFG_PCMCIA_PBR2; pcmp->pcmc_por2 = CFG_PCMCIA_POR2 @@ -700,7 +741,7 @@ set_pcmcia_timing (int pmode) | timings #endif ; - PRINTF ("PBR2: %08x POR2: %08x\n", pcmp->pcmc_pbr2, pcmp->pcmc_por2); + debug ("PBR2: %08x POR2: %08x\n", pcmp->pcmc_pbr2, pcmp->pcmc_por2); pcmp->pcmc_pbr3 = CFG_PCMCIA_PBR3; pcmp->pcmc_por3 = CFG_PCMCIA_POR3 @@ -708,7 +749,7 @@ set_pcmcia_timing (int pmode) | timings #endif ; - PRINTF ("PBR3: %08x POR3: %08x\n", pcmp->pcmc_pbr3, pcmp->pcmc_por3); + debug ("PBR3: %08x POR3: %08x\n", pcmp->pcmc_pbr3, pcmp->pcmc_por3); /* IDE 1 */ @@ -718,7 +759,7 @@ set_pcmcia_timing (int pmode) | timings #endif ; - PRINTF ("PBR4: %08x POR4: %08x\n", pcmp->pcmc_pbr4, pcmp->pcmc_por4); + debug ("PBR4: %08x POR4: %08x\n", pcmp->pcmc_pbr4, pcmp->pcmc_por4); pcmp->pcmc_pbr5 = CFG_PCMCIA_PBR5; pcmp->pcmc_por5 = CFG_PCMCIA_POR5 @@ -726,7 +767,7 @@ set_pcmcia_timing (int pmode) | timings #endif ; - PRINTF ("PBR5: %08x POR5: %08x\n", pcmp->pcmc_pbr5, pcmp->pcmc_por5); + debug ("PBR5: %08x POR5: %08x\n", pcmp->pcmc_pbr5, pcmp->pcmc_por5); pcmp->pcmc_pbr6 = CFG_PCMCIA_PBR6; pcmp->pcmc_por6 = CFG_PCMCIA_POR6 @@ -734,7 +775,7 @@ set_pcmcia_timing (int pmode) | timings #endif ; - PRINTF ("PBR6: %08x POR6: %08x\n", pcmp->pcmc_pbr6, pcmp->pcmc_por6); + debug ("PBR6: %08x POR6: %08x\n", pcmp->pcmc_pbr6, pcmp->pcmc_por6); pcmp->pcmc_pbr7 = CFG_PCMCIA_PBR7; pcmp->pcmc_por7 = CFG_PCMCIA_POR7 @@ -742,7 +783,7 @@ set_pcmcia_timing (int pmode) | timings #endif ; - PRINTF ("PBR7: %08x POR7: %08x\n", pcmp->pcmc_pbr7, pcmp->pcmc_por7); + debug ("PBR7: %08x POR7: %08x\n", pcmp->pcmc_pbr7, pcmp->pcmc_por7); } @@ -750,44 +791,43 @@ set_pcmcia_timing (int pmode) /* ------------------------------------------------------------------------- */ -#ifdef __PPC__ +#if defined(__PPC__) || defined(CONFIG_PXA_PCMCIA) static void __inline__ 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)+port)); + /* Ensure I/O operations complete */ - __asm__ volatile("eieio"); + EIEIO; *((uchar *)(ATA_CURR_BASE(dev)+port)) = val; -#if 0 - printf ("ide_outb: 0x%08lx <== 0x%02x\n", ATA_CURR_BASE(dev)+port, val); -#endif } #else /* ! __PPC__ */ static void __inline__ ide_outb(int dev, int port, unsigned char val) { - outb(val, port); + outb(val, ATA_CURR_BASE(dev)+port); } #endif /* __PPC__ */ -#ifdef __PPC__ +#if defined(__PPC__) || defined(CONFIG_PXA_PCMCIA) static unsigned char __inline__ ide_inb(int dev, int port) { uchar val; /* Ensure I/O operations complete */ - __asm__ volatile("eieio"); + EIEIO; val = *((uchar *)(ATA_CURR_BASE(dev)+port)); -#if 0 - printf ("ide_inb: 0x%08lx ==> 0x%02x\n", ATA_CURR_BASE(dev)+port, val); -#endif + debug ("ide_inb (dev= %d, port= 0x%x) : @ 0x%08lx -> 0x%02x\n", + dev, port, (ATA_CURR_BASE(dev)+port), val); return (val); } #else /* ! __PPC__ */ static unsigned char __inline__ ide_inb(int dev, int port) { - return inb(port); + return inb(ATA_CURR_BASE(dev)+port); } #endif /* __PPC__ */ @@ -798,83 +838,154 @@ output_data_short(int dev, ulong *sect_buf, int words) { ushort *dbuf; volatile ushort *pbuf; - + pbuf = (ushort *)(ATA_CURR_BASE(dev)+ATA_DATA_REG); dbuf = (ushort *)sect_buf; while (words--) { - __asm__ volatile ("eieio"); + EIEIO; *pbuf = *dbuf++; - __asm__ volatile ("eieio"); + EIEIO; } if (words&1) - *pbuf = 0; + *pbuf = 0; } # endif /* CONFIG_AMIGAONEG3SE */ +#endif /* __PPC_ */ +/* 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_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) { +#if defined(CONFIG_HMI10) || 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); +#else *dbuf++ = ld_le16(pbuf); *dbuf++ = ld_le16(pbuf); +#endif /* !MIPS */ } +#endif } -#else /* ! __PPC__ */ -#define input_swap_data(x,y,z) input_data(x,y,z) -#endif /* __PPC__ */ - - +#endif /* __LITTLE_ENDIAN || CONFIG_AU1X00 */ -#ifdef __PPC__ +#if defined(__PPC__) || defined(CONFIG_PXA_PCMCIA) static void output_data(int dev, ulong *sect_buf, int words) { +#if defined(CONFIG_HMI10) || 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--) { - __asm__ volatile ("eieio"); + EIEIO; *pbuf = *dbuf++; - __asm__ volatile ("eieio"); + EIEIO; *pbuf = *dbuf++; } +#endif } #else /* ! __PPC__ */ static void output_data(int dev, ulong *sect_buf, int words) { - outsw(ATA_DATA_REG, sect_buf, words<<1); + outsw(ATA_CURR_BASE(dev)+ATA_DATA_REG, sect_buf, words<<1); } #endif /* __PPC__ */ -#ifdef __PPC__ +#if defined(__PPC__) || defined(CONFIG_PXA_PCMCIA) static void input_data(int dev, ulong *sect_buf, int words) { +#if defined(CONFIG_HMI10) || 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--) { - __asm__ volatile ("eieio"); + EIEIO; *dbuf++ = *pbuf; - __asm__ volatile ("eieio"); + EIEIO; *dbuf++ = *pbuf; } +#endif } #else /* ! __PPC__ */ static void input_data(int dev, ulong *sect_buf, int words) { - insw(ATA_DATA_REG, sect_buf, words << 1); + insw(ATA_CURR_BASE(dev)+ATA_DATA_REG, sect_buf, words << 1); } #endif /* __PPC__ */ @@ -889,15 +1000,14 @@ input_data_short(int dev, ulong *sect_buf, int words) pbuf = (ushort *)(ATA_CURR_BASE(dev)+ATA_DATA_REG); dbuf = (ushort *)sect_buf; while (words--) { - __asm__ volatile ("eieio"); + EIEIO; *dbuf++ = *pbuf; - __asm__ volatile ("eieio"); + EIEIO; } - if (words&1) - { - ushort dummy; - dummy = *pbuf; + if (words&1) { + ushort dummy; + dummy = *pbuf; } } #endif @@ -912,8 +1022,10 @@ static void ide_ident (block_dev_desc_t *dev_desc) #ifdef CONFIG_AMIGAONEG3SE int max_bus_scan; - int retries = 0; char *s; +#endif +#ifdef CONFIG_ATAPI + int retries = 0; int do_retry = 0; #endif @@ -944,15 +1056,11 @@ static void ide_ident (block_dev_desc_t *dev_desc) dev_desc->if_type=IF_TYPE_IDE; #ifdef CONFIG_ATAPI -#ifdef CONFIG_AMIGAONEG3SE do_retry = 0; retries = 0; /* Warning: This will be tricky to read */ - while (retries <= 1) - { -#endif /* CONFIG_AMIGAONEG3SE */ - + while (retries <= 1) { /* check signature */ if ((ide_inb(device,ATA_SECT_CNT) == 0x01) && (ide_inb(device,ATA_SECT_NUM) == 0x01) && @@ -968,8 +1076,7 @@ static void ide_ident (block_dev_desc_t *dev_desc) * to become ready */ c = ide_wait (device, ATAPI_TIME_OUT); - } - else + } else #endif { /* Start Ident Command @@ -984,40 +1091,53 @@ static void ide_ident (block_dev_desc_t *dev_desc) if (((c & ATA_STAT_DRQ) == 0) || ((c & (ATA_STAT_FAULT|ATA_STAT_ERR)) != 0) ) { +#ifdef CONFIG_ATAPI #ifdef CONFIG_AMIGAONEG3SE - if (retries == 0) { - do_retry = 1; - } else { - dev_desc->type=DEV_TYPE_UNKNOWN; - return; + s = getenv("ide_doreset"); + if (s && strcmp(s, "on") == 0) +#endif + { + /* 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 */ } -#else - dev_desc->type=DEV_TYPE_UNKNOWN; - return; -#endif /* CONFIG_AMIGAONEG3SE */ - } - -#ifdef CONFIG_AMIGAONEG3SE - s = getenv("ide_doreset"); - if (s && strcmp(s, "on") == 0 && 1 == do_retry) { - /* Need to soft reset the device in case it's an ATAPI... */ - PRINTF("Retrying...\n"); + /* Select device + */ ide_outb (device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device)); - udelay(100000); - ide_outb (device, ATA_COMMAND, 0x08); - udelay (100000); /* 100 ms */ retries++; - } else { - retries = 100; +#else + return; +#endif } +#ifdef CONFIG_ATAPI + else + break; } /* see above - ugly to read */ -#endif /* CONFIG_AMIGAONEG3SE */ + + if (retries == 2) /* Not found */ + return; +#endif input_swap_data (device, iobuf, ATA_SECTORWORDS); ident_cpy (dev_desc->revision, iop->fw_rev, sizeof(dev_desc->revision)); ident_cpy (dev_desc->vendor, iop->model, sizeof(dev_desc->vendor)); ident_cpy (dev_desc->product, iop->serial_no, sizeof(dev_desc->product)); +#ifdef __LITTLE_ENDIAN + /* + * firmware revision and model number have Big Endian Byte + * order in Word. Convert both to little endian. + * + * See CF+ and CompactFlash Specification Revision 2.0: + * 6.2.1.6: Identfy Drive, Table 39 for more details + */ + + strswab (dev_desc->revision); + strswab (dev_desc->vendor); +#endif /* __LITTLE_ENDIAN */ if ((iop->config & 0x0080)==0x0080) dev_desc->removable = 1; @@ -1033,16 +1153,16 @@ static void ide_ident (block_dev_desc_t *dev_desc) printf ("tPIO = 0x%02x = %d\n",mode, mode); if (mode > 2) { /* 2 is maximum allowed tPIO value */ mode = 2; - PRINTF ("Override tPIO -> 2\n"); + debug ("Override tPIO -> 2\n"); } if (iop->field_valid & 2) { /* drive implements ATA2? */ - PRINTF ("Drive implements ATA2\n"); + debug ("Drive implements ATA2\n"); if (iop->capability & 8) { /* drive supports use_iordy? */ cycle_time = iop->eide_pio_iordy; } else { cycle_time = iop->eide_pio; } - PRINTF ("cycle time = %d\n", cycle_time); + debug ("cycle time = %d\n", cycle_time); 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 */ @@ -1059,8 +1179,30 @@ static void ide_ident (block_dev_desc_t *dev_desc) } #endif /* CONFIG_ATAPI */ +#ifdef __BIG_ENDIAN /* 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 */ /* assuming HD */ dev_desc->type=DEV_TYPE_HARDDISK; dev_desc->blksz=ATA_BLOCKSIZE; @@ -1075,8 +1217,7 @@ static void ide_ident (block_dev_desc_t *dev_desc) 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_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 */ @@ -1086,13 +1227,20 @@ static void ide_ident (block_dev_desc_t *dev_desc) /* ------------------------------------------------------------------------- */ -ulong ide_read (int device, ulong blknr, ulong blkcnt, ulong *buffer) +ulong ide_read (int device, lbaint_t blknr, ulong blkcnt, ulong *buffer) { ulong n = 0; unsigned char c; unsigned char pwrsave=0; /* power save */ +#ifdef CONFIG_LBA48 + unsigned char lba48 = 0; - PRINTF ("ide_read dev %d start %lX, blocks %lX buffer at %lX\n", + if (blknr & 0x0000fffff0000000) { + /* more than 28 bits used, use 48bit mode */ + lba48 = 1; + } +#endif + debug ("ide_read dev %d start %qX, blocks %lX buffer at %lX\n", device, blknr, blkcnt, (ulong)buffer); ide_led (DEVICE_LED(device), 1); /* LED on */ @@ -1122,7 +1270,7 @@ ulong ide_read (int device, ulong blknr, ulong blkcnt, ulong *buffer) printf ("No Powersaving mode %X\n", c); } else { c = ide_inb(device,ATA_SECT_CNT); - PRINTF("Powersaving %02X\n",c); + debug ("Powersaving %02X\n",c); if(c==0) pwrsave=1; } @@ -1136,15 +1284,33 @@ ulong ide_read (int device, ulong blknr, ulong blkcnt, ulong *buffer) printf ("IDE read: device %d not ready\n", device); 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); + ide_outb (device, ATA_LBA_MID, (blknr >> 32) & 0xFF); + ide_outb (device, ATA_LBA_HIGH, (blknr >> 40) & 0xFF); + } +#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); - ide_outb (device, ATA_DEV_HD, ATA_LBA | - ATA_DEVICE(device) | - ((blknr >> 24) & 0xF) ); - ide_outb (device, ATA_COMMAND, ATA_CMD_READ); + +#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); + } udelay (50); @@ -1156,8 +1322,13 @@ ulong ide_read (int device, ulong blknr, ulong blkcnt, ulong *buffer) } if ((c&(ATA_STAT_DRQ|ATA_STAT_BUSY|ATA_STAT_ERR)) != ATA_STAT_DRQ) { - printf ("Error (no IRQ) dev %d blk %ld: status 0x%02x\n", +#if defined(CFG_64BIT_LBA) && defined(CFG_64BIT_VSPRINTF) + printf ("Error (no IRQ) dev %d blk %qd: status 0x%02x\n", device, blknr, c); +#else + printf ("Error (no IRQ) dev %d blk %ld: status 0x%02x\n", + device, (ulong)blknr, c); +#endif break; } @@ -1176,10 +1347,18 @@ IDE_READ_E: /* ------------------------------------------------------------------------- */ -ulong ide_write (int device, ulong blknr, ulong blkcnt, ulong *buffer) +ulong ide_write (int device, lbaint_t blknr, ulong blkcnt, ulong *buffer) { ulong n = 0; unsigned char c; +#ifdef CONFIG_LBA48 + unsigned char lba48 = 0; + + if (blknr & 0x0000fffff0000000) { + /* more than 28 bits used, use 48bit mode */ + lba48 = 1; + } +#endif ide_led (DEVICE_LED(device), 1); /* LED on */ @@ -1195,23 +1374,46 @@ ulong ide_write (int device, ulong blknr, ulong blkcnt, ulong *buffer) printf ("IDE read: device %d not ready\n", device); 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); + ide_outb (device, ATA_LBA_MID, (blknr >> 32) & 0xFF); + ide_outb (device, ATA_LBA_HIGH, (blknr >> 40) & 0xFF); + } +#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); - ide_outb (device, ATA_DEV_HD, ATA_LBA | - ATA_DEVICE(device) | - ((blknr >> 24) & 0xF) ); - ide_outb (device, ATA_COMMAND, ATA_CMD_WRITE); + +#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); + } udelay (50); c = ide_wait (device, IDE_TIME_OUT); /* can't take over 500 ms */ if ((c&(ATA_STAT_DRQ|ATA_STAT_BUSY|ATA_STAT_ERR)) != ATA_STAT_DRQ) { - printf ("Error (no IRQ) dev %d blk %ld: status 0x%02x\n", +#if defined(CFG_64BIT_LBA) && defined(CFG_64BIT_VSPRINTF) + printf ("Error (no IRQ) dev %d blk %qd: status 0x%02x\n", device, blknr, c); +#else + printf ("Error (no IRQ) dev %d blk %ld: status 0x%02x\n", + device, (ulong)blknr, c); +#endif goto WR_OUT; } @@ -1231,27 +1433,31 @@ WR_OUT: /* * 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' */ -static void ident_cpy (unsigned char *dest, unsigned char *src, unsigned int len) +static void ident_cpy (unsigned char *dst, unsigned char *src, unsigned int len) { - int start,end; + unsigned char *end, *last; - start=0; - while (startstart) { - if (src[end]!=' ') - break; - end--; - } - for ( ; start<=end; start++) { - *dest++=src[start]; + last = dst; + end = src + len - 1; + + /* reserve space for '\0' */ + if (len < 2) + goto OUT; + + /* skip leading white space */ + while ((*src) && (src>4; - AT_PRINTF("atapi_issue 1 returned sense key %X status %02X\n",err,c); + debug ("atapi_issue 1 returned sense key %X status %02X\n",err,c); } else { printf ("ATTAPI_ISSUE: (no DRQ) after sending ccb (%x) status 0x%02x\n", ccb[0],c); err=0xFF; @@ -1543,18 +1779,18 @@ unsigned char atapi_issue(int device,unsigned char* ccb,int ccblen, unsigned cha goto AI_OUT; } if(n!=buflen) { - AT_PRINTF("WARNING, transfer bytes %d not equal with requested %d\n",n,buflen); + debug ("WARNING, transfer bytes %d not equal with requested %d\n",n,buflen); } if(n!=0) { /* data transfer */ - AT_PRINTF("ATAPI_ISSUE: %d Bytes to transfer\n",n); + debug ("ATAPI_ISSUE: %d Bytes to transfer\n",n); /* we transfer shorts */ n>>=1; /* ok now decide if it is an in or output */ if ((ide_inb(device, ATA_SECT_CNT)&0x02)==0) { - AT_PRINTF("Write to device\n"); + debug ("Write to device\n"); output_data_shorts(device,(unsigned short *)buffer,n); } else { - AT_PRINTF("Read from device @ %p shorts %d\n",buffer,n); + debug ("Read from device @ %p shorts %d\n",buffer,n); input_data_shorts(device,(unsigned short *)buffer,n); } } @@ -1564,7 +1800,7 @@ unsigned char atapi_issue(int device,unsigned char* ccb,int ccblen, unsigned cha c = atapi_wait_mask(device,ATAPI_TIME_OUT,mask,res); if ((c & ATA_STAT_ERR) == ATA_STAT_ERR) { err=(ide_inb(device,ATA_ERROR_REG) >> 4); - AT_PRINTF("atapi_issue 2 returned sense key %X status %X\n",err,c); + debug ("atapi_issue 2 returned sense key %X status %X\n",err,c); } else { err = 0; } @@ -1612,7 +1848,7 @@ retry: if (res==0xFF) return (0xFF); /* error */ - AT_PRINTF("(auto_req)atapi_issue returned sense key %X\n",res); + 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)); @@ -1624,8 +1860,8 @@ retry: asc=(sense_data[12]); ascq=(sense_data[13]); - AT_PRINTF("ATAPI_CMD_REQ_SENSE returned %x\n",res); - AT_PRINTF(" Sense page: %02X key %02X ASC %02X ASCQ %02X\n", + 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, @@ -1651,13 +1887,13 @@ retry: goto error; } if(asc==0x3a) { - AT_PRINTF("Media not present\n"); + debug ("Media not present\n"); goto error; } #ifdef CONFIG_AMIGAONEG3SE if ((sense_data[2]&0xF)==0x0B) { - AT_PRINTF("ABORTED COMMAND...retry\n"); + debug ("ABORTED COMMAND...retry\n"); if (retrycnt++ < 4) goto retry; return (0xFF); @@ -1666,7 +1902,7 @@ retry: if ((sense_data[2]&0xf) == 0x02 && sense_data[12] == 0x04 && sense_data[13] == 0x01 ) { - AT_PRINTF("Waiting for unit to become active\n"); + debug ("Waiting for unit to become active\n"); udelay(timeout); if (retrycnt++ < 4) goto retry; @@ -1676,12 +1912,11 @@ retry: printf ("ERROR: Unknown Sense key %02X ASC %02X ASCQ %02X\n",key,asc,ascq); error: - AT_PRINTF ("ERROR Sense key %02X ASC %02X ASCQ %02X\n",key,asc,ascq); + debug ("ERROR Sense key %02X ASC %02X ASCQ %02X\n",key,asc,ascq); return (0xFF); } - static void atapi_inquiry(block_dev_desc_t * dev_desc) { unsigned char ccb[12]; /* Command descriptor block */ @@ -1700,7 +1935,7 @@ static void atapi_inquiry(block_dev_desc_t * dev_desc) ccb[4]=40; /* allocation Legnth */ c=atapi_issue_autoreq(device,ccb,12,(unsigned char *)iobuf,40); - AT_PRINTF("ATAPI_CMD_INQUIRY returned %x\n",c); + debug ("ATAPI_CMD_INQUIRY returned %x\n",c); if (c!=0) return; @@ -1726,7 +1961,7 @@ static void atapi_inquiry(block_dev_desc_t * dev_desc) c=atapi_issue_autoreq(device,ccb,12,(unsigned char *)iobuf,0); - AT_PRINTF("ATAPI_CMD_START_STOP returned %x\n",c); + debug ("ATAPI_CMD_START_STOP returned %x\n",c); if (c!=0) return; @@ -1734,7 +1969,7 @@ static void atapi_inquiry(block_dev_desc_t * dev_desc) memset(iobuf,0,sizeof(iobuf)); c=atapi_issue_autoreq(device,ccb,12,(unsigned char *)iobuf,0); - AT_PRINTF("ATAPI_CMD_UNIT_TEST_READY returned %x\n",c); + debug ("ATAPI_CMD_UNIT_TEST_READY returned %x\n",c); if (c!=0) return; @@ -1742,11 +1977,11 @@ static void atapi_inquiry(block_dev_desc_t * dev_desc) memset(iobuf,0,sizeof(iobuf)); ccb[0]=ATAPI_CMD_READ_CAP; c=atapi_issue_autoreq(device,ccb,12,(unsigned char *)iobuf,8); - AT_PRINTF("ATAPI_CMD_READ_CAP returned %x\n",c); + debug ("ATAPI_CMD_READ_CAP returned %x\n",c); if (c!=0) return; - AT_PRINTF("Read Cap: LBA %02X%02X%02X%02X blksize %02X%02X%02X%02X\n", + 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]); @@ -1758,6 +1993,9 @@ static void atapi_inquiry(block_dev_desc_t * dev_desc) ((unsigned long)iobuf[5]<<16) + ((unsigned long)iobuf[6]<< 8) + ((unsigned long)iobuf[7]); +#ifdef CONFIG_LBA48 + dev_desc->lba48 = 0; /* ATAPI devices cannot use 48bit addressing (ATA/ATAPI v7) */ +#endif return; } @@ -1771,13 +2009,13 @@ static void atapi_inquiry(block_dev_desc_t * dev_desc) #define ATAPI_READ_BLOCK_SIZE 2048 /* assuming CD part */ #define ATAPI_READ_MAX_BLOCK ATAPI_READ_MAX_BYTES/ATAPI_READ_BLOCK_SIZE /* max blocks */ -ulong atapi_read (int device, ulong blknr, ulong blkcnt, ulong *buffer) +ulong atapi_read (int device, lbaint_t blknr, ulong blkcnt, ulong *buffer) { ulong n = 0; unsigned char ccb[12]; /* Command descriptor block */ ulong cnt; - AT_PRINTF("atapi_read dev %d start %lX, blocks %lX buffer at %lX\n", + debug ("atapi_read dev %d start %lX, blocks %lX buffer at %lX\n", device, blknr, blkcnt, (ulong)buffer); do { @@ -1816,4 +2054,23 @@ ulong atapi_read (int device, ulong blknr, ulong blkcnt, ulong *buffer) #endif /* CONFIG_ATAPI */ +U_BOOT_CMD( + ide, 5, 1, do_ide, + "ide - IDE sub-system\n", + "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'\n" +); + +U_BOOT_CMD( + diskboot, 3, 1, do_diskboot, + "diskboot- boot from IDE device\n", + "loadAddr dev:part\n" +); + #endif /* CONFIG_COMMANDS & CFG_CMD_IDE */