📄 cmd_ide.c.svn-base
字号:
/* * (C) Copyright 2000-2002 * 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 */#include <common.h>#include <config.h>#include <watchdog.h>#include <command.h>#include <image.h>#include <asm/byteorder.h>#if defined(CONFIG_IDE_8xx_DIRECT) || defined(CONFIG_IDE_PCMCIA)# include <pcmcia.h>#endif#ifdef CONFIG_8xx# include <mpc8xx.h>#endif#ifdef CONFIG_MPC5xxx#include <mpc5xxx.h>#endif#include <ide.h>#include <ata.h>#ifdef CONFIG_STATUS_LED# include <status_led.h>#endif#ifndef __PPC__#include <asm/io.h>#ifdef __MIPS__/* Macros depend on this variable */static unsigned long mips_io_port_base = 0;#endif#endif#ifdef CONFIG_SHOW_BOOT_PROGRESS# include <status_led.h># define SHOW_BOOT_PROGRESS(arg) show_boot_progress(arg)#else# define SHOW_BOOT_PROGRESS(arg)#endif#ifdef __PPC__# define EIEIO __asm__ volatile ("eieio")#else# define EIEIO /* nothing */#endif#undef IDE_DEBUG#ifdef IDE_DEBUG#define PRINTF(fmt,args...) printf (fmt ,##args)#else#define PRINTF(fmt,args...)#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 * 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 CFG_PIO_MODE#define CFG_PIO_MODE 0 /* use a relaxed default */#endifstatic int pio_mode = CFG_PIO_MODE;/* Make clock cycles and always round up */#define PCMCIA_MK_CLKS( t, T ) (( (t) * (T) + 999U ) / 1000U )#endif /* CONFIG_IDE_8xx_DIRECT *//* ------------------------------------------------------------------------- *//* Current I/O Device */static int curr_device = -1;/* Current offset for IDE0 / IDE1 bus access */ulong ide_bus_offset[CFG_IDE_MAXBUS] = {#if defined(CFG_ATA_IDE0_OFFSET) CFG_ATA_IDE0_OFFSET,#endif#if defined(CFG_ATA_IDE1_OFFSET) && (CFG_IDE_MAXBUS > 1) CFG_ATA_IDE1_OFFSET,#endif};#define ATA_CURR_BASE(dev) (CFG_ATA_BASE_ADDR+ide_bus_offset[IDE_BUS(dev)])#ifndef CONFIG_AMIGAONEG3SEstatic int ide_bus_ok[CFG_IDE_MAXBUS];#elsestatic int ide_bus_ok[CFG_IDE_MAXBUS] = {0,};#endifstatic block_dev_desc_t ide_dev_desc[CFG_IDE_MAXDEVICE];/* ------------------------------------------------------------------------- */#ifdef CONFIG_IDE_LED#if !defined(CONFIG_KUP4K) && !defined(CONFIG_KUP4X) &&!defined(CONFIG_BMS2003)static void ide_led (uchar led, uchar status);#elseextern void ide_led (uchar led, uchar status);#endif#else#ifndef CONFIG_AMIGAONEG3SE#define ide_led(a,b) /* dummy */#elseextern void ide_led(uchar led, uchar status);#define LED_IDE1 1#define LED_IDE2 2#define CONFIG_IDE_LED 1#define DEVICE_LED(x) 1#endif#endif#ifdef CONFIG_IDE_RESETstatic void ide_reset (void);#else#define ide_reset() /* dummy */#endifstatic 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 __inline__ ide_outb(int dev, int port, unsigned char val);static unsigned char __inline__ ide_inb(int dev, int port);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);#ifdef CONFIG_ATAPIstatic void atapi_inquiry(block_dev_desc_t *dev_desc);ulong atapi_read (int device, lbaint_t blknr, ulong blkcnt, ulong *buffer);#endif#ifdef CONFIG_IDE_8xx_DIRECTstatic void set_pcmcia_timing (int pmode);#endif/* ------------------------------------------------------------------------- */int do_ide (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]){ int rcode = 0; switch (argc) { case 0: case 1: printf ("Usage:\n%s\n", cmdtp->usage); return 1; case 2: if (strncmp(argv[1],"res",3) == 0) { puts ("\nReset IDE"#ifdef CONFIG_IDE_8xx_DIRECT " on PCMCIA " PCMCIA_SLOT_MSG#endif ": "); ide_init (); return 0; } else if (strncmp(argv[1],"inf",3) == 0) { int i; putc ('\n'); for (i=0; i<CFG_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; } else if (strncmp(argv[1],"dev",3) == 0) { if ((curr_device < 0) || (curr_device >= CFG_IDE_MAXDEVICE)) { puts ("\nno IDE devices available\n"); return 1; } 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<CFG_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; } printf ("Usage:\n%s\n", cmdtp->usage); return 1; case 3: if (strncmp(argv[1],"dev",3) == 0) { int dev = (int)simple_strtoul(argv[2], NULL, 10); printf ("\nIDE device %d: ", dev); if (dev >= CFG_IDE_MAXDEVICE) { puts ("unknown device\n"); return 1; } dev_print(&ide_dev_desc[dev]); /*ide_print (dev);*/ if (ide_dev_desc[dev].type == DEV_TYPE_UNKNOWN) { return 1; } curr_device = dev; 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); if (ide_dev_desc[dev].part_type!=PART_TYPE_UNKNOWN) { print_part(&ide_dev_desc[dev]); } else { printf ("\nIDE device %d not available\n", dev); rcode = 1; } return rcode;#if 0 } else if (strncmp(argv[1],"pio",4) == 0) { int mode = (int)simple_strtoul(argv[2], NULL, 10); if ((mode >= 0) && (mode <= IDE_MAX_PIO_MODE)) { puts ("\nSetting "); pio_mode = mode; ide_init (); } else { printf ("\nInvalid PIO mode %d (0 ... %d only)\n", mode, IDE_MAX_PIO_MODE); } return;#endif } printf ("Usage:\n%s\n", cmdtp->usage); return 1; default: /* at least 4 args */ if (strcmp(argv[1],"read") == 0) { ulong addr = simple_strtoul(argv[2], 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, (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;#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); printf ("%ld blocks written: %s\n", n, (n==cnt) ? "OK" : "ERROR"); if (n==cnt) { return 0; } else { return 1; } } else { printf ("Usage:\n%s\n", cmdtp->usage); rcode = 1; } return rcode; }}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; disk_partition_t info; image_header_t *hdr; int rcode = 0; switch (argc) { case 1: addr = CFG_LOAD_ADDR; boot_device = getenv ("bootdevice"); break; case 2: addr = simple_strtoul(argv[1], NULL, 16); boot_device = getenv ("bootdevice"); break; case 3: addr = simple_strtoul(argv[1], NULL, 16); boot_device = argv[2]; break; default: printf ("Usage:\n%s\n", cmdtp->usage); SHOW_BOOT_PROGRESS (-1); return 1; } if (!boot_device) { puts ("\n** No boot device **\n"); SHOW_BOOT_PROGRESS (-1); return 1; } dev = simple_strtoul(boot_device, &ep, 16); if (ide_dev_desc[dev].type==DEV_TYPE_UNKNOWN) { printf ("\n** Device %d not available\n", dev); SHOW_BOOT_PROGRESS (-1); return 1; } if (*ep) { if (*ep != ':') { puts ("\n** Invalid boot device, use `dev[:part]' **\n"); SHOW_BOOT_PROGRESS (-1); return 1; } part = simple_strtoul(++ep, NULL, 16); } if (get_partition_info (&ide_dev_desc[dev], 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)) { printf ("\n** Invalid partition type \"%.32s\"" " (expect \"" BOOT_PART_TYPE "\")\n", info.type); SHOW_BOOT_PROGRESS (-1); return 1; } printf ("\nLoading from IDE device %d, partition %d: " "Name: %.32s Type: %.32s\n", dev, part, info.name, info.type); PRINTF ("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) { printf ("** Read error on %d:%d\n", dev, part); SHOW_BOOT_PROGRESS (-1); return 1; } 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 { printf("\n** Bad Magic Number **\n"); SHOW_BOOT_PROGRESS (-1); return 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); SHOW_BOOT_PROGRESS (-1); return 1; } /* Loading ok, update default load address */ load_addr = addr; /* Check if we should attempt an auto-start */ if (((ep = getenv("autostart")) != NULL) && (strcmp(ep,"yes") == 0)) { char *local_args[2]; extern int do_bootm (cmd_tbl_t *, int, int, char *[]); local_args[0] = argv[0]; local_args[1] = NULL; printf ("Automatic boot of image at addr 0x%08lX ...\n", addr); do_bootm (cmdtp, 0, 1, local_args); rcode = 1; } return rcode;}/* ------------------------------------------------------------------------- */void ide_init (void){#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 unsigned char c; int i, bus;#ifdef CONFIG_AMIGAONEG3SE unsigned int max_bus_scan; 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();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -