VirtualBox

Changeset 81129 in vbox for trunk/src/VBox


Ignore:
Timestamp:
Oct 7, 2019 1:41:26 PM (5 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
133761
Message:

Devices/PC/BIOS/virtio.c: Updates

File:
1 edited

Legend:

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

    r81090 r81129  
    3030# define DBG_VIRTIO(...)
    3131#endif
     32
     33/* The maximum CDB size. */
     34#define VIRTIO_SCSI_CDB_SZ      16
     35/** Maximum sense data to return. */
     36#define VIRTIO_SCSI_SENSE_SZ    32
     37
     38/**
     39 * VirtIO queue descriptor.
     40 */
     41typedef struct
     42{
     43    /** 64bit guest physical address of the buffer, split into high and low part because we work in real mode. */
     44    uint32_t        GCPhysBufLow;
     45    uint32_t        GCPhysBufHigh;
     46    /** Length of the buffer in bytes. */
     47    uint32_t        cbBuf;
     48    /** Flags for the buffer. */
     49    uint16_t        fFlags;
     50    /** Next field where the buffer is continued if _NEXT flag is set. */
     51    uint16_t        idxNext;
     52} virtio_q_desc_t;
     53
     54#define VIRTIO_Q_DESC_F_NEXT     0x1
     55#define VIRTIO_Q_DESC_F_WRITE    0x2
     56#define VIRTIO_Q_DESC_F_INDIRECT 0x4
     57
     58/**
     59 * VirtIO available ring.
     60 */
     61typedef struct
     62{
     63    /** Flags. */
     64    uint16_t        fFlags;
     65    /** Next index to write an available buffer by the driver. */
     66    uint16_t        idxNextFree;
     67    /** The ring - we only provide one entry. */
     68    uint16_t        au16Ring[1];
     69    /** Used event index. */
     70    uint16_t        u16EvtUsed;
     71} virtio_q_avail_t;
     72
     73/**
     74 * VirtIO queue used element.
     75 */
     76typedef struct
     77{
     78    /** Index of the start of the descriptor chain. */
     79    uint32_t        u32Id;
     80    /** Number of bytes used in the descriptor chain. */
     81    uint32_t        cbUsed;
     82} virtio_q_used_elem_t;
     83
     84/**
     85 * VirtIo used ring.
     86 */
     87typedef struct
     88{
     89    /** Flags. */
     90    uint16_t             fFlags;
     91    /** Index where the next entry would be written by the device. */
     92    uint16_t             idxNextUsed;
     93    /** The used ring. */
     94    virtio_q_used_elem_t aRing[1];
     95} virtio_q_used_t;
     96
     97/**
     98 * VirtIO queue structure we are using, needs to be aligned on a 16byte boundary.
     99 */
     100typedef struct
     101{
     102    /** The descriptor table, using 4 max. */
     103    virtio_q_desc_t      aDescTbl[4];
     104    /** Available ring. */
     105    virtio_q_avail_t     AvailRing;
     106    /** Used ring. */
     107    virtio_q_used_t      UsedRing;
     108} virtio_q_t;
     109
     110/**
     111 * VirtIO SCSI request structure passed in the queue.
     112 */
     113typedef struct
     114{
     115    /** The LUN to address. */
     116    uint8_t                 au8Lun[8];
     117    /** Request ID - split into low and high part. */
     118    uint32_t                u32IdLow;
     119    uint32_t                u32IdHigh;
     120    /** Task attributes. */
     121    uint8_t                 u8TaskAttr;
     122    /** Priority. */
     123    uint8_t                 u8Prio;
     124    /** CRN value, usually 0. */
     125    uint8_t                 u8Crn;
     126    /** The CDB. */
     127    uint8_t                 abCdb[VIRTIO_SCSI_CDB_SZ];
     128} virtio_scsi_req_hdr_t;
     129
     130/**
     131 * VirtIO SCSI status structure filled by the device.
     132 */
     133typedef struct
     134{
     135    /** Returned sense length. */
     136    uint32_t                cbSense;
     137    /** Residual amount of bytes left. */
     138    uint32_t                cbResidual;
     139    /** Status qualifier. */
     140    uint16_t                u16StatusQual;
     141    /** Status code. */
     142    uint8_t                 u8Status;
     143    /** Response code. */
     144    uint8_t                 u8Response;
     145    /** Sense data. */
     146    uint8_t                 abSense[VIRTIO_SCSI_SENSE_SZ];
     147} virtio_scsi_req_sts_t;
     148
     149/**
     150 * VirtIO config for the different data structures.
     151 */
     152typedef struct
     153{
     154    /** BAR where to find it. */
     155    uint8_t         u8Bar;
     156    /** Padding. */
     157    uint8_t         abPad[3];
     158    /** Offset within the bar. */
     159    uint32_t        u32Offset;
     160    /** Length of the structure in bytes. */
     161    uint32_t        u32Length;
     162} virtio_bar_cfg_t;
    32163
    33164/**
     
    55186
    56187/**
    57  * VirtIO config for the different data structures.
    58  */
    59 typedef struct
    60 {
    61     /** BAR where to find it. */
    62     uint8_t         u8Bar;
    63     /** Padding. */
    64     uint8_t         abPad[3];
    65     /** Offset within the bar. */
    66     uint32_t        u32Offset;
    67     /** Length of the structure in bytes. */
    68     uint32_t        u32Length;
    69 } virtio_bar_cfg_t;
    70 
    71 /**
    72188 * VirtIO-SCSI controller data.
    73189 */
    74190typedef struct
    75191{
     192    /** The queue used - must be first for alignment reasons. */
     193    virtio_q_t       Queue;
    76194    /** The BAR configs read from the PCI configuration space, see VIRTIO_PCI_CAP_*_CFG,
    77195     * only use 4 because VIRTIO_PCI_CAP_PCI_CFG is not part of this. */
     
    88206} virtio_t;
    89207
    90 /* The AHCI specific data must fit into 1KB (statically allocated). */
     208/* The VirtIO specific data must fit into 1KB (statically allocated). */
    91209ct_assert(sizeof(virtio_t) <= 1024);
    92210
     
    107225#define RT_BIT_32(bit) ((uint32_t)(1L << (bit)))
    108226
    109 /* Warning: Destroys high bits of EAX. */
    110 uint32_t inpd(uint16_t port);
    111 #pragma aux inpd =      \
    112     ".386"              \
    113     "in     eax, dx"    \
    114     "mov    dx, ax"     \
    115     "shr    eax, 16"    \
    116     "xchg   ax, dx"     \
    117     parm [dx] value [dx ax] modify nomemory;
    118 
    119 /* Warning: Destroys high bits of EAX. */
    120 void outpd(uint16_t port, uint32_t val);
    121 #pragma aux outpd =     \
    122     ".386"              \
    123     "xchg   ax, cx"     \
    124     "shl    eax, 16"    \
    125     "mov    ax, cx"     \
    126     "out    dx, eax"    \
    127     parm [dx] [cx ax] modify nomemory;
    128 
     227#define VIRTIO_COMMON_REG_DEV_FEAT_SLCT 0x00
     228#define VIRTIO_COMMON_REG_DEV_FEAT      0x04
     229# define VIRTIO_CMN_REG_DEV_FEAT_SCSI_INOUT 0x01
     230#define VIRTIO_COMMON_REG_DRV_FEAT_SLCT 0x08
     231#define VIRTIO_COMMON_REG_DRV_FEAT      0x0c
     232#define VIRTIO_COMMON_REG_MSIX_CFG      0x10
     233#define VIRTIO_COMMON_REG_NUM_QUEUES    0x12
     234#define VIRTIO_COMMON_REG_DEV_STS       0x14
     235# define VIRTIO_CMN_REG_DEV_STS_F_RST     0x00
     236# define VIRTIO_CMN_REG_DEV_STS_F_ACK     0x01
     237# define VIRTIO_CMN_REG_DEV_STS_F_DRV     0x02
     238# define VIRTIO_CMN_REG_DEV_STS_F_DRV_OK  0x04
     239# define VIRTIO_CMN_REG_DEV_STS_F_FEAT_OK 0x08
     240# define VIRTIO_CMN_REG_DEV_STS_F_DEV_RST 0x40
     241# define VIRTIO_CMN_REG_DEV_STS_F_FAILED  0x80
     242#define VIRTIO_COMMON_REG_CFG_GEN       0x15
     243
     244#define VIRTIO_COMMON_REG_Q_SELECT      0x16
     245#define VIRTIO_COMMON_REG_Q_SIZE        0x18
     246#define VIRTIO_COMMON_REG_Q_MSIX_VEC    0x1a
     247#define VIRTIO_COMMON_REG_Q_ENABLE      0x1c
     248#define VIRTIO_COMMON_REG_Q_NOTIFY_OFF  0x1e
     249#define VIRTIO_COMMON_REG_Q_DESC        0x20
     250#define VIRTIO_COMMON_REG_Q_DRIVER      0x28
     251#define VIRTIO_COMMON_REG_Q_DEVICE      0x30
     252
     253#define VIRTIO_DEV_CFG_REG_Q_NUM        0x00
     254#define VIRTIO_DEV_CFG_REG_SEG_MAX      0x04
     255#define VIRTIO_DEV_CFG_REG_SECT_MAX     0x08
     256#define VIRTIO_DEV_CFG_REG_CMD_PER_LUN  0x0c
     257#define VIRTIO_DEV_CFG_REG_EVT_INFO_SZ  0x10
     258#define VIRTIO_DEV_CFG_REG_SENSE_SZ     0x14
     259#define VIRTIO_DEV_CFG_REG_CDB_SZ       0x18
     260#define VIRTIO_DEV_CFG_REG_MAX_CHANNEL  0x1c
     261#define VIRTIO_DEV_CFG_REG_MAX_TGT      0x1e
     262#define VIRTIO_DEV_CFG_REG_MAX_LUN      0x20
     263
     264#define VIRTIO_SCSI_Q_CONTROL           0x00
     265#define VIRTIO_SCSI_Q_EVENT             0x01
     266#define VIRTIO_SCSI_Q_REQUEST           0x02
    129267
    130268/* Machinery to save/restore high bits of EAX. 32-bit port I/O needs to use
     
    157295}
    158296
     297static void virtio_reg_set_bar_offset_length(virtio_t __far *virtio, uint8_t u8Bar, uint32_t offReg, uint8_t cb)
     298{
     299    pci_write_config_byte(virtio->u8Bus, virtio->u8DevFn, virtio->u8PciCfgOff  +  4, u8Bar);
     300    pci_write_config_dword(virtio->u8Bus, virtio->u8DevFn, virtio->u8PciCfgOff +  8, offReg);
     301    pci_write_config_dword(virtio->u8Bus, virtio->u8DevFn, virtio->u8PciCfgOff + 12, (uint32_t)cb);
     302}
     303
     304static void virtio_reg_common_access_prepare(virtio_t __far *virtio, uint16_t offReg, uint16_t cbAcc)
     305{
     306    virtio_reg_set_bar_offset_length(virtio,
     307                                     virtio->aBarCfgs[VIRTIO_PCI_CAP_COMMON_CFG - 1].u8Bar,
     308                                     virtio->aBarCfgs[VIRTIO_PCI_CAP_COMMON_CFG - 1].u32Offset + offReg,
     309                                     cbAcc);
     310}
     311
     312static void virtio_reg_dev_access_prepare(virtio_t __far *virtio, uint16_t offReg, uint16_t cbAcc)
     313{
     314    virtio_reg_set_bar_offset_length(virtio,
     315                                     virtio->aBarCfgs[VIRTIO_PCI_CAP_DEVICE_CFG - 1].u8Bar,
     316                                     virtio->aBarCfgs[VIRTIO_PCI_CAP_DEVICE_CFG - 1].u32Offset + offReg,
     317                                     cbAcc);
     318}
     319
     320static uint8_t virtio_reg_common_read_u8(virtio_t __far *virtio, uint16_t offReg)
     321{
     322    virtio_reg_common_access_prepare(virtio, offReg, sizeof(uint8_t));
     323    return pci_read_config_byte(virtio->u8Bus, virtio->u8DevFn, virtio->u8PciCfgOff + sizeof(virtio_pci_cap_t));
     324}
     325
     326static void virtio_reg_common_write_u8(virtio_t __far *virtio, uint16_t offReg, uint8_t u8Val)
     327{
     328    virtio_reg_common_access_prepare(virtio, offReg, sizeof(uint8_t));
     329    pci_write_config_byte(virtio->u8Bus, virtio->u8DevFn, virtio->u8PciCfgOff + sizeof(virtio_pci_cap_t), u8Val);
     330}
     331
     332static uint16_t virtio_reg_common_read_u16(virtio_t __far *virtio, uint16_t offReg)
     333{
     334    virtio_reg_common_access_prepare(virtio, offReg, sizeof(uint16_t));
     335    return pci_read_config_word(virtio->u8Bus, virtio->u8DevFn, virtio->u8PciCfgOff + sizeof(virtio_pci_cap_t));
     336}
     337
     338static void virtio_reg_common_write_u16(virtio_t __far *virtio, uint16_t offReg, uint16_t u16Val)
     339{
     340    virtio_reg_common_access_prepare(virtio, offReg, sizeof(uint16_t));
     341    pci_write_config_word(virtio->u8Bus, virtio->u8DevFn, virtio->u8PciCfgOff + sizeof(virtio_pci_cap_t), u16Val);
     342}
     343
     344static uint32_t virtio_reg_common_read_u32(virtio_t __far *virtio, uint16_t offReg)
     345{
     346    virtio_reg_common_access_prepare(virtio, offReg, sizeof(uint32_t));
     347    return pci_read_config_dword(virtio->u8Bus, virtio->u8DevFn, virtio->u8PciCfgOff + sizeof(virtio_pci_cap_t));
     348}
     349
     350static void virtio_reg_common_write_u32(virtio_t __far *virtio, uint16_t offReg, uint32_t u32Val)
     351{
     352    virtio_reg_common_access_prepare(virtio, offReg, sizeof(uint32_t));
     353    pci_write_config_dword(virtio->u8Bus, virtio->u8DevFn, virtio->u8PciCfgOff + sizeof(virtio_pci_cap_t), u32Val);
     354}
     355
     356static uint16_t virtio_reg_dev_cfg_read_u16(virtio_t __far *virtio, uint16_t offReg)
     357{
     358    virtio_reg_dev_access_prepare(virtio, offReg, sizeof(uint16_t));
     359    return pci_read_config_word(virtio->u8Bus, virtio->u8DevFn, virtio->u8PciCfgOff + sizeof(virtio_pci_cap_t));
     360}
     361
     362static uint32_t virtio_reg_dev_cfg_read_u32(virtio_t __far *virtio, uint16_t offReg)
     363{
     364    virtio_reg_dev_access_prepare(virtio, offReg, sizeof(uint32_t));
     365    return pci_read_config_dword(virtio->u8Bus, virtio->u8DevFn, virtio->u8PciCfgOff + sizeof(virtio_pci_cap_t));
     366}
     367
     368static void virtio_reg_dev_cfg_write_u32(virtio_t __far *virtio, uint16_t offReg, uint32_t u32Val)
     369{
     370    virtio_reg_dev_access_prepare(virtio, offReg, sizeof(uint32_t));
     371    pci_write_config_dword(virtio->u8Bus, virtio->u8DevFn, virtio->u8PciCfgOff + sizeof(virtio_pci_cap_t), u32Val);
     372}
     373
    159374/**
    160375 * Allocates 1K of conventional memory.
     
    167382    base_mem_kb = read_word(0x00, 0x0413);
    168383
    169     DBG_VIRTIO("AHCI: %dK of base mem\n", base_mem_kb);
     384    DBG_VIRTIO("VirtIO: %dK of base mem\n", base_mem_kb);
    170385
    171386    if (base_mem_kb == 0)
     
    178393
    179394    return virtio_seg;
     395}
     396
     397/**
     398 * Converts a segment:offset pair into a 32bit physical address.
     399 */
     400static uint32_t virtio_addr_to_phys(void __far *ptr)
     401{
     402    return ((uint32_t)FP_SEG(ptr) << 4) + FP_OFF(ptr);
    180403}
    181404
     
    188411    uint16_t            ebda_seg;
    189412    uint16_t            virtio_seg;
     413    uint32_t            fFeatures;
     414    uint8_t             u8DevStat;
    190415    bio_dsk_t __far     *bios_dsk;
    191416    virtio_t __far      *virtio;
     
    215440     * this time and fill in the data.
    216441     */
    217     u8PciCapOff = pci_read_config_byte(u8Bus, u8DevFn, u8PciCapOffVirtIo);
    218 
     442    u8PciCapOff = u8PciCapOffVirtIo;
    219443    while (u8PciCapOff != 0)
    220444    {
     
    222446        uint8_t cbPciCap   = pci_read_config_byte(u8Bus, u8DevFn, u8PciCapOff + 2); /* Capability length. */
    223447
     448        DBG_VIRTIO("Capability ID 0x%x at 0x%x\n", u8PciCapId, u8PciCapOff);
     449
    224450        if (   u8PciCapId == PCI_CAP_ID_VNDR
    225             && cbPciCap == sizeof(virtio_pci_cap_t))
     451            && cbPciCap >= sizeof(virtio_pci_cap_t))
    226452        {
    227453            /* Read in the config type and see what we got. */
    228             uint8_t i;
    229             virtio_pci_cap_t VirtIoPciCap;
    230             uint8_t *pbTmp = (uint8_t *)&VirtIoPciCap;
    231 
    232             for (i = 0; i < sizeof(VirtIoPciCap); i++)
    233                 *pbTmp++ = pci_read_config_byte(u8Bus, u8DevFn, u8PciCapOff + 1);
    234 
    235             switch (VirtIoPciCap.u8VirtIoCfgType)
     454            uint8_t u8PciVirtioCfg = pci_read_config_byte(u8Bus, u8DevFn, u8PciCapOff + 3);
     455
     456            DBG_VIRTIO("VirtIO: CFG ID 0x%x\n", u8PciVirtioCfg);
     457            switch (u8PciVirtioCfg)
    236458            {
    237459                case VIRTIO_PCI_CAP_COMMON_CFG:
     
    240462                case VIRTIO_PCI_CAP_DEVICE_CFG:
    241463                {
    242                     virtio_bar_cfg_t *pBarCfg = &virtio->aBarCfgs[VirtIoPciCap.u8VirtIoCfgType - 1];
    243 
    244                     pBarCfg->u8Bar     = VirtIoPciCap.u8Bar;
    245                     pBarCfg->u32Offset = VirtIoPciCap.u32Offset;
    246                     pBarCfg->u32Length = VirtIoPciCap.u32Length;
     464                    virtio_bar_cfg_t __far *pBarCfg = &virtio->aBarCfgs[u8PciVirtioCfg - 1];
     465
     466                    pBarCfg->u8Bar     = pci_read_config_byte(u8Bus, u8DevFn, u8PciCapOff + 4);
     467                    pBarCfg->u32Offset = pci_read_config_dword(u8Bus, u8DevFn, u8PciCapOff + 8);
     468                    pBarCfg->u32Length = pci_read_config_dword(u8Bus, u8DevFn, u8PciCapOff + 12);
    247469                    break;
    248470                }
    249471                case VIRTIO_PCI_CAP_PCI_CFG:
    250472                    virtio->u8PciCfgOff = u8PciCapOff;
     473                    DBG_VIRTIO("VirtIO PCI CAP window offset: %x\n", u8PciCapOff);
    251474                    break;
    252475                default:
    253                     DBG_VIRTIO("VirtIO SCSI HBA with unknown PCI capability type 0x%x\n", VirtIoPciCap.u8VirtIoCfgType);
     476                    DBG_VIRTIO("VirtIO SCSI HBA with unknown PCI capability type 0x%x\n", u8PciVirtioCfg);
    254477            }
    255 
    256             u8PciCapOff = VirtIoPciCap.u8PciCapNext; /* Saves one VM exit. */
    257478        }
    258         else
    259             u8PciCapOff = pci_read_config_byte(u8Bus, u8DevFn, u8PciCapOff + 1);
     479
     480        u8PciCapOff = pci_read_config_byte(u8Bus, u8DevFn, u8PciCapOff + 1);
    260481    }
    261482
    262     /** @todo Start reading actual registers, initializing the controller, detecting disks, etc. */
     483    /* Reset the device. */
     484    u8DevStat = VIRTIO_CMN_REG_DEV_STS_F_RST;
     485    virtio_reg_common_write_u8(virtio, VIRTIO_COMMON_REG_DEV_STS, u8DevStat);
     486    /* Acknowledge presence. */
     487    u8DevStat |= VIRTIO_CMN_REG_DEV_STS_F_ACK;
     488    virtio_reg_common_write_u8(virtio, VIRTIO_COMMON_REG_DEV_STS, u8DevStat);
     489    /* Our driver knows how to operatet the device. */
     490    u8DevStat |= VIRTIO_CMN_REG_DEV_STS_F_DRV;
     491    virtio_reg_common_write_u8(virtio, VIRTIO_COMMON_REG_DEV_STS, u8DevStat);
     492
     493    /* Read the feature bits and only program the VIRTIO_CMN_REG_DEV_FEAT_SCSI_INOUT bit if available. */
     494    fFeatures = virtio_reg_common_read_u32(virtio, VIRTIO_COMMON_REG_DEV_FEAT);
     495    fFeatures &= VIRTIO_CMN_REG_DEV_FEAT_SCSI_INOUT;
     496
     497    /* Check that the device is sane. */
     498    if (   virtio_reg_dev_cfg_read_u32(virtio, VIRTIO_DEV_CFG_REG_Q_NUM) < 1
     499        || virtio_reg_dev_cfg_read_u32(virtio, VIRTIO_DEV_CFG_REG_CDB_SZ) < 16
     500        || virtio_reg_dev_cfg_read_u32(virtio, VIRTIO_DEV_CFG_REG_SENSE_SZ) < 32
     501        || virtio_reg_dev_cfg_read_u32(virtio, VIRTIO_DEV_CFG_REG_SECT_MAX) < 1)
     502    {
     503        DBG_VIRTIO("VirtIO-SCSI: Invalid SCSI device configuration, ignoring device\n");
     504        return 0;
     505    }
     506
     507    virtio_reg_common_write_u32(virtio, VIRTIO_COMMON_REG_DEV_FEAT, fFeatures);
     508
     509    /* Set the features OK bit. */
     510    u8DevStat |= VIRTIO_CMN_REG_DEV_STS_F_FEAT_OK;
     511    virtio_reg_common_write_u8(virtio, VIRTIO_COMMON_REG_DEV_STS, u8DevStat);
     512
     513    /* Read again and check the the okay bit is still set. */
     514    if (!(virtio_reg_common_read_u8(virtio, VIRTIO_COMMON_REG_DEV_STS) & VIRTIO_CMN_REG_DEV_STS_F_FEAT_OK))
     515    {
     516        DBG_VIRTIO("VirtIO-SCSI: Device doesn't accept our feature set, ignoring device\n");
     517        return 0;
     518    }
     519
     520    /* Disable event and control queue. */
     521    virtio_reg_common_write_u16(virtio, VIRTIO_COMMON_REG_Q_SELECT, VIRTIO_SCSI_Q_CONTROL);
     522    virtio_reg_common_write_u16(virtio, VIRTIO_COMMON_REG_Q_SIZE, 0);
     523    virtio_reg_common_write_u16(virtio, VIRTIO_COMMON_REG_Q_ENABLE, 0);
     524
     525    virtio_reg_common_write_u16(virtio, VIRTIO_COMMON_REG_Q_SELECT, VIRTIO_SCSI_Q_EVENT);
     526    virtio_reg_common_write_u16(virtio, VIRTIO_COMMON_REG_Q_SIZE, 0);
     527    virtio_reg_common_write_u16(virtio, VIRTIO_COMMON_REG_Q_ENABLE, 0);
     528
     529    /* Setup the request queue. */
     530    virtio_reg_common_write_u16(virtio, VIRTIO_COMMON_REG_Q_SELECT, VIRTIO_SCSI_Q_REQUEST);
     531    virtio_reg_common_write_u16(virtio, VIRTIO_COMMON_REG_Q_SIZE, 1);
     532    virtio_reg_common_write_u16(virtio, VIRTIO_COMMON_REG_Q_ENABLE, 1);
     533
     534    /* Set queue area addresses (only low part, leave high part 0). */
     535    virtio_reg_common_write_u32(virtio, VIRTIO_COMMON_REG_Q_DESC,     virtio_addr_to_phys(&virtio->Queue.aDescTbl[0]));
     536    virtio_reg_common_write_u32(virtio, VIRTIO_COMMON_REG_Q_DESC + 4, 0);
     537
     538    virtio_reg_common_write_u32(virtio, VIRTIO_COMMON_REG_Q_DRIVER,     virtio_addr_to_phys(&virtio->Queue.AvailRing));
     539    virtio_reg_common_write_u32(virtio, VIRTIO_COMMON_REG_Q_DRIVER + 4, 0);
     540
     541    virtio_reg_common_write_u32(virtio, VIRTIO_COMMON_REG_Q_DEVICE,     virtio_addr_to_phys(&virtio->Queue.UsedRing));
     542    virtio_reg_common_write_u32(virtio, VIRTIO_COMMON_REG_Q_DEVICE + 4, 0);
     543
     544    virtio_reg_dev_cfg_write_u32(virtio, VIRTIO_DEV_CFG_REG_CDB_SZ, VIRTIO_SCSI_CDB_SZ);
     545    virtio_reg_dev_cfg_write_u32(virtio, VIRTIO_DEV_CFG_REG_SENSE_SZ, VIRTIO_SCSI_SENSE_SZ);
     546
     547    /* Bring the device into operational mode. */
     548    u8DevStat |= VIRTIO_CMN_REG_DEV_STS_F_DRV_OK;
     549    virtio_reg_common_write_u8(virtio, VIRTIO_COMMON_REG_DEV_STS, u8DevStat);
     550
     551    /** @todo Detect attached devices. */
    263552
    264553    return 0;
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