X-Git-Url: https://git.kernelconcepts.de/?a=blobdiff_plain;f=common%2Fcmd_ide.c;h=50ada33e869d8ae02abc90d0f3dc804556153906;hb=6e5923851ec5c11a36136abc77160d834537c4dd;hp=f1b24be684f5f58769dcfa5727b2ea1af4f3670f;hpb=cceb871fff195f2981b4cbedbcfa8e3c7bbe5c7b;p=karo-tx-uboot.git diff --git a/common/cmd_ide.c b/common/cmd_ide.c index f1b24be684..50ada33e86 100644 --- a/common/cmd_ide.c +++ b/common/cmd_ide.c @@ -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 */ +static unsigned long mips_io_port_base = 0; +#endif #endif #ifdef CONFIG_SHOW_BOOT_PROGRESS @@ -67,6 +72,7 @@ #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 +109,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,9 +126,8 @@ 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]; @@ -132,7 +139,7 @@ static 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) static void ide_led (uchar led, uchar status); #else extern void ide_led (uchar led, uchar status); @@ -166,9 +173,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 +180,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 +303,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 +332,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); @@ -474,9 +490,9 @@ 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 + DECLARE_GLOBAL_DATA_PTR; volatile immap_t *immr = (immap_t *)CFG_IMMR; volatile pcmconf8xx_t *pcmp = &(immr->im_pcmcia); #endif @@ -487,6 +503,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,6 +534,7 @@ 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, @@ -520,6 +551,7 @@ void ide_init (void) 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 +562,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. @@ -590,8 +622,7 @@ void ide_init (void) ide_led ((LED_IDE1 | LED_IDE2), 0); /* LED's off */ #ifdef CONFIG_AMIGAONEG3SE /* If this is the second bus, the first one was OK */ - if (bus != 0) - { + if (bus != 0) { ide_bus_ok[bus] = 0; goto skip_bus; } @@ -630,6 +661,7 @@ void ide_init (void) #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; @@ -750,44 +782,47 @@ 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) { + PRINTF ("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 */ +#ifdef __PPC__ __asm__ volatile("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 + *((uchar *)(ATA_CURR_BASE(dev)+port)) = val; } #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 */ +#ifdef __PPC__ __asm__ volatile("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 + val = *((uchar *)(ATA_CURR_BASE(dev)+port)); + PRINTF ("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,7 +833,7 @@ 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--) { @@ -811,70 +846,140 @@ output_data_short(int dev, ulong *sect_buf, int words) *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) +#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) { +#ifndef CONFIG_HMI10 volatile ushort *pbuf = (ushort *)(ATA_CURR_BASE(dev)+ATA_DATA_REG); ushort *dbuf = (ushort *)sect_buf; + PRINTF("in input swap data base for read is %lx\n", (unsigned long) pbuf); + while (words--) { *dbuf++ = ld_le16(pbuf); *dbuf++ = ld_le16(pbuf); } -} -#else /* ! __PPC__ */ -#define input_swap_data(x,y,z) input_data(x,y,z) -#endif /* __PPC__ */ - +#else /* CONFIG_HMI10 */ + 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; + } + } +#endif /* CONFIG_HMI10 */ +} +#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) { +#ifndef CONFIG_HMI10 ushort *dbuf; volatile ushort *pbuf; pbuf = (ushort *)(ATA_CURR_BASE(dev)+ATA_DATA_REG); dbuf = (ushort *)sect_buf; while (words--) { +#ifdef __PPC__ __asm__ volatile ("eieio"); +#endif *pbuf = *dbuf++; +#ifdef __PPC__ __asm__ volatile ("eieio"); +#endif *pbuf = *dbuf++; } +#else /* CONFIG_HMI10 */ + 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--) { + __asm__ volatile ("eieio"); + *pbuf_even = *dbuf++; + __asm__ volatile ("eieio"); + *pbuf_odd = *dbuf++; + __asm__ volatile ("eieio"); + *pbuf_even = *dbuf++; + __asm__ volatile ("eieio"); + *pbuf_odd = *dbuf++; + } +#endif /* CONFIG_HMI10 */ } #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) { +#ifndef CONFIG_HMI10 ushort *dbuf; volatile ushort *pbuf; pbuf = (ushort *)(ATA_CURR_BASE(dev)+ATA_DATA_REG); dbuf = (ushort *)sect_buf; + + PRINTF("in input data base for read is %lx\n", (unsigned long) pbuf); + while (words--) { +#ifdef __PPC__ __asm__ volatile ("eieio"); +#endif *dbuf++ = *pbuf; +#ifdef __PPC__ __asm__ volatile ("eieio"); +#endif *dbuf++ = *pbuf; } +#else /* CONFIG_HMI10 */ + 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--) { + __asm__ volatile ("eieio"); + *dbuf++ = *pbuf_even; + __asm__ volatile ("eieio"); + *dbuf++ = *pbuf_odd; + __asm__ volatile ("eieio"); + *dbuf++ = *pbuf_even; + __asm__ volatile ("eieio"); + *dbuf++ = *pbuf_odd; + } +#endif /* CONFIG_HMI10 */ } #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__ */ @@ -894,8 +999,7 @@ input_data_short(int dev, ulong *sect_buf, int words) __asm__ volatile ("eieio"); } - if (words&1) - { + if (words&1) { ushort dummy; dummy = *pbuf; } @@ -949,8 +1053,7 @@ static void ide_ident (block_dev_desc_t *dev_desc) retries = 0; /* Warning: This will be tricky to read */ - while (retries <= 1) - { + while (retries <= 1) { #endif /* CONFIG_AMIGAONEG3SE */ /* check signature */ @@ -968,8 +1071,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 @@ -988,11 +1090,9 @@ static void ide_ident (block_dev_desc_t *dev_desc) if (retries == 0) { do_retry = 1; } else { - dev_desc->type=DEV_TYPE_UNKNOWN; return; } #else - dev_desc->type=DEV_TYPE_UNKNOWN; return; #endif /* CONFIG_AMIGAONEG3SE */ } @@ -1018,6 +1118,18 @@ static void ide_ident (block_dev_desc_t *dev_desc) 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; @@ -1059,8 +1171,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; @@ -1086,13 +1220,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 + PRINTF ("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 */ @@ -1136,15 +1277,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 +1315,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 +1340,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 +1367,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 +1426,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) && (srclba48 = 0; /* ATAPI devices cannot use 48bit addressing (ATA/ATAPI v7) */ +#endif return; } @@ -1771,7 +2015,7 @@ 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 */ @@ -1816,4 +2060,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 */