#include <inttypes.h>
#include <pci.h>
#include <scsi.h>
+#include <dm/device-internal.h>
+#include <dm/uclass-internal.h>
+#if !defined(CONFIG_DM_SCSI)
#ifdef CONFIG_SCSI_DEV_LIST
#define SCSI_DEV_LIST CONFIG_SCSI_DEV_LIST
#else
#endif
#define SCSI_DEV_LIST {SCSI_VEND_ID, SCSI_DEV_ID}
#endif
+#endif
#if defined(CONFIG_PCI) && !defined(CONFIG_SCSI_AHCI_PLAT)
const struct pci_device_id scsi_device_list[] = { SCSI_DEV_LIST };
static unsigned char tempbuff[512]; /* temporary data buffer */
+#if !defined(CONFIG_DM_SCSI)
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];
+#endif
/* almost the maximum amount of the scsi_ext command.. */
#define SCSI_MAX_READ_BLK 0xFFFF
pccb->msgout[0] = SCSI_IDENTIFY; /* NOT USED */
}
-static void scsi_init_dev_desc(struct blk_desc *dev_desc, int devnum)
+/**
+ * scsi_init_dev_desc_priv - initialize only SCSI specific blk_desc properties
+ *
+ * @dev_desc: Block device description pointer
+ */
+static void scsi_init_dev_desc_priv(struct blk_desc *dev_desc)
{
dev_desc->target = 0xff;
dev_desc->lun = 0xff;
- dev_desc->lba = 0;
- dev_desc->blksz = 0;
dev_desc->log2blksz =
LOG2_INVALID(typeof(dev_desc->log2blksz));
dev_desc->type = DEV_TYPE_UNKNOWN;
dev_desc->product[0] = 0;
dev_desc->revision[0] = 0;
dev_desc->removable = false;
- dev_desc->if_type = IF_TYPE_SCSI;
- dev_desc->devnum = devnum;
- dev_desc->part_type = PART_TYPE_UNKNOWN;
#ifndef CONFIG_BLK
dev_desc->block_read = scsi_read;
dev_desc->block_write = scsi_write;
#endif
}
+#if !defined(CONFIG_DM_SCSI)
+/**
+ * scsi_init_dev_desc - initialize all SCSI specific blk_desc properties
+ *
+ * @dev_desc: Block device description pointer
+ * @devnum: Device number
+ */
+static void scsi_init_dev_desc(struct blk_desc *dev_desc, int devnum)
+{
+ dev_desc->lba = 0;
+ dev_desc->blksz = 0;
+ dev_desc->if_type = IF_TYPE_SCSI;
+ dev_desc->devnum = devnum;
+ dev_desc->part_type = PART_TYPE_UNKNOWN;
+
+ scsi_init_dev_desc_priv(dev_desc);
+}
+#endif
/**
* scsi_detect_dev - Detect scsi device
*
* @target: target id
+ * @lun: target lun
* @dev_desc: block device description
*
* The scsi_detect_dev detects and fills a dev_desc structure when the device is
- * detected. The LUN number is taken from the struct blk_desc *dev_desc.
+ * detected.
*
* Return: 0 on success, error value otherwise
*/
-static int scsi_detect_dev(int target, struct blk_desc *dev_desc)
+static int scsi_detect_dev(int target, int lun, struct blk_desc *dev_desc)
{
unsigned char perq, modi;
lbaint_t capacity;
ccb *pccb = (ccb *)&tempccb;
pccb->target = target;
- pccb->lun = dev_desc->lun;
+ pccb->lun = lun;
pccb->pdata = (unsigned char *)&tempbuff;
pccb->datalen = 512;
scsi_setup_inquiry(pccb);
dev_desc->blksz = blksz;
dev_desc->log2blksz = LOG2(dev_desc->blksz);
dev_desc->type = perq;
- part_init(&dev_desc[0]);
removable:
return 0;
}
* (re)-scan the scsi bus and reports scsi device info
* to the user if mode = 1
*/
-void scsi_scan(int mode)
+#if defined(CONFIG_DM_SCSI)
+static int do_scsi_scan_one(struct udevice *dev, int id, int lun, int mode)
+{
+ int ret;
+ struct udevice *bdev;
+ struct blk_desc bd;
+ struct blk_desc *bdesc;
+ char str[10];
+
+ /*
+ * detect the scsi driver to get information about its geometry (block
+ * size, number of blocks) and other parameters (ids, type, ...)
+ */
+ scsi_init_dev_desc_priv(&bd);
+ if (scsi_detect_dev(id, lun, &bd))
+ return -ENODEV;
+
+ /*
+ * Create only one block device and do detection
+ * to make sure that there won't be a lot of
+ * block devices created
+ */
+ snprintf(str, sizeof(str), "id%dlun%d", id, lun);
+ ret = blk_create_devicef(dev, "scsi_blk", str, IF_TYPE_SCSI, -1,
+ bd.blksz, bd.blksz * bd.lba, &bdev);
+ if (ret) {
+ debug("Can't create device\n");
+ return ret;
+ }
+
+ bdesc = dev_get_uclass_platdata(bdev);
+ bdesc->target = id;
+ bdesc->lun = lun;
+ bdesc->removable = bd.removable;
+ bdesc->type = bd.type;
+ memcpy(&bdesc->vendor, &bd.vendor, sizeof(bd.vendor));
+ memcpy(&bdesc->product, &bd.product, sizeof(bd.product));
+ memcpy(&bdesc->revision, &bd.revision, sizeof(bd.revision));
+ part_init(bdesc);
+
+ if (mode == 1) {
+ printf(" Device %d: ", 0);
+ dev_print(bdesc);
+ }
+ return 0;
+}
+
+int scsi_scan(int mode)
+{
+ unsigned char i, lun;
+ struct uclass *uc;
+ struct udevice *dev; /* SCSI controller */
+ int ret;
+
+ if (mode == 1)
+ printf("scanning bus for devices...\n");
+
+ blk_unbind_all(IF_TYPE_SCSI);
+
+ ret = uclass_get(UCLASS_SCSI, &uc);
+ if (ret)
+ return ret;
+
+ uclass_foreach_dev(dev, uc) {
+ struct scsi_platdata *plat; /* scsi controller platdata */
+
+ /* probe SCSI controller driver */
+ ret = device_probe(dev);
+ if (ret)
+ return ret;
+
+ /* Get controller platdata */
+ plat = dev_get_platdata(dev);
+
+ for (i = 0; i < plat->max_id; i++)
+ for (lun = 0; lun < plat->max_lun; lun++)
+ do_scsi_scan_one(dev, i, lun, mode);
+ }
+
+ return 0;
+}
+#else
+int scsi_scan(int mode)
{
unsigned char i, lun;
int ret;
scsi_max_devs = 0;
for (i = 0; i < CONFIG_SYS_SCSI_MAX_SCSI_ID; i++) {
for (lun = 0; lun < CONFIG_SYS_SCSI_MAX_LUN; lun++) {
- scsi_dev_desc[scsi_max_devs].lun = lun;
- ret = scsi_detect_dev(i, &scsi_dev_desc[scsi_max_devs]);
+ ret = scsi_detect_dev(i, lun,
+ &scsi_dev_desc[scsi_max_devs]);
if (ret)
continue;
+ part_init(&scsi_dev_desc[scsi_max_devs]);
if (mode == 1) {
printf(" Device %d: ", 0);
#ifndef CONFIG_SPL_BUILD
setenv_ulong("scsidevs", scsi_max_devs);
#endif
+ return 0;
}
+#endif
#ifdef CONFIG_BLK
static const struct blk_ops scsi_blk_ops = {