VirtualBox

Changeset 81407 in vbox for trunk/src/VBox/Devices/PC


Ignore:
Timestamp:
Oct 21, 2019 1:08:46 PM (5 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
134121
Message:

PC/BIOS/virtio.c: Updates

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Devices/PC/BIOS/virtio.c

    r81135 r81407  
    2323#include "pciutil.h"
    2424#include "vds.h"
     25#include "scsi.h"
    2526
    2627#define DEBUG_VIRTIO 1
     
    3132#endif
    3233
    33 #define SCSI_INQUIRY       0x12
     34#define VBSCSI_MAX_DEVICES 16 /* Maximum number of devices a SCSI device currently supported. */
    3435
    3536/* The maximum CDB size. */
     
    432433{
    433434    uint16_t idxUsedOld = virtio->Queue.UsedRing.idxNextUsed;
     435    uint64_t idxNext = virtio->Queue.AvailRing.idxNextFree;
    434436
    435437    _fmemset(&virtio->ScsiReqHdr, 0, sizeof(virtio->ScsiReqHdr));
     
    452454    virtio->Queue.aDescTbl[1].GCPhysBufLow  = virtio_addr_to_phys(&virtio->ScsiReqSts);
    453455    virtio->Queue.aDescTbl[1].GCPhysBufHigh = 0;
    454     virtio->Queue.aDescTbl[1].cbBuf         = sizeof(virtio->ScsiReqHdr);
     456    virtio->Queue.aDescTbl[1].cbBuf         = sizeof(virtio->ScsiReqSts);
    455457    virtio->Queue.aDescTbl[1].fFlags        = VIRTIO_Q_DESC_F_WRITE | VIRTIO_Q_DESC_F_NEXT;
    456458    virtio->Queue.aDescTbl[1].idxNext       = 2;
     
    469471    /* Notify the device about the new command. */
    470472    DBG_VIRTIO("VirtIO: Submitting new request, Queue.offNotify=0x%x\n", virtio->Queue.offNotify);
    471     virtio_reg_notify_write_u16(virtio, virtio->Queue.offNotify, 0);
     473    virtio_reg_notify_write_u16(virtio, virtio->Queue.offNotify, idxNext);
    472474
    473475    /* Wait for it to complete. */
     
    481483static int virtio_scsi_detect_devices(virtio_t __far *virtio)
    482484{
    483     uint8_t     buffer[0x0200];
    484     uint8_t     rc;
    485     uint8_t     aCDB[16];
    486 
    487     aCDB[0] = SCSI_INQUIRY;
    488     aCDB[1] = 0;
    489     aCDB[2] = 0;
    490     aCDB[3] = 0;
    491     aCDB[4] = 5; /* Allocation length. */
    492     aCDB[5] = 0;
    493 
    494     rc = virtio_scsi_cmd_data_in(virtio, 0, aCDB, 6, buffer, 5);
    495     if (rc != 0)
    496         BX_PANIC("%s: SCSI_INQUIRY failed\n", __func__);
    497 
    498     return rc;
     485    int                 i;
     486    uint8_t             buffer[0x0200];
     487    bio_dsk_t __far     *bios_dsk;
     488
     489    bios_dsk = read_word(0x0040, 0x000E) :> &EbdaData->bdisk;
     490
     491    /* Go through target devices. */
     492    for (i = 0; i < VBSCSI_MAX_DEVICES; i++)
     493    {
     494        uint8_t     rc;
     495        uint8_t     aCDB[16];
     496        uint8_t     hd_index, devcount_scsi;
     497
     498        aCDB[0] = SCSI_INQUIRY;
     499        aCDB[1] = 0;
     500        aCDB[2] = 0;
     501        aCDB[3] = 0;
     502        aCDB[4] = 5; /* Allocation length. */
     503        aCDB[5] = 0;
     504
     505        rc = virtio_scsi_cmd_data_in(virtio, i, aCDB, 6, buffer, 5);
     506        if (rc != 0)
     507            BX_PANIC("%s: SCSI_INQUIRY failed\n", __func__);
     508
     509        devcount_scsi = bios_dsk->scsi_devcount;
     510
     511        /* Check the attached device. */
     512        if (   ((buffer[0] & 0xe0) == 0)
     513            && ((buffer[0] & 0x1f) == 0x00))
     514        {
     515            DBG_VIRTIO("%s: Disk detected at %d\n", __func__, i);
     516
     517            /* We add the disk only if the maximum is not reached yet. */
     518            if (devcount_scsi < BX_MAX_SCSI_DEVICES)
     519            {
     520                uint64_t    sectors, t;
     521                uint32_t    sector_size, cylinders;
     522                uint16_t    heads, sectors_per_track;
     523                uint8_t     hdcount;
     524                uint8_t     cmos_base;
     525
     526                /* Issue a read capacity command now. */
     527                _fmemset(aCDB, 0, sizeof(aCDB));
     528                aCDB[0] = SCSI_SERVICE_ACT;
     529                aCDB[1] = SCSI_READ_CAP_16;
     530                aCDB[13] = 32; /* Allocation length. */
     531
     532                rc = virtio_scsi_cmd_data_in(virtio, i, aCDB, 16, buffer, 32);
     533                if (rc != 0)
     534                    BX_PANIC("%s: SCSI_READ_CAPACITY failed\n", __func__);
     535
     536                /* The value returned is the last addressable LBA, not
     537                 * the size, which what "+ 1" is for.
     538                 */
     539                sectors = swap_64(*(uint64_t *)buffer) + 1;
     540
     541                sector_size =   ((uint32_t)buffer[8] << 24)
     542                              | ((uint32_t)buffer[9] << 16)
     543                              | ((uint32_t)buffer[10] << 8)
     544                              | ((uint32_t)buffer[11]);
     545
     546                /* We only support the disk if sector size is 512 bytes. */
     547                if (sector_size != 512)
     548                {
     549                    /* Leave a log entry. */
     550                    BX_INFO("Disk %d has an unsupported sector size of %u\n", i, sector_size);
     551                    continue;
     552                }
     553
     554                /* Get logical CHS geometry. */
     555                switch (devcount_scsi)
     556                {
     557                    case 0:
     558                        cmos_base = 0x90;
     559                        break;
     560                    case 1:
     561                        cmos_base = 0x98;
     562                        break;
     563                    case 2:
     564                        cmos_base = 0xA0;
     565                        break;
     566                    case 3:
     567                        cmos_base = 0xA8;
     568                        break;
     569                    default:
     570                        cmos_base = 0;
     571                }
     572
     573                if (cmos_base && inb_cmos(cmos_base + 7))
     574                {
     575                    /* If provided, grab the logical geometry from CMOS. */
     576                    cylinders         = inb_cmos(cmos_base + 0) + (inb_cmos(cmos_base + 1) << 8);
     577                    heads             = inb_cmos(cmos_base + 2);
     578                    sectors_per_track = inb_cmos(cmos_base + 7);
     579                }
     580                else
     581                {
     582                    /* Calculate default logical geometry. NB: Very different
     583                     * from default ATA/SATA logical geometry!
     584                     */
     585                    if (sectors >= (uint32_t)4 * 1024 * 1024)
     586                    {
     587                        heads = 255;
     588                        sectors_per_track = 63;
     589                        /* Approximate x / (255 * 63) using shifts */
     590                        t = (sectors >> 6) + (sectors >> 12);
     591                        cylinders = (t >> 8) + (t >> 16);
     592                    }
     593                    else if (sectors >= (uint32_t)2 * 1024 * 1024)
     594                    {
     595                        heads = 128;
     596                        sectors_per_track = 32;
     597                        cylinders = sectors >> 12;
     598                    }
     599                    else
     600                    {
     601                        heads = 64;
     602                        sectors_per_track = 32;
     603                        cylinders = sectors >> 11;
     604                    }
     605                }
     606
     607                /* Calculate index into the generic disk table. */
     608                hd_index = devcount_scsi + BX_MAX_ATA_DEVICES;
     609
     610                //bios_dsk->scsidev[devcount_scsi].io_base   = io_base;
     611                bios_dsk->scsidev[devcount_scsi].target_id = i;
     612                bios_dsk->devices[hd_index].type        = DSK_TYPE_SCSI;
     613                bios_dsk->devices[hd_index].device      = DSK_DEVICE_HD;
     614                bios_dsk->devices[hd_index].removable   = 0;
     615                bios_dsk->devices[hd_index].lock        = 0;
     616                bios_dsk->devices[hd_index].blksize     = sector_size;
     617                bios_dsk->devices[hd_index].translation = GEO_TRANSLATION_LBA;
     618
     619                /* Write LCHS/PCHS values. */
     620                bios_dsk->devices[hd_index].lchs.heads = heads;
     621                bios_dsk->devices[hd_index].lchs.spt   = sectors_per_track;
     622                bios_dsk->devices[hd_index].pchs.heads = heads;
     623                bios_dsk->devices[hd_index].pchs.spt   = sectors_per_track;
     624
     625                if (cylinders > 1024) {
     626                    bios_dsk->devices[hd_index].lchs.cylinders = 1024;
     627                    bios_dsk->devices[hd_index].pchs.cylinders = 1024;
     628                } else {
     629                    bios_dsk->devices[hd_index].lchs.cylinders = (uint16_t)cylinders;
     630                    bios_dsk->devices[hd_index].pchs.cylinders = (uint16_t)cylinders;
     631                }
     632
     633                BX_INFO("SCSI %d-ID#%d: LCHS=%lu/%u/%u 0x%llx sectors\n", devcount_scsi,
     634                        i, (uint32_t)cylinders, heads, sectors_per_track, sectors);
     635
     636                bios_dsk->devices[hd_index].sectors = sectors;
     637
     638                /* Store the id of the disk in the ata hdidmap. */
     639                hdcount = bios_dsk->hdcount;
     640                bios_dsk->hdidmap[hdcount] = devcount_scsi + BX_MAX_ATA_DEVICES;
     641                hdcount++;
     642                bios_dsk->hdcount = hdcount;
     643
     644                /* Update hdcount in the BDA. */
     645                hdcount = read_byte(0x40, 0x75);
     646                hdcount++;
     647                write_byte(0x40, 0x75, hdcount);
     648
     649                devcount_scsi++;
     650            }
     651            else
     652            {
     653                /* We reached the maximum of SCSI disks we can boot from. We can quit detecting. */
     654                break;
     655            }
     656        }
     657        else if (   ((buffer[0] & 0xe0) == 0)
     658                 && ((buffer[0] & 0x1f) == 0x05))
     659        {
     660            uint8_t     cdcount;
     661            uint8_t     removable;
     662
     663            BX_INFO("SCSI %d-ID#%d: CD/DVD-ROM\n", devcount_scsi, i);
     664
     665            /* Calculate index into the generic device table. */
     666            hd_index = devcount_scsi + BX_MAX_ATA_DEVICES;
     667
     668            removable = buffer[1] & 0x80 ? 1 : 0;
     669
     670            //bios_dsk->scsidev[devcount_scsi].io_base   = io_base;
     671            bios_dsk->scsidev[devcount_scsi].target_id = i;
     672            bios_dsk->devices[hd_index].type        = DSK_TYPE_SCSI;
     673            bios_dsk->devices[hd_index].device      = DSK_DEVICE_CDROM;
     674            bios_dsk->devices[hd_index].removable   = removable;
     675            bios_dsk->devices[hd_index].blksize     = 2048;
     676            bios_dsk->devices[hd_index].translation = GEO_TRANSLATION_NONE;
     677
     678            /* Store the ID of the device in the BIOS cdidmap. */
     679            cdcount = bios_dsk->cdcount;
     680            bios_dsk->cdidmap[cdcount] = devcount_scsi + BX_MAX_ATA_DEVICES;
     681            cdcount++;
     682            bios_dsk->cdcount = cdcount;
     683
     684            devcount_scsi++;
     685        }
     686        else
     687            DBG_VIRTIO("%s: No supported device detected at %d\n", __func__, i);
     688
     689        bios_dsk->scsi_devcount = devcount_scsi;
     690    }
    499691}
    500692
     
    588780    u8DevStat |= VIRTIO_CMN_REG_DEV_STS_F_ACK;
    589781    virtio_reg_common_write_u8(virtio, VIRTIO_COMMON_REG_DEV_STS, u8DevStat);
    590     /* Our driver knows how to operatet the device. */
     782    /* Our driver knows how to operate the device. */
    591783    u8DevStat |= VIRTIO_CMN_REG_DEV_STS_F_DRV;
    592784    virtio_reg_common_write_u8(virtio, VIRTIO_COMMON_REG_DEV_STS, u8DevStat);
    593785
     786#if 0
    594787    /* Read the feature bits and only program the VIRTIO_CMN_REG_DEV_FEAT_SCSI_INOUT bit if available. */
    595788    fFeatures = virtio_reg_common_read_u32(virtio, VIRTIO_COMMON_REG_DEV_FEAT);
    596789    fFeatures &= VIRTIO_CMN_REG_DEV_FEAT_SCSI_INOUT;
     790#endif
    597791
    598792    /* Check that the device is sane. */
     
    606800    }
    607801
    608     virtio_reg_common_write_u32(virtio, VIRTIO_COMMON_REG_DEV_FEAT, fFeatures);
     802    virtio_reg_common_write_u32(virtio, VIRTIO_COMMON_REG_DRV_FEAT, VIRTIO_CMN_REG_DEV_FEAT_SCSI_INOUT);
    609803
    610804    /* Set the features OK bit. */
     
    721915            DBG_VIRTIO("VirtIO SCSI HBA with all required capabilities at 0x%x\n", u8PciCapOffVirtIo);
    722916
     917            /* Enable PCI memory, I/O, bus mastering access in command register. */
     918            pci_write_config_word(u8Bus, u8DevFn, 4, 0x7);
     919
    723920            rc = virtio_scsi_hba_init(u8Bus, u8DevFn, u8PciCapOffVirtIo);
    724921        }
Note: See TracChangeset for help on using the changeset viewer.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette