diff options
Diffstat (limited to 'drivers/scsi/scsi.c')
-rw-r--r-- | drivers/scsi/scsi.c | 115 |
1 files changed, 56 insertions, 59 deletions
diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c index 48cb2a2818..69de6a53d5 100644 --- a/drivers/scsi/scsi.c +++ b/drivers/scsi/scsi.c @@ -45,7 +45,7 @@ static struct blk_desc scsi_dev_desc[CONFIG_SYS_SCSI_MAX_DEVICE]; #endif /* almost the maximum amount of the scsi_ext command.. */ -#define SCSI_MAX_READ_BLK 0xFFFF +#define SCSI_MAX_BLK 0xFFFF #define SCSI_LBA48_READ 0xFFFFFFF static void scsi_print_error(struct scsi_cmd *pccb) @@ -83,6 +83,22 @@ void scsi_setup_read16(struct scsi_cmd *pccb, lbaint_t start, } #endif +static void scsi_setup_inquiry(struct scsi_cmd *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 */ +} + +#ifdef CONFIG_BLK static void scsi_setup_read_ext(struct scsi_cmd *pccb, lbaint_t start, unsigned short blocks) { @@ -126,36 +142,13 @@ static void scsi_setup_write_ext(struct scsi_cmd *pccb, lbaint_t start, pccb->cmd[7], pccb->cmd[8]); } -static void scsi_setup_inquiry(struct scsi_cmd *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 */ -} - -#ifdef CONFIG_BLK static ulong scsi_read(struct udevice *dev, lbaint_t blknr, lbaint_t blkcnt, void *buffer) -#else -static ulong scsi_read(struct blk_desc *block_dev, lbaint_t blknr, - lbaint_t blkcnt, void *buffer) -#endif { -#ifdef CONFIG_BLK struct blk_desc *block_dev = dev_get_uclass_platdata(dev); struct udevice *bdev = dev->parent; -#else - struct udevice *bdev = NULL; -#endif - lbaint_t start, blks; + struct scsi_platdata *uc_plat = dev_get_uclass_platdata(bdev); + lbaint_t start, blks, max_blks; uintptr_t buf_addr; unsigned short smallblks = 0; struct scsi_cmd *pccb = (struct scsi_cmd *)&tempccb; @@ -166,28 +159,33 @@ static ulong scsi_read(struct blk_desc *block_dev, lbaint_t blknr, buf_addr = (unsigned long)buffer; start = blknr; blks = blkcnt; + if (uc_plat->max_bytes_per_req) + max_blks = uc_plat->max_bytes_per_req / block_dev->blksz; + else + max_blks = SCSI_MAX_BLK; + debug("\nscsi_read: dev %d startblk " LBAF ", blccnt " LBAF " buffer %lx\n", block_dev->devnum, start, blks, (unsigned long)buffer); do { pccb->pdata = (unsigned char *)buf_addr; + pccb->dma_dir = DMA_FROM_DEVICE; #ifdef CONFIG_SYS_64BIT_LBA if (start > SCSI_LBA48_READ) { unsigned long blocks; - blocks = min_t(lbaint_t, blks, SCSI_MAX_READ_BLK); + blocks = min_t(lbaint_t, blks, max_blks); pccb->datalen = block_dev->blksz * blocks; scsi_setup_read16(pccb, start, blocks); start += blocks; blks -= blocks; } else #endif - if (blks > SCSI_MAX_READ_BLK) { - pccb->datalen = block_dev->blksz * - SCSI_MAX_READ_BLK; - smallblks = SCSI_MAX_READ_BLK; + if (blks > max_blks) { + pccb->datalen = block_dev->blksz * max_blks; + smallblks = max_blks; scsi_setup_read_ext(pccb, start, smallblks); - start += SCSI_MAX_READ_BLK; - blks -= SCSI_MAX_READ_BLK; + start += max_blks; + blks -= max_blks; } else { pccb->datalen = block_dev->blksz * blks; smallblks = (unsigned short)blks; @@ -214,24 +212,13 @@ static ulong scsi_read(struct blk_desc *block_dev, lbaint_t blknr, * scsi_write */ -/* Almost the maximum amount of the scsi_ext command.. */ -#define SCSI_MAX_WRITE_BLK 0xFFFF - -#ifdef CONFIG_BLK static ulong scsi_write(struct udevice *dev, lbaint_t blknr, lbaint_t blkcnt, const void *buffer) -#else -static ulong scsi_write(struct blk_desc *block_dev, lbaint_t blknr, - lbaint_t blkcnt, const void *buffer) -#endif { -#ifdef CONFIG_BLK struct blk_desc *block_dev = dev_get_uclass_platdata(dev); struct udevice *bdev = dev->parent; -#else - struct udevice *bdev = NULL; -#endif - lbaint_t start, blks; + struct scsi_platdata *uc_plat = dev_get_uclass_platdata(bdev); + lbaint_t start, blks, max_blks; uintptr_t buf_addr; unsigned short smallblks; struct scsi_cmd *pccb = (struct scsi_cmd *)&tempccb; @@ -242,17 +229,22 @@ static ulong scsi_write(struct blk_desc *block_dev, lbaint_t blknr, buf_addr = (unsigned long)buffer; start = blknr; blks = blkcnt; + if (uc_plat->max_bytes_per_req) + max_blks = uc_plat->max_bytes_per_req / block_dev->blksz; + else + max_blks = SCSI_MAX_BLK; + debug("\n%s: dev %d startblk " LBAF ", blccnt " LBAF " buffer %lx\n", __func__, block_dev->devnum, start, blks, (unsigned long)buffer); do { pccb->pdata = (unsigned char *)buf_addr; - if (blks > SCSI_MAX_WRITE_BLK) { - pccb->datalen = (block_dev->blksz * - SCSI_MAX_WRITE_BLK); - smallblks = SCSI_MAX_WRITE_BLK; + pccb->dma_dir = DMA_TO_DEVICE; + if (blks > max_blks) { + pccb->datalen = block_dev->blksz * max_blks; + smallblks = max_blks; scsi_setup_write_ext(pccb, start, smallblks); - start += SCSI_MAX_WRITE_BLK; - blks -= SCSI_MAX_WRITE_BLK; + start += max_blks; + blks -= max_blks; } else { pccb->datalen = block_dev->blksz * blks; smallblks = (unsigned short)blks; @@ -273,6 +265,7 @@ static ulong scsi_write(struct blk_desc *block_dev, lbaint_t blknr, __func__, start, smallblks, buf_addr); return blkcnt; } +#endif #if defined(CONFIG_PCI) && !defined(CONFIG_SCSI_AHCI_PLAT) && \ !defined(CONFIG_DM_SCSI) @@ -394,6 +387,7 @@ static int scsi_read_capacity(struct udevice *dev, struct scsi_cmd *pccb, pccb->msgout[0] = SCSI_IDENTIFY; /* NOT USED */ pccb->datalen = 16; + pccb->dma_dir = DMA_FROM_DEVICE; if (scsi_exec(dev, pccb)) return 1; @@ -450,10 +444,6 @@ static void scsi_init_dev_desc_priv(struct blk_desc *dev_desc) dev_desc->product[0] = 0; dev_desc->revision[0] = 0; dev_desc->removable = false; -#if !CONFIG_IS_ENABLED(BLK) - dev_desc->block_read = scsi_read; - dev_desc->block_write = scsi_write; -#endif } #if !defined(CONFIG_DM_SCSI) @@ -494,11 +484,13 @@ static int scsi_detect_dev(struct udevice *dev, int target, int lun, lbaint_t capacity; unsigned long blksz; struct scsi_cmd *pccb = (struct scsi_cmd *)&tempccb; + int count, err; pccb->target = target; pccb->lun = lun; pccb->pdata = (unsigned char *)&tempbuff; pccb->datalen = 512; + pccb->dma_dir = DMA_FROM_DEVICE; scsi_setup_inquiry(pccb); if (scsi_exec(dev, pccb)) { if (pccb->contr_stat == SCSI_SEL_TIME_OUT) { @@ -529,9 +521,14 @@ static int scsi_detect_dev(struct udevice *dev, int target, int lun, dev_desc->target = pccb->target; dev_desc->lun = pccb->lun; - pccb->datalen = 0; - scsi_setup_test_unit_ready(pccb); - if (scsi_exec(dev, pccb)) { + for (count = 0; count < 3; count++) { + pccb->datalen = 0; + scsi_setup_test_unit_ready(pccb); + err = scsi_exec(dev, pccb); + if (!err) + break; + } + if (err) { if (dev_desc->removable) { dev_desc->type = perq; goto removable; |