]> git.kernelconcepts.de Git - karo-tx-uboot.git/blobdiff - common/cmd_scsi.c
MAINTAINERS: fix Andreas Bießmann AVR32 entry
[karo-tx-uboot.git] / common / cmd_scsi.c
index f3d0c72168d81516e39eb51eca71603f0900a52b..d15b567dbb2411225c99b77eef0108f6a2e638b1 100644 (file)
 /*
  * SCSI support.
  */
-
 #include <common.h>
 #include <command.h>
-#include <cmd_boot.h>
 #include <asm/processor.h>
 #include <scsi.h>
 #include <image.h>
-#include <cmd_disk.h>
 #include <pci.h>
 
-
-#undef SCSI_DEBUG
-
-#ifdef SCSI_DEBUG
-#define        PRINTF(fmt,args...)     printf (fmt ,##args)
-#else
-#define PRINTF(fmt,args...)
-#endif
-
-#if (CONFIG_COMMANDS & CFG_CMD_SCSI)
-
 #ifdef CONFIG_SCSI_SYM53C8XX
 #define SCSI_VEND_ID   0x1000
 #ifndef CONFIG_SCSI_DEV_ID
 #else
 #define SCSI_DEV_ID            CONFIG_SCSI_DEV_ID
 #endif
-#else
-#error CONFIG_SCSI_SYM53C8XX must be defined
+#elif defined CONFIG_SATA_ULI5288
+
+#define SCSI_VEND_ID 0x10b9
+#define SCSI_DEV_ID  0x5288
+
+#elif !defined(CONFIG_SCSI_AHCI_PLAT)
+#error no scsi device defined
 #endif
 
 
@@ -68,7 +59,7 @@ static int scsi_max_devs; /* number of highest available scsi device */
 
 static int scsi_curr_dev; /* current device */
 
-static block_dev_desc_t scsi_dev_desc[CFG_SCSI_MAX_DEVICE];
+static block_dev_desc_t scsi_dev_desc[CONFIG_SYS_SCSI_MAX_DEVICE];
 
 /********************************************************************************
  *  forward declerations of some Setup Routines
@@ -81,7 +72,7 @@ void scsi_setup_inquiry(ccb * pccb);
 void scsi_ident_cpy (unsigned char *dest, unsigned char *src, unsigned int len);
 
 
-ulong scsi_read(int device, ulong blknr, ulong blkcnt, ulong *buffer);
+ulong scsi_read(int device, ulong blknr, ulong blkcnt, void *buffer);
 
 
 /*********************************************************************************
@@ -97,7 +88,7 @@ void scsi_scan(int mode)
        if(mode==1) {
                printf("scanning bus for devices...\n");
        }
-       for(i=0;i<CFG_SCSI_MAX_DEVICE;i++) {
+       for(i=0;i<CONFIG_SYS_SCSI_MAX_DEVICE;i++) {
                scsi_dev_desc[i].target=0xff;
                scsi_dev_desc[i].lun=0xff;
                scsi_dev_desc[i].lba=0;
@@ -113,16 +104,16 @@ void scsi_scan(int mode)
                scsi_dev_desc[i].block_read=scsi_read;
        }
        scsi_max_devs=0;
-       for(i=0;i<CFG_SCSI_MAX_SCSI_ID;i++) {
+       for(i=0;i<CONFIG_SYS_SCSI_MAX_SCSI_ID;i++) {
                pccb->target=i;
-               for(lun=0;lun<CFG_SCSI_MAX_LUN;lun++) {
+               for(lun=0;lun<CONFIG_SYS_SCSI_MAX_LUN;lun++) {
                        pccb->lun=lun;
                        pccb->pdata=(unsigned char *)&tempbuff;
                        pccb->datalen=512;
                        scsi_setup_inquiry(pccb);
                        if(scsi_exec(pccb)!=TRUE) {
                                if(pccb->contr_stat==SCSI_SEL_TIME_OUT) {
-                                       PRINTF("Selection timeout ID %d\n",pccb->target);
+                                       debug ("Selection timeout ID %d\n",pccb->target);
                                        continue; /* selection timeout => assuming no device present */
                                }
                                scsi_print_error(pccb);
@@ -136,9 +127,12 @@ void scsi_scan(int mode)
                        if((modi&0x80)==0x80) /* drive is removable */
                                scsi_dev_desc[scsi_max_devs].removable=TRUE;
                        /* get info for this device */
-                       scsi_ident_cpy(&scsi_dev_desc[scsi_max_devs].vendor[0],&tempbuff[8],8);
-                       scsi_ident_cpy(&scsi_dev_desc[scsi_max_devs].product[0],&tempbuff[16],16);
-                       scsi_ident_cpy(&scsi_dev_desc[scsi_max_devs].revision[0],&tempbuff[32],4);
+                       scsi_ident_cpy((unsigned char *)&scsi_dev_desc[scsi_max_devs].vendor[0],
+                                      &tempbuff[8], 8);
+                       scsi_ident_cpy((unsigned char *)&scsi_dev_desc[scsi_max_devs].product[0],
+                                      &tempbuff[16], 16);
+                       scsi_ident_cpy((unsigned char *)&scsi_dev_desc[scsi_max_devs].revision[0],
+                                      &tempbuff[32], 4);
                        scsi_dev_desc[scsi_max_devs].target=pccb->target;
                        scsi_dev_desc[scsi_max_devs].lun=pccb->lun;
 
@@ -177,11 +171,10 @@ removable:
        if(scsi_max_devs>0)
                scsi_curr_dev=0;
        else
-               scsi_curr_dev=-1;
+               scsi_curr_dev = -1;
 }
 
-
-
+#ifdef CONFIG_PCI
 void scsi_init(void)
 {
        int busdevfunc;
@@ -199,31 +192,33 @@ void scsi_init(void)
        scsi_low_level_init(busdevfunc);
        scsi_scan(1);
 }
+#endif
 
+#ifdef CONFIG_PARTITIONS
 block_dev_desc_t * scsi_get_dev(int dev)
 {
-       return((block_dev_desc_t *)&scsi_dev_desc[dev]);
+       return (dev < CONFIG_SYS_SCSI_MAX_DEVICE) ? &scsi_dev_desc[dev] : NULL;
 }
-
-
+#endif
 
 /******************************************************************************
  * scsi boot command intepreter. Derived from diskboot
  */
-int do_scsiboot (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+int do_scsiboot (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 {
        char *boot_device = NULL;
        char *ep;
        int dev, part = 0;
-       ulong cnt;
-       ulong addr;
+       ulong addr, cnt;
        disk_partition_t info;
        image_header_t *hdr;
-       int rcode = 0;
+#if defined(CONFIG_FIT)
+       const void *fit_hdr = NULL;
+#endif
 
        switch (argc) {
        case 1:
-               addr = CFG_LOAD_ADDR;
+               addr = CONFIG_SYS_LOAD_ADDR;
                boot_device = getenv ("bootdevice");
                break;
        case 2:
@@ -235,8 +230,7 @@ int do_scsiboot (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
                boot_device = argv[2];
                break;
        default:
-               printf ("Usage:\n%s\n", cmdtp->usage);
-               return 1;
+               return CMD_RET_USAGE;
        }
 
        if (!boot_device) {
@@ -262,8 +256,8 @@ int do_scsiboot (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
                printf("error reading partinfo\n");
                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);
@@ -274,7 +268,7 @@ int do_scsiboot (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 (scsi_read (dev, info.start, 1, (ulong *)addr) != 1) {
@@ -282,51 +276,71 @@ int do_scsiboot (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
                return 1;
        }
 
-       hdr = (image_header_t *)addr;
+       switch (genimg_get_format ((void *)addr)) {
+       case IMAGE_FORMAT_LEGACY:
+               hdr = (image_header_t *)addr;
 
-       if (hdr->ih_magic == IH_MAGIC) {
+               if (!image_check_hcrc (hdr)) {
+                       puts ("\n** Bad Header Checksum **\n");
+                       return 1;
+               }
 
-               print_image_hdr (hdr);
-               cnt = (hdr->ih_size + sizeof(image_header_t));
-               cnt += info.blksz - 1;
-               cnt /= info.blksz;
-               cnt -= 1;
-       } else {
-               printf("\n** Bad Magic Number **\n");
+               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:
+               puts ("** Unknown image type\n");
                return 1;
        }
 
+       cnt += info.blksz - 1;
+       cnt /= info.blksz;
+       cnt -= 1;
+
        if (scsi_read (dev, info.start+1, cnt,
                      (ulong *)(addr+info.blksz)) != cnt) {
                printf ("** Read error on %d:%d\n", dev, part);
                return 1;
        }
+
+#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)) {
+                       puts ("** Bad FIT image format\n");
+                       return 1;
+               }
+               fit_print_contents (fit_hdr);
+       }
+#endif
+
        /* Loading ok, update default load address */
        load_addr = addr;
 
        flush_cache (addr, (cnt+1)*info.blksz);
 
-       /* 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);
-               rcode = do_bootm (cmdtp, 0, 1, local_args);
-       }
-        return rcode;
+       return bootm_maybe_autostart(cmdtp, argv[0]);
 }
 
 /*********************************************************************************
  * scsi command intepreter
  */
-int do_scsi (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+int do_scsi (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 {
        switch (argc) {
-    case 0:
-    case 1:    printf ("Usage:\n%s\n", cmdtp->usage);  return 1;
-    case 2:
+       case 0:
+       case 1:
+               return CMD_RET_USAGE;
+
+       case 2:
                        if (strncmp(argv[1],"res",3) == 0) {
                                printf("\nReset SCSI\n");
                                scsi_bus_reset();
@@ -335,7 +349,7 @@ int do_scsi (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
                        }
                        if (strncmp(argv[1],"inf",3) == 0) {
                                int i;
-                               for (i=0; i<CFG_SCSI_MAX_DEVICE; ++i) {
+                               for (i=0; i<CONFIG_SYS_SCSI_MAX_DEVICE; ++i) {
                                        if(scsi_dev_desc[i].type==DEV_TYPE_UNKNOWN)
                                                continue; /* list only known devices */
                                        printf ("SCSI dev. %d:  ", i);
@@ -344,7 +358,7 @@ int do_scsi (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
                                return 0;
                        }
                        if (strncmp(argv[1],"dev",3) == 0) {
-                               if ((scsi_curr_dev < 0) || (scsi_curr_dev >= CFG_SCSI_MAX_DEVICE)) {
+                               if ((scsi_curr_dev < 0) || (scsi_curr_dev >= CONFIG_SYS_SCSI_MAX_DEVICE)) {
                                        printf("\nno SCSI devices available\n");
                                        return 1;
                                }
@@ -358,12 +372,12 @@ int do_scsi (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
                        }
                        if (strncmp(argv[1],"part",4) == 0) {
                                int dev, ok;
-                               for (ok=0, dev=0; dev<CFG_SCSI_MAX_DEVICE; ++dev) {
+                               for (ok=0, dev=0; dev<CONFIG_SYS_SCSI_MAX_DEVICE; ++dev) {
                                        if (scsi_dev_desc[dev].type!=DEV_TYPE_UNKNOWN) {
                                                ok++;
                                                if (dev)
                                                        printf("\n");
-                                               PRINTF("print_part of %x\n",dev);
+                                               debug ("print_part of %x\n",dev);
                                                        print_part(&scsi_dev_desc[dev]);
                                        }
                                }
@@ -371,13 +385,12 @@ int do_scsi (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
                                        printf("\nno SCSI devices available\n");
                                return 1;
                        }
-                       printf ("Usage:\n%s\n", cmdtp->usage);
-                       return 1;
-       case 3:
+                       return CMD_RET_USAGE;
+       case 3:
                        if (strncmp(argv[1],"dev",3) == 0) {
                                int dev = (int)simple_strtoul(argv[2], NULL, 10);
                                printf ("\nSCSI device %d: ", dev);
-                               if (dev >= CFG_SCSI_MAX_DEVICE) {
+                               if (dev >= CONFIG_SYS_SCSI_MAX_DEVICE) {
                                        printf("unknown device\n");
                                        return 1;
                                }
@@ -400,8 +413,7 @@ int do_scsi (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
                                }
                                return 1;
                        }
-                       printf ("Usage:\n%s\n", cmdtp->usage);
-                       return 1;
+                       return CMD_RET_USAGE;
     default:
                        /* at least 4 args */
                        if (strcmp(argv[1],"read") == 0) {
@@ -416,8 +428,7 @@ int do_scsi (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
                                return 0;
                        }
        } /* switch */
-       printf ("Usage:\n%s\n", cmdtp->usage);
-       return 1;
+       return CMD_RET_USAGE;
 }
 
 /****************************************************************************************
@@ -426,7 +437,7 @@ int do_scsi (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
 
 #define SCSI_MAX_READ_BLK 0xFFFF /* almost the maximum amount of the scsi_ext command.. */
 
-ulong scsi_read(int device, ulong blknr, ulong blkcnt, ulong *buffer)
+ulong scsi_read(int device, ulong blknr, ulong blkcnt, void *buffer)
 {
        ulong start,blks, buf_addr;
        unsigned short smallblks;
@@ -439,7 +450,7 @@ ulong scsi_read(int device, ulong blknr, ulong blkcnt, ulong *buffer)
        buf_addr=(unsigned long)buffer;
        start=blknr;
        blks=blkcnt;
-       PRINTF("\nscsi_read: dev %d startblk %lx, blccnt %lx buffer %lx\n",device,start,blks,(unsigned long)buffer);
+       debug ("\nscsi_read: dev %d startblk %lx, blccnt %lx buffer %lx\n",device,start,blks,(unsigned long)buffer);
        do {
                pccb->pdata=(unsigned char *)buf_addr;
                if(blks>SCSI_MAX_READ_BLK) {
@@ -456,7 +467,7 @@ ulong scsi_read(int device, ulong blknr, ulong blkcnt, ulong *buffer)
                        start+=blks;
                        blks=0;
                }
-               PRINTF("scsi_read_ext: startblk %lx, blccnt %x buffer %lx\n",start,smallblks,buf_addr);
+               debug ("scsi_read_ext: startblk %lx, blccnt %x buffer %lx\n",start,smallblks,buf_addr);
                if(scsi_exec(pccb)!=TRUE) {
                        scsi_print_error(pccb);
                        blkcnt-=blks;
@@ -464,7 +475,7 @@ ulong scsi_read(int device, ulong blknr, ulong blkcnt, ulong *buffer)
                }
                buf_addr+=pccb->datalen;
        } while(blks!=0);
-       PRINTF("scsi_read_ext: end startblk %lx, blccnt %x buffer %lx\n",start,smallblks,buf_addr);
+       debug ("scsi_read_ext: end startblk %lx, blccnt %x buffer %lx\n",start,smallblks,buf_addr);
        return(blkcnt);
 }
 
@@ -494,7 +505,6 @@ void scsi_ident_cpy (unsigned char *dest, unsigned char *src, unsigned int len)
 }
 
 
-
 /* Trim trailing blanks, and NUL-terminate string
  */
 void scsi_trim_trail (unsigned char *str, unsigned int len)
@@ -556,7 +566,7 @@ void scsi_setup_read_ext(ccb * pccb, unsigned long start, unsigned short blocks)
        pccb->cmd[6]=0;
        pccb->cmdlen=10;
        pccb->msgout[0]=SCSI_IDENTIFY; /* NOT USED */
-       PRINTF("scsi_setup_read_ext: cmd: %02X %02X startblk %02X%02X%02X%02X blccnt %02X%02X\n",
+       debug ("scsi_setup_read_ext: cmd: %02X %02X startblk %02X%02X%02X%02X blccnt %02X%02X\n",
                pccb->cmd[0],pccb->cmd[1],
                pccb->cmd[2],pccb->cmd[3],pccb->cmd[4],pccb->cmd[5],
                pccb->cmd[7],pccb->cmd[8]);
@@ -572,7 +582,7 @@ void scsi_setup_read6(ccb * pccb, unsigned long start, unsigned short blocks)
        pccb->cmd[5]=0;
        pccb->cmdlen=6;
        pccb->msgout[0]=SCSI_IDENTIFY; /* NOT USED */
-       PRINTF("scsi_setup_read6: cmd: %02X %02X startblk %02X%02X blccnt %02X\n",
+       debug ("scsi_setup_read6: cmd: %02X %02X startblk %02X%02X blccnt %02X\n",
                pccb->cmd[0],pccb->cmd[1],
                pccb->cmd[2],pccb->cmd[3],pccb->cmd[4]);
 }
@@ -593,6 +603,21 @@ void scsi_setup_inquiry(ccb * pccb)
        pccb->msgout[0]=SCSI_IDENTIFY; /* NOT USED */
 }
 
-#endif /* #if (CONFIG_COMMANDS & CFG_CMD_SCSI) */
-
 
+U_BOOT_CMD(
+       scsi, 5, 1, do_scsi,
+       "SCSI sub-system",
+       "reset - reset SCSI controller\n"
+       "scsi info  - show available SCSI devices\n"
+       "scsi scan  - (re-)scan SCSI bus\n"
+       "scsi device [dev] - show or set current device\n"
+       "scsi part [dev] - print partition table of one or all SCSI devices\n"
+       "scsi read addr blk# cnt - read `cnt' blocks starting at block `blk#'\n"
+       "     to memory address `addr'"
+);
+
+U_BOOT_CMD(
+       scsiboot, 3, 1, do_scsiboot,
+       "boot from SCSI device",
+       "loadAddr dev:part"
+);