?? cmd_ide.c
字號:
/* * (C) Copyright 2000, 2001 * Wolfgang Denk, DENX Software Engineering, wd@denx.de. * * See file CREDITS for list of people who contributed to this * project. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, * MA 02111-1307 USA * *//* * IDE support */#include <armboot.h>#include <config.h>#include <command.h>#include <image.h>#ifdef CONFIG_IDE_PCMCIA# include <pcmcia.h>#endif#include <ide.h>#include <ata.h>#include <part.h>#include <cmd_ide.h>#include <cmd_disk.h>#include <cmd_pcmcia.h>#ifdef CONFIG_STATUS_LED# include <status_led.h>#endif//#undef IDE_DEBUG#define IDE_DEBUG#ifdef IDE_DEBUG#define PRINTF(fmt,args...) printf (fmt ,##args)#else#define PRINTF(fmt,args...)#endif#if (CONFIG_COMMANDS & CFG_CMD_IDE)/* 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 )/* ------------------------------------------------------------------------- *//* Current I/O Device */static int curr_device = -1;/* Current offset for IDE0 / IDE1 bus access */#ifdef CONFIG_BAB750extern ulong bus_offset[];#elsestatic ulong bus_offset[CFG_IDE_MAXBUS] = { CFG_ATA_IDE0_OFFSET,#if CFG_IDE_MAXBUS > 1 CFG_ATA_IDE1_OFFSET,#endif};#endif//#define ATA_CURR_BASE(dev) (CFG_ATA_BASE_ADDR+bus_offset[IDE_BUS(dev)])#define ATA_CURR_BASE(dev) (bus_offset[IDE_BUS(dev)])static int ide_bus_ok[CFG_IDE_MAXBUS];static block_dev_desc_t ide_dev_desc[CFG_IDE_MAXDEVICE];/* ------------------------------------------------------------------------- */#ifdef CONFIG_IDE_LEDstatic void ide_led (uchar led, uchar status);#else#define ide_led(a,b) /* dummy */#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);#ifdef CONFIG_PIP405#define IDE_TIME_OUT 2000 /* 2 sec timeout */#else#define IDE_TIME_OUT 500 /* 500ms timeout */#endif#define ATAPI_TIME_OUT 7000 /* 7 sec timeout (5 sec seems to work...) */static void __inline__ outb(int dev, int port, unsigned char val);static unsigned char __inline__ inb(int dev, int port);static void input_swap_data(int dev, ulong *sect_buf, int words);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, ulong blknr, ulong blkcnt, ulong *buffer);#endif#ifdef CONFIG_IDE_PCMCIAstatic void set_pcmcia_timing (int pmode);#else#define set_pcmcia_timing(a) /* dummy */#endif/* ------------------------------------------------------------------------- */int do_ide (cmd_tbl_t *cmdtp, bd_t *bd, 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_PCMCIA " on PCMCIA " PCMCIA_SLOT_MSG#endif ": "); ide_init(bd); 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 (bd); } 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 blk = simple_strtoul(argv[3], NULL, 16); ulong cnt = simple_strtoul(argv[4], NULL, 16); ulong n; printf ("\nIDE read: device %d block # %ld, count %ld ... ", curr_device, blk, cnt); n = ide_dev_desc[curr_device].block_read (curr_device, blk, cnt, (ulong *)addr);/* n = ide_read (curr_device, blk, cnt, (ulong *)addr); */ 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 blk = simple_strtoul(argv[3], NULL, 16); ulong cnt = simple_strtoul(argv[4], NULL, 16); ulong n; printf ("\nIDE write: device %d block # %ld, count %ld ... ", curr_device, blk, cnt); 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, bd_t *bd, 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 (bd, "bootdevice"); break; case 2: addr = simple_strtoul(argv[1], NULL, 16); boot_device = getenv (bd, "bootdevice"); break; case 3: addr = simple_strtoul(argv[1], NULL, 16); boot_device = argv[2]; break; default: printf ("Usage:\n%s\n", cmdtp->usage); return 1; } if (!boot_device) { puts ("\n** No boot device **\n"); 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); return 1; } if (*ep) { if (*ep != ':') { puts ("\n** Invalid boot device, use `dev[:part]' **\n"); return 1; } part = simple_strtoul(++ep, NULL, 16); } if (get_partition_info (&ide_dev_desc[dev], part, &info)) { return 1; } if (strncmp(info.type, BOOT_PART_TYPE, sizeof(info.type)) != 0) { printf ("\n** Invalid partition type \"%.32s\"" " (expect \"" BOOT_PART_TYPE "\")\n", info.type); 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); return 1; } hdr = (image_header_t *)addr; if (SWAP32(hdr->ih_magic) == IH_MAGIC) { print_image_hdr (hdr); cnt = (SWAP32(hdr->ih_size) + sizeof(image_header_t)); cnt += info.blksz - 1; cnt /= info.blksz; cnt -= 1; } else { printf("\n** Bad Magic Number **\n"); 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); return 1; } /* Loading ok, update default load address */ load_addr = addr; /* Check if we should attempt an auto-start */ if (((ep = getenv(bd, "autostart")) != NULL) && (strcmp(ep,"yes") == 0)) { char *local_args[2]; extern int do_bootm (cmd_tbl_t *, bd_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, bd, 0, 1, local_args); rcode = 1; } return rcode;}/* ------------------------------------------------------------------------- */void ide_init (bd_t *bd){#ifdef CONFIG_IDE_PCMCIA volatile immap_t *immr = (immap_t *)CFG_IMMR; volatile pcmconf8xx_t *pcmp = &(immr->im_pcmcia);#endif unsigned char c; int i, bus;#ifdef CONFIG_IDE_PCCARD extern int pcmcia_on (void);# if defined(CONFIG_WATCHDOG) watchdog_reset ();# endif /* CONFIG_WATCHDOG */ /* initialize the PCMCIA IDE adapter card */ if (pcmcia_on()) return; udelay (1000000); /* 1 s */#endif /* CONFIG_IDE_PCCARD */#if defined(CONFIG_WATCHDOG) watchdog_reset ();#endif /* CONFIG_WATCHDOG */#define WE_DONT_HAVE_BD_BI_BUSFREQ 100000 /* 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, WE_DONT_HAVE_BD_BI_BUSFREQ); pio_config_clk[i].t_length = PCMCIA_MK_CLKS(pio_config_ns[i].t_length,
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -