aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoman Kagan <rkagan@virtuozzo.com>2017-04-26 17:18:07 +0300
committerKevin O'Connor <kevin@koconnor.net>2017-05-02 19:57:04 -0400
commitcf480dd3edd851db8ad62342937e25c064960b31 (patch)
treefe359656716dc20e9d4c0531204b7f563a14b4ae
parent0a6e0a8ddd3b3654e772268050be4fbee0d88a08 (diff)
downloadseabios-hppa-cf480dd3edd851db8ad62342937e25c064960b31.zip
seabios-hppa-cf480dd3edd851db8ad62342937e25c064960b31.tar.gz
seabios-hppa-cf480dd3edd851db8ad62342937e25c064960b31.tar.bz2
mpt-scsi: try to enumerate luns with REPORT LUNS
Enumerate active luns with REPORT LUNS and, if that fails[*], fall back to sequentially enumerating them up to (arbitrarily chosen) #8. Note that this patch also makes mpt_scsi_cmd accept luns other than 0; I've no idea what was the original motivation not to, and what can break due to this change (nothing broke in my basic tests with QEMU). [*] in current QEMU, REPORT LUNS does fail in mptsas1068 because the returned data is smaller than the allocation length which is (wrongly) considered an underflow. Signed-off-by: Roman Kagan <rkagan@virtuozzo.com>
-rw-r--r--src/hw/mpt-scsi.c40
1 files changed, 26 insertions, 14 deletions
diff --git a/src/hw/mpt-scsi.c b/src/hw/mpt-scsi.c
index a37e44c..7bc8a85 100644
--- a/src/hw/mpt-scsi.c
+++ b/src/hw/mpt-scsi.c
@@ -118,9 +118,6 @@ static int
mpt_scsi_cmd(u32 iobase, struct disk_op_s *op,
u8 *cdb, u16 target, u16 lun, u16 blocksize)
{
- if (lun != 0)
- return DISK_RET_ENOTREADY;
-
u32 end = timer_calc(MPT_POLL_TIMEOUT);
u8 sense_buf[18];
@@ -198,14 +195,10 @@ mpt_scsi_process_op(struct disk_op_s *op)
return mpt_scsi_cmd(iobase, op, cdbcmd, target, lun, blocksize);
}
-static int
-mpt_scsi_add_lun(struct pci_device *pci, u32 iobase, u8 target, u8 lun)
+static void
+mpt_scsi_init_lun(struct mpt_lun_s *llun, struct pci_device *pci,
+ u32 iobase, u8 target, u8 lun)
{
- struct mpt_lun_s *llun = malloc_fseg(sizeof(*llun));
- if (!llun) {
- warn_noalloc();
- return -1;
- }
memset(llun, 0, sizeof(*llun));
llun->drive.type = DTYPE_MPT_SCSI;
llun->drive.cntl_id = pci->bdf;
@@ -213,9 +206,24 @@ mpt_scsi_add_lun(struct pci_device *pci, u32 iobase, u8 target, u8 lun)
llun->target = target;
llun->lun = lun;
llun->iobase = iobase;
+}
- char *name = znprintf(MAXDESCSIZE, "mpt %pP %d:%d", pci, target, lun);
- int prio = bootprio_find_scsi_device(pci, target, lun);
+static int
+mpt_scsi_add_lun(u32 lun, struct drive_s *tmpl_drv)
+{
+ struct mpt_lun_s *tmpl_llun =
+ container_of(tmpl_drv, struct mpt_lun_s, drive);
+ struct mpt_lun_s *llun = malloc_fseg(sizeof(*llun));
+ if (!llun) {
+ warn_noalloc();
+ return -1;
+ }
+ mpt_scsi_init_lun(llun, tmpl_llun->pci, tmpl_llun->iobase,
+ tmpl_llun->target, lun);
+
+ char *name = znprintf(MAXDESCSIZE, "mpt %pP %d:%d",
+ llun->pci, llun->target, llun->lun);
+ int prio = bootprio_find_scsi_device(llun->pci, llun->target, llun->lun);
int ret = scsi_drive_setup(&llun->drive, name, prio);
free(name);
if (ret) {
@@ -231,8 +239,12 @@ fail:
static void
mpt_scsi_scan_target(struct pci_device *pci, u32 iobase, u8 target)
{
- /* TODO: send REPORT LUNS. For now, only LUN 0 is recognized. */
- mpt_scsi_add_lun(pci, iobase, target, 0);
+ struct mpt_lun_s llun0;
+
+ mpt_scsi_init_lun(&llun0, pci, iobase, target, 0);
+
+ if (scsi_rep_luns_scan(&llun0.drive, mpt_scsi_add_lun) < 0)
+ scsi_sequential_scan(&llun0.drive, 8, mpt_scsi_add_lun);
}
static inline void