diff options
author | Roman Kagan <rkagan@virtuozzo.com> | 2017-04-26 17:18:07 +0300 |
---|---|---|
committer | Kevin O'Connor <kevin@koconnor.net> | 2017-05-02 19:57:04 -0400 |
commit | cf480dd3edd851db8ad62342937e25c064960b31 (patch) | |
tree | fe359656716dc20e9d4c0531204b7f563a14b4ae /src/hw | |
parent | 0a6e0a8ddd3b3654e772268050be4fbee0d88a08 (diff) | |
download | seabios-cf480dd3edd851db8ad62342937e25c064960b31.tar.gz |
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>
Diffstat (limited to 'src/hw')
-rw-r--r-- | src/hw/mpt-scsi.c | 40 |
1 files changed, 26 insertions, 14 deletions
diff --git a/src/hw/mpt-scsi.c b/src/hw/mpt-scsi.c index a37e44c4..7bc8a85b 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 |