From 73a9cfde783421aa7355143bc5b535ae81126d2c Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 1 May 2016 11:35:57 -0600 Subject: dm: scsi: Remove the forward declarations Reorder the code to avoid needing forward declarations. Signed-off-by: Simon Glass --- cmd/scsi.c | 764 ++++++++++++++++++++++++++++++------------------------------- 1 file changed, 371 insertions(+), 393 deletions(-) (limited to 'cmd') diff --git a/cmd/scsi.c b/cmd/scsi.c index 8991125c66..9ba070f8b9 100644 --- a/cmd/scsi.c +++ b/cmd/scsi.c @@ -50,130 +50,230 @@ static int scsi_curr_dev; /* current device */ static struct blk_desc scsi_dev_desc[CONFIG_SYS_SCSI_MAX_DEVICE]; -/******************************************************************************** - * forward declerations of some Setup Routines +/**************************************************************************************** + * scsi_read */ -void scsi_setup_test_unit_ready(ccb * pccb); -void scsi_setup_read6(ccb * pccb, lbaint_t start, unsigned short blocks); -void scsi_setup_read_ext(ccb * pccb, lbaint_t start, unsigned short blocks); -void scsi_setup_read16(ccb * pccb, lbaint_t start, unsigned long blocks); -static void scsi_setup_write_ext(ccb *pccb, lbaint_t start, - unsigned short blocks); -void scsi_setup_inquiry(ccb * pccb); -void scsi_ident_cpy (unsigned char *dest, unsigned char *src, unsigned int len); +/* almost the maximum amount of the scsi_ext command.. */ +#define SCSI_MAX_READ_BLK 0xFFFF +#define SCSI_LBA48_READ 0xFFFFFFF +#ifdef CONFIG_SYS_64BIT_LBA +void scsi_setup_read16(ccb * pccb, lbaint_t start, unsigned long blocks) +{ + pccb->cmd[0] = SCSI_READ16; + pccb->cmd[1] = pccb->lun<<5; + pccb->cmd[2] = ((unsigned char) (start >> 56)) & 0xff; + pccb->cmd[3] = ((unsigned char) (start >> 48)) & 0xff; + pccb->cmd[4] = ((unsigned char) (start >> 40)) & 0xff; + pccb->cmd[5] = ((unsigned char) (start >> 32)) & 0xff; + pccb->cmd[6] = ((unsigned char) (start >> 24)) & 0xff; + pccb->cmd[7] = ((unsigned char) (start >> 16)) & 0xff; + pccb->cmd[8] = ((unsigned char) (start >> 8)) & 0xff; + pccb->cmd[9] = ((unsigned char) (start)) & 0xff; + pccb->cmd[10] = 0; + pccb->cmd[11] = ((unsigned char) (blocks >> 24)) & 0xff; + pccb->cmd[12] = ((unsigned char) (blocks >> 16)) & 0xff; + pccb->cmd[13] = ((unsigned char) (blocks >> 8)) & 0xff; + pccb->cmd[14] = (unsigned char) blocks & 0xff; + pccb->cmd[15] = 0; + pccb->cmdlen = 16; + pccb->msgout[0] = SCSI_IDENTIFY; /* NOT USED */ + debug ("scsi_setup_read16: cmd: %02X %02X " + "startblk %02X%02X%02X%02X%02X%02X%02X%02X " + "blccnt %02X%02X%02X%02X\n", + pccb->cmd[0], pccb->cmd[1], + pccb->cmd[2], pccb->cmd[3], pccb->cmd[4], pccb->cmd[5], + pccb->cmd[6], pccb->cmd[7], pccb->cmd[8], pccb->cmd[9], + pccb->cmd[11], pccb->cmd[12], pccb->cmd[13], pccb->cmd[14]); +} +#endif -static int scsi_read_capacity(ccb *pccb, lbaint_t *capacity, - unsigned long *blksz); -static ulong scsi_read(struct blk_desc *block_dev, lbaint_t blknr, - lbaint_t blkcnt, void *buffer); -static ulong scsi_write(struct blk_desc *block_dev, lbaint_t blknr, - lbaint_t blkcnt, const void *buffer); +void scsi_setup_read_ext(ccb * pccb, lbaint_t start, unsigned short blocks) +{ + pccb->cmd[0]=SCSI_READ10; + pccb->cmd[1]=pccb->lun<<5; + pccb->cmd[2]=((unsigned char) (start>>24))&0xff; + pccb->cmd[3]=((unsigned char) (start>>16))&0xff; + pccb->cmd[4]=((unsigned char) (start>>8))&0xff; + pccb->cmd[5]=((unsigned char) (start))&0xff; + pccb->cmd[6]=0; + pccb->cmd[7]=((unsigned char) (blocks>>8))&0xff; + pccb->cmd[8]=(unsigned char) blocks & 0xff; + pccb->cmd[6]=0; + pccb->cmdlen=10; + pccb->msgout[0]=SCSI_IDENTIFY; /* NOT USED */ + 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]); +} +void scsi_setup_write_ext(ccb *pccb, lbaint_t start, unsigned short blocks) +{ + pccb->cmd[0] = SCSI_WRITE10; + pccb->cmd[1] = pccb->lun << 5; + pccb->cmd[2] = ((unsigned char) (start>>24)) & 0xff; + pccb->cmd[3] = ((unsigned char) (start>>16)) & 0xff; + pccb->cmd[4] = ((unsigned char) (start>>8)) & 0xff; + pccb->cmd[5] = ((unsigned char) (start)) & 0xff; + pccb->cmd[6] = 0; + pccb->cmd[7] = ((unsigned char) (blocks>>8)) & 0xff; + pccb->cmd[8] = (unsigned char)blocks & 0xff; + pccb->cmd[9] = 0; + pccb->cmdlen = 10; + pccb->msgout[0] = SCSI_IDENTIFY; /* NOT USED */ + debug("%s: cmd: %02X %02X startblk %02X%02X%02X%02X blccnt %02X%02X\n", + __func__, + pccb->cmd[0], pccb->cmd[1], + pccb->cmd[2], pccb->cmd[3], pccb->cmd[4], pccb->cmd[5], + pccb->cmd[7], pccb->cmd[8]); +} -/********************************************************************************* - * (re)-scan the scsi bus and reports scsi device info - * to the user if mode = 1 - */ -void scsi_scan(int mode) +void scsi_setup_read6(ccb * pccb, lbaint_t start, unsigned short blocks) { - unsigned char i,perq,modi,lun; - lbaint_t capacity; - unsigned long blksz; - ccb* pccb=(ccb *)&tempccb; + pccb->cmd[0]=SCSI_READ6; + pccb->cmd[1]=pccb->lun<<5 | (((unsigned char)(start>>16))&0x1f); + pccb->cmd[2]=((unsigned char) (start>>8))&0xff; + pccb->cmd[3]=((unsigned char) (start))&0xff; + pccb->cmd[4]=(unsigned char) blocks & 0xff; + pccb->cmd[5]=0; + pccb->cmdlen=6; + pccb->msgout[0]=SCSI_IDENTIFY; /* NOT USED */ + 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]); +} - if(mode==1) { - printf("scanning bus for devices...\n"); - } - for(i=0;itarget=i; - for(lun=0;lunlun=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) { - debug ("Selection timeout ID %d\n",pccb->target); - continue; /* selection timeout => assuming no device present */ - } - scsi_print_error(pccb); - continue; - } - perq=tempbuff[0]; - modi=tempbuff[1]; - if((perq & 0x1f)==0x1f) { - continue; /* skip unknown devices */ - } - if((modi&0x80)==0x80) /* drive is removable */ - scsi_dev_desc[scsi_max_devs].removable=true; - /* get info for this device */ - 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; - pccb->datalen=0; - scsi_setup_test_unit_ready(pccb); - if (scsi_exec(pccb) != true) { - if (scsi_dev_desc[scsi_max_devs].removable == true) { - scsi_dev_desc[scsi_max_devs].type=perq; - goto removable; - } - scsi_print_error(pccb); - continue; - } - if (scsi_read_capacity(pccb, &capacity, &blksz)) { - scsi_print_error(pccb); - continue; - } - scsi_dev_desc[scsi_max_devs].lba=capacity; - scsi_dev_desc[scsi_max_devs].blksz=blksz; - scsi_dev_desc[scsi_max_devs].log2blksz = - LOG2(scsi_dev_desc[scsi_max_devs].blksz); - scsi_dev_desc[scsi_max_devs].type=perq; - part_init(&scsi_dev_desc[scsi_max_devs]); -removable: - if(mode==1) { - printf (" Device %d: ", scsi_max_devs); - dev_print(&scsi_dev_desc[scsi_max_devs]); - } /* if mode */ - scsi_max_devs++; - } /* next LUN */ - } - if(scsi_max_devs>0) - scsi_curr_dev=0; +void scsi_setup_inquiry(ccb * pccb) +{ + pccb->cmd[0]=SCSI_INQUIRY; + pccb->cmd[1]=pccb->lun<<5; + pccb->cmd[2]=0; + pccb->cmd[3]=0; + if(pccb->datalen>255) + pccb->cmd[4]=255; else - scsi_curr_dev = -1; + pccb->cmd[4]=(unsigned char)pccb->datalen; + pccb->cmd[5]=0; + pccb->cmdlen=6; + pccb->msgout[0]=SCSI_IDENTIFY; /* NOT USED */ +} - printf("Found %d device(s).\n", scsi_max_devs); -#ifndef CONFIG_SPL_BUILD - setenv_ulong("scsidevs", scsi_max_devs); +static ulong scsi_read(struct blk_desc *block_dev, lbaint_t blknr, + lbaint_t blkcnt, void *buffer) +{ + int device = block_dev->devnum; + lbaint_t start, blks; + uintptr_t buf_addr; + unsigned short smallblks = 0; + ccb* pccb=(ccb *)&tempccb; + device&=0xff; + /* Setup device + */ + pccb->target=scsi_dev_desc[device].target; + pccb->lun=scsi_dev_desc[device].lun; + buf_addr=(unsigned long)buffer; + start=blknr; + blks=blkcnt; + debug("\nscsi_read: dev %d startblk " LBAF + ", blccnt " LBAF " buffer %lx\n", + device, start, blks, (unsigned long)buffer); + do { + pccb->pdata=(unsigned char *)buf_addr; +#ifdef CONFIG_SYS_64BIT_LBA + if (start > SCSI_LBA48_READ) { + unsigned long blocks; + blocks = min_t(lbaint_t, blks, SCSI_MAX_READ_BLK); + pccb->datalen = scsi_dev_desc[device].blksz * blocks; + scsi_setup_read16(pccb, start, blocks); + start += blocks; + blks -= blocks; + } else #endif + if (blks > SCSI_MAX_READ_BLK) { + pccb->datalen=scsi_dev_desc[device].blksz * SCSI_MAX_READ_BLK; + smallblks=SCSI_MAX_READ_BLK; + scsi_setup_read_ext(pccb,start,smallblks); + start+=SCSI_MAX_READ_BLK; + blks-=SCSI_MAX_READ_BLK; + } + else { + pccb->datalen=scsi_dev_desc[device].blksz * blks; + smallblks=(unsigned short) blks; + scsi_setup_read_ext(pccb,start,smallblks); + start+=blks; + blks=0; + } + debug("scsi_read_ext: startblk " LBAF + ", blccnt %x buffer %" PRIXPTR "\n", + start, smallblks, buf_addr); + if (scsi_exec(pccb) != true) { + scsi_print_error(pccb); + blkcnt-=blks; + break; + } + buf_addr+=pccb->datalen; + } while(blks!=0); + debug("scsi_read_ext: end startblk " LBAF + ", blccnt %x buffer %" PRIXPTR "\n", start, smallblks, buf_addr); + return(blkcnt); +} + +/******************************************************************************* + * scsi_write + */ + +/* Almost the maximum amount of the scsi_ext command.. */ +#define SCSI_MAX_WRITE_BLK 0xFFFF + +static ulong scsi_write(struct blk_desc *block_dev, lbaint_t blknr, + lbaint_t blkcnt, const void *buffer) +{ + int device = block_dev->devnum; + lbaint_t start, blks; + uintptr_t buf_addr; + unsigned short smallblks; + ccb* pccb = (ccb *)&tempccb; + device &= 0xff; + /* Setup device + */ + pccb->target = scsi_dev_desc[device].target; + pccb->lun = scsi_dev_desc[device].lun; + buf_addr = (unsigned long)buffer; + start = blknr; + blks = blkcnt; + debug("\n%s: dev %d startblk " LBAF ", blccnt " LBAF " buffer %lx\n", + __func__, device, start, blks, (unsigned long)buffer); + do { + pccb->pdata = (unsigned char *)buf_addr; + if (blks > SCSI_MAX_WRITE_BLK) { + pccb->datalen = (scsi_dev_desc[device].blksz * + SCSI_MAX_WRITE_BLK); + smallblks = SCSI_MAX_WRITE_BLK; + scsi_setup_write_ext(pccb, start, smallblks); + start += SCSI_MAX_WRITE_BLK; + blks -= SCSI_MAX_WRITE_BLK; + } else { + pccb->datalen = scsi_dev_desc[device].blksz * blks; + smallblks = (unsigned short)blks; + scsi_setup_write_ext(pccb, start, smallblks); + start += blks; + blks = 0; + } + debug("%s: startblk " LBAF ", blccnt %x buffer %" PRIXPTR "\n", + __func__, start, smallblks, buf_addr); + if (scsi_exec(pccb) != true) { + scsi_print_error(pccb); + blkcnt -= blks; + break; + } + buf_addr += pccb->datalen; + } while (blks != 0); + debug("%s: end startblk " LBAF ", blccnt %x buffer %" PRIXPTR "\n", + __func__, start, smallblks, buf_addr); + return blkcnt; } int scsi_get_disk_count(void) @@ -327,192 +427,69 @@ int do_scsi (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) printf("... is now current device\n"); return 0; } - if (strncmp(argv[1],"part",4) == 0) { - int dev = (int)simple_strtoul(argv[2], NULL, 10); - if(scsi_dev_desc[dev].type != DEV_TYPE_UNKNOWN) { - part_print(&scsi_dev_desc[dev]); - } - else { - printf ("\nSCSI device %d not available\n", dev); - } - return 1; - } - return CMD_RET_USAGE; - 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 ("\nSCSI read: device %d block # %ld, count %ld ... ", - scsi_curr_dev, blk, cnt); - n = scsi_read(&scsi_dev_desc[scsi_curr_dev], - blk, cnt, (ulong *)addr); - printf ("%ld blocks read: %s\n",n,(n==cnt) ? "OK" : "ERROR"); - return 0; - } 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("\nSCSI write: device %d block # %ld, " - "count %ld ... ", - scsi_curr_dev, blk, cnt); - n = scsi_write(&scsi_dev_desc[scsi_curr_dev], - blk, cnt, (ulong *)addr); - printf("%ld blocks written: %s\n", n, - (n == cnt) ? "OK" : "ERROR"); - return 0; - } - } /* switch */ - return CMD_RET_USAGE; -} - -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'\n" - "scsi write addr blk# cnt - write `cnt' blocks starting at block\n" - " `blk#' from memory address `addr'" -); - -U_BOOT_CMD( - scsiboot, 3, 1, do_scsiboot, - "boot from SCSI device", - "loadAddr dev:part" -); -#endif - -/**************************************************************************************** - * scsi_read - */ - -/* almost the maximum amount of the scsi_ext command.. */ -#define SCSI_MAX_READ_BLK 0xFFFF -#define SCSI_LBA48_READ 0xFFFFFFF - -static ulong scsi_read(struct blk_desc *block_dev, lbaint_t blknr, - lbaint_t blkcnt, void *buffer) -{ - int device = block_dev->devnum; - lbaint_t start, blks; - uintptr_t buf_addr; - unsigned short smallblks = 0; - ccb* pccb=(ccb *)&tempccb; - device&=0xff; - /* Setup device - */ - pccb->target=scsi_dev_desc[device].target; - pccb->lun=scsi_dev_desc[device].lun; - buf_addr=(unsigned long)buffer; - start=blknr; - blks=blkcnt; - debug("\nscsi_read: dev %d startblk " LBAF - ", blccnt " LBAF " buffer %lx\n", - device, start, blks, (unsigned long)buffer); - do { - pccb->pdata=(unsigned char *)buf_addr; -#ifdef CONFIG_SYS_64BIT_LBA - if (start > SCSI_LBA48_READ) { - unsigned long blocks; - blocks = min_t(lbaint_t, blks, SCSI_MAX_READ_BLK); - pccb->datalen = scsi_dev_desc[device].blksz * blocks; - scsi_setup_read16(pccb, start, blocks); - start += blocks; - blks -= blocks; - } else -#endif - if (blks > SCSI_MAX_READ_BLK) { - pccb->datalen=scsi_dev_desc[device].blksz * SCSI_MAX_READ_BLK; - smallblks=SCSI_MAX_READ_BLK; - scsi_setup_read_ext(pccb,start,smallblks); - start+=SCSI_MAX_READ_BLK; - blks-=SCSI_MAX_READ_BLK; - } - else { - pccb->datalen=scsi_dev_desc[device].blksz * blks; - smallblks=(unsigned short) blks; - scsi_setup_read_ext(pccb,start,smallblks); - start+=blks; - blks=0; - } - debug("scsi_read_ext: startblk " LBAF - ", blccnt %x buffer %" PRIXPTR "\n", - start, smallblks, buf_addr); - if (scsi_exec(pccb) != true) { - scsi_print_error(pccb); - blkcnt-=blks; - break; - } - buf_addr+=pccb->datalen; - } while(blks!=0); - debug("scsi_read_ext: end startblk " LBAF - ", blccnt %x buffer %" PRIXPTR "\n", start, smallblks, buf_addr); - return(blkcnt); -} - -/******************************************************************************* - * scsi_write - */ - -/* Almost the maximum amount of the scsi_ext command.. */ -#define SCSI_MAX_WRITE_BLK 0xFFFF - -static ulong scsi_write(struct blk_desc *block_dev, lbaint_t blknr, - lbaint_t blkcnt, const void *buffer) -{ - int device = block_dev->devnum; - lbaint_t start, blks; - uintptr_t buf_addr; - unsigned short smallblks; - ccb* pccb = (ccb *)&tempccb; - device &= 0xff; - /* Setup device - */ - pccb->target = scsi_dev_desc[device].target; - pccb->lun = scsi_dev_desc[device].lun; - buf_addr = (unsigned long)buffer; - start = blknr; - blks = blkcnt; - debug("\n%s: dev %d startblk " LBAF ", blccnt " LBAF " buffer %lx\n", - __func__, device, start, blks, (unsigned long)buffer); - do { - pccb->pdata = (unsigned char *)buf_addr; - if (blks > SCSI_MAX_WRITE_BLK) { - pccb->datalen = (scsi_dev_desc[device].blksz * - SCSI_MAX_WRITE_BLK); - smallblks = SCSI_MAX_WRITE_BLK; - scsi_setup_write_ext(pccb, start, smallblks); - start += SCSI_MAX_WRITE_BLK; - blks -= SCSI_MAX_WRITE_BLK; - } else { - pccb->datalen = scsi_dev_desc[device].blksz * blks; - smallblks = (unsigned short)blks; - scsi_setup_write_ext(pccb, start, smallblks); - start += blks; - blks = 0; - } - debug("%s: startblk " LBAF ", blccnt %x buffer %" PRIXPTR "\n", - __func__, start, smallblks, buf_addr); - if (scsi_exec(pccb) != true) { - scsi_print_error(pccb); - blkcnt -= blks; - break; - } - buf_addr += pccb->datalen; - } while (blks != 0); - debug("%s: end startblk " LBAF ", blccnt %x buffer %" PRIXPTR "\n", - __func__, start, smallblks, buf_addr); - return blkcnt; + if (strncmp(argv[1],"part",4) == 0) { + int dev = (int)simple_strtoul(argv[2], NULL, 10); + if(scsi_dev_desc[dev].type != DEV_TYPE_UNKNOWN) { + part_print(&scsi_dev_desc[dev]); + } + else { + printf ("\nSCSI device %d not available\n", dev); + } + return 1; + } + return CMD_RET_USAGE; + 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 ("\nSCSI read: device %d block # %ld, count %ld ... ", + scsi_curr_dev, blk, cnt); + n = scsi_read(&scsi_dev_desc[scsi_curr_dev], + blk, cnt, (ulong *)addr); + printf ("%ld blocks read: %s\n",n,(n==cnt) ? "OK" : "ERROR"); + return 0; + } 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("\nSCSI write: device %d block # %ld, " + "count %ld ... ", + scsi_curr_dev, blk, cnt); + n = scsi_write(&scsi_dev_desc[scsi_curr_dev], + blk, cnt, (ulong *)addr); + printf("%ld blocks written: %s\n", n, + (n == cnt) ? "OK" : "ERROR"); + return 0; + } + } /* switch */ + return CMD_RET_USAGE; } +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'\n" + "scsi write addr blk# cnt - write `cnt' blocks starting at block\n" + " `blk#' from memory address `addr'" +); + +U_BOOT_CMD( + scsiboot, 3, 1, do_scsiboot, + "boot from SCSI device", + "loadAddr dev:part" +); +#endif + /* copy src to dest, skipping leading and trailing blanks * and null terminate the string */ @@ -630,105 +607,106 @@ void scsi_setup_test_unit_ready(ccb * pccb) pccb->msgout[0]=SCSI_IDENTIFY; /* NOT USED */ } -#ifdef CONFIG_SYS_64BIT_LBA -void scsi_setup_read16(ccb * pccb, lbaint_t start, unsigned long blocks) -{ - pccb->cmd[0] = SCSI_READ16; - pccb->cmd[1] = pccb->lun<<5; - pccb->cmd[2] = ((unsigned char) (start >> 56)) & 0xff; - pccb->cmd[3] = ((unsigned char) (start >> 48)) & 0xff; - pccb->cmd[4] = ((unsigned char) (start >> 40)) & 0xff; - pccb->cmd[5] = ((unsigned char) (start >> 32)) & 0xff; - pccb->cmd[6] = ((unsigned char) (start >> 24)) & 0xff; - pccb->cmd[7] = ((unsigned char) (start >> 16)) & 0xff; - pccb->cmd[8] = ((unsigned char) (start >> 8)) & 0xff; - pccb->cmd[9] = ((unsigned char) (start)) & 0xff; - pccb->cmd[10] = 0; - pccb->cmd[11] = ((unsigned char) (blocks >> 24)) & 0xff; - pccb->cmd[12] = ((unsigned char) (blocks >> 16)) & 0xff; - pccb->cmd[13] = ((unsigned char) (blocks >> 8)) & 0xff; - pccb->cmd[14] = (unsigned char) blocks & 0xff; - pccb->cmd[15] = 0; - pccb->cmdlen = 16; - pccb->msgout[0] = SCSI_IDENTIFY; /* NOT USED */ - debug ("scsi_setup_read16: cmd: %02X %02X " - "startblk %02X%02X%02X%02X%02X%02X%02X%02X " - "blccnt %02X%02X%02X%02X\n", - pccb->cmd[0], pccb->cmd[1], - pccb->cmd[2], pccb->cmd[3], pccb->cmd[4], pccb->cmd[5], - pccb->cmd[6], pccb->cmd[7], pccb->cmd[8], pccb->cmd[9], - pccb->cmd[11], pccb->cmd[12], pccb->cmd[13], pccb->cmd[14]); -} -#endif - -void scsi_setup_read_ext(ccb * pccb, lbaint_t start, unsigned short blocks) -{ - pccb->cmd[0]=SCSI_READ10; - pccb->cmd[1]=pccb->lun<<5; - pccb->cmd[2]=((unsigned char) (start>>24))&0xff; - pccb->cmd[3]=((unsigned char) (start>>16))&0xff; - pccb->cmd[4]=((unsigned char) (start>>8))&0xff; - pccb->cmd[5]=((unsigned char) (start))&0xff; - pccb->cmd[6]=0; - pccb->cmd[7]=((unsigned char) (blocks>>8))&0xff; - pccb->cmd[8]=(unsigned char) blocks & 0xff; - pccb->cmd[6]=0; - pccb->cmdlen=10; - pccb->msgout[0]=SCSI_IDENTIFY; /* NOT USED */ - 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]); -} - -void scsi_setup_write_ext(ccb *pccb, lbaint_t start, unsigned short blocks) -{ - pccb->cmd[0] = SCSI_WRITE10; - pccb->cmd[1] = pccb->lun << 5; - pccb->cmd[2] = ((unsigned char) (start>>24)) & 0xff; - pccb->cmd[3] = ((unsigned char) (start>>16)) & 0xff; - pccb->cmd[4] = ((unsigned char) (start>>8)) & 0xff; - pccb->cmd[5] = ((unsigned char) (start)) & 0xff; - pccb->cmd[6] = 0; - pccb->cmd[7] = ((unsigned char) (blocks>>8)) & 0xff; - pccb->cmd[8] = (unsigned char)blocks & 0xff; - pccb->cmd[9] = 0; - pccb->cmdlen = 10; - pccb->msgout[0] = SCSI_IDENTIFY; /* NOT USED */ - debug("%s: cmd: %02X %02X startblk %02X%02X%02X%02X blccnt %02X%02X\n", - __func__, - pccb->cmd[0], pccb->cmd[1], - pccb->cmd[2], pccb->cmd[3], pccb->cmd[4], pccb->cmd[5], - pccb->cmd[7], pccb->cmd[8]); -} - -void scsi_setup_read6(ccb * pccb, lbaint_t start, unsigned short blocks) +/********************************************************************************* + * (re)-scan the scsi bus and reports scsi device info + * to the user if mode = 1 + */ +void scsi_scan(int mode) { - pccb->cmd[0]=SCSI_READ6; - pccb->cmd[1]=pccb->lun<<5 | (((unsigned char)(start>>16))&0x1f); - pccb->cmd[2]=((unsigned char) (start>>8))&0xff; - pccb->cmd[3]=((unsigned char) (start))&0xff; - pccb->cmd[4]=(unsigned char) blocks & 0xff; - pccb->cmd[5]=0; - pccb->cmdlen=6; - pccb->msgout[0]=SCSI_IDENTIFY; /* NOT USED */ - 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]); -} + unsigned char i,perq,modi,lun; + lbaint_t capacity; + unsigned long blksz; + ccb* pccb=(ccb *)&tempccb; + if(mode==1) { + printf("scanning bus for devices...\n"); + } + for(i=0;itarget=i; + for(lun=0;lunlun=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) { + debug ("Selection timeout ID %d\n",pccb->target); + continue; /* selection timeout => assuming no device present */ + } + scsi_print_error(pccb); + continue; + } + perq=tempbuff[0]; + modi=tempbuff[1]; + if((perq & 0x1f)==0x1f) { + continue; /* skip unknown devices */ + } + if((modi&0x80)==0x80) /* drive is removable */ + scsi_dev_desc[scsi_max_devs].removable=true; + /* get info for this device */ + 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; -void scsi_setup_inquiry(ccb * pccb) -{ - pccb->cmd[0]=SCSI_INQUIRY; - pccb->cmd[1]=pccb->lun<<5; - pccb->cmd[2]=0; - pccb->cmd[3]=0; - if(pccb->datalen>255) - pccb->cmd[4]=255; + pccb->datalen=0; + scsi_setup_test_unit_ready(pccb); + if (scsi_exec(pccb) != true) { + if (scsi_dev_desc[scsi_max_devs].removable == true) { + scsi_dev_desc[scsi_max_devs].type=perq; + goto removable; + } + scsi_print_error(pccb); + continue; + } + if (scsi_read_capacity(pccb, &capacity, &blksz)) { + scsi_print_error(pccb); + continue; + } + scsi_dev_desc[scsi_max_devs].lba=capacity; + scsi_dev_desc[scsi_max_devs].blksz=blksz; + scsi_dev_desc[scsi_max_devs].log2blksz = + LOG2(scsi_dev_desc[scsi_max_devs].blksz); + scsi_dev_desc[scsi_max_devs].type=perq; + part_init(&scsi_dev_desc[scsi_max_devs]); +removable: + if(mode==1) { + printf (" Device %d: ", scsi_max_devs); + dev_print(&scsi_dev_desc[scsi_max_devs]); + } /* if mode */ + scsi_max_devs++; + } /* next LUN */ + } + if(scsi_max_devs>0) + scsi_curr_dev=0; else - pccb->cmd[4]=(unsigned char)pccb->datalen; - pccb->cmd[5]=0; - pccb->cmdlen=6; - pccb->msgout[0]=SCSI_IDENTIFY; /* NOT USED */ + scsi_curr_dev = -1; + + printf("Found %d device(s).\n", scsi_max_devs); +#ifndef CONFIG_SPL_BUILD + setenv_ulong("scsidevs", scsi_max_devs); +#endif } -- cgit v1.2.1 From f1d4d9379e1f83118307012a3edcc4ea20e12d92 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 1 May 2016 11:35:58 -0600 Subject: dm: scsi: Fix up code style Update the code style of this file so that it passes checkpatch.pl. Signed-off-by: Simon Glass --- cmd/scsi.c | 459 ++++++++++++++++++++++++++++++------------------------------- 1 file changed, 226 insertions(+), 233 deletions(-) (limited to 'cmd') diff --git a/cmd/scsi.c b/cmd/scsi.c index 9ba070f8b9..751fc5818a 100644 --- a/cmd/scsi.c +++ b/cmd/scsi.c @@ -50,59 +50,53 @@ static int scsi_curr_dev; /* current device */ static struct blk_desc scsi_dev_desc[CONFIG_SYS_SCSI_MAX_DEVICE]; -/**************************************************************************************** - * scsi_read - */ - /* almost the maximum amount of the scsi_ext command.. */ #define SCSI_MAX_READ_BLK 0xFFFF #define SCSI_LBA48_READ 0xFFFFFFF #ifdef CONFIG_SYS_64BIT_LBA -void scsi_setup_read16(ccb * pccb, lbaint_t start, unsigned long blocks) +void scsi_setup_read16(ccb *pccb, lbaint_t start, unsigned long blocks) { pccb->cmd[0] = SCSI_READ16; - pccb->cmd[1] = pccb->lun<<5; - pccb->cmd[2] = ((unsigned char) (start >> 56)) & 0xff; - pccb->cmd[3] = ((unsigned char) (start >> 48)) & 0xff; - pccb->cmd[4] = ((unsigned char) (start >> 40)) & 0xff; - pccb->cmd[5] = ((unsigned char) (start >> 32)) & 0xff; - pccb->cmd[6] = ((unsigned char) (start >> 24)) & 0xff; - pccb->cmd[7] = ((unsigned char) (start >> 16)) & 0xff; - pccb->cmd[8] = ((unsigned char) (start >> 8)) & 0xff; - pccb->cmd[9] = ((unsigned char) (start)) & 0xff; + pccb->cmd[1] = pccb->lun << 5; + pccb->cmd[2] = (unsigned char)(start >> 56) & 0xff; + pccb->cmd[3] = (unsigned char)(start >> 48) & 0xff; + pccb->cmd[4] = (unsigned char)(start >> 40) & 0xff; + pccb->cmd[5] = (unsigned char)(start >> 32) & 0xff; + pccb->cmd[6] = (unsigned char)(start >> 24) & 0xff; + pccb->cmd[7] = (unsigned char)(start >> 16) & 0xff; + pccb->cmd[8] = (unsigned char)(start >> 8) & 0xff; + pccb->cmd[9] = (unsigned char)start & 0xff; pccb->cmd[10] = 0; - pccb->cmd[11] = ((unsigned char) (blocks >> 24)) & 0xff; - pccb->cmd[12] = ((unsigned char) (blocks >> 16)) & 0xff; - pccb->cmd[13] = ((unsigned char) (blocks >> 8)) & 0xff; - pccb->cmd[14] = (unsigned char) blocks & 0xff; + pccb->cmd[11] = (unsigned char)(blocks >> 24) & 0xff; + pccb->cmd[12] = (unsigned char)(blocks >> 16) & 0xff; + pccb->cmd[13] = (unsigned char)(blocks >> 8) & 0xff; + pccb->cmd[14] = (unsigned char)blocks & 0xff; pccb->cmd[15] = 0; pccb->cmdlen = 16; pccb->msgout[0] = SCSI_IDENTIFY; /* NOT USED */ - debug ("scsi_setup_read16: cmd: %02X %02X " - "startblk %02X%02X%02X%02X%02X%02X%02X%02X " - "blccnt %02X%02X%02X%02X\n", - pccb->cmd[0], pccb->cmd[1], - pccb->cmd[2], pccb->cmd[3], pccb->cmd[4], pccb->cmd[5], - pccb->cmd[6], pccb->cmd[7], pccb->cmd[8], pccb->cmd[9], - pccb->cmd[11], pccb->cmd[12], pccb->cmd[13], pccb->cmd[14]); + debug("scsi_setup_read16: cmd: %02X %02X startblk %02X%02X%02X%02X%02X%02X%02X%02X blccnt %02X%02X%02X%02X\n", + pccb->cmd[0], pccb->cmd[1], + pccb->cmd[2], pccb->cmd[3], pccb->cmd[4], pccb->cmd[5], + pccb->cmd[6], pccb->cmd[7], pccb->cmd[8], pccb->cmd[9], + pccb->cmd[11], pccb->cmd[12], pccb->cmd[13], pccb->cmd[14]); } #endif void scsi_setup_read_ext(ccb * pccb, lbaint_t start, unsigned short blocks) { - pccb->cmd[0]=SCSI_READ10; - pccb->cmd[1]=pccb->lun<<5; - pccb->cmd[2]=((unsigned char) (start>>24))&0xff; - pccb->cmd[3]=((unsigned char) (start>>16))&0xff; - pccb->cmd[4]=((unsigned char) (start>>8))&0xff; - pccb->cmd[5]=((unsigned char) (start))&0xff; - pccb->cmd[6]=0; - pccb->cmd[7]=((unsigned char) (blocks>>8))&0xff; - pccb->cmd[8]=(unsigned char) blocks & 0xff; - pccb->cmd[6]=0; + pccb->cmd[0] = SCSI_READ10; + pccb->cmd[1] = pccb->lun << 5; + pccb->cmd[2] = (unsigned char)(start >> 24) & 0xff; + pccb->cmd[3] = (unsigned char)(start >> 16) & 0xff; + pccb->cmd[4] = (unsigned char)(start >> 8) & 0xff; + pccb->cmd[5] = (unsigned char)start & 0xff; + pccb->cmd[6] = 0; + pccb->cmd[7] = (unsigned char)(blocks >> 8) & 0xff; + pccb->cmd[8] = (unsigned char)blocks & 0xff; + pccb->cmd[6] = 0; pccb->cmdlen=10; - pccb->msgout[0]=SCSI_IDENTIFY; /* NOT USED */ + pccb->msgout[0] = SCSI_IDENTIFY; /* NOT USED */ 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], @@ -113,12 +107,12 @@ void scsi_setup_write_ext(ccb *pccb, lbaint_t start, unsigned short blocks) { pccb->cmd[0] = SCSI_WRITE10; pccb->cmd[1] = pccb->lun << 5; - pccb->cmd[2] = ((unsigned char) (start>>24)) & 0xff; - pccb->cmd[3] = ((unsigned char) (start>>16)) & 0xff; - pccb->cmd[4] = ((unsigned char) (start>>8)) & 0xff; - pccb->cmd[5] = ((unsigned char) (start)) & 0xff; + pccb->cmd[2] = (unsigned char)(start >> 24) & 0xff; + pccb->cmd[3] = (unsigned char)(start >> 16) & 0xff; + pccb->cmd[4] = (unsigned char)(start >> 8) & 0xff; + pccb->cmd[5] = (unsigned char)start & 0xff; pccb->cmd[6] = 0; - pccb->cmd[7] = ((unsigned char) (blocks>>8)) & 0xff; + pccb->cmd[7] = ((unsigned char)(blocks >> 8)) & 0xff; pccb->cmd[8] = (unsigned char)blocks & 0xff; pccb->cmd[9] = 0; pccb->cmdlen = 10; @@ -132,33 +126,33 @@ void scsi_setup_write_ext(ccb *pccb, lbaint_t start, unsigned short blocks) void scsi_setup_read6(ccb * pccb, lbaint_t start, unsigned short blocks) { - pccb->cmd[0]=SCSI_READ6; - pccb->cmd[1]=pccb->lun<<5 | (((unsigned char)(start>>16))&0x1f); - pccb->cmd[2]=((unsigned char) (start>>8))&0xff; - pccb->cmd[3]=((unsigned char) (start))&0xff; - pccb->cmd[4]=(unsigned char) blocks & 0xff; - pccb->cmd[5]=0; + pccb->cmd[0] = SCSI_READ6; + pccb->cmd[1] = pccb->lun << 5 | ((unsigned char)(start >> 16) & 0x1f); + pccb->cmd[2] = (unsigned char)(start >> 8) & 0xff; + pccb->cmd[3] = (unsigned char)start & 0xff; + pccb->cmd[4] = (unsigned char)blocks & 0xff; + pccb->cmd[5] = 0; pccb->cmdlen=6; - pccb->msgout[0]=SCSI_IDENTIFY; /* NOT USED */ - 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]); + pccb->msgout[0] = SCSI_IDENTIFY; /* NOT USED */ + 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]); } void scsi_setup_inquiry(ccb * pccb) { - pccb->cmd[0]=SCSI_INQUIRY; - pccb->cmd[1]=pccb->lun<<5; - pccb->cmd[2]=0; - pccb->cmd[3]=0; - if(pccb->datalen>255) - pccb->cmd[4]=255; + pccb->cmd[0] = SCSI_INQUIRY; + pccb->cmd[1] = pccb->lun << 5; + pccb->cmd[2] = 0; + pccb->cmd[3] = 0; + if (pccb->datalen > 255) + pccb->cmd[4] = 255; else - pccb->cmd[4]=(unsigned char)pccb->datalen; - pccb->cmd[5]=0; + pccb->cmd[4] = (unsigned char)pccb->datalen; + pccb->cmd[5] = 0; pccb->cmdlen=6; - pccb->msgout[0]=SCSI_IDENTIFY; /* NOT USED */ + pccb->msgout[0] = SCSI_IDENTIFY; /* NOT USED */ } static ulong scsi_read(struct blk_desc *block_dev, lbaint_t blknr, @@ -170,18 +164,18 @@ static ulong scsi_read(struct blk_desc *block_dev, lbaint_t blknr, unsigned short smallblks = 0; ccb* pccb=(ccb *)&tempccb; device&=0xff; - /* Setup device - */ - pccb->target=scsi_dev_desc[device].target; - pccb->lun=scsi_dev_desc[device].lun; - buf_addr=(unsigned long)buffer; - start=blknr; - blks=blkcnt; + + /* Setup device */ + pccb->target = scsi_dev_desc[device].target; + pccb->lun = scsi_dev_desc[device].lun; + buf_addr = (unsigned long)buffer; + start = blknr; + blks = blkcnt; debug("\nscsi_read: dev %d startblk " LBAF ", blccnt " LBAF " buffer %lx\n", device, start, blks, (unsigned long)buffer); do { - pccb->pdata=(unsigned char *)buf_addr; + pccb->pdata = (unsigned char *)buf_addr; #ifdef CONFIG_SYS_64BIT_LBA if (start > SCSI_LBA48_READ) { unsigned long blocks; @@ -193,17 +187,18 @@ static ulong scsi_read(struct blk_desc *block_dev, lbaint_t blknr, } else #endif if (blks > SCSI_MAX_READ_BLK) { - pccb->datalen=scsi_dev_desc[device].blksz * SCSI_MAX_READ_BLK; - smallblks=SCSI_MAX_READ_BLK; - scsi_setup_read_ext(pccb,start,smallblks); - start+=SCSI_MAX_READ_BLK; - blks-=SCSI_MAX_READ_BLK; + pccb->datalen = scsi_dev_desc[device].blksz * + SCSI_MAX_READ_BLK; + smallblks = SCSI_MAX_READ_BLK; + scsi_setup_read_ext(pccb, start, smallblks); + start += SCSI_MAX_READ_BLK; + blks -= SCSI_MAX_READ_BLK; } else { - pccb->datalen=scsi_dev_desc[device].blksz * blks; - smallblks=(unsigned short) blks; - scsi_setup_read_ext(pccb,start,smallblks); - start+=blks; + pccb->datalen = scsi_dev_desc[device].blksz * blks; + smallblks = (unsigned short)blks; + scsi_setup_read_ext(pccb, start, smallblks); + start += blks; blks=0; } debug("scsi_read_ext: startblk " LBAF @@ -211,14 +206,14 @@ static ulong scsi_read(struct blk_desc *block_dev, lbaint_t blknr, start, smallblks, buf_addr); if (scsi_exec(pccb) != true) { scsi_print_error(pccb); - blkcnt-=blks; + blkcnt -= blks; break; } buf_addr+=pccb->datalen; - } while(blks!=0); + } while (blks != 0); debug("scsi_read_ext: end startblk " LBAF ", blccnt %x buffer %" PRIXPTR "\n", start, smallblks, buf_addr); - return(blkcnt); + return blkcnt; } /******************************************************************************* @@ -365,106 +360,106 @@ int do_scsi (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) return CMD_RET_USAGE; case 2: - if (strncmp(argv[1],"res",3) == 0) { - printf("\nReset SCSI\n"); - scsi_bus_reset(); - scsi_scan(1); - return 0; - } - if (strncmp(argv[1],"inf",3) == 0) { - int i; - for (i=0; i= CONFIG_SYS_SCSI_MAX_DEVICE)) { - printf("\nno SCSI devices available\n"); - return 1; - } - printf ("\n Device %d: ", scsi_curr_dev); - dev_print(&scsi_dev_desc[scsi_curr_dev]); - return 0; - } - if (strncmp(argv[1],"scan",4) == 0) { - scsi_scan(1); - return 0; + if (strncmp(argv[1], "res", 3) == 0) { + printf("\nReset SCSI\n"); + scsi_bus_reset(); + scsi_scan(1); + return 0; + } + if (strncmp(argv[1], "inf", 3) == 0) { + int 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); + dev_print(&scsi_dev_desc[i]); } - if (strncmp(argv[1],"part",4) == 0) { - int dev, ok; - for (ok=0, dev=0; dev= CONFIG_SYS_SCSI_MAX_DEVICE) { + printf("\nno SCSI devices available\n"); return 1; } - 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 >= CONFIG_SYS_SCSI_MAX_DEVICE) { - printf("unknown device\n"); - return 1; - } - printf ("\n Device %d: ", dev); - dev_print(&scsi_dev_desc[dev]); - if(scsi_dev_desc[dev].type == DEV_TYPE_UNKNOWN) { - return 1; - } - scsi_curr_dev = dev; - printf("... is now current device\n"); - return 0; - } - if (strncmp(argv[1],"part",4) == 0) { - int dev = (int)simple_strtoul(argv[2], NULL, 10); - if(scsi_dev_desc[dev].type != DEV_TYPE_UNKNOWN) { + printf("\n Device %d: ", scsi_curr_dev); + dev_print(&scsi_dev_desc[scsi_curr_dev]); + return 0; + } + if (strncmp(argv[1], "scan", 4) == 0) { + scsi_scan(1); + return 0; + } + if (strncmp(argv[1], "part", 4) == 0) { + int dev, ok; + 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"); + debug("print_part of %x\n", dev); part_print(&scsi_dev_desc[dev]); } - else { - printf ("\nSCSI device %d not available\n", dev); - } - return 1; } - return CMD_RET_USAGE; - 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 ("\nSCSI read: device %d block # %ld, count %ld ... ", - scsi_curr_dev, blk, cnt); - n = scsi_read(&scsi_dev_desc[scsi_curr_dev], - blk, cnt, (ulong *)addr); - printf ("%ld blocks read: %s\n",n,(n==cnt) ? "OK" : "ERROR"); - return 0; - } 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("\nSCSI write: device %d block # %ld, " - "count %ld ... ", - scsi_curr_dev, blk, cnt); - n = scsi_write(&scsi_dev_desc[scsi_curr_dev], - blk, cnt, (ulong *)addr); - printf("%ld blocks written: %s\n", n, - (n == cnt) ? "OK" : "ERROR"); - return 0; + if (!ok) + printf("\nno SCSI devices available\n"); + return 1; + } + 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 >= CONFIG_SYS_SCSI_MAX_DEVICE) { + printf("unknown device\n"); + return 1; } + printf("\n Device %d: ", dev); + dev_print(&scsi_dev_desc[dev]); + if (scsi_dev_desc[dev].type == DEV_TYPE_UNKNOWN) + return 1; + scsi_curr_dev = dev; + printf("... is now current device\n"); + return 0; + } + if (strncmp(argv[1], "part", 4) == 0) { + int dev = (int)simple_strtoul(argv[2], NULL, 10); + if (scsi_dev_desc[dev].type != DEV_TYPE_UNKNOWN) + part_print(&scsi_dev_desc[dev]); + else + printf("\nSCSI device %d not available\n", dev); + return 1; + } + return CMD_RET_USAGE; + 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("\nSCSI read: device %d block # %ld, count %ld ... ", + scsi_curr_dev, blk, cnt); + n = scsi_read(&scsi_dev_desc[scsi_curr_dev], + blk, cnt, (ulong *)addr); + printf("%ld blocks read: %s\n", n, + n == cnt ? "OK" : "ERROR"); + return 0; + } 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("\nSCSI write: device %d block # %ld, count %ld ... ", + scsi_curr_dev, blk, cnt); + n = scsi_write(&scsi_dev_desc[scsi_curr_dev], + blk, cnt, (ulong *)addr); + printf("%ld blocks written: %s\n", n, + n == cnt ? "OK" : "ERROR"); + return 0; + } } /* switch */ return CMD_RET_USAGE; } @@ -493,25 +488,24 @@ U_BOOT_CMD( /* copy src to dest, skipping leading and trailing blanks * and null terminate the string */ -void scsi_ident_cpy (unsigned char *dest, unsigned char *src, unsigned int len) +void scsi_ident_cpy(unsigned char *dest, unsigned char *src, unsigned int len) { int start,end; - start=0; - while(startstart) { - if(src[end]!=' ') + end = len-1; + while (end > start) { + if (src[end] != ' ') break; end--; } - for( ; start<=end; start++) { - *dest++=src[start]; - } + for (; start <= end; start++) + *dest ++= src[start]; *dest='\0'; } @@ -534,7 +528,7 @@ int scsi_read_capacity(ccb *pccb, lbaint_t *capacity, unsigned long *blksz) { *capacity = 0; - memset(pccb->cmd, 0, sizeof(pccb->cmd)); + memset(pccb->cmd, '\0', sizeof(pccb->cmd)); pccb->cmd[0] = SCSI_RD_CAPAC10; pccb->cmd[1] = pccb->lun << 5; pccb->cmdlen = 10; @@ -559,8 +553,7 @@ int scsi_read_capacity(ccb *pccb, lbaint_t *capacity, unsigned long *blksz) } /* Read capacity (10) was insufficient. Use read capacity (16). */ - - memset(pccb->cmd, 0, sizeof(pccb->cmd)); + memset(pccb->cmd, '\0', sizeof(pccb->cmd)); pccb->cmd[0] = SCSI_RD_CAPAC16; pccb->cmd[1] = 0x10; pccb->cmdlen = 16; @@ -597,14 +590,14 @@ int scsi_read_capacity(ccb *pccb, lbaint_t *capacity, unsigned long *blksz) */ void scsi_setup_test_unit_ready(ccb * pccb) { - pccb->cmd[0]=SCSI_TST_U_RDY; - pccb->cmd[1]=pccb->lun<<5; - pccb->cmd[2]=0; - pccb->cmd[3]=0; - pccb->cmd[4]=0; - pccb->cmd[5]=0; - pccb->cmdlen=6; - pccb->msgout[0]=SCSI_IDENTIFY; /* NOT USED */ + pccb->cmd[0] = SCSI_TST_U_RDY; + pccb->cmd[1] = pccb->lun << 5; + pccb->cmd[2] = 0; + pccb->cmd[3] = 0; + pccb->cmd[4] = 0; + pccb->cmd[5] = 0; + pccb->cmdlen = 6; + pccb->msgout[0] = SCSI_IDENTIFY; /* NOT USED */ } /********************************************************************************* @@ -618,50 +611,49 @@ void scsi_scan(int mode) unsigned long blksz; ccb* pccb=(ccb *)&tempccb; - if(mode==1) { + if (mode == 1) printf("scanning bus for devices...\n"); - } - for(i=0;itarget=i; - for(lun=0;lunlun=lun; - pccb->pdata=(unsigned char *)&tempbuff; - pccb->datalen=512; + scsi_max_devs = 0; + for (i = 0; i < CONFIG_SYS_SCSI_MAX_SCSI_ID; i++) { + pccb->target = i; + 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) { - debug ("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); continue; } - perq=tempbuff[0]; - modi=tempbuff[1]; - if((perq & 0x1f)==0x1f) { + perq = tempbuff[0]; + modi = tempbuff[1]; + if ((perq & 0x1f) == 0x1f) continue; /* skip unknown devices */ - } - if((modi&0x80)==0x80) /* drive is removable */ - scsi_dev_desc[scsi_max_devs].removable=true; + if ((modi & 0x80) == 0x80) /* drive is removable */ + scsi_dev_desc[scsi_max_devs].removable = true; /* get info for this device */ scsi_ident_cpy((unsigned char *)&scsi_dev_desc[scsi_max_devs].vendor[0], &tempbuff[8], 8); @@ -669,14 +661,15 @@ void scsi_scan(int mode) &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; + scsi_dev_desc[scsi_max_devs].target = pccb->target; + scsi_dev_desc[scsi_max_devs].lun = pccb->lun; - pccb->datalen=0; + pccb->datalen = 0; scsi_setup_test_unit_ready(pccb); if (scsi_exec(pccb) != true) { - if (scsi_dev_desc[scsi_max_devs].removable == true) { - scsi_dev_desc[scsi_max_devs].type=perq; + if (scsi_dev_desc[scsi_max_devs].removable) { + scsi_dev_desc[scsi_max_devs].type = + perq; goto removable; } scsi_print_error(pccb); @@ -686,11 +679,11 @@ void scsi_scan(int mode) scsi_print_error(pccb); continue; } - scsi_dev_desc[scsi_max_devs].lba=capacity; - scsi_dev_desc[scsi_max_devs].blksz=blksz; + scsi_dev_desc[scsi_max_devs].lba = capacity; + scsi_dev_desc[scsi_max_devs].blksz = blksz; scsi_dev_desc[scsi_max_devs].log2blksz = LOG2(scsi_dev_desc[scsi_max_devs].blksz); - scsi_dev_desc[scsi_max_devs].type=perq; + scsi_dev_desc[scsi_max_devs].type = perq; part_init(&scsi_dev_desc[scsi_max_devs]); removable: if(mode==1) { @@ -700,8 +693,8 @@ removable: scsi_max_devs++; } /* next LUN */ } - if(scsi_max_devs>0) - scsi_curr_dev=0; + if (scsi_max_devs > 0) + scsi_curr_dev = 0; else scsi_curr_dev = -1; -- cgit v1.2.1 From 53dbcdd0cd4b90077b0b3893bcf25354ed825cec Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 1 May 2016 11:35:59 -0600 Subject: dm: ide: Correct various code style problems Adjust common/ide.c so that it passes most checkpatch.pl checks. Signed-off-by: Simon Glass --- cmd/ide.c | 57 +++++++++++++++++++++++++++++---------------------------- 1 file changed, 29 insertions(+), 28 deletions(-) (limited to 'cmd') diff --git a/cmd/ide.c b/cmd/ide.c index c4c08c8855..a46d0acfd6 100644 --- a/cmd/ide.c +++ b/cmd/ide.c @@ -58,13 +58,13 @@ struct blk_desc ide_dev_desc[CONFIG_SYS_IDE_MAXDEVICE]; /* ------------------------------------------------------------------------- */ #ifdef CONFIG_IDE_RESET -static void ide_reset (void); +static void ide_reset(void); #else #define ide_reset() /* dummy */ #endif static void ide_ident(struct blk_desc *dev_desc); -static uchar ide_wait (int dev, ulong t); +static uchar ide_wait(int dev, ulong t); #define IDE_TIME_OUT 2000 /* 2 sec timeout */ @@ -72,14 +72,15 @@ static uchar ide_wait (int dev, ulong t); #define IDE_SPIN_UP_TIME_OUT 5000 /* 5 sec spin-up timeout */ -static void ident_cpy (unsigned char *dest, unsigned char *src, unsigned int len); +static void ident_cpy(unsigned char *dest, unsigned char *src, + unsigned int len); #ifndef CONFIG_SYS_ATA_PORT_ADDR #define CONFIG_SYS_ATA_PORT_ADDR(port) (port) #endif #ifdef CONFIG_ATAPI -static void atapi_inquiry(struct blk_desc *dev_desc); +static void atapi_inquiry(struct blk_desc *dev_desc); static ulong atapi_read(struct blk_desc *block_dev, lbaint_t blknr, lbaint_t blkcnt, void *buffer); #endif @@ -150,7 +151,7 @@ int do_ide(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) return CMD_RET_USAGE; case 3: if (strncmp(argv[1], "dev", 3) == 0) { - int dev = (int) simple_strtoul(argv[2], NULL, 10); + int dev = (int)simple_strtoul(argv[2], NULL, 10); printf("\nIDE device %d: ", dev); if (dev >= CONFIG_SYS_IDE_MAXDEVICE) { @@ -169,7 +170,7 @@ int do_ide(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) return 0; } else if (strncmp(argv[1], "part", 4) == 0) { - int dev = (int) simple_strtoul(argv[2], NULL, 10); + int dev = (int)simple_strtoul(argv[2], NULL, 10); if (ide_dev_desc[dev].part_type != PART_TYPE_UNKNOWN) { part_print(&ide_dev_desc[dev]); @@ -194,13 +195,13 @@ int do_ide(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) #ifdef CONFIG_SYS_64BIT_LBA lbaint_t blk = simple_strtoull(argv[3], NULL, 16); - printf("\nIDE read: device %d block # %lld, count %ld ... ", - curr_device, blk, cnt); + printf("\nIDE read: device %d block # %lld, 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); + printf("\nIDE read: device %d block # %ld, count %ld...", + curr_device, blk, cnt); #endif dev_desc = &ide_dev_desc[curr_device]; @@ -223,13 +224,13 @@ int do_ide(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) #ifdef CONFIG_SYS_64BIT_LBA lbaint_t blk = simple_strtoull(argv[3], NULL, 16); - printf("\nIDE write: device %d block # %lld, count %ld ... ", - curr_device, blk, cnt); + printf("\nIDE write: device %d block # %lld, 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); + printf("\nIDE write: device %d block # %ld, count %ld...", + curr_device, blk, cnt); #endif n = ide_write(&ide_dev_desc[curr_device], blk, cnt, (ulong *)addr); @@ -833,7 +834,7 @@ ulong ide_read(struct blk_desc *block_dev, lbaint_t blknr, lbaint_t blkcnt, } IDE_READ_E: ide_led(DEVICE_LED(device), 0); /* LED off */ - return (n); + return n; } /* ------------------------------------------------------------------------- */ @@ -922,7 +923,7 @@ ulong ide_write(struct blk_desc *block_dev, lbaint_t blknr, lbaint_t blkcnt, } WR_OUT: ide_led(DEVICE_LED(device), 0); /* LED off */ - return (n); + return n; } /* ------------------------------------------------------------------------- */ @@ -974,7 +975,7 @@ static uchar ide_wait(int dev, ulong t) if (delay-- == 0) break; } - return (c); + return c; } /* ------------------------------------------------------------------------- */ @@ -1098,7 +1099,7 @@ static uchar atapi_wait_mask(int dev, ulong t, uchar mask, uchar res) if (delay-- == 0) break; } - return (c); + return c; } /* @@ -1142,7 +1143,7 @@ unsigned char atapi_issue(int device, unsigned char *ccb, int ccblen, if ((c & mask) != res) { /* DRQ must be 1, BSY 0 */ printf("ATAPI_ISSUE: Error (no IRQ) before sending ccb dev %d status 0x%02x\n", - device, c); + device, c); err = 0xFF; goto AI_OUT; } @@ -1166,10 +1167,10 @@ unsigned char atapi_issue(int device, unsigned char *ccb, int ccblen, if (c & ATA_STAT_ERR) { err = (ide_inb(device, ATA_ERROR_REG)) >> 4; debug("atapi_issue 1 returned sense key %X status %02X\n", - err, c); + err, c); } else { printf("ATAPI_ISSUE: (no DRQ) after sending ccb (%x) status 0x%02x\n", - ccb[0], c); + ccb[0], c); err = 0xFF; } goto AI_OUT; @@ -1190,7 +1191,7 @@ unsigned char atapi_issue(int device, unsigned char *ccb, int ccblen, } if (n != buflen) { debug("WARNING, transfer bytes %d not equal with requested %d\n", - n, buflen); + n, buflen); } if (n != 0) { /* data transfer */ debug("ATAPI_ISSUE: %d Bytes to transfer\n", n); @@ -1220,7 +1221,7 @@ unsigned char atapi_issue(int device, unsigned char *ccb, int ccblen, } AI_OUT: ide_led(DEVICE_LED(device), 0); /* LED off */ - return (err); + return err; } /* @@ -1297,7 +1298,7 @@ retry: ascq); error: debug("ERROR Sense key %02X ASC %02X ASCQ %02X\n", key, asc, ascq); - return (0xFF); + return 0xFF; } @@ -1402,8 +1403,8 @@ ulong atapi_read(struct blk_desc *block_dev, lbaint_t blknr, lbaint_t blkcnt, unsigned char ccb[12]; /* Command descriptor block */ ulong cnt; - debug("atapi_read dev %d start " LBAF " blocks " LBAF " buffer at %lX\n", - device, blknr, blkcnt, (ulong) buffer); + debug("atapi_read dev %d start " LBAF " blocks " LBAF + " buffer at %lX\n", device, blknr, blkcnt, (ulong) buffer); do { if (blkcnt > ATAPI_READ_MAX_BLOCK) @@ -1428,14 +1429,14 @@ ulong atapi_read(struct blk_desc *block_dev, lbaint_t blknr, lbaint_t blkcnt, (unsigned char *) buffer, cnt * ATAPI_READ_BLOCK_SIZE) == 0xFF) { - return (n); + return n; } n += cnt; blkcnt -= cnt; blknr += cnt; buffer += (cnt * ATAPI_READ_BLOCK_SIZE); } while (blkcnt > 0); - return (n); + return n; } /* ------------------------------------------------------------------------- */ -- cgit v1.2.1 From ed73508dec40afee7c90048fac510796bf91314d Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 1 May 2016 11:36:00 -0600 Subject: dm: ide: Remove the forward declarations Reorder the code to avoid needing forward declarations. Fix up code style as needed. Signed-off-by: Simon Glass --- cmd/ide.c | 1924 ++++++++++++++++++++++++++++++------------------------------- 1 file changed, 946 insertions(+), 978 deletions(-) (limited to 'cmd') diff --git a/cmd/ide.c b/cmd/ide.c index a46d0acfd6..db26f4320d 100644 --- a/cmd/ide.c +++ b/cmd/ide.c @@ -57,491 +57,518 @@ static int ide_bus_ok[CONFIG_SYS_IDE_MAXBUS]; struct blk_desc ide_dev_desc[CONFIG_SYS_IDE_MAXDEVICE]; /* ------------------------------------------------------------------------- */ -#ifdef CONFIG_IDE_RESET -static void ide_reset(void); -#else -#define ide_reset() /* dummy */ -#endif - -static void ide_ident(struct blk_desc *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 ident_cpy(unsigned char *dest, unsigned char *src, - unsigned int len); - #ifndef CONFIG_SYS_ATA_PORT_ADDR #define CONFIG_SYS_ATA_PORT_ADDR(port) (port) #endif -#ifdef CONFIG_ATAPI -static void atapi_inquiry(struct blk_desc *dev_desc); -static ulong atapi_read(struct blk_desc *block_dev, lbaint_t blknr, - lbaint_t blkcnt, void *buffer); +#ifndef CONFIG_IDE_LED /* define LED macros, they are not used anyways */ +# define DEVICE_LED(x) 0 +# define LED_IDE1 1 +# define LED_IDE2 2 #endif +#ifdef CONFIG_IDE_RESET +extern void ide_set_reset(int idereset); -/* ------------------------------------------------------------------------- */ - -int do_ide(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) +static void ide_reset(void) { - int rcode = 0; - - switch (argc) { - case 0: - case 1: - return CMD_RET_USAGE; - 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; + int i; - putc('\n'); + curr_device = -1; + for (i = 0; i < CONFIG_SYS_IDE_MAXBUS; ++i) + ide_bus_ok[i] = 0; + for (i = 0; i < CONFIG_SYS_IDE_MAXDEVICE; ++i) + ide_dev_desc[i].type = DEV_TYPE_UNKNOWN; - for (i = 0; i < CONFIG_SYS_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; + ide_set_reset(1); /* assert reset */ - } else if (strncmp(argv[1], "dev", 3) == 0) { - if ((curr_device < 0) - || (curr_device >= CONFIG_SYS_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; + /* the reset signal shall be asserted for et least 25 us */ + udelay(25); - for (ok = 0, dev = 0; - dev < CONFIG_SYS_IDE_MAXDEVICE; - ++dev) { - if (ide_dev_desc[dev].part_type != - PART_TYPE_UNKNOWN) { - ++ok; - if (dev) - putc('\n'); - part_print(&ide_dev_desc[dev]); - } - } - if (!ok) { - puts("\nno IDE devices available\n"); - rcode++; - } - return rcode; - } - return CMD_RET_USAGE; - case 3: - if (strncmp(argv[1], "dev", 3) == 0) { - int dev = (int)simple_strtoul(argv[2], NULL, 10); + WATCHDOG_RESET(); - printf("\nIDE device %d: ", dev); - if (dev >= CONFIG_SYS_IDE_MAXDEVICE) { - puts("unknown device\n"); - return 1; - } - dev_print(&ide_dev_desc[dev]); - /*ide_print (dev); */ + /* de-assert RESET signal */ + ide_set_reset(0); - if (ide_dev_desc[dev].type == DEV_TYPE_UNKNOWN) - return 1; + /* wait 250 ms */ + for (i = 0; i < 250; ++i) + udelay(1000); +} +#else +#define ide_reset() /* dummy */ +#endif /* CONFIG_IDE_RESET */ - curr_device = dev; +/* + * Wait until Busy bit is off, or timeout (in ms) + * Return last status + */ +static uchar ide_wait(int dev, ulong t) +{ + ulong delay = 10 * t; /* poll every 100 us */ + uchar c; - puts("... is now current device\n"); + while ((c = ide_inb(dev, ATA_STATUS)) & ATA_STAT_BUSY) { + udelay(100); + if (delay-- == 0) + break; + } + return c; +} - return 0; - } else if (strncmp(argv[1], "part", 4) == 0) { - int dev = (int)simple_strtoul(argv[2], NULL, 10); +/* + * 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 *dst, unsigned char *src, + unsigned int len) +{ + unsigned char *end, *last; - if (ide_dev_desc[dev].part_type != PART_TYPE_UNKNOWN) { - part_print(&ide_dev_desc[dev]); - } else { - printf("\nIDE device %d not available\n", - dev); - rcode = 1; - } - return rcode; - } + last = dst; + end = src + len - 1; - return CMD_RET_USAGE; - default: - /* at least 4 args */ + /* reserve space for '\0' */ + if (len < 2) + goto OUT; - if (strcmp(argv[1], "read") == 0) { - ulong addr = simple_strtoul(argv[2], NULL, 16); - ulong cnt = simple_strtoul(argv[4], NULL, 16); - struct blk_desc *dev_desc; - ulong n; + /* skip leading white space */ + while ((*src) && (src < end) && (*src == ' ')) + ++src; -#ifdef CONFIG_SYS_64BIT_LBA - lbaint_t blk = simple_strtoull(argv[3], NULL, 16); + /* copy string, omitting trailing white space */ + while ((*src) && (src < end)) { + *dst++ = *src; + if (*src++ != ' ') + last = dst; + } +OUT: + *last = '\0'; +} - printf("\nIDE read: device %d block # %lld, count %ld...", - curr_device, blk, cnt); -#else - lbaint_t blk = simple_strtoul(argv[3], NULL, 16); +#ifdef CONFIG_ATAPI +/**************************************************************************** + * ATAPI Support + */ - printf("\nIDE read: device %d block # %ld, count %ld...", - curr_device, blk, cnt); -#endif +#if defined(CONFIG_IDE_SWAP_IO) +/* since ATAPI may use commands with not 4 bytes alligned length + * we have our own transfer functions, 2 bytes alligned */ +__weak void ide_output_data_shorts(int dev, ushort *sect_buf, int shorts) +{ + ushort *dbuf; + volatile ushort *pbuf; - dev_desc = &ide_dev_desc[curr_device]; - n = blk_dread(dev_desc, blk, cnt, (ulong *)addr); - /* flush cache after read */ - flush_cache(addr, - cnt * ide_dev_desc[curr_device].blksz); + pbuf = (ushort *)(ATA_CURR_BASE(dev) + ATA_DATA_REG); + dbuf = (ushort *)sect_buf; - 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; + debug("in output data shorts base for read is %lx\n", + (unsigned long) pbuf); -#ifdef CONFIG_SYS_64BIT_LBA - lbaint_t blk = simple_strtoull(argv[3], NULL, 16); + while (shorts--) { + EIEIO; + *pbuf = *dbuf++; + } +} - printf("\nIDE write: device %d block # %lld, count %ld...", - curr_device, blk, cnt); -#else - lbaint_t blk = simple_strtoul(argv[3], NULL, 16); +__weak void ide_input_data_shorts(int dev, ushort *sect_buf, int shorts) +{ + ushort *dbuf; + volatile ushort *pbuf; - printf("\nIDE write: device %d block # %ld, count %ld...", - curr_device, blk, cnt); -#endif - n = ide_write(&ide_dev_desc[curr_device], blk, cnt, - (ulong *)addr); + pbuf = (ushort *)(ATA_CURR_BASE(dev) + ATA_DATA_REG); + dbuf = (ushort *)sect_buf; - printf("%ld blocks written: %s\n", - n, (n == cnt) ? "OK" : "ERROR"); - if (n == cnt) - return 0; - else - return 1; - } else { - return CMD_RET_USAGE; - } + debug("in input data shorts base for read is %lx\n", + (unsigned long) pbuf); - return rcode; + while (shorts--) { + EIEIO; + *dbuf++ = *pbuf; } } -int do_diskboot(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) +#else /* ! CONFIG_IDE_SWAP_IO */ +__weak void ide_output_data_shorts(int dev, ushort *sect_buf, int shorts) { - return common_diskboot(cmdtp, "ide", argc, argv); + outsw(ATA_CURR_BASE(dev) + ATA_DATA_REG, sect_buf, shorts); } -/* ------------------------------------------------------------------------- */ - -__weak void ide_led(uchar led, uchar status) +__weak void ide_input_data_shorts(int dev, ushort *sect_buf, int shorts) { -#if defined(CONFIG_IDE_LED) && defined(PER8_BASE) /* required by LED_PORT */ - static uchar led_buffer; /* Buffer for current LED status */ - - uchar *led_port = LED_PORT; + insw(ATA_CURR_BASE(dev) + ATA_DATA_REG, sect_buf, shorts); +} - if (status) /* switch LED on */ - led_buffer |= led; - else /* switch LED off */ - led_buffer &= ~led; +#endif /* CONFIG_IDE_SWAP_IO */ - *led_port = led_buffer; -#endif -} - -#ifndef CONFIG_IDE_LED /* define LED macros, they are not used anyways */ -# define DEVICE_LED(x) 0 -# define LED_IDE1 1 -# define LED_IDE2 2 -#endif - -/* ------------------------------------------------------------------------- */ - -__weak void ide_outb(int dev, int port, unsigned char val) +/* + * Wait until (Status & mask) == res, or timeout (in ms) + * Return last status + * This is used since some ATAPI CD ROMs clears their Busy Bit first + * and then they set their DRQ Bit + */ +static uchar atapi_wait_mask(int dev, ulong t, uchar mask, uchar res) { - debug("ide_outb (dev= %d, port= 0x%x, val= 0x%02x) : @ 0x%08lx\n", - dev, port, val, - (ATA_CURR_BASE(dev) + CONFIG_SYS_ATA_PORT_ADDR(port))); + ulong delay = 10 * t; /* poll every 100 us */ + uchar c; -#if defined(CONFIG_IDE_AHB) - if (port) { - /* write command */ - ide_write_register(dev, port, val); - } else { - /* write data */ - outb(val, (ATA_CURR_BASE(dev))); + /* prevents to read the status before valid */ + c = ide_inb(dev, ATA_DEV_CTL); + + while (((c = ide_inb(dev, ATA_STATUS)) & mask) != res) { + /* break if error occurs (doesn't make sense to wait more) */ + if ((c & ATA_STAT_ERR) == ATA_STAT_ERR) + break; + udelay(100); + if (delay-- == 0) + break; } -#else - outb(val, (ATA_CURR_BASE(dev) + CONFIG_SYS_ATA_PORT_ADDR(port))); -#endif + return c; } -__weak unsigned char ide_inb(int dev, int port) +/* + * issue an atapi command + */ +unsigned char atapi_issue(int device, unsigned char *ccb, int ccblen, + unsigned char *buffer, int buflen) { - uchar val; - -#if defined(CONFIG_IDE_AHB) - val = ide_read_register(dev, port); -#else - val = inb((ATA_CURR_BASE(dev) + CONFIG_SYS_ATA_PORT_ADDR(port))); -#endif + unsigned char c, err, mask, res; + int n; - debug("ide_inb (dev= %d, port= 0x%x) : @ 0x%08lx -> 0x%02x\n", - dev, port, - (ATA_CURR_BASE(dev) + CONFIG_SYS_ATA_PORT_ADDR(port)), val); - return val; -} + ide_led(DEVICE_LED(device), 1); /* LED on */ -void ide_init(void) -{ - unsigned char c; - int i, bus; + /* Select device + */ + mask = ATA_STAT_BUSY | ATA_STAT_DRQ; + res = 0; + ide_outb(device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device)); + c = atapi_wait_mask(device, ATAPI_TIME_OUT, mask, res); + if ((c & mask) != res) { + printf("ATAPI_ISSUE: device %d not ready status %X\n", device, + c); + err = 0xFF; + goto AI_OUT; + } + /* write taskfile */ + ide_outb(device, ATA_ERROR_REG, 0); /* no DMA, no overlaped */ + ide_outb(device, ATA_SECT_CNT, 0); + ide_outb(device, ATA_SECT_NUM, 0); + ide_outb(device, ATA_CYL_LOW, (unsigned char) (buflen & 0xFF)); + ide_outb(device, ATA_CYL_HIGH, + (unsigned char) ((buflen >> 8) & 0xFF)); + ide_outb(device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device)); -#ifdef CONFIG_IDE_8xx_PCCARD - extern int ide_devices_found; /* Initialized in check_ide_device() */ -#endif /* CONFIG_IDE_8xx_PCCARD */ + ide_outb(device, ATA_COMMAND, ATAPI_CMD_PACKET); + udelay(50); -#ifdef CONFIG_IDE_PREINIT - WATCHDOG_RESET(); + mask = ATA_STAT_DRQ | ATA_STAT_BUSY | ATA_STAT_ERR; + res = ATA_STAT_DRQ; + c = atapi_wait_mask(device, ATAPI_TIME_OUT, mask, res); - if (ide_preinit()) { - puts("ide_preinit failed\n"); - return; + if ((c & mask) != res) { /* DRQ must be 1, BSY 0 */ + printf("ATAPI_ISSUE: Error (no IRQ) before sending ccb dev %d status 0x%02x\n", + device, c); + err = 0xFF; + goto AI_OUT; } -#endif /* CONFIG_IDE_PREINIT */ - WATCHDOG_RESET(); + /* write command block */ + ide_output_data_shorts(device, (unsigned short *)ccb, ccblen / 2); + /* ATAPI Command written wait for completition */ + udelay(5000); /* device must set bsy */ + + mask = ATA_STAT_DRQ | ATA_STAT_BUSY | ATA_STAT_ERR; /* - * Reset the IDE just to be sure. - * Light LED's to show + * if no data wait for DRQ = 0 BSY = 0 + * if data wait for DRQ = 1 BSY = 0 */ - ide_led((LED_IDE1 | LED_IDE2), 1); /* LED's on */ - - /* ATAPI Drives seems to need a proper IDE Reset */ - ide_reset(); - -#ifdef CONFIG_IDE_INIT_POSTRESET - WATCHDOG_RESET(); - - if (ide_init_postreset()) { - puts("ide_preinit_postreset failed\n"); - return; + res = 0; + if (buflen) + res = ATA_STAT_DRQ; + c = atapi_wait_mask(device, ATAPI_TIME_OUT, mask, res); + if ((c & mask) != res) { + if (c & ATA_STAT_ERR) { + err = (ide_inb(device, ATA_ERROR_REG)) >> 4; + debug("atapi_issue 1 returned sense key %X status %02X\n", + err, c); + } else { + printf("ATAPI_ISSUE: (no DRQ) after sending ccb (%x) status 0x%02x\n", + ccb[0], c); + err = 0xFF; + } + goto AI_OUT; } -#endif /* CONFIG_IDE_INIT_POSTRESET */ + n = ide_inb(device, ATA_CYL_HIGH); + n <<= 8; + n += ide_inb(device, ATA_CYL_LOW); + if (n > buflen) { + printf("ERROR, transfer bytes %d requested only %d\n", n, + buflen); + err = 0xff; + goto AI_OUT; + } + if ((n == 0) && (buflen < 0)) { + printf("ERROR, transfer bytes %d requested %d\n", n, buflen); + err = 0xff; + goto AI_OUT; + } + if (n != buflen) { + debug("WARNING, transfer bytes %d not equal with requested %d\n", + n, buflen); + } + if (n != 0) { /* data transfer */ + 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) { + debug("Write to device\n"); + ide_output_data_shorts(device, (unsigned short *)buffer, + n); + } else { + debug("Read from device @ %p shorts %d\n", buffer, n); + ide_input_data_shorts(device, (unsigned short *)buffer, + n); + } + } + udelay(5000); /* seems that some CD ROMs need this... */ + mask = ATA_STAT_BUSY | ATA_STAT_ERR; + res = 0; + 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); + debug("atapi_issue 2 returned sense key %X status %X\n", err, + c); + } else { + err = 0; + } +AI_OUT: + ide_led(DEVICE_LED(device), 0); /* LED off */ + return err; +} - /* - * Wait for IDE to get ready. - * According to spec, this can take up to 31 seconds! - */ - for (bus = 0; bus < CONFIG_SYS_IDE_MAXBUS; ++bus) { - int dev = - bus * (CONFIG_SYS_IDE_MAXDEVICE / - CONFIG_SYS_IDE_MAXBUS); +/* + * sending the command to atapi_issue. If an status other than good + * returns, an request_sense will be issued + */ -#ifdef CONFIG_IDE_8xx_PCCARD - /* Skip non-ide devices from probing */ - if ((ide_devices_found & (1 << bus)) == 0) { - ide_led((LED_IDE1 | LED_IDE2), 0); /* LED's off */ - continue; - } -#endif - printf("Bus %d: ", bus); +#define ATAPI_DRIVE_NOT_READY 100 +#define ATAPI_UNIT_ATTN 10 - ide_bus_ok[bus] = 0; +unsigned char atapi_issue_autoreq(int device, + unsigned char *ccb, + int ccblen, + unsigned char *buffer, int buflen) +{ + unsigned char sense_data[18], sense_ccb[12]; + unsigned char res, key, asc, ascq; + int notready, unitattn; - /* Select device - */ - udelay(100000); /* 100 ms */ - ide_outb(dev, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(dev)); - udelay(100000); /* 100 ms */ - i = 0; - do { - udelay(10000); /* 10 ms */ + unitattn = ATAPI_UNIT_ATTN; + notready = ATAPI_DRIVE_NOT_READY; - c = ide_inb(dev, ATA_STATUS); - i++; - if (i > (ATA_RESET_TIME * 100)) { - puts("** Timeout **\n"); - /* LED's off */ - ide_led((LED_IDE1 | LED_IDE2), 0); - return; - } - if ((i >= 100) && ((i % 100) == 0)) - putc('.'); +retry: + res = atapi_issue(device, ccb, ccblen, buffer, buflen); + if (res == 0) + return 0; /* Ok */ - } while (c & ATA_STAT_BUSY); + if (res == 0xFF) + return 0xFF; /* error */ - if (c & (ATA_STAT_BUSY | ATA_STAT_FAULT)) { - puts("not available "); - debug("Status = 0x%02X ", c); -#ifndef CONFIG_ATAPI /* ATAPI Devices do not set DRDY */ - } else if ((c & ATA_STAT_READY) == 0) { - puts("not available "); - debug("Status = 0x%02X ", c); -#endif - } else { - puts("OK "); - ide_bus_ok[bus] = 1; - } - WATCHDOG_RESET(); - } + debug("(auto_req)atapi_issue returned sense key %X\n", res); - putc('\n'); + memset(sense_ccb, 0, sizeof(sense_ccb)); + memset(sense_data, 0, sizeof(sense_data)); + sense_ccb[0] = ATAPI_CMD_REQ_SENSE; + sense_ccb[4] = 18; /* allocation Length */ - ide_led((LED_IDE1 | LED_IDE2), 0); /* LED's off */ + res = atapi_issue(device, sense_ccb, 12, sense_data, 18); + key = (sense_data[2] & 0xF); + asc = (sense_data[12]); + ascq = (sense_data[13]); - curr_device = -1; - for (i = 0; i < CONFIG_SYS_IDE_MAXDEVICE; ++i) { - int led = (IDE_BUS(i) == 0) ? LED_IDE1 : LED_IDE2; - ide_dev_desc[i].type = DEV_TYPE_UNKNOWN; - ide_dev_desc[i].if_type = IF_TYPE_IDE; - ide_dev_desc[i].devnum = i; - ide_dev_desc[i].part_type = PART_TYPE_UNKNOWN; - ide_dev_desc[i].blksz = 0; - ide_dev_desc[i].log2blksz = - LOG2_INVALID(typeof(ide_dev_desc[i].log2blksz)); - ide_dev_desc[i].lba = 0; - ide_dev_desc[i].block_read = ide_read; - ide_dev_desc[i].block_write = ide_write; - if (!ide_bus_ok[IDE_BUS(i)]) - continue; - ide_led(led, 1); /* LED on */ - ide_ident(&ide_dev_desc[i]); - ide_led(led, 0); /* LED off */ - dev_print(&ide_dev_desc[i]); + 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, ascq); - if ((ide_dev_desc[i].lba > 0) && (ide_dev_desc[i].blksz > 0)) { - /* initialize partition type */ - part_init(&ide_dev_desc[i]); - if (curr_device < 0) - curr_device = i; + if ((key == 0)) + return 0; /* ok device ready */ + + if ((key == 6) || (asc == 0x29) || (asc == 0x28)) { /* Unit Attention */ + if (unitattn-- > 0) { + udelay(200 * 1000); + goto retry; } + printf("Unit Attention, tried %d\n", ATAPI_UNIT_ATTN); + goto error; } - WATCHDOG_RESET(); + if ((asc == 0x4) && (ascq == 0x1)) { + /* not ready, but will be ready soon */ + if (notready-- > 0) { + udelay(200 * 1000); + goto retry; + } + printf("Drive not ready, tried %d times\n", + ATAPI_DRIVE_NOT_READY); + goto error; + } + if (asc == 0x3a) { + debug("Media not present\n"); + goto error; + } + + printf("ERROR: Unknown Sense key %02X ASC %02X ASCQ %02X\n", key, asc, + ascq); +error: + debug("ERROR Sense key %02X ASC %02X ASCQ %02X\n", key, asc, ascq); + return 0xFF; } -/* ------------------------------------------------------------------------- */ +/* + * atapi_read: + * we transfer only one block per command, since the multiple DRQ per + * command is not yet implemented + */ +#define ATAPI_READ_MAX_BYTES 2048 /* we read max 2kbytes */ +#define ATAPI_READ_BLOCK_SIZE 2048 /* assuming CD part */ +#define ATAPI_READ_MAX_BLOCK (ATAPI_READ_MAX_BYTES/ATAPI_READ_BLOCK_SIZE) -#ifdef CONFIG_PARTITIONS -struct blk_desc *ide_get_dev(int dev) +ulong atapi_read(struct blk_desc *block_dev, lbaint_t blknr, lbaint_t blkcnt, + void *buffer) { - return (dev < CONFIG_SYS_IDE_MAXDEVICE) ? &ide_dev_desc[dev] : NULL; -} -#endif + int device = block_dev->devnum; + ulong n = 0; + unsigned char ccb[12]; /* Command descriptor block */ + ulong cnt; -/* ------------------------------------------------------------------------- */ + debug("atapi_read dev %d start " LBAF " blocks " LBAF + " buffer at %lX\n", device, blknr, blkcnt, (ulong) buffer); -/* We only need to swap data if we are running on a big endian cpu. */ -#if defined(__LITTLE_ENDIAN) -__weak void ide_input_swap_data(int dev, ulong *sect_buf, int words) -{ - ide_input_data(dev, sect_buf, words); + do { + if (blkcnt > ATAPI_READ_MAX_BLOCK) + cnt = ATAPI_READ_MAX_BLOCK; + else + cnt = blkcnt; + + ccb[0] = ATAPI_CMD_READ_12; + ccb[1] = 0; /* reserved */ + ccb[2] = (unsigned char) (blknr >> 24) & 0xFF; /* MSB Block */ + ccb[3] = (unsigned char) (blknr >> 16) & 0xFF; /* */ + ccb[4] = (unsigned char) (blknr >> 8) & 0xFF; + ccb[5] = (unsigned char) blknr & 0xFF; /* LSB Block */ + ccb[6] = (unsigned char) (cnt >> 24) & 0xFF; /* MSB Block cnt */ + ccb[7] = (unsigned char) (cnt >> 16) & 0xFF; + ccb[8] = (unsigned char) (cnt >> 8) & 0xFF; + ccb[9] = (unsigned char) cnt & 0xFF; /* LSB Block */ + ccb[10] = 0; /* reserved */ + ccb[11] = 0; /* reserved */ + + if (atapi_issue_autoreq(device, ccb, 12, + (unsigned char *)buffer, + cnt * ATAPI_READ_BLOCK_SIZE) + == 0xFF) { + return n; + } + n += cnt; + blkcnt -= cnt; + blknr += cnt; + buffer += (cnt * ATAPI_READ_BLOCK_SIZE); + } while (blkcnt > 0); + return n; } -#else -__weak void ide_input_swap_data(int dev, ulong *sect_buf, int words) + +static void atapi_inquiry(struct blk_desc *dev_desc) { - volatile ushort *pbuf = - (ushort *) (ATA_CURR_BASE(dev) + ATA_DATA_REG); - ushort *dbuf = (ushort *) sect_buf; + unsigned char ccb[12]; /* Command descriptor block */ + unsigned char iobuf[64]; /* temp buf */ + unsigned char c; + int device; - debug("in input swap data base for read is %lx\n", - (unsigned long) pbuf); + device = dev_desc->devnum; + dev_desc->type = DEV_TYPE_UNKNOWN; /* not yet valid */ + dev_desc->block_read = atapi_read; - while (words--) { -#ifdef __MIPS__ - *dbuf++ = swab16p((u16 *) pbuf); - *dbuf++ = swab16p((u16 *) pbuf); -#else - *dbuf++ = ld_le16(pbuf); - *dbuf++ = ld_le16(pbuf); -#endif /* !MIPS */ - } -} -#endif /* __LITTLE_ENDIAN */ + memset(ccb, 0, sizeof(ccb)); + memset(iobuf, 0, sizeof(iobuf)); + ccb[0] = ATAPI_CMD_INQUIRY; + ccb[4] = 40; /* allocation Legnth */ + c = atapi_issue_autoreq(device, ccb, 12, (unsigned char *)iobuf, 40); -#if defined(CONFIG_IDE_SWAP_IO) -__weak void ide_output_data(int dev, const ulong *sect_buf, int words) -{ - ushort *dbuf; - volatile ushort *pbuf; + debug("ATAPI_CMD_INQUIRY returned %x\n", c); + if (c != 0) + return; - pbuf = (ushort *) (ATA_CURR_BASE(dev) + ATA_DATA_REG); - dbuf = (ushort *) sect_buf; - while (words--) { - EIEIO; - *pbuf = *dbuf++; - EIEIO; - *pbuf = *dbuf++; - } -} -#else /* ! CONFIG_IDE_SWAP_IO */ -__weak void ide_output_data(int dev, const ulong *sect_buf, int words) -{ -#if defined(CONFIG_IDE_AHB) - ide_write_data(dev, sect_buf, words); -#else - outsw(ATA_CURR_BASE(dev) + ATA_DATA_REG, sect_buf, words << 1); -#endif -} -#endif /* CONFIG_IDE_SWAP_IO */ + /* copy device ident strings */ + ident_cpy((unsigned char *)dev_desc->vendor, &iobuf[8], 8); + ident_cpy((unsigned char *)dev_desc->product, &iobuf[16], 16); + ident_cpy((unsigned char *)dev_desc->revision, &iobuf[32], 5); -#if defined(CONFIG_IDE_SWAP_IO) -__weak void ide_input_data(int dev, ulong *sect_buf, int words) -{ - ushort *dbuf; - volatile ushort *pbuf; + dev_desc->lun = 0; + dev_desc->lba = 0; + dev_desc->blksz = 0; + dev_desc->log2blksz = LOG2_INVALID(typeof(dev_desc->log2blksz)); + dev_desc->type = iobuf[0] & 0x1f; - pbuf = (ushort *) (ATA_CURR_BASE(dev) + ATA_DATA_REG); - dbuf = (ushort *) sect_buf; + if ((iobuf[1] & 0x80) == 0x80) + dev_desc->removable = 1; + else + dev_desc->removable = 0; - debug("in input data base for read is %lx\n", (unsigned long) pbuf); + memset(ccb, 0, sizeof(ccb)); + memset(iobuf, 0, sizeof(iobuf)); + ccb[0] = ATAPI_CMD_START_STOP; + ccb[4] = 0x03; /* start */ - while (words--) { - EIEIO; - *dbuf++ = *pbuf; - EIEIO; - *dbuf++ = *pbuf; - } -} -#else /* ! CONFIG_IDE_SWAP_IO */ -__weak void ide_input_data(int dev, ulong *sect_buf, int words) -{ -#if defined(CONFIG_IDE_AHB) - ide_read_data(dev, sect_buf, words); -#else - insw(ATA_CURR_BASE(dev) + ATA_DATA_REG, sect_buf, words << 1); + c = atapi_issue_autoreq(device, ccb, 12, (unsigned char *)iobuf, 0); + + debug("ATAPI_CMD_START_STOP returned %x\n", c); + if (c != 0) + return; + + memset(ccb, 0, sizeof(ccb)); + memset(iobuf, 0, sizeof(iobuf)); + c = atapi_issue_autoreq(device, ccb, 12, (unsigned char *)iobuf, 0); + + debug("ATAPI_CMD_UNIT_TEST_READY returned %x\n", c); + if (c != 0) + return; + + memset(ccb, 0, sizeof(ccb)); + memset(iobuf, 0, sizeof(iobuf)); + ccb[0] = ATAPI_CMD_READ_CAP; + c = atapi_issue_autoreq(device, ccb, 12, (unsigned char *)iobuf, 8); + debug("ATAPI_CMD_READ_CAP returned %x\n", c); + if (c != 0) + return; + + 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]); + + dev_desc->lba = ((unsigned long) iobuf[0] << 24) + + ((unsigned long) iobuf[1] << 16) + + ((unsigned long) iobuf[2] << 8) + ((unsigned long) iobuf[3]); + dev_desc->blksz = ((unsigned long) iobuf[4] << 24) + + ((unsigned long) iobuf[5] << 16) + + ((unsigned long) iobuf[6] << 8) + ((unsigned long) iobuf[7]); + dev_desc->log2blksz = LOG2(dev_desc->blksz); +#ifdef CONFIG_LBA48 + /* ATAPI devices cannot use 48bit addressing (ATA/ATAPI v7) */ + dev_desc->lba48 = 0; #endif + return; } -#endif /* CONFIG_IDE_SWAP_IO */ +#endif /* CONFIG_ATAPI */ -/* ------------------------------------------------------------------------- - */ static void ide_ident(struct blk_desc *dev_desc) { unsigned char c; @@ -633,11 +660,11 @@ static void ide_ident(struct blk_desc *dev_desc) ide_input_swap_data(device, (ulong *)&iop, ATA_SECTORWORDS); - ident_cpy((unsigned char *) dev_desc->revision, iop.fw_rev, + ident_cpy((unsigned char *)dev_desc->revision, iop.fw_rev, sizeof(dev_desc->revision)); - ident_cpy((unsigned char *) dev_desc->vendor, iop.model, + ident_cpy((unsigned char *)dev_desc->vendor, iop.model, sizeof(dev_desc->vendor)); - ident_cpy((unsigned char *) dev_desc->product, iop.serial_no, + ident_cpy((unsigned char *)dev_desc->product, iop.serial_no, sizeof(dev_desc->product)); #ifdef __LITTLE_ENDIAN /* @@ -711,737 +738,678 @@ static void ide_ident(struct blk_desc *dev_desc) #endif } +/* ------------------------------------------------------------------------- */ + +int do_ide(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) +{ + int rcode = 0; + + switch (argc) { + case 0: + case 1: + return CMD_RET_USAGE; + 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 < CONFIG_SYS_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 >= CONFIG_SYS_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 < CONFIG_SYS_IDE_MAXDEVICE; + ++dev) { + if (ide_dev_desc[dev].part_type != + PART_TYPE_UNKNOWN) { + ++ok; + if (dev) + putc('\n'); + part_print(&ide_dev_desc[dev]); + } + } + if (!ok) { + puts("\nno IDE devices available\n"); + rcode++; + } + return rcode; + } + return CMD_RET_USAGE; + 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 >= CONFIG_SYS_IDE_MAXDEVICE) { + puts("unknown device\n"); + return 1; + } + dev_print(&ide_dev_desc[dev]); + /*ide_print (dev); */ -ulong ide_read(struct blk_desc *block_dev, lbaint_t blknr, lbaint_t blkcnt, - void *buffer) -{ - int device = block_dev->devnum; - ulong n = 0; - unsigned char c; - unsigned char pwrsave = 0; /* power save */ + if (ide_dev_desc[dev].type == DEV_TYPE_UNKNOWN) + return 1; -#ifdef CONFIG_LBA48 - unsigned char lba48 = 0; + curr_device = dev; - if (blknr & 0x0000fffff0000000ULL) { - /* more than 28 bits used, use 48bit mode */ - lba48 = 1; - } -#endif - debug("ide_read dev %d start " LBAF ", blocks " LBAF " buffer at %lX\n", - device, blknr, blkcnt, (ulong) buffer); + puts("... is now current device\n"); - ide_led(DEVICE_LED(device), 1); /* LED on */ + return 0; + } else if (strncmp(argv[1], "part", 4) == 0) { + int dev = (int)simple_strtoul(argv[2], NULL, 10); - /* Select device - */ - ide_outb(device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device)); - c = ide_wait(device, IDE_TIME_OUT); + if (ide_dev_desc[dev].part_type != PART_TYPE_UNKNOWN) { + part_print(&ide_dev_desc[dev]); + } else { + printf("\nIDE device %d not available\n", + dev); + rcode = 1; + } + return rcode; + } - if (c & ATA_STAT_BUSY) { - printf("IDE read: device %d not ready\n", device); - goto IDE_READ_E; - } + return CMD_RET_USAGE; + default: + /* at least 4 args */ - /* first check if the drive is in Powersaving mode, if yes, - * increase the timeout value */ - ide_outb(device, ATA_COMMAND, ATA_CMD_CHK_PWR); - udelay(50); + if (strcmp(argv[1], "read") == 0) { + ulong addr = simple_strtoul(argv[2], NULL, 16); + ulong cnt = simple_strtoul(argv[4], NULL, 16); + struct blk_desc *dev_desc; + ulong n; - c = ide_wait(device, IDE_TIME_OUT); /* can't take over 500 ms */ +#ifdef CONFIG_SYS_64BIT_LBA + lbaint_t blk = simple_strtoull(argv[3], NULL, 16); - if (c & ATA_STAT_BUSY) { - printf("IDE read: device %d not ready\n", device); - goto IDE_READ_E; - } - if ((c & ATA_STAT_ERR) == ATA_STAT_ERR) { - printf("No Powersaving mode %X\n", c); - } else { - c = ide_inb(device, ATA_SECT_CNT); - debug("Powersaving %02X\n", c); - if (c == 0) - pwrsave = 1; - } + printf("\nIDE read: device %d block # %lld, 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 - while (blkcnt-- > 0) { + dev_desc = &ide_dev_desc[curr_device]; + n = blk_dread(dev_desc, blk, cnt, (ulong *)addr); + /* flush cache after read */ + flush_cache(addr, + cnt * ide_dev_desc[curr_device].blksz); - c = ide_wait(device, IDE_TIME_OUT); + 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; - if (c & ATA_STAT_BUSY) { - 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); #ifdef CONFIG_SYS_64BIT_LBA - ide_outb(device, ATA_LBA_MID, (blknr >> 32) & 0xFF); - ide_outb(device, ATA_LBA_HIGH, (blknr >> 40) & 0xFF); + lbaint_t blk = simple_strtoull(argv[3], NULL, 16); + + printf("\nIDE write: device %d block # %lld, count %ld...", + curr_device, blk, cnt); #else - ide_outb(device, ATA_LBA_MID, 0); - ide_outb(device, ATA_LBA_HIGH, 0); + 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(&ide_dev_desc[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 { + return CMD_RET_USAGE; } -#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); -#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); + return rcode; + } +} - } else -#endif - { - ide_outb(device, ATA_DEV_HD, ATA_LBA | - ATA_DEVICE(device) | ((blknr >> 24) & 0xF)); - ide_outb(device, ATA_COMMAND, ATA_CMD_READ); - } +int do_diskboot(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) +{ + return common_diskboot(cmdtp, "ide", argc, argv); +} - udelay(50); +/* ------------------------------------------------------------------------- */ - if (pwrsave) { - /* may take up to 4 sec */ - c = ide_wait(device, IDE_SPIN_UP_TIME_OUT); - pwrsave = 0; - } else { - /* can't take over 500 ms */ - c = ide_wait(device, IDE_TIME_OUT); - } +__weak void ide_led(uchar led, uchar status) +{ +#if defined(CONFIG_IDE_LED) && defined(PER8_BASE) /* required by LED_PORT */ + static uchar led_buffer; /* Buffer for current LED status */ - if ((c & (ATA_STAT_DRQ | ATA_STAT_BUSY | ATA_STAT_ERR)) != - ATA_STAT_DRQ) { - printf("Error (no IRQ) dev %d blk " LBAF ": status " - "%#02x\n", device, blknr, c); - break; - } + uchar *led_port = LED_PORT; - ide_input_data(device, buffer, ATA_SECTORWORDS); - (void) ide_inb(device, ATA_STATUS); /* clear IRQ */ + if (status) /* switch LED on */ + led_buffer |= led; + else /* switch LED off */ + led_buffer &= ~led; - ++n; - ++blknr; - buffer += ATA_BLOCKSIZE; - } -IDE_READ_E: - ide_led(DEVICE_LED(device), 0); /* LED off */ - return n; + *led_port = led_buffer; +#endif } /* ------------------------------------------------------------------------- */ +__weak void 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) + CONFIG_SYS_ATA_PORT_ADDR(port))); -ulong ide_write(struct blk_desc *block_dev, lbaint_t blknr, lbaint_t blkcnt, - const void *buffer) +#if defined(CONFIG_IDE_AHB) + if (port) { + /* write command */ + ide_write_register(dev, port, val); + } else { + /* write data */ + outb(val, (ATA_CURR_BASE(dev))); + } +#else + outb(val, (ATA_CURR_BASE(dev) + CONFIG_SYS_ATA_PORT_ADDR(port))); +#endif +} + +__weak unsigned char ide_inb(int dev, int port) +{ + uchar val; + +#if defined(CONFIG_IDE_AHB) + val = ide_read_register(dev, port); +#else + val = inb((ATA_CURR_BASE(dev) + CONFIG_SYS_ATA_PORT_ADDR(port))); +#endif + + debug("ide_inb (dev= %d, port= 0x%x) : @ 0x%08lx -> 0x%02x\n", + dev, port, + (ATA_CURR_BASE(dev) + CONFIG_SYS_ATA_PORT_ADDR(port)), val); + return val; +} + +void ide_init(void) { - int device = block_dev->devnum; - ulong n = 0; unsigned char c; + int i, bus; -#ifdef CONFIG_LBA48 - unsigned char lba48 = 0; +#ifdef CONFIG_IDE_8xx_PCCARD + extern int ide_devices_found; /* Initialized in check_ide_device() */ +#endif /* CONFIG_IDE_8xx_PCCARD */ - if (blknr & 0x0000fffff0000000ULL) { - /* more than 28 bits used, use 48bit mode */ - lba48 = 1; +#ifdef CONFIG_IDE_PREINIT + WATCHDOG_RESET(); + + if (ide_preinit()) { + puts("ide_preinit failed\n"); + return; } -#endif +#endif /* CONFIG_IDE_PREINIT */ - ide_led(DEVICE_LED(device), 1); /* LED on */ + WATCHDOG_RESET(); - /* Select device + /* + * Reset the IDE just to be sure. + * Light LED's to show */ - ide_outb(device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device)); + ide_led((LED_IDE1 | LED_IDE2), 1); /* LED's on */ - while (blkcnt-- > 0) { + /* ATAPI Drives seems to need a proper IDE Reset */ + ide_reset(); - c = ide_wait(device, IDE_TIME_OUT); +#ifdef CONFIG_IDE_INIT_POSTRESET + WATCHDOG_RESET(); - if (c & ATA_STAT_BUSY) { - 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); -#ifdef CONFIG_SYS_64BIT_LBA - ide_outb(device, ATA_LBA_MID, (blknr >> 32) & 0xFF); - ide_outb(device, ATA_LBA_HIGH, (blknr >> 40) & 0xFF); -#else - ide_outb(device, ATA_LBA_MID, 0); - ide_outb(device, ATA_LBA_HIGH, 0); -#endif + if (ide_init_postreset()) { + puts("ide_preinit_postreset failed\n"); + return; + } +#endif /* CONFIG_IDE_INIT_POSTRESET */ + + /* + * Wait for IDE to get ready. + * According to spec, this can take up to 31 seconds! + */ + for (bus = 0; bus < CONFIG_SYS_IDE_MAXBUS; ++bus) { + int dev = + bus * (CONFIG_SYS_IDE_MAXDEVICE / + CONFIG_SYS_IDE_MAXBUS); + +#ifdef CONFIG_IDE_8xx_PCCARD + /* Skip non-ide devices from probing */ + if ((ide_devices_found & (1 << bus)) == 0) { + ide_led((LED_IDE1 | LED_IDE2), 0); /* LED's off */ + continue; } #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); + printf("Bus %d: ", bus); -#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); + ide_bus_ok[bus] = 0; - } else -#endif - { - ide_outb(device, ATA_DEV_HD, ATA_LBA | - ATA_DEVICE(device) | ((blknr >> 24) & 0xF)); - ide_outb(device, ATA_COMMAND, ATA_CMD_WRITE); - } + /* Select device + */ + udelay(100000); /* 100 ms */ + ide_outb(dev, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(dev)); + udelay(100000); /* 100 ms */ + i = 0; + do { + udelay(10000); /* 10 ms */ - udelay(50); + c = ide_inb(dev, ATA_STATUS); + i++; + if (i > (ATA_RESET_TIME * 100)) { + puts("** Timeout **\n"); + /* LED's off */ + ide_led((LED_IDE1 | LED_IDE2), 0); + return; + } + if ((i >= 100) && ((i % 100) == 0)) + putc('.'); - /* can't take over 500 ms */ - c = ide_wait(device, IDE_TIME_OUT); + } while (c & ATA_STAT_BUSY); - if ((c & (ATA_STAT_DRQ | ATA_STAT_BUSY | ATA_STAT_ERR)) != - ATA_STAT_DRQ) { - printf("Error (no IRQ) dev %d blk " LBAF ": status " - "%#02x\n", device, blknr, c); - goto WR_OUT; + if (c & (ATA_STAT_BUSY | ATA_STAT_FAULT)) { + puts("not available "); + debug("Status = 0x%02X ", c); +#ifndef CONFIG_ATAPI /* ATAPI Devices do not set DRDY */ + } else if ((c & ATA_STAT_READY) == 0) { + puts("not available "); + debug("Status = 0x%02X ", c); +#endif + } else { + puts("OK "); + ide_bus_ok[bus] = 1; } - - ide_output_data(device, buffer, ATA_SECTORWORDS); - c = ide_inb(device, ATA_STATUS); /* clear IRQ */ - ++n; - ++blknr; - buffer += ATA_BLOCKSIZE; + WATCHDOG_RESET(); } -WR_OUT: - ide_led(DEVICE_LED(device), 0); /* LED off */ - return n; -} - -/* ------------------------------------------------------------------------- */ - -/* - * 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 *dst, unsigned char *src, - unsigned int len) -{ - unsigned char *end, *last; - last = dst; - end = src + len - 1; + putc('\n'); - /* reserve space for '\0' */ - if (len < 2) - goto OUT; + ide_led((LED_IDE1 | LED_IDE2), 0); /* LED's off */ - /* skip leading white space */ - while ((*src) && (src < end) && (*src == ' ')) - ++src; + curr_device = -1; + for (i = 0; i < CONFIG_SYS_IDE_MAXDEVICE; ++i) { + int led = (IDE_BUS(i) == 0) ? LED_IDE1 : LED_IDE2; + ide_dev_desc[i].type = DEV_TYPE_UNKNOWN; + ide_dev_desc[i].if_type = IF_TYPE_IDE; + ide_dev_desc[i].devnum = i; + ide_dev_desc[i].part_type = PART_TYPE_UNKNOWN; + ide_dev_desc[i].blksz = 0; + ide_dev_desc[i].log2blksz = + LOG2_INVALID(typeof(ide_dev_desc[i].log2blksz)); + ide_dev_desc[i].lba = 0; + ide_dev_desc[i].block_read = ide_read; + ide_dev_desc[i].block_write = ide_write; + if (!ide_bus_ok[IDE_BUS(i)]) + continue; + ide_led(led, 1); /* LED on */ + ide_ident(&ide_dev_desc[i]); + ide_led(led, 0); /* LED off */ + dev_print(&ide_dev_desc[i]); - /* copy string, omitting trailing white space */ - while ((*src) && (src < end)) { - *dst++ = *src; - if (*src++ != ' ') - last = dst; + if ((ide_dev_desc[i].lba > 0) && (ide_dev_desc[i].blksz > 0)) { + /* initialize partition type */ + part_init(&ide_dev_desc[i]); + if (curr_device < 0) + curr_device = i; + } } -OUT: - *last = '\0'; + WATCHDOG_RESET(); } /* ------------------------------------------------------------------------- */ -/* - * Wait until Busy bit is off, or timeout (in ms) - * Return last status - */ -static uchar ide_wait(int dev, ulong t) +#ifdef CONFIG_PARTITIONS +struct blk_desc *ide_get_dev(int dev) { - ulong delay = 10 * t; /* poll every 100 us */ - uchar c; - - while ((c = ide_inb(dev, ATA_STATUS)) & ATA_STAT_BUSY) { - udelay(100); - if (delay-- == 0) - break; - } - return c; + return (dev < CONFIG_SYS_IDE_MAXDEVICE) ? &ide_dev_desc[dev] : NULL; } +#endif /* ------------------------------------------------------------------------- */ -#ifdef CONFIG_IDE_RESET -extern void ide_set_reset(int idereset); - -static void ide_reset(void) +/* We only need to swap data if we are running on a big endian cpu. */ +#if defined(__LITTLE_ENDIAN) +__weak void ide_input_swap_data(int dev, ulong *sect_buf, int words) { - int i; - - curr_device = -1; - for (i = 0; i < CONFIG_SYS_IDE_MAXBUS; ++i) - ide_bus_ok[i] = 0; - for (i = 0; i < CONFIG_SYS_IDE_MAXDEVICE; ++i) - ide_dev_desc[i].type = DEV_TYPE_UNKNOWN; - - ide_set_reset(1); /* assert reset */ - - /* the reset signal shall be asserted for et least 25 us */ - udelay(25); - - WATCHDOG_RESET(); - - /* de-assert RESET signal */ - ide_set_reset(0); - - /* wait 250 ms */ - for (i = 0; i < 250; ++i) - udelay(1000); + ide_input_data(dev, sect_buf, words); } +#else +__weak void ide_input_swap_data(int dev, ulong *sect_buf, int words) +{ + volatile ushort *pbuf = + (ushort *)(ATA_CURR_BASE(dev) + ATA_DATA_REG); + ushort *dbuf = (ushort *)sect_buf; -#endif /* CONFIG_IDE_RESET */ - -/* ------------------------------------------------------------------------- */ + debug("in input swap data base for read is %lx\n", + (unsigned long) pbuf); -#if defined(CONFIG_OF_IDE_FIXUP) -int ide_device_present(int dev) -{ - if (dev >= CONFIG_SYS_IDE_MAXBUS) - return 0; - return (ide_dev_desc[dev].type == DEV_TYPE_UNKNOWN ? 0 : 1); + while (words--) { +#ifdef __MIPS__ + *dbuf++ = swab16p((u16 *)pbuf); + *dbuf++ = swab16p((u16 *)pbuf); +#else + *dbuf++ = ld_le16(pbuf); + *dbuf++ = ld_le16(pbuf); +#endif /* !MIPS */ + } } -#endif -/* ------------------------------------------------------------------------- */ +#endif /* __LITTLE_ENDIAN */ -#ifdef CONFIG_ATAPI -/**************************************************************************** - * ATAPI Support - */ #if defined(CONFIG_IDE_SWAP_IO) -/* since ATAPI may use commands with not 4 bytes alligned length - * we have our own transfer functions, 2 bytes alligned */ -__weak void ide_output_data_shorts(int dev, ushort *sect_buf, int shorts) +__weak void ide_output_data(int dev, const ulong *sect_buf, int words) { ushort *dbuf; volatile ushort *pbuf; - pbuf = (ushort *) (ATA_CURR_BASE(dev) + ATA_DATA_REG); - dbuf = (ushort *) sect_buf; - - debug("in output data shorts base for read is %lx\n", - (unsigned long) pbuf); - - while (shorts--) { + pbuf = (ushort *)(ATA_CURR_BASE(dev) + ATA_DATA_REG); + dbuf = (ushort *)sect_buf; + while (words--) { + EIEIO; + *pbuf = *dbuf++; EIEIO; *pbuf = *dbuf++; } } +#else /* ! CONFIG_IDE_SWAP_IO */ +__weak void ide_output_data(int dev, const ulong *sect_buf, int words) +{ +#if defined(CONFIG_IDE_AHB) + ide_write_data(dev, sect_buf, words); +#else + outsw(ATA_CURR_BASE(dev) + ATA_DATA_REG, sect_buf, words << 1); +#endif +} +#endif /* CONFIG_IDE_SWAP_IO */ -__weak void ide_input_data_shorts(int dev, ushort *sect_buf, int shorts) +#if defined(CONFIG_IDE_SWAP_IO) +__weak void ide_input_data(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; + pbuf = (ushort *)(ATA_CURR_BASE(dev) + ATA_DATA_REG); + dbuf = (ushort *)sect_buf; - debug("in input data shorts base for read is %lx\n", - (unsigned long) pbuf); + debug("in input data base for read is %lx\n", (unsigned long) pbuf); - while (shorts--) { + while (words--) { + EIEIO; + *dbuf++ = *pbuf; EIEIO; *dbuf++ = *pbuf; } } - #else /* ! CONFIG_IDE_SWAP_IO */ -__weak void ide_output_data_shorts(int dev, ushort *sect_buf, int shorts) -{ - outsw(ATA_CURR_BASE(dev) + ATA_DATA_REG, sect_buf, shorts); -} - -__weak void ide_input_data_shorts(int dev, ushort *sect_buf, int shorts) +__weak void ide_input_data(int dev, ulong *sect_buf, int words) { - insw(ATA_CURR_BASE(dev) + ATA_DATA_REG, sect_buf, shorts); +#if defined(CONFIG_IDE_AHB) + ide_read_data(dev, sect_buf, words); +#else + insw(ATA_CURR_BASE(dev) + ATA_DATA_REG, sect_buf, words << 1); +#endif } #endif /* CONFIG_IDE_SWAP_IO */ -/* - * Wait until (Status & mask) == res, or timeout (in ms) - * Return last status - * This is used since some ATAPI CD ROMs clears their Busy Bit first - * and then they set their DRQ Bit - */ -static uchar atapi_wait_mask(int dev, ulong t, uchar mask, uchar res) +/* ------------------------------------------------------------------------- */ + +ulong ide_read(struct blk_desc *block_dev, lbaint_t blknr, lbaint_t blkcnt, + void *buffer) { - ulong delay = 10 * t; /* poll every 100 us */ - uchar c; + int device = block_dev->devnum; + ulong n = 0; + unsigned char c; + unsigned char pwrsave = 0; /* power save */ - /* prevents to read the status before valid */ - c = ide_inb(dev, ATA_DEV_CTL); +#ifdef CONFIG_LBA48 + unsigned char lba48 = 0; - while (((c = ide_inb(dev, ATA_STATUS)) & mask) != res) { - /* break if error occurs (doesn't make sense to wait more) */ - if ((c & ATA_STAT_ERR) == ATA_STAT_ERR) - break; - udelay(100); - if (delay-- == 0) - break; + if (blknr & 0x0000fffff0000000ULL) { + /* more than 28 bits used, use 48bit mode */ + lba48 = 1; } - return c; -} - -/* - * issue an atapi command - */ -unsigned char atapi_issue(int device, unsigned char *ccb, int ccblen, - unsigned char *buffer, int buflen) -{ - unsigned char c, err, mask, res; - int n; +#endif + debug("ide_read dev %d start " LBAF ", blocks " LBAF " buffer at %lX\n", + device, blknr, blkcnt, (ulong) buffer); ide_led(DEVICE_LED(device), 1); /* LED on */ /* Select device */ - mask = ATA_STAT_BUSY | ATA_STAT_DRQ; - res = 0; - ide_outb(device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device)); - c = atapi_wait_mask(device, ATAPI_TIME_OUT, mask, res); - if ((c & mask) != res) { - printf("ATAPI_ISSUE: device %d not ready status %X\n", device, - c); - err = 0xFF; - goto AI_OUT; - } - /* write taskfile */ - ide_outb(device, ATA_ERROR_REG, 0); /* no DMA, no overlaped */ - ide_outb(device, ATA_SECT_CNT, 0); - ide_outb(device, ATA_SECT_NUM, 0); - ide_outb(device, ATA_CYL_LOW, (unsigned char) (buflen & 0xFF)); - ide_outb(device, ATA_CYL_HIGH, - (unsigned char) ((buflen >> 8) & 0xFF)); ide_outb(device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device)); + c = ide_wait(device, IDE_TIME_OUT); - ide_outb(device, ATA_COMMAND, ATAPI_CMD_PACKET); - udelay(50); - - mask = ATA_STAT_DRQ | ATA_STAT_BUSY | ATA_STAT_ERR; - res = ATA_STAT_DRQ; - c = atapi_wait_mask(device, ATAPI_TIME_OUT, mask, res); - - if ((c & mask) != res) { /* DRQ must be 1, BSY 0 */ - printf("ATAPI_ISSUE: Error (no IRQ) before sending ccb dev %d status 0x%02x\n", - device, c); - err = 0xFF; - goto AI_OUT; - } - - /* write command block */ - ide_output_data_shorts(device, (unsigned short *) ccb, ccblen / 2); - - /* ATAPI Command written wait for completition */ - udelay(5000); /* device must set bsy */ - - mask = ATA_STAT_DRQ | ATA_STAT_BUSY | ATA_STAT_ERR; - /* - * if no data wait for DRQ = 0 BSY = 0 - * if data wait for DRQ = 1 BSY = 0 - */ - res = 0; - if (buflen) - res = ATA_STAT_DRQ; - c = atapi_wait_mask(device, ATAPI_TIME_OUT, mask, res); - if ((c & mask) != res) { - if (c & ATA_STAT_ERR) { - err = (ide_inb(device, ATA_ERROR_REG)) >> 4; - debug("atapi_issue 1 returned sense key %X status %02X\n", - err, c); - } else { - printf("ATAPI_ISSUE: (no DRQ) after sending ccb (%x) status 0x%02x\n", - ccb[0], c); - err = 0xFF; - } - goto AI_OUT; - } - n = ide_inb(device, ATA_CYL_HIGH); - n <<= 8; - n += ide_inb(device, ATA_CYL_LOW); - if (n > buflen) { - printf("ERROR, transfer bytes %d requested only %d\n", n, - buflen); - err = 0xff; - goto AI_OUT; - } - if ((n == 0) && (buflen < 0)) { - printf("ERROR, transfer bytes %d requested %d\n", n, buflen); - err = 0xff; - goto AI_OUT; - } - if (n != buflen) { - debug("WARNING, transfer bytes %d not equal with requested %d\n", - n, buflen); - } - if (n != 0) { /* data transfer */ - 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) { - debug("Write to device\n"); - ide_output_data_shorts(device, - (unsigned short *) buffer, n); - } else { - debug("Read from device @ %p shorts %d\n", buffer, n); - ide_input_data_shorts(device, - (unsigned short *) buffer, n); - } - } - udelay(5000); /* seems that some CD ROMs need this... */ - mask = ATA_STAT_BUSY | ATA_STAT_ERR; - res = 0; - 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); - debug("atapi_issue 2 returned sense key %X status %X\n", err, - c); - } else { - err = 0; + if (c & ATA_STAT_BUSY) { + printf("IDE read: device %d not ready\n", device); + goto IDE_READ_E; } -AI_OUT: - ide_led(DEVICE_LED(device), 0); /* LED off */ - return err; -} - -/* - * sending the command to atapi_issue. If an status other than good - * returns, an request_sense will be issued - */ - -#define ATAPI_DRIVE_NOT_READY 100 -#define ATAPI_UNIT_ATTN 10 - -unsigned char atapi_issue_autoreq(int device, - unsigned char *ccb, - int ccblen, - unsigned char *buffer, int buflen) -{ - unsigned char sense_data[18], sense_ccb[12]; - unsigned char res, key, asc, ascq; - int notready, unitattn; - - unitattn = ATAPI_UNIT_ATTN; - notready = ATAPI_DRIVE_NOT_READY; - -retry: - res = atapi_issue(device, ccb, ccblen, buffer, buflen); - if (res == 0) - return 0; /* Ok */ - - if (res == 0xFF) - return 0xFF; /* error */ - - 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)); - sense_ccb[0] = ATAPI_CMD_REQ_SENSE; - sense_ccb[4] = 18; /* allocation Length */ - - res = atapi_issue(device, sense_ccb, 12, sense_data, 18); - key = (sense_data[2] & 0xF); - asc = (sense_data[12]); - ascq = (sense_data[13]); - 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, ascq); + /* first check if the drive is in Powersaving mode, if yes, + * increase the timeout value */ + ide_outb(device, ATA_COMMAND, ATA_CMD_CHK_PWR); + udelay(50); - if ((key == 0)) - return 0; /* ok device ready */ + c = ide_wait(device, IDE_TIME_OUT); /* can't take over 500 ms */ - if ((key == 6) || (asc == 0x29) || (asc == 0x28)) { /* Unit Attention */ - if (unitattn-- > 0) { - udelay(200 * 1000); - goto retry; - } - printf("Unit Attention, tried %d\n", ATAPI_UNIT_ATTN); - goto error; - } - if ((asc == 0x4) && (ascq == 0x1)) { - /* not ready, but will be ready soon */ - if (notready-- > 0) { - udelay(200 * 1000); - goto retry; - } - printf("Drive not ready, tried %d times\n", - ATAPI_DRIVE_NOT_READY); - goto error; + if (c & ATA_STAT_BUSY) { + printf("IDE read: device %d not ready\n", device); + goto IDE_READ_E; } - if (asc == 0x3a) { - debug("Media not present\n"); - goto error; + if ((c & ATA_STAT_ERR) == ATA_STAT_ERR) { + printf("No Powersaving mode %X\n", c); + } else { + c = ide_inb(device, ATA_SECT_CNT); + debug("Powersaving %02X\n", c); + if (c == 0) + pwrsave = 1; } - printf("ERROR: Unknown Sense key %02X ASC %02X ASCQ %02X\n", key, asc, - ascq); -error: - debug("ERROR Sense key %02X ASC %02X ASCQ %02X\n", key, asc, ascq); - return 0xFF; -} + while (blkcnt-- > 0) { -static void atapi_inquiry(struct blk_desc *dev_desc) -{ - unsigned char ccb[12]; /* Command descriptor block */ - unsigned char iobuf[64]; /* temp buf */ - unsigned char c; - int device; + c = ide_wait(device, IDE_TIME_OUT); - device = dev_desc->devnum; - dev_desc->type = DEV_TYPE_UNKNOWN; /* not yet valid */ - dev_desc->block_read = atapi_read; + if (c & ATA_STAT_BUSY) { + 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); +#ifdef CONFIG_SYS_64BIT_LBA + ide_outb(device, ATA_LBA_MID, (blknr >> 32) & 0xFF); + ide_outb(device, ATA_LBA_HIGH, (blknr >> 40) & 0xFF); +#else + ide_outb(device, ATA_LBA_MID, 0); + ide_outb(device, ATA_LBA_HIGH, 0); +#endif + } +#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); - memset(ccb, 0, sizeof(ccb)); - memset(iobuf, 0, sizeof(iobuf)); +#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); - ccb[0] = ATAPI_CMD_INQUIRY; - ccb[4] = 40; /* allocation Legnth */ - c = atapi_issue_autoreq(device, ccb, 12, (unsigned char *) iobuf, 40); + } else +#endif + { + ide_outb(device, ATA_DEV_HD, ATA_LBA | + ATA_DEVICE(device) | ((blknr >> 24) & 0xF)); + ide_outb(device, ATA_COMMAND, ATA_CMD_READ); + } - debug("ATAPI_CMD_INQUIRY returned %x\n", c); - if (c != 0) - return; + udelay(50); - /* copy device ident strings */ - ident_cpy((unsigned char *) dev_desc->vendor, &iobuf[8], 8); - ident_cpy((unsigned char *) dev_desc->product, &iobuf[16], 16); - ident_cpy((unsigned char *) dev_desc->revision, &iobuf[32], 5); + if (pwrsave) { + /* may take up to 4 sec */ + c = ide_wait(device, IDE_SPIN_UP_TIME_OUT); + pwrsave = 0; + } else { + /* can't take over 500 ms */ + c = ide_wait(device, IDE_TIME_OUT); + } - dev_desc->lun = 0; - dev_desc->lba = 0; - dev_desc->blksz = 0; - dev_desc->log2blksz = LOG2_INVALID(typeof(dev_desc->log2blksz)); - dev_desc->type = iobuf[0] & 0x1f; + if ((c & (ATA_STAT_DRQ | ATA_STAT_BUSY | ATA_STAT_ERR)) != + ATA_STAT_DRQ) { + printf("Error (no IRQ) dev %d blk " LBAF + ": status %#02x\n", device, blknr, c); + break; + } - if ((iobuf[1] & 0x80) == 0x80) - dev_desc->removable = 1; - else - dev_desc->removable = 0; + ide_input_data(device, buffer, ATA_SECTORWORDS); + (void) ide_inb(device, ATA_STATUS); /* clear IRQ */ - memset(ccb, 0, sizeof(ccb)); - memset(iobuf, 0, sizeof(iobuf)); - ccb[0] = ATAPI_CMD_START_STOP; - ccb[4] = 0x03; /* start */ + ++n; + ++blknr; + buffer += ATA_BLOCKSIZE; + } +IDE_READ_E: + ide_led(DEVICE_LED(device), 0); /* LED off */ + return n; +} - c = atapi_issue_autoreq(device, ccb, 12, (unsigned char *) iobuf, 0); +/* ------------------------------------------------------------------------- */ - debug("ATAPI_CMD_START_STOP returned %x\n", c); - if (c != 0) - return; - memset(ccb, 0, sizeof(ccb)); - memset(iobuf, 0, sizeof(iobuf)); - c = atapi_issue_autoreq(device, ccb, 12, (unsigned char *) iobuf, 0); +ulong ide_write(struct blk_desc *block_dev, lbaint_t blknr, lbaint_t blkcnt, + const void *buffer) +{ + int device = block_dev->devnum; + ulong n = 0; + unsigned char c; - debug("ATAPI_CMD_UNIT_TEST_READY returned %x\n", c); - if (c != 0) - return; +#ifdef CONFIG_LBA48 + unsigned char lba48 = 0; - memset(ccb, 0, sizeof(ccb)); - memset(iobuf, 0, sizeof(iobuf)); - ccb[0] = ATAPI_CMD_READ_CAP; - c = atapi_issue_autoreq(device, ccb, 12, (unsigned char *) iobuf, 8); - debug("ATAPI_CMD_READ_CAP returned %x\n", c); - if (c != 0) - return; + if (blknr & 0x0000fffff0000000ULL) { + /* more than 28 bits used, use 48bit mode */ + lba48 = 1; + } +#endif - 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]); + ide_led(DEVICE_LED(device), 1); /* LED on */ - dev_desc->lba = ((unsigned long) iobuf[0] << 24) + - ((unsigned long) iobuf[1] << 16) + - ((unsigned long) iobuf[2] << 8) + ((unsigned long) iobuf[3]); - dev_desc->blksz = ((unsigned long) iobuf[4] << 24) + - ((unsigned long) iobuf[5] << 16) + - ((unsigned long) iobuf[6] << 8) + ((unsigned long) iobuf[7]); - dev_desc->log2blksz = LOG2(dev_desc->blksz); -#ifdef CONFIG_LBA48 - /* ATAPI devices cannot use 48bit addressing (ATA/ATAPI v7) */ - dev_desc->lba48 = 0; -#endif - return; -} + /* Select device + */ + ide_outb(device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device)); + while (blkcnt-- > 0) { + c = ide_wait(device, IDE_TIME_OUT); -/* - * atapi_read: - * we transfer only one block per command, since the multiple DRQ per - * command is not yet implemented - */ -#define ATAPI_READ_MAX_BYTES 2048 /* we read max 2kbytes */ -#define ATAPI_READ_BLOCK_SIZE 2048 /* assuming CD part */ -#define ATAPI_READ_MAX_BLOCK (ATAPI_READ_MAX_BYTES/ATAPI_READ_BLOCK_SIZE) + if (c & ATA_STAT_BUSY) { + 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); +#ifdef CONFIG_SYS_64BIT_LBA + ide_outb(device, ATA_LBA_MID, (blknr >> 32) & 0xFF); + ide_outb(device, ATA_LBA_HIGH, (blknr >> 40) & 0xFF); +#else + ide_outb(device, ATA_LBA_MID, 0); + ide_outb(device, ATA_LBA_HIGH, 0); +#endif + } +#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); -ulong atapi_read(struct blk_desc *block_dev, lbaint_t blknr, lbaint_t blkcnt, - void *buffer) -{ - int device = block_dev->devnum; - ulong n = 0; - unsigned char ccb[12]; /* Command descriptor block */ - ulong cnt; +#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); - debug("atapi_read dev %d start " LBAF " blocks " LBAF - " buffer at %lX\n", device, blknr, blkcnt, (ulong) buffer); + } else +#endif + { + ide_outb(device, ATA_DEV_HD, ATA_LBA | + ATA_DEVICE(device) | ((blknr >> 24) & 0xF)); + ide_outb(device, ATA_COMMAND, ATA_CMD_WRITE); + } - do { - if (blkcnt > ATAPI_READ_MAX_BLOCK) - cnt = ATAPI_READ_MAX_BLOCK; - else - cnt = blkcnt; + udelay(50); - ccb[0] = ATAPI_CMD_READ_12; - ccb[1] = 0; /* reserved */ - ccb[2] = (unsigned char) (blknr >> 24) & 0xFF; /* MSB Block */ - ccb[3] = (unsigned char) (blknr >> 16) & 0xFF; /* */ - ccb[4] = (unsigned char) (blknr >> 8) & 0xFF; - ccb[5] = (unsigned char) blknr & 0xFF; /* LSB Block */ - ccb[6] = (unsigned char) (cnt >> 24) & 0xFF; /* MSB Block cnt */ - ccb[7] = (unsigned char) (cnt >> 16) & 0xFF; - ccb[8] = (unsigned char) (cnt >> 8) & 0xFF; - ccb[9] = (unsigned char) cnt & 0xFF; /* LSB Block */ - ccb[10] = 0; /* reserved */ - ccb[11] = 0; /* reserved */ + /* can't take over 500 ms */ + c = ide_wait(device, IDE_TIME_OUT); - if (atapi_issue_autoreq(device, ccb, 12, - (unsigned char *) buffer, - cnt * ATAPI_READ_BLOCK_SIZE) - == 0xFF) { - return n; + if ((c & (ATA_STAT_DRQ | ATA_STAT_BUSY | ATA_STAT_ERR)) != + ATA_STAT_DRQ) { + printf("Error (no IRQ) dev %d blk " LBAF + ": status %#02x\n", device, blknr, c); + goto WR_OUT; } - n += cnt; - blkcnt -= cnt; - blknr += cnt; - buffer += (cnt * ATAPI_READ_BLOCK_SIZE); - } while (blkcnt > 0); + + ide_output_data(device, buffer, ATA_SECTORWORDS); + c = ide_inb(device, ATA_STATUS); /* clear IRQ */ + ++n; + ++blknr; + buffer += ATA_BLOCKSIZE; + } +WR_OUT: + ide_led(DEVICE_LED(device), 0); /* LED off */ return n; } /* ------------------------------------------------------------------------- */ -#endif /* CONFIG_ATAPI */ +#if defined(CONFIG_OF_IDE_FIXUP) +int ide_device_present(int dev) +{ + if (dev >= CONFIG_SYS_IDE_MAXBUS) + return 0; + return ide_dev_desc[dev].type == DEV_TYPE_UNKNOWN ? 0 : 1; +} +#endif +/* ------------------------------------------------------------------------- */ U_BOOT_CMD(ide, 5, 1, do_ide, "IDE sub-system", -- cgit v1.2.1 From 2765c4d147011c9ac80cc014661321829056ee25 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 1 May 2016 11:36:01 -0600 Subject: dm: sata: Fix code style problems in cmd/sata.c This file has a few coding style problems. Fix these to make future updates easier. Signed-off-by: Simon Glass --- cmd/sata.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'cmd') diff --git a/cmd/sata.c b/cmd/sata.c index 8748ccef69..b1a64d9969 100644 --- a/cmd/sata.c +++ b/cmd/sata.c @@ -105,25 +105,27 @@ static int do_sata(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) case 1: return CMD_RET_USAGE; case 2: - if (strncmp(argv[1],"inf", 3) == 0) { + if (strncmp(argv[1], "inf", 3) == 0) { int i; + putc('\n'); for (i = 0; i < CONFIG_SYS_SATA_MAX_DEVICE; ++i) { if (sata_dev_desc[i].type == DEV_TYPE_UNKNOWN) continue; - printf ("SATA device %d: ", i); + printf("SATA device %d: ", i); dev_print(&sata_dev_desc[i]); } return 0; - } else if (strncmp(argv[1],"dev", 3) == 0) { - if ((sata_curr_device < 0) || (sata_curr_device >= CONFIG_SYS_SATA_MAX_DEVICE)) { + } else if (strncmp(argv[1], "dev", 3) == 0) { + if (sata_curr_device < 0 || + sata_curr_device >= CONFIG_SYS_SATA_MAX_DEVICE) { puts("\nno SATA devices available\n"); return 1; } printf("\nSATA device %d: ", sata_curr_device); dev_print(&sata_dev_desc[sata_curr_device]); return 0; - } else if (strncmp(argv[1],"part",4) == 0) { + } else if (strncmp(argv[1], "part", 4) == 0) { int dev, ok; for (ok = 0, dev = 0; dev < CONFIG_SYS_SATA_MAX_DEVICE; ++dev) { -- cgit v1.2.1 From c649e3c91cdc96a86ca2665fcfafaca5c4b384b1 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 1 May 2016 11:36:02 -0600 Subject: dm: scsi: Rename CONFIG_CMD_SCSI to CONFIG_SCSI This option currently enables both the command and the SCSI functionality. Rename the existing option to CONFIG_SCSI since most of the code relates to the feature. Signed-off-by: Simon Glass --- cmd/Makefile | 4 ++-- cmd/disk.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'cmd') diff --git a/cmd/Makefile b/cmd/Makefile index f95759e670..6612a3b2b5 100644 --- a/cmd/Makefile +++ b/cmd/Makefile @@ -112,7 +112,7 @@ obj-$(CONFIG_CMD_REMOTEPROC) += remoteproc.o obj-$(CONFIG_SANDBOX) += host.o obj-$(CONFIG_CMD_SATA) += sata.o obj-$(CONFIG_CMD_SF) += sf.o -obj-$(CONFIG_CMD_SCSI) += scsi.o +obj-$(CONFIG_SCSI) += scsi.o obj-$(CONFIG_CMD_SHA1SUM) += sha1sum.o obj-$(CONFIG_CMD_SETEXPR) += setexpr.o obj-$(CONFIG_CMD_SOFTSWITCH) += softswitch.o @@ -157,7 +157,7 @@ endif # !CONFIG_SPL_BUILD ifdef CONFIG_SPL_BUILD ifdef CONFIG_SPL_SATA_SUPPORT -obj-$(CONFIG_CMD_SCSI) += scsi.o +obj-$(CONFIG_SCSI) += scsi.o endif endif # CONFIG_SPL_BUILD diff --git a/cmd/disk.c b/cmd/disk.c index 2fd1717e6a..fcc4123127 100644 --- a/cmd/disk.c +++ b/cmd/disk.c @@ -8,7 +8,7 @@ #include #include -#if defined(CONFIG_CMD_IDE) || defined(CONFIG_CMD_SCSI) || \ +#if defined(CONFIG_CMD_IDE) || defined(CONFIG_SCSI) || \ defined(CONFIG_USB_STORAGE) int common_diskboot(cmd_tbl_t *cmdtp, const char *intf, int argc, char *const argv[]) -- cgit v1.2.1 From 11f610edf01abc96ca10e82e1752648ee911705b Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 1 May 2016 11:36:09 -0600 Subject: dm: scsi: Separate the non-command code into its own file At present the SCSI command code includes both the command-processing code and the core SCSI functions and data structures. Separate the latter into its own file, adding functions as needed to avoid the command code accessing data structures directly. This functions use the new legacy block functions. With this commit: - There is no CONFIG option referenced from the command code - The concept of a 'current SCSI device' is confined to the command code This will make it easier to convert this code to driver model. Signed-off-by: Simon Glass --- cmd/Makefile | 6 - cmd/scsi.c | 626 +++-------------------------------------------------------- 2 files changed, 29 insertions(+), 603 deletions(-) (limited to 'cmd') diff --git a/cmd/Makefile b/cmd/Makefile index 6612a3b2b5..e3e0c74ffc 100644 --- a/cmd/Makefile +++ b/cmd/Makefile @@ -155,12 +155,6 @@ obj-$(CONFIG_CMD_PMIC) += pmic.o obj-$(CONFIG_CMD_REGULATOR) += regulator.o endif # !CONFIG_SPL_BUILD -ifdef CONFIG_SPL_BUILD -ifdef CONFIG_SPL_SATA_SUPPORT -obj-$(CONFIG_SCSI) += scsi.o -endif -endif # CONFIG_SPL_BUILD - obj-$(CONFIG_CMD_BLOB) += blob.o # core command diff --git a/cmd/scsi.c b/cmd/scsi.c index 751fc5818a..387ca1a262 100644 --- a/cmd/scsi.c +++ b/cmd/scsi.c @@ -10,355 +10,27 @@ */ #include #include -#include -#include #include -#include -#include - -#ifdef CONFIG_SCSI_DEV_LIST -#define SCSI_DEV_LIST CONFIG_SCSI_DEV_LIST -#else -#ifdef CONFIG_SCSI_SYM53C8XX -#define SCSI_VEND_ID 0x1000 -#ifndef CONFIG_SCSI_DEV_ID -#define SCSI_DEV_ID 0x0001 -#else -#define SCSI_DEV_ID CONFIG_SCSI_DEV_ID -#endif -#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 -#define SCSI_DEV_LIST {SCSI_VEND_ID, SCSI_DEV_ID} -#endif - -#if defined(CONFIG_PCI) && !defined(CONFIG_SCSI_AHCI_PLAT) -const struct pci_device_id scsi_device_list[] = { SCSI_DEV_LIST }; -#endif -static ccb tempccb; /* temporary scsi command buffer */ - -static unsigned char tempbuff[512]; /* temporary data buffer */ - -static int scsi_max_devs; /* number of highest available scsi device */ static int scsi_curr_dev; /* current device */ -static struct blk_desc scsi_dev_desc[CONFIG_SYS_SCSI_MAX_DEVICE]; - -/* almost the maximum amount of the scsi_ext command.. */ -#define SCSI_MAX_READ_BLK 0xFFFF -#define SCSI_LBA48_READ 0xFFFFFFF - -#ifdef CONFIG_SYS_64BIT_LBA -void scsi_setup_read16(ccb *pccb, lbaint_t start, unsigned long blocks) -{ - pccb->cmd[0] = SCSI_READ16; - pccb->cmd[1] = pccb->lun << 5; - pccb->cmd[2] = (unsigned char)(start >> 56) & 0xff; - pccb->cmd[3] = (unsigned char)(start >> 48) & 0xff; - pccb->cmd[4] = (unsigned char)(start >> 40) & 0xff; - pccb->cmd[5] = (unsigned char)(start >> 32) & 0xff; - pccb->cmd[6] = (unsigned char)(start >> 24) & 0xff; - pccb->cmd[7] = (unsigned char)(start >> 16) & 0xff; - pccb->cmd[8] = (unsigned char)(start >> 8) & 0xff; - pccb->cmd[9] = (unsigned char)start & 0xff; - pccb->cmd[10] = 0; - pccb->cmd[11] = (unsigned char)(blocks >> 24) & 0xff; - pccb->cmd[12] = (unsigned char)(blocks >> 16) & 0xff; - pccb->cmd[13] = (unsigned char)(blocks >> 8) & 0xff; - pccb->cmd[14] = (unsigned char)blocks & 0xff; - pccb->cmd[15] = 0; - pccb->cmdlen = 16; - pccb->msgout[0] = SCSI_IDENTIFY; /* NOT USED */ - debug("scsi_setup_read16: cmd: %02X %02X startblk %02X%02X%02X%02X%02X%02X%02X%02X blccnt %02X%02X%02X%02X\n", - pccb->cmd[0], pccb->cmd[1], - pccb->cmd[2], pccb->cmd[3], pccb->cmd[4], pccb->cmd[5], - pccb->cmd[6], pccb->cmd[7], pccb->cmd[8], pccb->cmd[9], - pccb->cmd[11], pccb->cmd[12], pccb->cmd[13], pccb->cmd[14]); -} -#endif - -void scsi_setup_read_ext(ccb * pccb, lbaint_t start, unsigned short blocks) -{ - pccb->cmd[0] = SCSI_READ10; - pccb->cmd[1] = pccb->lun << 5; - pccb->cmd[2] = (unsigned char)(start >> 24) & 0xff; - pccb->cmd[3] = (unsigned char)(start >> 16) & 0xff; - pccb->cmd[4] = (unsigned char)(start >> 8) & 0xff; - pccb->cmd[5] = (unsigned char)start & 0xff; - pccb->cmd[6] = 0; - pccb->cmd[7] = (unsigned char)(blocks >> 8) & 0xff; - pccb->cmd[8] = (unsigned char)blocks & 0xff; - pccb->cmd[6] = 0; - pccb->cmdlen=10; - pccb->msgout[0] = SCSI_IDENTIFY; /* NOT USED */ - 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]); -} - -void scsi_setup_write_ext(ccb *pccb, lbaint_t start, unsigned short blocks) -{ - pccb->cmd[0] = SCSI_WRITE10; - pccb->cmd[1] = pccb->lun << 5; - pccb->cmd[2] = (unsigned char)(start >> 24) & 0xff; - pccb->cmd[3] = (unsigned char)(start >> 16) & 0xff; - pccb->cmd[4] = (unsigned char)(start >> 8) & 0xff; - pccb->cmd[5] = (unsigned char)start & 0xff; - pccb->cmd[6] = 0; - pccb->cmd[7] = ((unsigned char)(blocks >> 8)) & 0xff; - pccb->cmd[8] = (unsigned char)blocks & 0xff; - pccb->cmd[9] = 0; - pccb->cmdlen = 10; - pccb->msgout[0] = SCSI_IDENTIFY; /* NOT USED */ - debug("%s: cmd: %02X %02X startblk %02X%02X%02X%02X blccnt %02X%02X\n", - __func__, - pccb->cmd[0], pccb->cmd[1], - pccb->cmd[2], pccb->cmd[3], pccb->cmd[4], pccb->cmd[5], - pccb->cmd[7], pccb->cmd[8]); -} - -void scsi_setup_read6(ccb * pccb, lbaint_t start, unsigned short blocks) -{ - pccb->cmd[0] = SCSI_READ6; - pccb->cmd[1] = pccb->lun << 5 | ((unsigned char)(start >> 16) & 0x1f); - pccb->cmd[2] = (unsigned char)(start >> 8) & 0xff; - pccb->cmd[3] = (unsigned char)start & 0xff; - pccb->cmd[4] = (unsigned char)blocks & 0xff; - pccb->cmd[5] = 0; - pccb->cmdlen=6; - pccb->msgout[0] = SCSI_IDENTIFY; /* NOT USED */ - 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]); -} - - -void scsi_setup_inquiry(ccb * pccb) -{ - pccb->cmd[0] = SCSI_INQUIRY; - pccb->cmd[1] = pccb->lun << 5; - pccb->cmd[2] = 0; - pccb->cmd[3] = 0; - if (pccb->datalen > 255) - pccb->cmd[4] = 255; - else - pccb->cmd[4] = (unsigned char)pccb->datalen; - pccb->cmd[5] = 0; - pccb->cmdlen=6; - pccb->msgout[0] = SCSI_IDENTIFY; /* NOT USED */ -} - -static ulong scsi_read(struct blk_desc *block_dev, lbaint_t blknr, - lbaint_t blkcnt, void *buffer) -{ - int device = block_dev->devnum; - lbaint_t start, blks; - uintptr_t buf_addr; - unsigned short smallblks = 0; - ccb* pccb=(ccb *)&tempccb; - device&=0xff; - - /* Setup device */ - pccb->target = scsi_dev_desc[device].target; - pccb->lun = scsi_dev_desc[device].lun; - buf_addr = (unsigned long)buffer; - start = blknr; - blks = blkcnt; - debug("\nscsi_read: dev %d startblk " LBAF - ", blccnt " LBAF " buffer %lx\n", - device, start, blks, (unsigned long)buffer); - do { - pccb->pdata = (unsigned char *)buf_addr; -#ifdef CONFIG_SYS_64BIT_LBA - if (start > SCSI_LBA48_READ) { - unsigned long blocks; - blocks = min_t(lbaint_t, blks, SCSI_MAX_READ_BLK); - pccb->datalen = scsi_dev_desc[device].blksz * blocks; - scsi_setup_read16(pccb, start, blocks); - start += blocks; - blks -= blocks; - } else -#endif - if (blks > SCSI_MAX_READ_BLK) { - pccb->datalen = scsi_dev_desc[device].blksz * - SCSI_MAX_READ_BLK; - smallblks = SCSI_MAX_READ_BLK; - scsi_setup_read_ext(pccb, start, smallblks); - start += SCSI_MAX_READ_BLK; - blks -= SCSI_MAX_READ_BLK; - } - else { - pccb->datalen = scsi_dev_desc[device].blksz * blks; - smallblks = (unsigned short)blks; - scsi_setup_read_ext(pccb, start, smallblks); - start += blks; - blks=0; - } - debug("scsi_read_ext: startblk " LBAF - ", blccnt %x buffer %" PRIXPTR "\n", - start, smallblks, buf_addr); - if (scsi_exec(pccb) != true) { - scsi_print_error(pccb); - blkcnt -= blks; - break; - } - buf_addr+=pccb->datalen; - } while (blks != 0); - debug("scsi_read_ext: end startblk " LBAF - ", blccnt %x buffer %" PRIXPTR "\n", start, smallblks, buf_addr); - return blkcnt; -} - -/******************************************************************************* - * scsi_write - */ - -/* Almost the maximum amount of the scsi_ext command.. */ -#define SCSI_MAX_WRITE_BLK 0xFFFF - -static ulong scsi_write(struct blk_desc *block_dev, lbaint_t blknr, - lbaint_t blkcnt, const void *buffer) -{ - int device = block_dev->devnum; - lbaint_t start, blks; - uintptr_t buf_addr; - unsigned short smallblks; - ccb* pccb = (ccb *)&tempccb; - device &= 0xff; - /* Setup device - */ - pccb->target = scsi_dev_desc[device].target; - pccb->lun = scsi_dev_desc[device].lun; - buf_addr = (unsigned long)buffer; - start = blknr; - blks = blkcnt; - debug("\n%s: dev %d startblk " LBAF ", blccnt " LBAF " buffer %lx\n", - __func__, device, start, blks, (unsigned long)buffer); - do { - pccb->pdata = (unsigned char *)buf_addr; - if (blks > SCSI_MAX_WRITE_BLK) { - pccb->datalen = (scsi_dev_desc[device].blksz * - SCSI_MAX_WRITE_BLK); - smallblks = SCSI_MAX_WRITE_BLK; - scsi_setup_write_ext(pccb, start, smallblks); - start += SCSI_MAX_WRITE_BLK; - blks -= SCSI_MAX_WRITE_BLK; - } else { - pccb->datalen = scsi_dev_desc[device].blksz * blks; - smallblks = (unsigned short)blks; - scsi_setup_write_ext(pccb, start, smallblks); - start += blks; - blks = 0; - } - debug("%s: startblk " LBAF ", blccnt %x buffer %" PRIXPTR "\n", - __func__, start, smallblks, buf_addr); - if (scsi_exec(pccb) != true) { - scsi_print_error(pccb); - blkcnt -= blks; - break; - } - buf_addr += pccb->datalen; - } while (blks != 0); - debug("%s: end startblk " LBAF ", blccnt %x buffer %" PRIXPTR "\n", - __func__, start, smallblks, buf_addr); - return blkcnt; -} - -int scsi_get_disk_count(void) -{ - return scsi_max_devs; -} - -#if defined(CONFIG_PCI) && !defined(CONFIG_SCSI_AHCI_PLAT) -void scsi_init(void) -{ - int busdevfunc = -1; - int i; - /* - * Find a device from the list, this driver will support a single - * controller. - */ - for (i = 0; i < ARRAY_SIZE(scsi_device_list); i++) { - /* get PCI Device ID */ -#ifdef CONFIG_DM_PCI - struct udevice *dev; - int ret; - - ret = dm_pci_find_device(scsi_device_list[i].vendor, - scsi_device_list[i].device, 0, &dev); - if (!ret) { - busdevfunc = dm_pci_get_bdf(dev); - break; - } -#else - busdevfunc = pci_find_device(scsi_device_list[i].vendor, - scsi_device_list[i].device, - 0); -#endif - if (busdevfunc != -1) - break; - } - - if (busdevfunc == -1) { - printf("Error: SCSI Controller(s) "); - for (i = 0; i < ARRAY_SIZE(scsi_device_list); i++) { - printf("%04X:%04X ", - scsi_device_list[i].vendor, - scsi_device_list[i].device); - } - printf("not found\n"); - return; - } -#ifdef DEBUG - else { - printf("SCSI Controller (%04X,%04X) found (%d:%d:%d)\n", - scsi_device_list[i].vendor, - scsi_device_list[i].device, - (busdevfunc >> 16) & 0xFF, - (busdevfunc >> 11) & 0x1F, - (busdevfunc >> 8) & 0x7); - } -#endif - bootstage_start(BOOTSTAGE_ID_ACCUM_SCSI, "ahci"); - scsi_low_level_init(busdevfunc); - scsi_scan(1); - bootstage_accum(BOOTSTAGE_ID_ACCUM_SCSI); -} -#endif - -#ifdef CONFIG_PARTITIONS -struct blk_desc *scsi_get_dev(int dev) -{ - return (dev < CONFIG_SYS_SCSI_MAX_DEVICE) ? &scsi_dev_desc[dev] : NULL; -} -#endif - -#ifndef CONFIG_SPL_BUILD -/****************************************************************************** +/* * scsi boot command intepreter. Derived from diskboot */ -int do_scsiboot (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +int do_scsiboot(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) { return common_diskboot(cmdtp, "scsi", argc, argv); } -/********************************************************************************* +/* * scsi command intepreter */ -int do_scsi (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +int do_scsi(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) { switch (argc) { case 0: case 1: return CMD_RET_USAGE; - case 2: if (strncmp(argv[1], "res", 3) == 0) { printf("\nReset SCSI\n"); @@ -367,23 +39,15 @@ int do_scsi (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) return 0; } if (strncmp(argv[1], "inf", 3) == 0) { - int 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); - dev_print(&scsi_dev_desc[i]); - } + blk_list_devices(IF_TYPE_SCSI); return 0; } if (strncmp(argv[1], "dev", 3) == 0) { - if (scsi_curr_dev < 0 || - scsi_curr_dev >= CONFIG_SYS_SCSI_MAX_DEVICE) { + if (blk_print_device_num(IF_TYPE_SCSI, scsi_curr_dev)) { printf("\nno SCSI devices available\n"); - return 1; + return CMD_RET_FAILURE; } - printf("\n Device %d: ", scsi_curr_dev); - dev_print(&scsi_dev_desc[scsi_curr_dev]); + return 0; } if (strncmp(argv[1], "scan", 4) == 0) { @@ -391,46 +55,32 @@ int do_scsi (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) return 0; } if (strncmp(argv[1], "part", 4) == 0) { - int dev, ok; - 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"); - debug("print_part of %x\n", dev); - part_print(&scsi_dev_desc[dev]); - } - } - if (!ok) + if (blk_list_part(IF_TYPE_SCSI)) printf("\nno SCSI devices available\n"); - return 1; + return 0; } 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 >= CONFIG_SYS_SCSI_MAX_DEVICE) { - printf("unknown device\n"); - return 1; + + if (!blk_show_device(IF_TYPE_SCSI, dev)) { + scsi_curr_dev = dev; + printf("... is now current device\n"); + } else { + return CMD_RET_FAILURE; } - printf("\n Device %d: ", dev); - dev_print(&scsi_dev_desc[dev]); - if (scsi_dev_desc[dev].type == DEV_TYPE_UNKNOWN) - return 1; - scsi_curr_dev = dev; - printf("... is now current device\n"); return 0; } if (strncmp(argv[1], "part", 4) == 0) { int dev = (int)simple_strtoul(argv[2], NULL, 10); - if (scsi_dev_desc[dev].type != DEV_TYPE_UNKNOWN) - part_print(&scsi_dev_desc[dev]); - else - printf("\nSCSI device %d not available\n", dev); - return 1; + + if (blk_print_part_devnum(IF_TYPE_SCSI, dev)) { + printf("\nSCSI device %d not available\n", + dev); + return CMD_RET_FAILURE; + } + return 0; } return CMD_RET_USAGE; default: @@ -440,10 +90,11 @@ int do_scsi (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) ulong blk = simple_strtoul(argv[3], NULL, 16); ulong cnt = simple_strtoul(argv[4], NULL, 16); ulong n; + printf("\nSCSI read: device %d block # %ld, count %ld ... ", scsi_curr_dev, blk, cnt); - n = scsi_read(&scsi_dev_desc[scsi_curr_dev], - blk, cnt, (ulong *)addr); + n = blk_read_devnum(IF_TYPE_SCSI, scsi_curr_dev, blk, + cnt, (ulong *)addr); printf("%ld blocks read: %s\n", n, n == cnt ? "OK" : "ERROR"); return 0; @@ -452,10 +103,11 @@ int do_scsi (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) ulong blk = simple_strtoul(argv[3], NULL, 16); ulong cnt = simple_strtoul(argv[4], NULL, 16); ulong n; + printf("\nSCSI write: device %d block # %ld, count %ld ... ", scsi_curr_dev, blk, cnt); - n = scsi_write(&scsi_dev_desc[scsi_curr_dev], - blk, cnt, (ulong *)addr); + n = blk_write_devnum(IF_TYPE_SCSI, scsi_curr_dev, blk, + cnt, (ulong *)addr); printf("%ld blocks written: %s\n", n, n == cnt ? "OK" : "ERROR"); return 0; @@ -483,223 +135,3 @@ U_BOOT_CMD( "boot from SCSI device", "loadAddr dev:part" ); -#endif - -/* copy src to dest, skipping leading and trailing blanks - * and null terminate the string - */ -void scsi_ident_cpy(unsigned char *dest, unsigned char *src, unsigned int len) -{ - int start,end; - - start = 0; - while (start < len) { - if (src[start] != ' ') - break; - start++; - } - end = len-1; - while (end > start) { - if (src[end] != ' ') - break; - end--; - } - for (; start <= end; start++) - *dest ++= src[start]; - *dest='\0'; -} - - -/* Trim trailing blanks, and NUL-terminate string - */ -void scsi_trim_trail (unsigned char *str, unsigned int len) -{ - unsigned char *p = str + len - 1; - - while (len-- > 0) { - *p-- = '\0'; - if (*p != ' ') { - return; - } - } -} - -int scsi_read_capacity(ccb *pccb, lbaint_t *capacity, unsigned long *blksz) -{ - *capacity = 0; - - memset(pccb->cmd, '\0', sizeof(pccb->cmd)); - pccb->cmd[0] = SCSI_RD_CAPAC10; - pccb->cmd[1] = pccb->lun << 5; - pccb->cmdlen = 10; - pccb->msgout[0] = SCSI_IDENTIFY; /* NOT USED */ - - pccb->datalen = 8; - if (scsi_exec(pccb) != true) - return 1; - - *capacity = ((lbaint_t)pccb->pdata[0] << 24) | - ((lbaint_t)pccb->pdata[1] << 16) | - ((lbaint_t)pccb->pdata[2] << 8) | - ((lbaint_t)pccb->pdata[3]); - - if (*capacity != 0xffffffff) { - /* Read capacity (10) was sufficient for this drive. */ - *blksz = ((unsigned long)pccb->pdata[4] << 24) | - ((unsigned long)pccb->pdata[5] << 16) | - ((unsigned long)pccb->pdata[6] << 8) | - ((unsigned long)pccb->pdata[7]); - return 0; - } - - /* Read capacity (10) was insufficient. Use read capacity (16). */ - memset(pccb->cmd, '\0', sizeof(pccb->cmd)); - pccb->cmd[0] = SCSI_RD_CAPAC16; - pccb->cmd[1] = 0x10; - pccb->cmdlen = 16; - pccb->msgout[0] = SCSI_IDENTIFY; /* NOT USED */ - - pccb->datalen = 16; - if (scsi_exec(pccb) != true) - return 1; - - *capacity = ((uint64_t)pccb->pdata[0] << 56) | - ((uint64_t)pccb->pdata[1] << 48) | - ((uint64_t)pccb->pdata[2] << 40) | - ((uint64_t)pccb->pdata[3] << 32) | - ((uint64_t)pccb->pdata[4] << 24) | - ((uint64_t)pccb->pdata[5] << 16) | - ((uint64_t)pccb->pdata[6] << 8) | - ((uint64_t)pccb->pdata[7]); - - *blksz = ((uint64_t)pccb->pdata[8] << 56) | - ((uint64_t)pccb->pdata[9] << 48) | - ((uint64_t)pccb->pdata[10] << 40) | - ((uint64_t)pccb->pdata[11] << 32) | - ((uint64_t)pccb->pdata[12] << 24) | - ((uint64_t)pccb->pdata[13] << 16) | - ((uint64_t)pccb->pdata[14] << 8) | - ((uint64_t)pccb->pdata[15]); - - return 0; -} - - -/************************************************************************************ - * Some setup (fill-in) routines - */ -void scsi_setup_test_unit_ready(ccb * pccb) -{ - pccb->cmd[0] = SCSI_TST_U_RDY; - pccb->cmd[1] = pccb->lun << 5; - pccb->cmd[2] = 0; - pccb->cmd[3] = 0; - pccb->cmd[4] = 0; - pccb->cmd[5] = 0; - pccb->cmdlen = 6; - pccb->msgout[0] = SCSI_IDENTIFY; /* NOT USED */ -} - -/********************************************************************************* - * (re)-scan the scsi bus and reports scsi device info - * to the user if mode = 1 - */ -void scsi_scan(int mode) -{ - unsigned char i,perq,modi,lun; - lbaint_t capacity; - unsigned long blksz; - ccb* pccb=(ccb *)&tempccb; - - if (mode == 1) - printf("scanning bus for devices...\n"); - 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; - scsi_dev_desc[i].blksz = 0; - scsi_dev_desc[i].log2blksz = - LOG2_INVALID(typeof(scsi_dev_desc[i].log2blksz)); - scsi_dev_desc[i].type = DEV_TYPE_UNKNOWN; - scsi_dev_desc[i].vendor[0] = 0; - scsi_dev_desc[i].product[0] = 0; - scsi_dev_desc[i].revision[0] = 0; - scsi_dev_desc[i].removable = false; - scsi_dev_desc[i].if_type = IF_TYPE_SCSI; - scsi_dev_desc[i].devnum = i; - scsi_dev_desc[i].part_type = PART_TYPE_UNKNOWN; - scsi_dev_desc[i].block_read = scsi_read; - scsi_dev_desc[i].block_write = scsi_write; - } - scsi_max_devs = 0; - for (i = 0; i < CONFIG_SYS_SCSI_MAX_SCSI_ID; i++) { - pccb->target = i; - 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) { - debug("Selection timeout ID %d\n", - pccb->target); - continue; /* selection timeout => assuming no device present */ - } - scsi_print_error(pccb); - continue; - } - perq = tempbuff[0]; - modi = tempbuff[1]; - if ((perq & 0x1f) == 0x1f) - continue; /* skip unknown devices */ - if ((modi & 0x80) == 0x80) /* drive is removable */ - scsi_dev_desc[scsi_max_devs].removable = true; - /* get info for this device */ - 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; - - pccb->datalen = 0; - scsi_setup_test_unit_ready(pccb); - if (scsi_exec(pccb) != true) { - if (scsi_dev_desc[scsi_max_devs].removable) { - scsi_dev_desc[scsi_max_devs].type = - perq; - goto removable; - } - scsi_print_error(pccb); - continue; - } - if (scsi_read_capacity(pccb, &capacity, &blksz)) { - scsi_print_error(pccb); - continue; - } - scsi_dev_desc[scsi_max_devs].lba = capacity; - scsi_dev_desc[scsi_max_devs].blksz = blksz; - scsi_dev_desc[scsi_max_devs].log2blksz = - LOG2(scsi_dev_desc[scsi_max_devs].blksz); - scsi_dev_desc[scsi_max_devs].type = perq; - part_init(&scsi_dev_desc[scsi_max_devs]); -removable: - if(mode==1) { - printf (" Device %d: ", scsi_max_devs); - dev_print(&scsi_dev_desc[scsi_max_devs]); - } /* if mode */ - scsi_max_devs++; - } /* next LUN */ - } - if (scsi_max_devs > 0) - scsi_curr_dev = 0; - else - scsi_curr_dev = -1; - - printf("Found %d device(s).\n", scsi_max_devs); -#ifndef CONFIG_SPL_BUILD - setenv_ulong("scsidevs", scsi_max_devs); -#endif -} -- cgit v1.2.1 From e9be1ee75ed27c4281cad5168b6c51d26b2e8a15 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 1 May 2016 11:36:10 -0600 Subject: dm: ide: Separate the non-command code into its own file At present the IDE command code includes both the command-processing code and the core IDE functions and data structures. Separate the latter into its own file, adding functions as needed to avoid the command code accessing data structures directly. With this commit: - Most CONFIG option are referenced from the non-command code - The concept of a 'current IDE device' is confined to the command code This will make it easier to convert this code to driver model. Signed-off-by: Simon Glass --- cmd/ide.c | 1297 +------------------------------------------------------------ 1 file changed, 21 insertions(+), 1276 deletions(-) (limited to 'cmd') diff --git a/cmd/ide.c b/cmd/ide.c index db26f4320d..c942744e72 100644 --- a/cmd/ide.c +++ b/cmd/ide.c @@ -29,717 +29,9 @@ # include #endif -#ifdef __PPC__ -# define EIEIO __asm__ volatile ("eieio") -# define SYNC __asm__ volatile ("sync") -#else -# define EIEIO /* nothing */ -# define SYNC /* nothing */ -#endif - -/* ------------------------------------------------------------------------- */ - /* Current I/O Device */ static int curr_device = -1; -/* Current offset for IDE0 / IDE1 bus access */ -ulong ide_bus_offset[CONFIG_SYS_IDE_MAXBUS] = { -#if defined(CONFIG_SYS_ATA_IDE0_OFFSET) - CONFIG_SYS_ATA_IDE0_OFFSET, -#endif -#if defined(CONFIG_SYS_ATA_IDE1_OFFSET) && (CONFIG_SYS_IDE_MAXBUS > 1) - CONFIG_SYS_ATA_IDE1_OFFSET, -#endif -}; - -static int ide_bus_ok[CONFIG_SYS_IDE_MAXBUS]; - -struct blk_desc ide_dev_desc[CONFIG_SYS_IDE_MAXDEVICE]; -/* ------------------------------------------------------------------------- */ - -#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 */ - -#ifndef CONFIG_SYS_ATA_PORT_ADDR -#define CONFIG_SYS_ATA_PORT_ADDR(port) (port) -#endif - -#ifndef CONFIG_IDE_LED /* define LED macros, they are not used anyways */ -# define DEVICE_LED(x) 0 -# define LED_IDE1 1 -# define LED_IDE2 2 -#endif - -#ifdef CONFIG_IDE_RESET -extern void ide_set_reset(int idereset); - -static void ide_reset(void) -{ - int i; - - curr_device = -1; - for (i = 0; i < CONFIG_SYS_IDE_MAXBUS; ++i) - ide_bus_ok[i] = 0; - for (i = 0; i < CONFIG_SYS_IDE_MAXDEVICE; ++i) - ide_dev_desc[i].type = DEV_TYPE_UNKNOWN; - - ide_set_reset(1); /* assert reset */ - - /* the reset signal shall be asserted for et least 25 us */ - udelay(25); - - WATCHDOG_RESET(); - - /* de-assert RESET signal */ - ide_set_reset(0); - - /* wait 250 ms */ - for (i = 0; i < 250; ++i) - udelay(1000); -} -#else -#define ide_reset() /* dummy */ -#endif /* CONFIG_IDE_RESET */ - -/* - * Wait until Busy bit is off, or timeout (in ms) - * Return last status - */ -static uchar ide_wait(int dev, ulong t) -{ - ulong delay = 10 * t; /* poll every 100 us */ - uchar c; - - while ((c = ide_inb(dev, ATA_STATUS)) & ATA_STAT_BUSY) { - udelay(100); - if (delay-- == 0) - break; - } - return c; -} - -/* - * 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 *dst, unsigned char *src, - unsigned int len) -{ - unsigned char *end, *last; - - last = dst; - end = src + len - 1; - - /* reserve space for '\0' */ - if (len < 2) - goto OUT; - - /* skip leading white space */ - while ((*src) && (src < end) && (*src == ' ')) - ++src; - - /* copy string, omitting trailing white space */ - while ((*src) && (src < end)) { - *dst++ = *src; - if (*src++ != ' ') - last = dst; - } -OUT: - *last = '\0'; -} - -#ifdef CONFIG_ATAPI -/**************************************************************************** - * ATAPI Support - */ - -#if defined(CONFIG_IDE_SWAP_IO) -/* since ATAPI may use commands with not 4 bytes alligned length - * we have our own transfer functions, 2 bytes alligned */ -__weak void ide_output_data_shorts(int dev, ushort *sect_buf, int shorts) -{ - ushort *dbuf; - volatile ushort *pbuf; - - pbuf = (ushort *)(ATA_CURR_BASE(dev) + ATA_DATA_REG); - dbuf = (ushort *)sect_buf; - - debug("in output data shorts base for read is %lx\n", - (unsigned long) pbuf); - - while (shorts--) { - EIEIO; - *pbuf = *dbuf++; - } -} - -__weak void ide_input_data_shorts(int dev, ushort *sect_buf, int shorts) -{ - ushort *dbuf; - volatile ushort *pbuf; - - pbuf = (ushort *)(ATA_CURR_BASE(dev) + ATA_DATA_REG); - dbuf = (ushort *)sect_buf; - - debug("in input data shorts base for read is %lx\n", - (unsigned long) pbuf); - - while (shorts--) { - EIEIO; - *dbuf++ = *pbuf; - } -} - -#else /* ! CONFIG_IDE_SWAP_IO */ -__weak void ide_output_data_shorts(int dev, ushort *sect_buf, int shorts) -{ - outsw(ATA_CURR_BASE(dev) + ATA_DATA_REG, sect_buf, shorts); -} - -__weak void ide_input_data_shorts(int dev, ushort *sect_buf, int shorts) -{ - insw(ATA_CURR_BASE(dev) + ATA_DATA_REG, sect_buf, shorts); -} - -#endif /* CONFIG_IDE_SWAP_IO */ - -/* - * Wait until (Status & mask) == res, or timeout (in ms) - * Return last status - * This is used since some ATAPI CD ROMs clears their Busy Bit first - * and then they set their DRQ Bit - */ -static uchar atapi_wait_mask(int dev, ulong t, uchar mask, uchar res) -{ - ulong delay = 10 * t; /* poll every 100 us */ - uchar c; - - /* prevents to read the status before valid */ - c = ide_inb(dev, ATA_DEV_CTL); - - while (((c = ide_inb(dev, ATA_STATUS)) & mask) != res) { - /* break if error occurs (doesn't make sense to wait more) */ - if ((c & ATA_STAT_ERR) == ATA_STAT_ERR) - break; - udelay(100); - if (delay-- == 0) - break; - } - return c; -} - -/* - * issue an atapi command - */ -unsigned char atapi_issue(int device, unsigned char *ccb, int ccblen, - unsigned char *buffer, int buflen) -{ - unsigned char c, err, mask, res; - int n; - - ide_led(DEVICE_LED(device), 1); /* LED on */ - - /* Select device - */ - mask = ATA_STAT_BUSY | ATA_STAT_DRQ; - res = 0; - ide_outb(device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device)); - c = atapi_wait_mask(device, ATAPI_TIME_OUT, mask, res); - if ((c & mask) != res) { - printf("ATAPI_ISSUE: device %d not ready status %X\n", device, - c); - err = 0xFF; - goto AI_OUT; - } - /* write taskfile */ - ide_outb(device, ATA_ERROR_REG, 0); /* no DMA, no overlaped */ - ide_outb(device, ATA_SECT_CNT, 0); - ide_outb(device, ATA_SECT_NUM, 0); - ide_outb(device, ATA_CYL_LOW, (unsigned char) (buflen & 0xFF)); - ide_outb(device, ATA_CYL_HIGH, - (unsigned char) ((buflen >> 8) & 0xFF)); - ide_outb(device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device)); - - ide_outb(device, ATA_COMMAND, ATAPI_CMD_PACKET); - udelay(50); - - mask = ATA_STAT_DRQ | ATA_STAT_BUSY | ATA_STAT_ERR; - res = ATA_STAT_DRQ; - c = atapi_wait_mask(device, ATAPI_TIME_OUT, mask, res); - - if ((c & mask) != res) { /* DRQ must be 1, BSY 0 */ - printf("ATAPI_ISSUE: Error (no IRQ) before sending ccb dev %d status 0x%02x\n", - device, c); - err = 0xFF; - goto AI_OUT; - } - - /* write command block */ - ide_output_data_shorts(device, (unsigned short *)ccb, ccblen / 2); - - /* ATAPI Command written wait for completition */ - udelay(5000); /* device must set bsy */ - - mask = ATA_STAT_DRQ | ATA_STAT_BUSY | ATA_STAT_ERR; - /* - * if no data wait for DRQ = 0 BSY = 0 - * if data wait for DRQ = 1 BSY = 0 - */ - res = 0; - if (buflen) - res = ATA_STAT_DRQ; - c = atapi_wait_mask(device, ATAPI_TIME_OUT, mask, res); - if ((c & mask) != res) { - if (c & ATA_STAT_ERR) { - err = (ide_inb(device, ATA_ERROR_REG)) >> 4; - debug("atapi_issue 1 returned sense key %X status %02X\n", - err, c); - } else { - printf("ATAPI_ISSUE: (no DRQ) after sending ccb (%x) status 0x%02x\n", - ccb[0], c); - err = 0xFF; - } - goto AI_OUT; - } - n = ide_inb(device, ATA_CYL_HIGH); - n <<= 8; - n += ide_inb(device, ATA_CYL_LOW); - if (n > buflen) { - printf("ERROR, transfer bytes %d requested only %d\n", n, - buflen); - err = 0xff; - goto AI_OUT; - } - if ((n == 0) && (buflen < 0)) { - printf("ERROR, transfer bytes %d requested %d\n", n, buflen); - err = 0xff; - goto AI_OUT; - } - if (n != buflen) { - debug("WARNING, transfer bytes %d not equal with requested %d\n", - n, buflen); - } - if (n != 0) { /* data transfer */ - 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) { - debug("Write to device\n"); - ide_output_data_shorts(device, (unsigned short *)buffer, - n); - } else { - debug("Read from device @ %p shorts %d\n", buffer, n); - ide_input_data_shorts(device, (unsigned short *)buffer, - n); - } - } - udelay(5000); /* seems that some CD ROMs need this... */ - mask = ATA_STAT_BUSY | ATA_STAT_ERR; - res = 0; - 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); - debug("atapi_issue 2 returned sense key %X status %X\n", err, - c); - } else { - err = 0; - } -AI_OUT: - ide_led(DEVICE_LED(device), 0); /* LED off */ - return err; -} - -/* - * sending the command to atapi_issue. If an status other than good - * returns, an request_sense will be issued - */ - -#define ATAPI_DRIVE_NOT_READY 100 -#define ATAPI_UNIT_ATTN 10 - -unsigned char atapi_issue_autoreq(int device, - unsigned char *ccb, - int ccblen, - unsigned char *buffer, int buflen) -{ - unsigned char sense_data[18], sense_ccb[12]; - unsigned char res, key, asc, ascq; - int notready, unitattn; - - unitattn = ATAPI_UNIT_ATTN; - notready = ATAPI_DRIVE_NOT_READY; - -retry: - res = atapi_issue(device, ccb, ccblen, buffer, buflen); - if (res == 0) - return 0; /* Ok */ - - if (res == 0xFF) - return 0xFF; /* error */ - - 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)); - sense_ccb[0] = ATAPI_CMD_REQ_SENSE; - sense_ccb[4] = 18; /* allocation Length */ - - res = atapi_issue(device, sense_ccb, 12, sense_data, 18); - key = (sense_data[2] & 0xF); - asc = (sense_data[12]); - ascq = (sense_data[13]); - - 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, ascq); - - if ((key == 0)) - return 0; /* ok device ready */ - - if ((key == 6) || (asc == 0x29) || (asc == 0x28)) { /* Unit Attention */ - if (unitattn-- > 0) { - udelay(200 * 1000); - goto retry; - } - printf("Unit Attention, tried %d\n", ATAPI_UNIT_ATTN); - goto error; - } - if ((asc == 0x4) && (ascq == 0x1)) { - /* not ready, but will be ready soon */ - if (notready-- > 0) { - udelay(200 * 1000); - goto retry; - } - printf("Drive not ready, tried %d times\n", - ATAPI_DRIVE_NOT_READY); - goto error; - } - if (asc == 0x3a) { - debug("Media not present\n"); - goto error; - } - - printf("ERROR: Unknown Sense key %02X ASC %02X ASCQ %02X\n", key, asc, - ascq); -error: - debug("ERROR Sense key %02X ASC %02X ASCQ %02X\n", key, asc, ascq); - return 0xFF; -} - -/* - * atapi_read: - * we transfer only one block per command, since the multiple DRQ per - * command is not yet implemented - */ -#define ATAPI_READ_MAX_BYTES 2048 /* we read max 2kbytes */ -#define ATAPI_READ_BLOCK_SIZE 2048 /* assuming CD part */ -#define ATAPI_READ_MAX_BLOCK (ATAPI_READ_MAX_BYTES/ATAPI_READ_BLOCK_SIZE) - -ulong atapi_read(struct blk_desc *block_dev, lbaint_t blknr, lbaint_t blkcnt, - void *buffer) -{ - int device = block_dev->devnum; - ulong n = 0; - unsigned char ccb[12]; /* Command descriptor block */ - ulong cnt; - - debug("atapi_read dev %d start " LBAF " blocks " LBAF - " buffer at %lX\n", device, blknr, blkcnt, (ulong) buffer); - - do { - if (blkcnt > ATAPI_READ_MAX_BLOCK) - cnt = ATAPI_READ_MAX_BLOCK; - else - cnt = blkcnt; - - ccb[0] = ATAPI_CMD_READ_12; - ccb[1] = 0; /* reserved */ - ccb[2] = (unsigned char) (blknr >> 24) & 0xFF; /* MSB Block */ - ccb[3] = (unsigned char) (blknr >> 16) & 0xFF; /* */ - ccb[4] = (unsigned char) (blknr >> 8) & 0xFF; - ccb[5] = (unsigned char) blknr & 0xFF; /* LSB Block */ - ccb[6] = (unsigned char) (cnt >> 24) & 0xFF; /* MSB Block cnt */ - ccb[7] = (unsigned char) (cnt >> 16) & 0xFF; - ccb[8] = (unsigned char) (cnt >> 8) & 0xFF; - ccb[9] = (unsigned char) cnt & 0xFF; /* LSB Block */ - ccb[10] = 0; /* reserved */ - ccb[11] = 0; /* reserved */ - - if (atapi_issue_autoreq(device, ccb, 12, - (unsigned char *)buffer, - cnt * ATAPI_READ_BLOCK_SIZE) - == 0xFF) { - return n; - } - n += cnt; - blkcnt -= cnt; - blknr += cnt; - buffer += (cnt * ATAPI_READ_BLOCK_SIZE); - } while (blkcnt > 0); - return n; -} - -static void atapi_inquiry(struct blk_desc *dev_desc) -{ - unsigned char ccb[12]; /* Command descriptor block */ - unsigned char iobuf[64]; /* temp buf */ - unsigned char c; - int device; - - device = dev_desc->devnum; - dev_desc->type = DEV_TYPE_UNKNOWN; /* not yet valid */ - dev_desc->block_read = atapi_read; - - memset(ccb, 0, sizeof(ccb)); - memset(iobuf, 0, sizeof(iobuf)); - - ccb[0] = ATAPI_CMD_INQUIRY; - ccb[4] = 40; /* allocation Legnth */ - c = atapi_issue_autoreq(device, ccb, 12, (unsigned char *)iobuf, 40); - - debug("ATAPI_CMD_INQUIRY returned %x\n", c); - if (c != 0) - return; - - /* copy device ident strings */ - ident_cpy((unsigned char *)dev_desc->vendor, &iobuf[8], 8); - ident_cpy((unsigned char *)dev_desc->product, &iobuf[16], 16); - ident_cpy((unsigned char *)dev_desc->revision, &iobuf[32], 5); - - dev_desc->lun = 0; - dev_desc->lba = 0; - dev_desc->blksz = 0; - dev_desc->log2blksz = LOG2_INVALID(typeof(dev_desc->log2blksz)); - dev_desc->type = iobuf[0] & 0x1f; - - if ((iobuf[1] & 0x80) == 0x80) - dev_desc->removable = 1; - else - dev_desc->removable = 0; - - memset(ccb, 0, sizeof(ccb)); - memset(iobuf, 0, sizeof(iobuf)); - ccb[0] = ATAPI_CMD_START_STOP; - ccb[4] = 0x03; /* start */ - - c = atapi_issue_autoreq(device, ccb, 12, (unsigned char *)iobuf, 0); - - debug("ATAPI_CMD_START_STOP returned %x\n", c); - if (c != 0) - return; - - memset(ccb, 0, sizeof(ccb)); - memset(iobuf, 0, sizeof(iobuf)); - c = atapi_issue_autoreq(device, ccb, 12, (unsigned char *)iobuf, 0); - - debug("ATAPI_CMD_UNIT_TEST_READY returned %x\n", c); - if (c != 0) - return; - - memset(ccb, 0, sizeof(ccb)); - memset(iobuf, 0, sizeof(iobuf)); - ccb[0] = ATAPI_CMD_READ_CAP; - c = atapi_issue_autoreq(device, ccb, 12, (unsigned char *)iobuf, 8); - debug("ATAPI_CMD_READ_CAP returned %x\n", c); - if (c != 0) - return; - - 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]); - - dev_desc->lba = ((unsigned long) iobuf[0] << 24) + - ((unsigned long) iobuf[1] << 16) + - ((unsigned long) iobuf[2] << 8) + ((unsigned long) iobuf[3]); - dev_desc->blksz = ((unsigned long) iobuf[4] << 24) + - ((unsigned long) iobuf[5] << 16) + - ((unsigned long) iobuf[6] << 8) + ((unsigned long) iobuf[7]); - dev_desc->log2blksz = LOG2(dev_desc->blksz); -#ifdef CONFIG_LBA48 - /* ATAPI devices cannot use 48bit addressing (ATA/ATAPI v7) */ - dev_desc->lba48 = 0; -#endif - return; -} - -#endif /* CONFIG_ATAPI */ - -static void ide_ident(struct blk_desc *dev_desc) -{ - unsigned char c; - hd_driveid_t iop; - -#ifdef CONFIG_ATAPI - int retries = 0; -#endif - int device; - - device = dev_desc->devnum; - printf(" Device %d: ", device); - - ide_led(DEVICE_LED(device), 1); /* LED on */ - /* Select device - */ - ide_outb(device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device)); - dev_desc->if_type = IF_TYPE_IDE; -#ifdef CONFIG_ATAPI - - retries = 0; - - /* Warning: This will be tricky to read */ - while (retries <= 1) { - /* check signature */ - if ((ide_inb(device, ATA_SECT_CNT) == 0x01) && - (ide_inb(device, ATA_SECT_NUM) == 0x01) && - (ide_inb(device, ATA_CYL_LOW) == 0x14) && - (ide_inb(device, ATA_CYL_HIGH) == 0xEB)) { - /* ATAPI Signature found */ - dev_desc->if_type = IF_TYPE_ATAPI; - /* - * Start Ident Command - */ - ide_outb(device, ATA_COMMAND, ATAPI_CMD_IDENT); - /* - * Wait for completion - ATAPI devices need more time - * to become ready - */ - c = ide_wait(device, ATAPI_TIME_OUT); - } else -#endif - { - /* - * Start Ident Command - */ - ide_outb(device, ATA_COMMAND, ATA_CMD_IDENT); - - /* - * Wait for completion - */ - c = ide_wait(device, IDE_TIME_OUT); - } - ide_led(DEVICE_LED(device), 0); /* LED off */ - - if (((c & ATA_STAT_DRQ) == 0) || - ((c & (ATA_STAT_FAULT | ATA_STAT_ERR)) != 0)) { -#ifdef CONFIG_ATAPI - { - /* - * 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 */ - } - /* - * Select device - */ - ide_outb(device, ATA_DEV_HD, - ATA_LBA | ATA_DEVICE(device)); - retries++; -#else - return; -#endif - } -#ifdef CONFIG_ATAPI - else - break; - } /* see above - ugly to read */ - - if (retries == 2) /* Not found */ - return; -#endif - - ide_input_swap_data(device, (ulong *)&iop, ATA_SECTORWORDS); - - ident_cpy((unsigned char *)dev_desc->revision, iop.fw_rev, - sizeof(dev_desc->revision)); - ident_cpy((unsigned char *)dev_desc->vendor, iop.model, - sizeof(dev_desc->vendor)); - ident_cpy((unsigned char *)dev_desc->product, iop.serial_no, - sizeof(dev_desc->product)); -#ifdef __LITTLE_ENDIAN - /* - * firmware revision, model, and serial number have Big Endian Byte - * order in Word. Convert all three to little endian. - * - * See CF+ and CompactFlash Specification Revision 2.0: - * 6.2.1.6: Identify Drive, Table 39 for more details - */ - - strswab(dev_desc->revision); - strswab(dev_desc->vendor); - strswab(dev_desc->product); -#endif /* __LITTLE_ENDIAN */ - - if ((iop.config & 0x0080) == 0x0080) - dev_desc->removable = 1; - else - dev_desc->removable = 0; - -#ifdef CONFIG_ATAPI - if (dev_desc->if_type == IF_TYPE_ATAPI) { - atapi_inquiry(dev_desc); - return; - } -#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; - dev_desc->log2blksz = LOG2(dev_desc->blksz); - dev_desc->lun = 0; /* just to fill something in... */ - -#if 0 /* only used to test the powersaving mode, - * if enabled, the drive goes after 5 sec - * in standby mode */ - ide_outb(device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device)); - c = ide_wait(device, IDE_TIME_OUT); - ide_outb(device, ATA_SECT_CNT, 1); - 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_COMMAND, 0xe3); - udelay(50); - c = ide_wait(device, IDE_TIME_OUT); /* can't take over 500 ms */ -#endif -} - -/* ------------------------------------------------------------------------- */ - int do_ide(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) { int rcode = 0; @@ -759,79 +51,41 @@ int do_ide(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) ide_init(); return 0; } else if (strncmp(argv[1], "inf", 3) == 0) { - int i; - - putc('\n'); - - for (i = 0; i < CONFIG_SYS_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]); - } + blk_list_devices(IF_TYPE_IDE); return 0; } else if (strncmp(argv[1], "dev", 3) == 0) { - if (curr_device < 0 || - curr_device >= CONFIG_SYS_IDE_MAXDEVICE) { - puts("\nno IDE devices available\n"); - return 1; + if (blk_print_device_num(IF_TYPE_IDE, curr_device)) { + printf("\nno IDE devices available\n"); + return CMD_RET_FAILURE; } - 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 < CONFIG_SYS_IDE_MAXDEVICE; - ++dev) { - if (ide_dev_desc[dev].part_type != - PART_TYPE_UNKNOWN) { - ++ok; - if (dev) - putc('\n'); - part_print(&ide_dev_desc[dev]); - } - } - if (!ok) { - puts("\nno IDE devices available\n"); - rcode++; - } - return rcode; + if (blk_list_part(IF_TYPE_IDE)) + printf("\nno IDE devices available\n"); + return 1; } return CMD_RET_USAGE; 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 >= CONFIG_SYS_IDE_MAXDEVICE) { - puts("unknown device\n"); - return 1; + if (!blk_show_device(IF_TYPE_IDE, dev)) { + curr_device = dev; + printf("... is now current device\n"); + } else { + return CMD_RET_FAILURE; } - 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) { - part_print(&ide_dev_desc[dev]); - } else { - printf("\nIDE device %d not available\n", - dev); - rcode = 1; + if (blk_print_part_devnum(IF_TYPE_IDE, dev)) { + printf("\nIDE device %d not available\n", dev); + return CMD_RET_FAILURE; } - return rcode; + return 1; } return CMD_RET_USAGE; @@ -841,7 +95,6 @@ int do_ide(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) if (strcmp(argv[1], "read") == 0) { ulong addr = simple_strtoul(argv[2], NULL, 16); ulong cnt = simple_strtoul(argv[4], NULL, 16); - struct blk_desc *dev_desc; ulong n; #ifdef CONFIG_SYS_64BIT_LBA @@ -856,11 +109,8 @@ int do_ide(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) curr_device, blk, cnt); #endif - dev_desc = &ide_dev_desc[curr_device]; - n = blk_dread(dev_desc, blk, cnt, (ulong *)addr); - /* flush cache after read */ - flush_cache(addr, - cnt * ide_dev_desc[curr_device].blksz); + n = blk_read_devnum(IF_TYPE_IDE, curr_device, blk, cnt, + (ulong *)addr); printf("%ld blocks read: %s\n", n, (n == cnt) ? "OK" : "ERROR"); @@ -884,8 +134,8 @@ int do_ide(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) printf("\nIDE write: device %d block # %ld, count %ld...", curr_device, blk, cnt); #endif - n = ide_write(&ide_dev_desc[curr_device], blk, cnt, - (ulong *)addr); + n = blk_write_devnum(IF_TYPE_IDE, curr_device, blk, cnt, + (ulong *)addr); printf("%ld blocks written: %s\n", n, n == cnt ? "OK" : "ERROR"); @@ -906,511 +156,6 @@ int do_diskboot(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) return common_diskboot(cmdtp, "ide", argc, argv); } -/* ------------------------------------------------------------------------- */ - -__weak void ide_led(uchar led, uchar status) -{ -#if defined(CONFIG_IDE_LED) && defined(PER8_BASE) /* required by LED_PORT */ - static uchar led_buffer; /* Buffer for current LED status */ - - uchar *led_port = LED_PORT; - - if (status) /* switch LED on */ - led_buffer |= led; - else /* switch LED off */ - led_buffer &= ~led; - - *led_port = led_buffer; -#endif -} - -/* ------------------------------------------------------------------------- */ - -__weak void 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) + CONFIG_SYS_ATA_PORT_ADDR(port))); - -#if defined(CONFIG_IDE_AHB) - if (port) { - /* write command */ - ide_write_register(dev, port, val); - } else { - /* write data */ - outb(val, (ATA_CURR_BASE(dev))); - } -#else - outb(val, (ATA_CURR_BASE(dev) + CONFIG_SYS_ATA_PORT_ADDR(port))); -#endif -} - -__weak unsigned char ide_inb(int dev, int port) -{ - uchar val; - -#if defined(CONFIG_IDE_AHB) - val = ide_read_register(dev, port); -#else - val = inb((ATA_CURR_BASE(dev) + CONFIG_SYS_ATA_PORT_ADDR(port))); -#endif - - debug("ide_inb (dev= %d, port= 0x%x) : @ 0x%08lx -> 0x%02x\n", - dev, port, - (ATA_CURR_BASE(dev) + CONFIG_SYS_ATA_PORT_ADDR(port)), val); - return val; -} - -void ide_init(void) -{ - unsigned char c; - int i, bus; - -#ifdef CONFIG_IDE_8xx_PCCARD - extern int ide_devices_found; /* Initialized in check_ide_device() */ -#endif /* CONFIG_IDE_8xx_PCCARD */ - -#ifdef CONFIG_IDE_PREINIT - WATCHDOG_RESET(); - - if (ide_preinit()) { - puts("ide_preinit failed\n"); - return; - } -#endif /* CONFIG_IDE_PREINIT */ - - WATCHDOG_RESET(); - - /* - * Reset the IDE just to be sure. - * Light LED's to show - */ - ide_led((LED_IDE1 | LED_IDE2), 1); /* LED's on */ - - /* ATAPI Drives seems to need a proper IDE Reset */ - ide_reset(); - -#ifdef CONFIG_IDE_INIT_POSTRESET - WATCHDOG_RESET(); - - if (ide_init_postreset()) { - puts("ide_preinit_postreset failed\n"); - return; - } -#endif /* CONFIG_IDE_INIT_POSTRESET */ - - /* - * Wait for IDE to get ready. - * According to spec, this can take up to 31 seconds! - */ - for (bus = 0; bus < CONFIG_SYS_IDE_MAXBUS; ++bus) { - int dev = - bus * (CONFIG_SYS_IDE_MAXDEVICE / - CONFIG_SYS_IDE_MAXBUS); - -#ifdef CONFIG_IDE_8xx_PCCARD - /* Skip non-ide devices from probing */ - if ((ide_devices_found & (1 << bus)) == 0) { - ide_led((LED_IDE1 | LED_IDE2), 0); /* LED's off */ - continue; - } -#endif - printf("Bus %d: ", bus); - - ide_bus_ok[bus] = 0; - - /* Select device - */ - udelay(100000); /* 100 ms */ - ide_outb(dev, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(dev)); - udelay(100000); /* 100 ms */ - i = 0; - do { - udelay(10000); /* 10 ms */ - - c = ide_inb(dev, ATA_STATUS); - i++; - if (i > (ATA_RESET_TIME * 100)) { - puts("** Timeout **\n"); - /* LED's off */ - ide_led((LED_IDE1 | LED_IDE2), 0); - return; - } - if ((i >= 100) && ((i % 100) == 0)) - putc('.'); - - } while (c & ATA_STAT_BUSY); - - if (c & (ATA_STAT_BUSY | ATA_STAT_FAULT)) { - puts("not available "); - debug("Status = 0x%02X ", c); -#ifndef CONFIG_ATAPI /* ATAPI Devices do not set DRDY */ - } else if ((c & ATA_STAT_READY) == 0) { - puts("not available "); - debug("Status = 0x%02X ", c); -#endif - } else { - puts("OK "); - ide_bus_ok[bus] = 1; - } - WATCHDOG_RESET(); - } - - putc('\n'); - - ide_led((LED_IDE1 | LED_IDE2), 0); /* LED's off */ - - curr_device = -1; - for (i = 0; i < CONFIG_SYS_IDE_MAXDEVICE; ++i) { - int led = (IDE_BUS(i) == 0) ? LED_IDE1 : LED_IDE2; - ide_dev_desc[i].type = DEV_TYPE_UNKNOWN; - ide_dev_desc[i].if_type = IF_TYPE_IDE; - ide_dev_desc[i].devnum = i; - ide_dev_desc[i].part_type = PART_TYPE_UNKNOWN; - ide_dev_desc[i].blksz = 0; - ide_dev_desc[i].log2blksz = - LOG2_INVALID(typeof(ide_dev_desc[i].log2blksz)); - ide_dev_desc[i].lba = 0; - ide_dev_desc[i].block_read = ide_read; - ide_dev_desc[i].block_write = ide_write; - if (!ide_bus_ok[IDE_BUS(i)]) - continue; - ide_led(led, 1); /* LED on */ - ide_ident(&ide_dev_desc[i]); - ide_led(led, 0); /* LED off */ - dev_print(&ide_dev_desc[i]); - - if ((ide_dev_desc[i].lba > 0) && (ide_dev_desc[i].blksz > 0)) { - /* initialize partition type */ - part_init(&ide_dev_desc[i]); - if (curr_device < 0) - curr_device = i; - } - } - WATCHDOG_RESET(); -} - -/* ------------------------------------------------------------------------- */ - -#ifdef CONFIG_PARTITIONS -struct blk_desc *ide_get_dev(int dev) -{ - return (dev < CONFIG_SYS_IDE_MAXDEVICE) ? &ide_dev_desc[dev] : NULL; -} -#endif - -/* ------------------------------------------------------------------------- */ - -/* We only need to swap data if we are running on a big endian cpu. */ -#if defined(__LITTLE_ENDIAN) -__weak void ide_input_swap_data(int dev, ulong *sect_buf, int words) -{ - ide_input_data(dev, sect_buf, words); -} -#else -__weak void ide_input_swap_data(int dev, ulong *sect_buf, int words) -{ - 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 /* __LITTLE_ENDIAN */ - - -#if defined(CONFIG_IDE_SWAP_IO) -__weak void ide_output_data(int dev, const 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--) { - EIEIO; - *pbuf = *dbuf++; - EIEIO; - *pbuf = *dbuf++; - } -} -#else /* ! CONFIG_IDE_SWAP_IO */ -__weak void ide_output_data(int dev, const ulong *sect_buf, int words) -{ -#if defined(CONFIG_IDE_AHB) - ide_write_data(dev, sect_buf, words); -#else - outsw(ATA_CURR_BASE(dev) + ATA_DATA_REG, sect_buf, words << 1); -#endif -} -#endif /* CONFIG_IDE_SWAP_IO */ - -#if defined(CONFIG_IDE_SWAP_IO) -__weak void ide_input_data(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; - - debug("in input data base for read is %lx\n", (unsigned long) pbuf); - - while (words--) { - EIEIO; - *dbuf++ = *pbuf; - EIEIO; - *dbuf++ = *pbuf; - } -} -#else /* ! CONFIG_IDE_SWAP_IO */ -__weak void ide_input_data(int dev, ulong *sect_buf, int words) -{ -#if defined(CONFIG_IDE_AHB) - ide_read_data(dev, sect_buf, words); -#else - insw(ATA_CURR_BASE(dev) + ATA_DATA_REG, sect_buf, words << 1); -#endif -} - -#endif /* CONFIG_IDE_SWAP_IO */ - -/* ------------------------------------------------------------------------- */ - -ulong ide_read(struct blk_desc *block_dev, lbaint_t blknr, lbaint_t blkcnt, - void *buffer) -{ - int device = block_dev->devnum; - ulong n = 0; - unsigned char c; - unsigned char pwrsave = 0; /* power save */ - -#ifdef CONFIG_LBA48 - unsigned char lba48 = 0; - - if (blknr & 0x0000fffff0000000ULL) { - /* more than 28 bits used, use 48bit mode */ - lba48 = 1; - } -#endif - debug("ide_read dev %d start " LBAF ", blocks " LBAF " buffer at %lX\n", - device, blknr, blkcnt, (ulong) buffer); - - ide_led(DEVICE_LED(device), 1); /* LED on */ - - /* Select device - */ - ide_outb(device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device)); - c = ide_wait(device, IDE_TIME_OUT); - - if (c & ATA_STAT_BUSY) { - printf("IDE read: device %d not ready\n", device); - goto IDE_READ_E; - } - - /* first check if the drive is in Powersaving mode, if yes, - * increase the timeout value */ - ide_outb(device, ATA_COMMAND, ATA_CMD_CHK_PWR); - udelay(50); - - c = ide_wait(device, IDE_TIME_OUT); /* can't take over 500 ms */ - - if (c & ATA_STAT_BUSY) { - printf("IDE read: device %d not ready\n", device); - goto IDE_READ_E; - } - if ((c & ATA_STAT_ERR) == ATA_STAT_ERR) { - printf("No Powersaving mode %X\n", c); - } else { - c = ide_inb(device, ATA_SECT_CNT); - debug("Powersaving %02X\n", c); - if (c == 0) - pwrsave = 1; - } - - - while (blkcnt-- > 0) { - - c = ide_wait(device, IDE_TIME_OUT); - - if (c & ATA_STAT_BUSY) { - 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); -#ifdef CONFIG_SYS_64BIT_LBA - ide_outb(device, ATA_LBA_MID, (blknr >> 32) & 0xFF); - ide_outb(device, ATA_LBA_HIGH, (blknr >> 40) & 0xFF); -#else - ide_outb(device, ATA_LBA_MID, 0); - ide_outb(device, ATA_LBA_HIGH, 0); -#endif - } -#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); - -#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); - - if (pwrsave) { - /* may take up to 4 sec */ - c = ide_wait(device, IDE_SPIN_UP_TIME_OUT); - pwrsave = 0; - } else { - /* can't take over 500 ms */ - c = ide_wait(device, IDE_TIME_OUT); - } - - if ((c & (ATA_STAT_DRQ | ATA_STAT_BUSY | ATA_STAT_ERR)) != - ATA_STAT_DRQ) { - printf("Error (no IRQ) dev %d blk " LBAF - ": status %#02x\n", device, blknr, c); - break; - } - - ide_input_data(device, buffer, ATA_SECTORWORDS); - (void) ide_inb(device, ATA_STATUS); /* clear IRQ */ - - ++n; - ++blknr; - buffer += ATA_BLOCKSIZE; - } -IDE_READ_E: - ide_led(DEVICE_LED(device), 0); /* LED off */ - return n; -} - -/* ------------------------------------------------------------------------- */ - - -ulong ide_write(struct blk_desc *block_dev, lbaint_t blknr, lbaint_t blkcnt, - const void *buffer) -{ - int device = block_dev->devnum; - ulong n = 0; - unsigned char c; - -#ifdef CONFIG_LBA48 - unsigned char lba48 = 0; - - if (blknr & 0x0000fffff0000000ULL) { - /* more than 28 bits used, use 48bit mode */ - lba48 = 1; - } -#endif - - ide_led(DEVICE_LED(device), 1); /* LED on */ - - /* Select device - */ - ide_outb(device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device)); - - while (blkcnt-- > 0) { - c = ide_wait(device, IDE_TIME_OUT); - - if (c & ATA_STAT_BUSY) { - 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); -#ifdef CONFIG_SYS_64BIT_LBA - ide_outb(device, ATA_LBA_MID, (blknr >> 32) & 0xFF); - ide_outb(device, ATA_LBA_HIGH, (blknr >> 40) & 0xFF); -#else - ide_outb(device, ATA_LBA_MID, 0); - ide_outb(device, ATA_LBA_HIGH, 0); -#endif - } -#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); - -#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); - - /* can't take over 500 ms */ - c = ide_wait(device, IDE_TIME_OUT); - - if ((c & (ATA_STAT_DRQ | ATA_STAT_BUSY | ATA_STAT_ERR)) != - ATA_STAT_DRQ) { - printf("Error (no IRQ) dev %d blk " LBAF - ": status %#02x\n", device, blknr, c); - goto WR_OUT; - } - - ide_output_data(device, buffer, ATA_SECTORWORDS); - c = ide_inb(device, ATA_STATUS); /* clear IRQ */ - ++n; - ++blknr; - buffer += ATA_BLOCKSIZE; - } -WR_OUT: - ide_led(DEVICE_LED(device), 0); /* LED off */ - return n; -} - -/* ------------------------------------------------------------------------- */ - -#if defined(CONFIG_OF_IDE_FIXUP) -int ide_device_present(int dev) -{ - if (dev >= CONFIG_SYS_IDE_MAXBUS) - return 0; - return ide_dev_desc[dev].type == DEV_TYPE_UNKNOWN ? 0 : 1; -} -#endif -/* ------------------------------------------------------------------------- */ - U_BOOT_CMD(ide, 5, 1, do_ide, "IDE sub-system", "reset - reset IDE controller\n" -- cgit v1.2.1 From d97dc8a0e6d38d11848ee78669639324edc0df01 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 1 May 2016 11:36:11 -0600 Subject: dm: sata: Separate the non-command code into its own file At present the SATA command code includes both the command-processing code and the core SATA functions and data structures. Separate the latter into its own file, adding functions as needed to avoid the command code accessing data structures directly. With this commit: - All CONFIG option are referenced from the non-command code - The concept of a 'current SATA device' is confined to the command code This will make it easier to convert this code to driver model. Signed-off-by: Simon Glass --- cmd/sata.c | 138 +++++++++---------------------------------------------------- 1 file changed, 20 insertions(+), 118 deletions(-) (limited to 'cmd') diff --git a/cmd/sata.c b/cmd/sata.c index b1a64d9969..d18b5233e6 100644 --- a/cmd/sata.c +++ b/cmd/sata.c @@ -16,70 +16,6 @@ #include static int sata_curr_device = -1; -struct blk_desc sata_dev_desc[CONFIG_SYS_SATA_MAX_DEVICE]; - -static unsigned long sata_bread(struct blk_desc *block_dev, lbaint_t start, - lbaint_t blkcnt, void *dst) -{ - return sata_read(block_dev->devnum, start, blkcnt, dst); -} - -static unsigned long sata_bwrite(struct blk_desc *block_dev, lbaint_t start, - lbaint_t blkcnt, const void *buffer) -{ - return sata_write(block_dev->devnum, start, blkcnt, buffer); -} - -int __sata_initialize(void) -{ - int rc; - int i; - - for (i = 0; i < CONFIG_SYS_SATA_MAX_DEVICE; i++) { - memset(&sata_dev_desc[i], 0, sizeof(struct blk_desc)); - sata_dev_desc[i].if_type = IF_TYPE_SATA; - sata_dev_desc[i].devnum = i; - sata_dev_desc[i].part_type = PART_TYPE_UNKNOWN; - sata_dev_desc[i].type = DEV_TYPE_HARDDISK; - sata_dev_desc[i].lba = 0; - sata_dev_desc[i].blksz = 512; - sata_dev_desc[i].log2blksz = LOG2(sata_dev_desc[i].blksz); - sata_dev_desc[i].block_read = sata_bread; - sata_dev_desc[i].block_write = sata_bwrite; - - rc = init_sata(i); - if (!rc) { - rc = scan_sata(i); - if (!rc && (sata_dev_desc[i].lba > 0) && - (sata_dev_desc[i].blksz > 0)) - part_init(&sata_dev_desc[i]); - } - } - sata_curr_device = 0; - return rc; -} -int sata_initialize(void) __attribute__((weak,alias("__sata_initialize"))); - -__weak int __sata_stop(void) -{ - int i, err = 0; - - for (i = 0; i < CONFIG_SYS_SATA_MAX_DEVICE; i++) - err |= reset_sata(i); - - if (err) - printf("Could not reset some SATA devices\n"); - - return err; -} -int sata_stop(void) __attribute__((weak, alias("__sata_stop"))); - -#ifdef CONFIG_PARTITIONS -struct blk_desc *sata_get_dev(int dev) -{ - return (dev < CONFIG_SYS_SATA_MAX_DEVICE) ? &sata_dev_desc[dev] : NULL; -} -#endif static int do_sata(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { @@ -106,70 +42,39 @@ static int do_sata(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) return CMD_RET_USAGE; case 2: if (strncmp(argv[1], "inf", 3) == 0) { - int i; - - putc('\n'); - for (i = 0; i < CONFIG_SYS_SATA_MAX_DEVICE; ++i) { - if (sata_dev_desc[i].type == DEV_TYPE_UNKNOWN) - continue; - printf("SATA device %d: ", i); - dev_print(&sata_dev_desc[i]); - } + blk_list_devices(IF_TYPE_SATA); return 0; } else if (strncmp(argv[1], "dev", 3) == 0) { - if (sata_curr_device < 0 || - sata_curr_device >= CONFIG_SYS_SATA_MAX_DEVICE) { - puts("\nno SATA devices available\n"); - return 1; + if (blk_print_device_num(IF_TYPE_SATA, + sata_curr_device)) { + printf("\nno SATA devices available\n"); + return CMD_RET_FAILURE; } - printf("\nSATA device %d: ", sata_curr_device); - dev_print(&sata_dev_desc[sata_curr_device]); return 0; } else if (strncmp(argv[1], "part", 4) == 0) { - int dev, ok; - - for (ok = 0, dev = 0; dev < CONFIG_SYS_SATA_MAX_DEVICE; ++dev) { - if (sata_dev_desc[dev].part_type != PART_TYPE_UNKNOWN) { - ++ok; - if (dev) - putc ('\n'); - part_print(&sata_dev_desc[dev]); - } - } - if (!ok) { + if (blk_list_part(IF_TYPE_SATA)) puts("\nno SATA devices available\n"); - rc ++; - } - return rc; + return 0; } return CMD_RET_USAGE; case 3: if (strncmp(argv[1], "dev", 3) == 0) { int dev = (int)simple_strtoul(argv[2], NULL, 10); - printf("\nSATA device %d: ", dev); - if (dev >= CONFIG_SYS_SATA_MAX_DEVICE) { - puts ("unknown device\n"); - return 1; + if (!blk_show_device(IF_TYPE_SATA, dev)) { + sata_curr_device = dev; + printf("... is now current device\n"); + } else { + return CMD_RET_FAILURE; } - dev_print(&sata_dev_desc[dev]); - - if (sata_dev_desc[dev].type == DEV_TYPE_UNKNOWN) - return 1; - - sata_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 (sata_dev_desc[dev].part_type != PART_TYPE_UNKNOWN) { - part_print(&sata_dev_desc[dev]); - } else { - printf("\nSATA device %d not available\n", dev); - rc = 1; + if (blk_print_part_devnum(IF_TYPE_SATA, dev)) { + printf("\nSATA device %d not available\n", + dev); + return CMD_RET_FAILURE; } return rc; } @@ -185,11 +90,8 @@ static int do_sata(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) printf("\nSATA read: device %d block # %ld, count %ld ... ", sata_curr_device, blk, cnt); - n = blk_dread(&sata_dev_desc[sata_curr_device], - blk, cnt, (u32 *)addr); - - /* flush cache after read */ - flush_cache(addr, cnt * sata_dev_desc[sata_curr_device].blksz); + n = blk_read_devnum(IF_TYPE_SATA, sata_curr_device, blk, + cnt, (ulong *)addr); printf("%ld blocks read: %s\n", n, (n==cnt) ? "OK" : "ERROR"); @@ -204,8 +106,8 @@ static int do_sata(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) printf("\nSATA write: device %d block # %ld, count %ld ... ", sata_curr_device, blk, cnt); - n = blk_dwrite(&sata_dev_desc[sata_curr_device], - blk, cnt, (u32 *)addr); + n = blk_write_devnum(IF_TYPE_SATA, sata_curr_device, + blk, cnt, (ulong *)addr); printf("%ld blocks written: %s\n", n, (n == cnt) ? "OK" : "ERROR"); -- cgit v1.2.1 From 57ebf67bad82da0b3ade1728fb39a64d1c29822f Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 1 May 2016 11:36:13 -0600 Subject: dm: usb: Drop the get_dev() function This function is implemented by the legacy block functions now. Drop it. Signed-off-by: Simon Glass --- cmd/usb.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) (limited to 'cmd') diff --git a/cmd/usb.c b/cmd/usb.c index f1a7debdf3..b83d3233b7 100644 --- a/cmd/usb.c +++ b/cmd/usb.c @@ -723,7 +723,8 @@ static int do_usb(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) int devno, ok = 0; if (argc == 2) { for (devno = 0; ; ++devno) { - stor_dev = usb_stor_get_dev(devno); + stor_dev = blk_get_devnum_by_type(IF_TYPE_USB, + devno); if (stor_dev == NULL) break; if (stor_dev->type != DEV_TYPE_UNKNOWN) { @@ -736,7 +737,7 @@ static int do_usb(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) } } else { devno = simple_strtoul(argv[2], NULL, 16); - stor_dev = usb_stor_get_dev(devno); + stor_dev = blk_get_devnum_by_type(IF_TYPE_USB, devno); if (stor_dev != NULL && stor_dev->type != DEV_TYPE_UNKNOWN) { ok++; @@ -762,7 +763,8 @@ static int do_usb(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) unsigned long n; printf("\nUSB read: device %d block # %ld, count %ld" " ... ", usb_stor_curr_dev, blk, cnt); - stor_dev = usb_stor_get_dev(usb_stor_curr_dev); + stor_dev = blk_get_devnum_by_type(IF_TYPE_USB, + usb_stor_curr_dev); n = blk_dread(stor_dev, blk, cnt, (ulong *)addr); printf("%ld blocks read: %s\n", n, (n == cnt) ? "OK" : "ERROR"); @@ -783,7 +785,8 @@ static int do_usb(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) unsigned long n; printf("\nUSB write: device %d block # %ld, count %ld" " ... ", usb_stor_curr_dev, blk, cnt); - stor_dev = usb_stor_get_dev(usb_stor_curr_dev); + stor_dev = blk_get_devnum_by_type(IF_TYPE_USB, + usb_stor_curr_dev); n = blk_dwrite(stor_dev, blk, cnt, (ulong *)addr); printf("%ld blocks write: %s\n", n, (n == cnt) ? "OK" : "ERROR"); @@ -796,7 +799,7 @@ static int do_usb(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) if (argc == 3) { int dev = (int)simple_strtoul(argv[2], NULL, 10); printf("\nUSB device %d: ", dev); - stor_dev = usb_stor_get_dev(dev); + stor_dev = blk_get_devnum_by_type(IF_TYPE_USB, dev); if (stor_dev == NULL) { printf("unknown device\n"); return 1; @@ -810,7 +813,8 @@ static int do_usb(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) return 0; } else { printf("\nUSB device %d: ", usb_stor_curr_dev); - stor_dev = usb_stor_get_dev(usb_stor_curr_dev); + stor_dev = blk_get_devnum_by_type(IF_TYPE_USB, + usb_stor_curr_dev); dev_print(stor_dev); if (stor_dev->type == DEV_TYPE_UNKNOWN) return 1; -- cgit v1.2.1 From 3c457f4d2e47cc91385abe15d3c825d0ce1a2b6f Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 1 May 2016 11:36:15 -0600 Subject: dm: mmc: Drop the get_dev() function This function is implemented by the legacy block functions now. Drop it. Signed-off-by: Simon Glass --- cmd/mmc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'cmd') diff --git a/cmd/mmc.c b/cmd/mmc.c index c5454bf2e1..4f251870ee 100644 --- a/cmd/mmc.c +++ b/cmd/mmc.c @@ -432,7 +432,7 @@ static int do_mmc_part(cmd_tbl_t *cmdtp, int flag, if (!mmc) return CMD_RET_FAILURE; - mmc_dev = mmc_get_dev(curr_device); + mmc_dev = blk_get_devnum_by_type(IF_TYPE_MMC, curr_device); if (mmc_dev != NULL && mmc_dev->type != DEV_TYPE_UNKNOWN) { part_print(mmc_dev); return CMD_RET_SUCCESS; -- cgit v1.2.1 From 69f45cd53b8ad8bc3afef2cf2410baf58fe75a6f Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 1 May 2016 13:52:29 -0600 Subject: dm: mmc: Use the new select_hwpart() API Avoid calling directly into the MMC code - use the new API call instead. Signed-off-by: Simon Glass --- cmd/mmc.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'cmd') diff --git a/cmd/mmc.c b/cmd/mmc.c index 4f251870ee..8695c19187 100644 --- a/cmd/mmc.c +++ b/cmd/mmc.c @@ -314,12 +314,14 @@ static int do_mmcrpmb(cmd_tbl_t *cmdtp, int flag, } /* Switch to the RPMB partition */ original_part = mmc->block_dev.hwpart; - if (mmc_select_hwpart(curr_device, MMC_PART_RPMB) != 0) + if (blk_select_hwpart_devnum(IF_TYPE_MMC, curr_device, MMC_PART_RPMB) != + 0) return CMD_RET_FAILURE; ret = cp->cmd(cmdtp, flag, argc, argv); /* Return to original partition */ - if (mmc_select_hwpart(curr_device, original_part) != 0) + if (blk_select_hwpart_devnum(IF_TYPE_MMC, curr_device, original_part) != + 0) return CMD_RET_FAILURE; return ret; } @@ -467,7 +469,7 @@ static int do_mmc_dev(cmd_tbl_t *cmdtp, int flag, if (!mmc) return CMD_RET_FAILURE; - ret = mmc_select_hwpart(dev, part); + ret = blk_select_hwpart_devnum(IF_TYPE_MMC, dev, part); printf("switch to partitions #%d, %s\n", part, (!ret) ? "OK" : "ERROR"); if (ret) -- cgit v1.2.1 From c40fdca6b7db469d3982cc44fd68a269adb41b25 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 1 May 2016 13:52:35 -0600 Subject: dm: mmc: Move the device list into a separate file At present the MMC subsystem maintains its own list of MMC devices. This cannot work with driver model, which needs to maintain this itself. Move the list code into a separate 'legacy' file. The core MMC code remains, and will be shared with the driver-model implementation. Signed-off-by: Simon Glass --- cmd/mmc.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'cmd') diff --git a/cmd/mmc.c b/cmd/mmc.c index 8695c19187..eb4a547a97 100644 --- a/cmd/mmc.c +++ b/cmd/mmc.c @@ -348,7 +348,7 @@ static int do_mmc_read(cmd_tbl_t *cmdtp, int flag, printf("\nMMC read: dev # %d, block # %d, count %d ... ", curr_device, blk, cnt); - n = blk_dread(&mmc->block_dev, blk, cnt, addr); + n = blk_dread(mmc_get_blk_desc(mmc), blk, cnt, addr); /* flush cache after read */ flush_cache((ulong)addr, cnt * 512); /* FIXME */ printf("%d blocks read: %s\n", n, (n == cnt) ? "OK" : "ERROR"); @@ -380,7 +380,7 @@ static int do_mmc_write(cmd_tbl_t *cmdtp, int flag, printf("Error: card is write protected!\n"); return CMD_RET_FAILURE; } - n = blk_dwrite(&mmc->block_dev, blk, cnt, addr); + n = blk_dwrite(mmc_get_blk_desc(mmc), blk, cnt, addr); printf("%d blocks written: %s\n", n, (n == cnt) ? "OK" : "ERROR"); return (n == cnt) ? CMD_RET_SUCCESS : CMD_RET_FAILURE; @@ -408,7 +408,7 @@ static int do_mmc_erase(cmd_tbl_t *cmdtp, int flag, printf("Error: card is write protected!\n"); return CMD_RET_FAILURE; } - n = blk_derase(&mmc->block_dev, blk, cnt); + n = blk_derase(mmc_get_blk_desc(mmc), blk, cnt); printf("%d blocks erased: %s\n", n, (n == cnt) ? "OK" : "ERROR"); return (n == cnt) ? CMD_RET_SUCCESS : CMD_RET_FAILURE; @@ -480,7 +480,7 @@ static int do_mmc_dev(cmd_tbl_t *cmdtp, int flag, printf("mmc%d is current device\n", curr_device); else printf("mmc%d(part %d) is current device\n", - curr_device, mmc->block_dev.hwpart); + curr_device, mmc_get_blk_desc(mmc)->hwpart); return CMD_RET_SUCCESS; } -- cgit v1.2.1