VirtualBox

Changeset 89168 in vbox for trunk


Ignore:
Timestamp:
May 19, 2021 1:35:28 PM (4 years ago)
Author:
vboxsync
Message:

Devices/PC/BIOS: Implement basic BusLogic and LsiLogic drivers to be able to get rid of the crappy VBoxSCSI interface, bugref:4841

Location:
trunk/src/VBox/Devices/PC/BIOS
Files:
2 added
8 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Devices/PC/BIOS/Makefile.kmk

    r84958 r89168  
    6767        ahci.c \
    6868        virtio.c \
     69        buslogic.c \
     70        lsilogic.c \
    6971        apm.c \
    7072        pcibios.c \
  • trunk/src/VBox/Devices/PC/BIOS/disk.c

    r83027 r89168  
    9090#ifdef VBOX_WITH_SCSI
    9191    [DSK_TYPE_SCSI] = { scsi_read_sectors, scsi_write_sectors },
    92 #endif
    93 #ifdef VBOX_WITH_VIRTIO_SCSI
    94     [DSK_TYPE_VIRTIO_SCSI] = { virtio_scsi_read_sectors, virtio_scsi_write_sectors },
    9592#endif
    9693};
  • trunk/src/VBox/Devices/PC/BIOS/ebda.h

    r82968 r89168  
    55
    66/*
    7  * Copyright (C) 2006-2020 Oracle Corporation
     7 * Copyright (C) 2006-2021 Oracle Corporation
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    106106 */
    107107enum dsk_type_enm {
    108     DSK_TYPE_NONE,        /* Unknown device. */
    109     DSK_TYPE_UNKNOWN,     /* Unknown ATA device. */
    110     DSK_TYPE_ATA,         /* ATA disk. */
    111     DSK_TYPE_ATAPI,       /* ATAPI device. */
    112     DSK_TYPE_SCSI,        /* SCSI disk. */
    113     DSK_TYPE_AHCI,        /* SATA disk via AHCI. */
    114     DSK_TYPE_VIRTIO_SCSI, /* SCSI disk. */
    115     DSKTYP_CNT            /* Number of disk types. */
     108    DSK_TYPE_NONE,          /* Unknown device. */
     109    DSK_TYPE_UNKNOWN,       /* Unknown ATA device. */
     110    DSK_TYPE_ATA,           /* ATA disk. */
     111    DSK_TYPE_ATAPI,         /* ATAPI device. */
     112    DSK_TYPE_SCSI,          /* SCSI disk. */
     113    DSK_TYPE_AHCI,          /* SATA disk via AHCI. */
     114    DSKTYP_CNT              /* Number of disk types. */
    116115};
    117116
     
    197196/* SCSI specific device information. */
    198197typedef struct {
    199     uint16_t    io_base;        /* Port base for HBA communication. */
     198    uint16_t    hba_seg;        /* Segment of HBA driver data block. */
     199    uint8_t     idx_hba;        /* The HBA driver to use. */
    200200    uint8_t     target_id;      /* Target ID. */
    201201} scsi_dev_t;
     
    209209    uint8_t     port;           /* SATA port. */
    210210} ahci_dev_t;
    211 
    212 #endif
    213 
    214 #ifdef VBOX_WITH_VIRTIO_SCSI
    215 
    216 /* VirtIO SCSI specific device information. */
    217 typedef struct {
    218     uint8_t     target;           /* Target ID. */
    219 } virtio_scsi_dev_t;
    220211
    221212#endif
     
    261252extern uint16_t ata_cmd_packet(uint16_t device, uint8_t cmdlen, char __far *cmdbuf,
    262253                               uint16_t header, uint32_t length, uint8_t inout, char __far *buffer);
    263 extern uint16_t virtio_scsi_cmd_packet(uint16_t device, uint8_t cmdlen, char __far *cmdbuf,
    264                                        uint16_t skip_b, uint32_t length, uint8_t inout, char __far *buffer);
    265254
    266255extern uint16_t ata_soft_reset(uint16_t device);
     
    290279    scsi_dev_t  scsidev[BX_MAX_SCSI_DEVICES];
    291280    uint8_t     scsi_devcount;      /* Number of SCSI devices. */
    292 # ifdef VBOX_WITH_VIRTIO_SCSI
    293     uint16_t    virtio_seg;         /* Segment of VirtIO data block. */
    294 # endif
    295281#endif
    296282
     
    400386int __fastcall ahci_write_sectors(bio_dsk_t __far *bios_dsk);
    401387
    402 int __fastcall virtio_scsi_read_sectors(bio_dsk_t __far *bios_dsk);
    403 int __fastcall virtio_scsi_write_sectors(bio_dsk_t __far *bios_dsk);
    404 
    405388extern void set_geom_lba(chs_t __far *lgeo, uint64_t nsectors);
    406389extern int edd_fill_dpt(dpt_t __far *dpt, bio_dsk_t __far *bios_dsk, uint8_t device);
  • trunk/src/VBox/Devices/PC/BIOS/eltorito.c

    r82968 r89168  
    121121    [DSK_TYPE_SCSI]   = { scsi_cmd_packet },
    122122#endif
    123 #ifdef VBOX_WITH_VIRTIO_SCSI
    124     [DSK_TYPE_VIRTIO_SCSI] = { virtio_scsi_cmd_packet },
    125 #endif
    126123};
    127124
  • trunk/src/VBox/Devices/PC/BIOS/orgs.asm

    r84901 r89168  
    142142extrn           _ahci_init:near
    143143endif
    144 ifdef VBOX_WITH_VIRTIO_SCSI
    145 extrn           _virtio_scsi_init:near
    146 endif
    147144if VBOX_BIOS_CPU ge 80286
    148145extrn           _int15_blkmove:near
     
    647644endif
    648645
    649 ifdef VBOX_WITH_VIRTIO_SCSI
    650                 ; VirtIO-SCSI driver setup
    651                 call    _virtio_scsi_init
    652 endif
    653 
    654646                ;; floppy setup
    655647                call    floppy_post
  • trunk/src/VBox/Devices/PC/BIOS/scsi.c

    r82968 r89168  
    3131#endif
    3232
    33 #define VBSCSI_BUSY     (1 << 0)
    34 #define VBSCSI_ERROR    (1 << 1)
    35 
    36 /* The I/O port of the BusLogic SCSI adapter. */
    37 #define BUSLOGIC_BIOS_IO_PORT       0x430
    38 /* The I/O port of the LsiLogic SCSI adapter. */
    39 #define LSILOGIC_BIOS_IO_PORT       0x434
    40 /* The I/O port of the LsiLogic SAS adapter. */
    41 #define LSILOGIC_SAS_BIOS_IO_PORT   0x438
    42 
    43 #define VBSCSI_REGISTER_STATUS   0
    44 #define VBSCSI_REGISTER_COMMAND  0
    45 #define VBSCSI_REGISTER_DATA_IN  1
    46 #define VBSCSI_REGISTER_IDENTIFY 2
    47 #define VBSCSI_REGISTER_RESET    3
    48 #define VBSCSI_REGISTER_DEVSTAT  3
    49 
    50 #define VBSCSI_MAX_DEVICES 16 /* Maximum number of devices a SCSI device can have. */
    51 
    52 /* Data transfer direction. */
    53 #define SCSI_TXDIR_FROM_DEVICE 0
    54 #define SCSI_TXDIR_TO_DEVICE   1
    55 
    56 void insb_discard(unsigned nbytes, unsigned port);
    57 #pragma aux insb_discard =  \
    58     ".286"                  \
    59     "again:"                \
    60     "in al,dx"              \
    61     "loop again"            \
    62     parm [cx] [dx] modify exact [cx ax] nomemory;
    63 
    64 
    65 int scsi_cmd_data_in(uint16_t io_base, uint8_t target_id, uint8_t __far *aCDB,
    66                      uint8_t cbCDB, uint8_t __far *buffer, uint32_t length)
    67 {
    68     /* Check that the adapter is ready. */
    69     uint8_t     status, sizes;
    70     uint16_t    i;
    71 
    72     do
    73         status = inb(io_base + VBSCSI_REGISTER_STATUS);
    74     while (status & VBSCSI_BUSY);
    75 
    76     sizes = ((length >> 12) & 0xF0) | ((cbCDB == 16) ? 0 : cbCDB);
    77     outb(io_base + VBSCSI_REGISTER_COMMAND, target_id);                 /* Write the target ID. */
    78     outb(io_base + VBSCSI_REGISTER_COMMAND, SCSI_TXDIR_FROM_DEVICE);    /* Write the transfer direction. */
    79     outb(io_base + VBSCSI_REGISTER_COMMAND, sizes);                     /* Write CDB size and top bufsize bits. */
    80     outb(io_base + VBSCSI_REGISTER_COMMAND, length);                    /* Write the buffer size. */
    81     outb(io_base + VBSCSI_REGISTER_COMMAND, (length >> 8));
    82     for (i = 0; i < cbCDB; i++)                                         /* Write the CDB. */
    83         outb(io_base + VBSCSI_REGISTER_COMMAND, aCDB[i]);
    84 
    85     /* Now wait for the command to complete. */
    86     do
    87         status = inb(io_base + VBSCSI_REGISTER_STATUS);
    88     while (status & VBSCSI_BUSY);
    89 
    90     /* If any error occurred, inform the caller and don't bother reading the data. */
    91     if (status & VBSCSI_ERROR) {
    92         outb(io_base + VBSCSI_REGISTER_RESET, 0);
    93 
    94         status = inb(io_base + VBSCSI_REGISTER_DEVSTAT);
    95         DBG_SCSI("%s: read failed, device status %02X\n", __func__, status);
    96         return 4;   /* Sector not found */
    97     }
    98 
    99     /* Read in the data. The transfer length may be exactly 64K or more,
    100      * which needs a bit of care when we're using 16-bit 'rep ins'.
    101      */
    102     while (length > 32768) {
    103         DBG_SCSI("%s: reading 32K to %X:%X\n", __func__, FP_SEG(buffer), FP_OFF(buffer));
    104         rep_insb(buffer, 32768, io_base + VBSCSI_REGISTER_DATA_IN);
    105         length -= 32768;
    106         buffer = (FP_SEG(buffer) + (32768 >> 4)) :> FP_OFF(buffer);
    107     }
    108 
    109     DBG_SCSI("%s: reading %ld bytes to %X:%X\n", __func__, length, FP_SEG(buffer), FP_OFF(buffer));
    110     rep_insb(buffer, length, io_base + VBSCSI_REGISTER_DATA_IN);
    111 
    112     return 0;
    113 }
    114 
    115 int scsi_cmd_data_out(uint16_t io_base, uint8_t target_id, uint8_t __far *aCDB,
    116                       uint8_t cbCDB, uint8_t __far *buffer, uint32_t length)
    117 {
    118     /* Check that the adapter is ready. */
    119     uint8_t     status, sizes;
    120     uint16_t    i;
    121 
    122     do
    123         status = inb(io_base + VBSCSI_REGISTER_STATUS);
    124     while (status & VBSCSI_BUSY);
    125 
    126 
    127     sizes = ((length >> 12) & 0xF0) | ((cbCDB == 16) ? 0 : cbCDB);
    128     outb(io_base + VBSCSI_REGISTER_COMMAND, target_id);                 /* Write the target ID. */
    129     outb(io_base + VBSCSI_REGISTER_COMMAND, SCSI_TXDIR_TO_DEVICE);      /* Write the transfer direction. */
    130     outb(io_base + VBSCSI_REGISTER_COMMAND, sizes);                     /* Write CDB size and top bufsize bits. */
    131     outb(io_base + VBSCSI_REGISTER_COMMAND, length);                    /* Write the buffer size. */
    132     outb(io_base + VBSCSI_REGISTER_COMMAND, (length >> 8));
    133     for (i = 0; i < cbCDB; i++)                                         /* Write the CDB. */
    134         outb(io_base + VBSCSI_REGISTER_COMMAND, aCDB[i]);
    135 
    136     /* Write out the data. The transfer length may be exactly 64K or more,
    137      * which needs a bit of care when we're using 16-bit 'rep outs'.
    138      */
    139     while (length > 32768) {
    140         DBG_SCSI("%s: writing 32K from %X:%X\n", __func__, FP_SEG(buffer), FP_OFF(buffer));
    141         rep_outsb(buffer, 32768, io_base + VBSCSI_REGISTER_DATA_IN);
    142         length -= 32768;
    143         buffer = (FP_SEG(buffer) + (32768 >> 4)) :> FP_OFF(buffer);
    144     }
    145 
    146     DBG_SCSI("%s: writing %ld bytes from %X:%X\n", __func__, length, FP_SEG(buffer), FP_OFF(buffer));
    147     rep_outsb(buffer, length, io_base + VBSCSI_REGISTER_DATA_IN);
    148 
    149     /* Now wait for the command to complete. */
    150     do
    151         status = inb(io_base + VBSCSI_REGISTER_STATUS);
    152     while (status & VBSCSI_BUSY);
    153 
    154     /* If any error occurred, inform the caller. */
    155     if (status & VBSCSI_ERROR) {
    156         outb(io_base + VBSCSI_REGISTER_RESET, 0);
    157 
    158         status = inb(io_base + VBSCSI_REGISTER_DEVSTAT);
    159         DBG_SCSI("%s: write failed, device status %02X\n", __func__, status);
    160         return 4;   /* Sector not found */
    161     }
    162 
    163     return 0;
     33#define VBSCSI_MAX_DEVICES 16 /* Maximum number of devices a SCSI device currently supported. */
     34
     35#define VBOX_SCSI_NO_HBA 0xffff
     36
     37typedef int (* scsi_hba_init)(void __far *pvHba, uint8_t u8Bus, uint8_t u8DevFn);
     38typedef int (* scsi_hba_cmd_data_out)(void __far *pvHba, uint8_t idTgt, uint8_t __far *aCDB,
     39                                      uint8_t cbCDB, uint8_t __far *buffer, uint32_t length);
     40typedef int (* scsi_hba_cmd_data_in)(void __far *pvHba, uint8_t idTgt, uint8_t __far *aCDB,
     41                                     uint8_t cbCDB, uint8_t __far *buffer, uint32_t length, uint16_t skip_a,
     42                                     uint16_t skip_b);
     43
     44typedef struct
     45{
     46    uint16_t              idPciVendor;
     47    uint16_t              idPciDevice;
     48    scsi_hba_init         init;
     49    scsi_hba_cmd_data_out cmd_data_out;
     50    scsi_hba_cmd_data_in  cmd_data_in;
     51} scsi_hba_t;
     52
     53/* Machinery to save/restore high bits of EAX. 32-bit port I/O needs to use
     54 * EAX, but saving/restoring EAX around each port access would be inefficient.
     55 * Instead, each externally callable routine must save the high bits before
     56 * modifying them and restore the high bits before exiting.
     57 */
     58
     59/* Note: Reading high EAX bits destroys them - *must* be restored later. */
     60uint16_t eax_hi_rd(void);
     61#pragma aux eax_hi_rd = \
     62    ".386"              \
     63    "shr    eax, 16"    \
     64    value [ax] modify nomemory;
     65
     66void eax_hi_wr(uint16_t);
     67#pragma aux eax_hi_wr = \
     68    ".386"              \
     69    "shl    eax, 16"    \
     70    parm [ax] modify nomemory;
     71
     72void inline high_bits_save(uint16_t __far *pu16EaxHi)
     73{
     74    *pu16EaxHi = eax_hi_rd();
     75}
     76
     77void inline high_bits_restore(uint16_t u16EaxHi)
     78{
     79    eax_hi_wr(u16EaxHi);
     80}
     81
     82/* Pointers to the HBA specific access routines. */
     83scsi_hba_t hbaacc[] =
     84{
     85    { 0x1000, 0x0030, lsilogic_scsi_init, lsilogic_scsi_cmd_data_out, lsilogic_scsi_cmd_data_in }, /* SPI */
     86    { 0x1000, 0x0054, lsilogic_scsi_init, lsilogic_scsi_cmd_data_out, lsilogic_scsi_cmd_data_in }, /* SAS */
     87    { 0x104b, 0x1040, buslogic_scsi_init, buslogic_scsi_cmd_data_out, buslogic_scsi_cmd_data_in },
     88#ifdef VBOX_WITH_VIRTIO_SCSI
     89    { 0x1af4, 0x1048, virtio_scsi_init,   virtio_scsi_cmd_data_out,   virtio_scsi_cmd_data_in   }
     90#endif
     91};
     92
     93/**
     94 * Allocates 1K of conventional memory.
     95 */
     96static uint16_t scsi_hba_mem_alloc(void)
     97{
     98    uint16_t    base_mem_kb;
     99    uint16_t    hba_seg;
     100
     101    base_mem_kb = read_word(0x00, 0x0413);
     102
     103    DBG_SCSI("SCSI: %dK of base mem\n", base_mem_kb);
     104
     105    if (base_mem_kb == 0)
     106        return 0;
     107
     108    base_mem_kb--; /* Allocate one block. */
     109    hba_seg = (((uint32_t)base_mem_kb * 1024) >> 4); /* Calculate start segment. */
     110
     111    write_word(0x00, 0x0413, base_mem_kb);
     112
     113    return hba_seg;
    164114}
    165115
     
    176126    cdb_rw16            cdb;
    177127    uint32_t            count;
    178     uint16_t            io_base;
     128    uint16_t            hba_seg;
     129    uint8_t             idx_hba;
    179130    uint8_t             target_id;
    180131    uint8_t             device_id;
     132    uint16_t            eax_hi;
    181133
    182134    device_id = VBOX_GET_SCSI_DEVICE(bios_dsk->drqp.dev_id);
     
    185137
    186138    count    = bios_dsk->drqp.nsect;
     139
     140    high_bits_save(&eax_hi);
    187141
    188142    /* Prepare a CDB. */
     
    194148
    195149
    196     io_base   = bios_dsk->scsidev[device_id].io_base;
     150    hba_seg   = bios_dsk->scsidev[device_id].hba_seg;
     151    idx_hba   = bios_dsk->scsidev[device_id].idx_hba;
    197152    target_id = bios_dsk->scsidev[device_id].target_id;
    198153
     
    200155             count, device_id, bios_dsk->scsidev[device_id].target_id);
    201156
    202     rc = scsi_cmd_data_in(io_base, target_id, (void __far *)&cdb, 16,
    203                           bios_dsk->drqp.buffer, (count * 512L));
    204 
     157    rc = hbaacc[idx_hba].cmd_data_in(hba_seg :> 0, target_id, (void __far *)&cdb, 16,
     158                                     bios_dsk->drqp.buffer, (count * 512L), 0, 0);
    205159    if (!rc)
    206160    {
     
    209163    }
    210164    DBG_SCSI("%s: transferred %u sectors\n", __func__, bios_dsk->drqp.nsect);
     165    high_bits_restore(eax_hi);
    211166
    212167    return rc;
     
    225180    cdb_rw16            cdb;
    226181    uint32_t            count;
    227     uint16_t            io_base;
     182    uint16_t            hba_seg;
     183    uint8_t             idx_hba;
    228184    uint8_t             target_id;
    229185    uint8_t             device_id;
     186    uint16_t            eax_hi;
    230187
    231188    device_id = VBOX_GET_SCSI_DEVICE(bios_dsk->drqp.dev_id);
     
    234191
    235192    count    = bios_dsk->drqp.nsect;
     193
     194    high_bits_save(&eax_hi);
    236195
    237196    /* Prepare a CDB. */
     
    242201    cdb.pad2    = 0;
    243202
    244     io_base   = bios_dsk->scsidev[device_id].io_base;
     203    hba_seg   = bios_dsk->scsidev[device_id].hba_seg;
     204    idx_hba   = bios_dsk->scsidev[device_id].idx_hba;
    245205    target_id = bios_dsk->scsidev[device_id].target_id;
    246206
     
    248208             count, device_id, bios_dsk->scsidev[device_id].target_id);
    249209
    250     rc = scsi_cmd_data_out(io_base, target_id, (void __far *)&cdb, 16,
    251                            bios_dsk->drqp.buffer, (count * 512L));
    252 
     210    rc = hbaacc[idx_hba].cmd_data_out(hba_seg :> 0, target_id, (void __far *)&cdb, 16,
     211                                      bios_dsk->drqp.buffer, (count * 512L));
    253212    if (!rc)
    254213    {
     
    257216    }
    258217    DBG_SCSI("%s: transferred %u sectors\n", __func__, bios_dsk->drqp.nsect);
     218    high_bits_restore(eax_hi);
    259219
    260220    return rc;
     
    280240 */
    281241uint16_t scsi_cmd_packet(uint16_t device_id, uint8_t cmdlen, char __far *cmdbuf,
    282                          uint16_t before, uint32_t length, uint8_t inout, char __far *buffer)
     242                         uint16_t skip_b, uint32_t length, uint8_t inout, char __far *buffer)
    283243{
    284244    bio_dsk_t __far *bios_dsk = read_word(0x0040, 0x000E) :> &EbdaData->bdisk;
    285     uint32_t        read_len;
    286     uint8_t         status, sizes;
    287     uint16_t        i;
    288     uint16_t        io_base;
     245    uint8_t         rc;
    289246    uint8_t         target_id;
     247    uint16_t        hba_seg;
     248    uint8_t         idx_hba;
     249    uint16_t        eax_hi;
    290250
    291251    /* Data out is currently not supported. */
     
    295255    }
    296256
     257    /* The skip length must be even. */
     258    if (skip_b & 1) {
     259        DBG_SCSI("%s: skip must be even (%04x)\n", __func__, skip_b);
     260        return 1;
     261    }
     262
    297263    /* Convert to SCSI specific device number. */
    298264    device_id = VBOX_GET_SCSI_DEVICE(device_id);
     
    304270             bios_dsk->drqp.nsect, bios_dsk->drqp.sect_sz);
    305271
    306     cmdlen -= 2; /* ATAPI uses 12-byte command packets for a READ 10. */
    307 
    308     io_base   = bios_dsk->scsidev[device_id].io_base;
     272    high_bits_save(&eax_hi);
     273    hba_seg   = bios_dsk->scsidev[device_id].hba_seg;
     274    idx_hba   = bios_dsk->scsidev[device_id].idx_hba;
    309275    target_id = bios_dsk->scsidev[device_id].target_id;
    310276
    311     /* Wait until the adapter is ready. */
    312     do
    313         status = inb(io_base + VBSCSI_REGISTER_STATUS);
    314     while (status & VBSCSI_BUSY);
    315 
    316     /* On the SCSI level, we have to transfer whole sectors. */
    317     /* NB: With proper residual length support, this should not be necessary; we should
    318      * be able to avoid transferring the 'after' part of the sector.
    319      */
    320     read_len = length + before + bios_dsk->drqp.skip_a;
    321 
    322     sizes = (((read_len) >> 12) & 0xF0) | cmdlen;
    323     outb(io_base + VBSCSI_REGISTER_COMMAND, target_id);                 /* Write the target ID. */
    324     outb(io_base + VBSCSI_REGISTER_COMMAND, SCSI_TXDIR_FROM_DEVICE);    /* Write the transfer direction. */
    325     outb(io_base + VBSCSI_REGISTER_COMMAND, sizes);                     /* Write the CDB size. */
    326     outb(io_base + VBSCSI_REGISTER_COMMAND, read_len);                  /* Write the buffer size. */
    327     outb(io_base + VBSCSI_REGISTER_COMMAND, (read_len) >> 8);
    328     for (i = 0; i < cmdlen; i++)                                        /* Write the CDB. */
    329         outb(io_base + VBSCSI_REGISTER_COMMAND, cmdbuf[i]);
    330 
    331     /* Now wait for the command to complete. */
    332     do
    333         status = inb(io_base + VBSCSI_REGISTER_STATUS);
    334     while (status & VBSCSI_BUSY);
    335 
    336     /* If any error occurred, inform the caller and don't bother reading the data. */
    337     if (status & VBSCSI_ERROR) {
    338         outb(io_base + VBSCSI_REGISTER_RESET, 0);
    339 
    340         status = inb(io_base + VBSCSI_REGISTER_DEVSTAT);
    341         DBG_SCSI("%s: read failed, device status %02X\n", __func__, status);
    342         return 3;
    343     }
    344 
    345     /* Transfer the data read from the device. */
    346 
    347     if (before)     /* If necessary, throw away data which needs to be skipped. */
    348         insb_discard(before, io_base + VBSCSI_REGISTER_DATA_IN);
    349 
    350     bios_dsk->drqp.trsfbytes = length;
    351 
    352     /* The requested length may be exactly 64K or more, which needs
    353      * a bit of care when we're using 16-bit 'rep ins'.
    354      */
    355     while (length > 32768) {
    356         DBG_SCSI("%s: reading 32K to %X:%X\n", __func__, FP_SEG(buffer), FP_OFF(buffer));
    357         rep_insb(buffer, 32768, io_base + VBSCSI_REGISTER_DATA_IN);
    358         length -= 32768;
    359         buffer = (FP_SEG(buffer) + (32768 >> 4)) :> FP_OFF(buffer);
    360     }
    361 
    362     DBG_SCSI("%s: reading %ld bytes to %X:%X\n", __func__, length, FP_SEG(buffer), FP_OFF(buffer));
    363     rep_insb(buffer, length, io_base + VBSCSI_REGISTER_DATA_IN);
    364 
    365     if (bios_dsk->drqp.skip_a)  /* If necessary, throw away more data. */
    366         insb_discard(bios_dsk->drqp.skip_a, io_base + VBSCSI_REGISTER_DATA_IN);
    367 
    368     return 0;
     277    bios_dsk->drqp.lba     = length << 8;     /// @todo xfer length limit
     278    bios_dsk->drqp.buffer  = buffer;
     279    bios_dsk->drqp.nsect   = length / bios_dsk->drqp.sect_sz;
     280
     281    DBG_SCSI("%s: reading %u bytes, device %d, target %d\n", __func__,
     282             length, device_id, bios_dsk->scsidev[device_id].target_id);
     283
     284    rc = hbaacc[idx_hba].cmd_data_in(hba_seg :> 0, target_id, (void __far *)cmdbuf, cmdlen,
     285                                     bios_dsk->drqp.buffer, length, skip_b, bios_dsk->drqp.skip_a);
     286    if (!rc)
     287        bios_dsk->drqp.trsfbytes = length;
     288
     289    DBG_SCSI("%s: transferred %u bytes\n", __func__, length);
     290    high_bits_restore(eax_hi);
     291
     292    return rc;
    369293}
    370294
     
    375299 * @param   io_base    The I/O base port of the controller.
    376300 */
    377 void scsi_enumerate_attached_devices(uint16_t io_base)
     301static void scsi_enumerate_attached_devices(uint16_t hba_seg, uint8_t idx_hba)
    378302{
    379303    int                 i;
     
    397321        aCDB[5] = 0;
    398322
    399         rc = scsi_cmd_data_in(io_base, i, aCDB, 6, buffer, 5);
     323        rc = hbaacc[idx_hba].cmd_data_in(hba_seg :> 0, i, aCDB, 6, buffer, 5, 0, 0);
    400324        if (rc != 0)
    401             BX_PANIC("%s: SCSI_INQUIRY failed\n", __func__);
     325        {
     326            DBG_SCSI("%s: SCSI_INQUIRY failed\n", __func__); /* Not a fatal error if the device doesn't exist. */
     327            continue;
     328        }
    402329
    403330        devcount_scsi = bios_dsk->scsi_devcount;
     
    424351                aCDB[13] = 32; /* Allocation length. */
    425352
    426                 rc = scsi_cmd_data_in(io_base, i, aCDB, 16, buffer, 32);
     353                rc = hbaacc[idx_hba].cmd_data_in(hba_seg :> 0, i, aCDB, 16, buffer, 32, 0, 0);
    427354                if (rc != 0)
    428355                    BX_PANIC("%s: SCSI_READ_CAPACITY failed\n", __func__);
     
    502429                hd_index = devcount_scsi + BX_MAX_ATA_DEVICES;
    503430
    504                 bios_dsk->scsidev[devcount_scsi].io_base   = io_base;
     431                bios_dsk->scsidev[devcount_scsi].hba_seg   = hba_seg;
     432                bios_dsk->scsidev[devcount_scsi].idx_hba   = idx_hba;
    505433                bios_dsk->scsidev[devcount_scsi].target_id = i;
    506434                bios_dsk->devices[hd_index].type        = DSK_TYPE_SCSI;
     
    562490            removable = buffer[1] & 0x80 ? 1 : 0;
    563491
    564             bios_dsk->scsidev[devcount_scsi].io_base   = io_base;
     492            bios_dsk->scsidev[devcount_scsi].hba_seg   = hba_seg;
     493            bios_dsk->scsidev[devcount_scsi].idx_hba   = idx_hba;
    565494            bios_dsk->scsidev[devcount_scsi].target_id = i;
    566495            bios_dsk->devices[hd_index].type        = DSK_TYPE_SCSI;
     
    585514}
    586515
    587 void scsi_pci_init(uint16_t vendor_id, uint16_t device_id)
    588 {
    589     uint16_t    bus_dev_fn;
    590 
    591     bus_dev_fn = pci_find_device(vendor_id, device_id);
    592     if (bus_dev_fn == -1) {
    593         DBG_SCSI("%s: Adapter %x:%x not found, how come?!\n", __func__, vendor_id, device_id);
    594         return;
    595     }
    596 
    597     DBG_SCSI("%s: Adapter %x:%x found at %x, enabling BM\n", __func__, vendor_id, device_id, bus_dev_fn);
    598     /* Enable PCI memory, I/O, bus mastering access in command register. */
    599     pci_write_config_word(bus_dev_fn >> 8, (uint8_t)bus_dev_fn, 4, 0x7);
    600 }
    601 
    602516/**
    603517 * Init the SCSI driver and detect attached disks.
     
    605519void BIOSCALL scsi_init(void)
    606520{
    607     uint8_t             identifier;
     521    int i;
    608522    bio_dsk_t __far     *bios_dsk;
    609523
    610524    bios_dsk = read_word(0x0040, 0x000E) :> &EbdaData->bdisk;
    611 
    612525    bios_dsk->scsi_devcount = 0;
    613526
    614     identifier = 0;
    615 
    616     /* Detect the BusLogic adapter. */
    617     outb(BUSLOGIC_BIOS_IO_PORT+VBSCSI_REGISTER_IDENTIFY, 0x55);
    618     identifier = inb(BUSLOGIC_BIOS_IO_PORT+VBSCSI_REGISTER_IDENTIFY);
    619 
    620     if (identifier == 0x55)
     527    /* Walk the supported drivers and try to detect the HBA. */
     528    for (i = 0; i < sizeof(hbaacc)/sizeof(hbaacc[0]); i++)
    621529    {
    622         /* Detected - Enumerate attached devices. */
    623         DBG_SCSI("%s: BusLogic SCSI adapter detected\n", __func__);
    624         outb(BUSLOGIC_BIOS_IO_PORT+VBSCSI_REGISTER_RESET, 0);
    625         scsi_enumerate_attached_devices(BUSLOGIC_BIOS_IO_PORT);
    626         scsi_pci_init(0x104B, 0x1040);
     530        uint16_t busdevfn = pci_find_device(hbaacc[i].idPciVendor, hbaacc[i].idPciDevice);
     531        if (busdevfn != VBOX_SCSI_NO_HBA)
     532        {
     533            int rc;
     534            uint8_t  u8Bus, u8DevFn;
     535            uint16_t hba_seg = scsi_hba_mem_alloc();
     536            if (hba_seg == 0) /* No point in trying the rest if we are out of memory. */
     537                break;
     538
     539            u8Bus = (busdevfn & 0xff00) >> 8;
     540            u8DevFn = busdevfn & 0x00ff;
     541
     542            DBG_SCSI("SCSI HBA at Bus %u DevFn 0x%x (raw 0x%x)\n", u8Bus, u8DevFn, busdevfn);
     543            rc = hbaacc[i].init(hba_seg :> 0, u8Bus, u8DevFn);
     544            if (!rc)
     545                scsi_enumerate_attached_devices(hba_seg, i);
     546            /** @todo Free memory on error. */
     547        }
    627548    }
    628     else
    629     {
    630         DBG_SCSI("%s: BusLogic SCSI adapter not detected\n", __func__);
    631     }
    632 
    633     /* Detect the LSI Logic parallel SCSI adapter. */
    634     outb(LSILOGIC_BIOS_IO_PORT+VBSCSI_REGISTER_IDENTIFY, 0x55);
    635     identifier = inb(LSILOGIC_BIOS_IO_PORT+VBSCSI_REGISTER_IDENTIFY);
    636 
    637     if (identifier == 0x55)
    638     {
    639         /* Detected - Enumerate attached devices. */
    640         DBG_SCSI("%s: LSI Logic SCSI adapter detected\n", __func__);
    641         outb(LSILOGIC_BIOS_IO_PORT+VBSCSI_REGISTER_RESET, 0);
    642         scsi_enumerate_attached_devices(LSILOGIC_BIOS_IO_PORT);
    643         scsi_pci_init(0x1000, 0x0030);
    644     }
    645     else
    646     {
    647         DBG_SCSI("%s: LSI Logic SCSI adapter not detected\n", __func__);
    648     }
    649 
    650     /* Detect the LSI Logic SAS adapter. */
    651     outb(LSILOGIC_SAS_BIOS_IO_PORT+VBSCSI_REGISTER_IDENTIFY, 0x55);
    652     identifier = inb(LSILOGIC_SAS_BIOS_IO_PORT+VBSCSI_REGISTER_IDENTIFY);
    653 
    654     if (identifier == 0x55)
    655     {
    656         /* Detected - Enumerate attached devices. */
    657         DBG_SCSI("%s: LSI Logic SAS adapter detected\n", __func__);
    658         outb(LSILOGIC_SAS_BIOS_IO_PORT+VBSCSI_REGISTER_RESET, 0);
    659         scsi_enumerate_attached_devices(LSILOGIC_SAS_BIOS_IO_PORT);
    660         scsi_pci_init(0x1000, 0x0054);
    661     }
    662     else
    663     {
    664         DBG_SCSI("%s: LSI Logic SAS adapter not detected\n", __func__);
    665     }
    666 }
     549}
  • trunk/src/VBox/Devices/PC/BIOS/scsi.h

    r82968 r89168  
    5757ct_assert(sizeof(cdb_rw16) == 16);
    5858
     59extern int lsilogic_scsi_init(void __far *pvHba, uint8_t u8Bus, uint8_t u8DevFn);
     60extern int lsilogic_scsi_cmd_data_out(void __far *pvHba, uint8_t idTgt, uint8_t __far *aCDB,
     61                                      uint8_t cbCDB, uint8_t __far *buffer, uint32_t length);
     62extern int lsilogic_scsi_cmd_data_in(void __far *pvHba, uint8_t idTgt, uint8_t __far *aCDB,
     63                                     uint8_t cbCDB, uint8_t __far *buffer, uint32_t length, uint16_t skip_a,
     64                                     uint16_t skip_b);
     65
     66extern int buslogic_scsi_init(void __far *pvHba, uint8_t u8Bus, uint8_t u8DevFn);
     67extern int buslogic_scsi_cmd_data_out(void __far *pvHba, uint8_t idTgt, uint8_t __far *aCDB,
     68                                      uint8_t cbCDB, uint8_t __far *buffer, uint32_t length);
     69extern int buslogic_scsi_cmd_data_in(void __far *pvHba, uint8_t idTgt, uint8_t __far *aCDB,
     70                                     uint8_t cbCDB, uint8_t __far *buffer, uint32_t length, uint16_t skip_a,
     71                                     uint16_t skip_b);
     72
     73extern int virtio_scsi_init(void __far *pvHba, uint8_t u8Bus, uint8_t u8DevFn);
     74extern int virtio_scsi_cmd_data_out(void __far *pvHba, uint8_t idTgt, uint8_t __far *aCDB,
     75                                    uint8_t cbCDB, uint8_t __far *buffer, uint32_t length);
     76extern int virtio_scsi_cmd_data_in(void __far *pvHba, uint8_t idTgt, uint8_t __far *aCDB,
     77                                   uint8_t cbCDB, uint8_t __far *buffer, uint32_t length, uint16_t skip_a,
     78                                   uint16_t skip_b);
     79
    5980#endif /* !VBOX_INCLUDED_SRC_PC_BIOS_scsi_h */
    6081
  • trunk/src/VBox/Devices/PC/BIOS/virtio.c

    r82968 r89168  
    3131# define DBG_VIRTIO(...)
    3232#endif
    33 
    34 #define VBSCSI_MAX_DEVICES 16 /* Maximum number of devices a SCSI device currently supported. */
    3533
    3634/* The maximum CDB size. */
     
    225223
    226224#define PCI_CAP_ID_VNDR                 0x09
    227 #define VBOX_VIRTIO_NO_DEVICE 0xffff
    228225
    229226#define VBOX_VIRTIO_NIL_CFG             0xff
     
    280277#define VIRTIO_SCSI_STS_RESPONSE_OK     0x00
    281278
    282 /* Machinery to save/restore high bits of EAX. 32-bit port I/O needs to use
    283  * EAX, but saving/restoring EAX around each port access would be inefficient.
    284  * Instead, each externally callable routine must save the high bits before
    285  * modifying them and restore the high bits before exiting.
    286  */
    287 
    288 /* Note: Reading high EAX bits destroys them - *must* be restored later. */
    289 uint16_t eax_hi_rd(void);
    290 #pragma aux eax_hi_rd = \
    291     ".386"              \
    292     "shr    eax, 16"    \
    293     value [ax] modify nomemory;
    294 
    295 void eax_hi_wr(uint16_t);
    296 #pragma aux eax_hi_wr = \
    297     ".386"              \
    298     "shl    eax, 16"    \
    299     parm [ax] modify nomemory;
    300 
    301 void inline high_bits_save(virtio_t __far *virtio)
    302 {
    303     virtio->saved_eax_hi = eax_hi_rd();
    304 }
    305 
    306 void inline high_bits_restore(virtio_t __far *virtio)
    307 {
    308     eax_hi_wr(virtio->saved_eax_hi);
    309 }
    310 
    311279static void virtio_reg_set_bar_offset_length(virtio_t __far *virtio, uint8_t u8Bar, uint32_t offReg, uint32_t cb)
    312280{
     
    403371
    404372/**
    405  * Allocates 1K of conventional memory.
    406  */
    407 static uint16_t virtio_mem_alloc(void)
    408 {
    409     uint16_t    base_mem_kb;
    410     uint16_t    virtio_seg;
    411 
    412     base_mem_kb = read_word(0x00, 0x0413);
    413 
    414     DBG_VIRTIO("VirtIO: %dK of base mem\n", base_mem_kb);
    415 
    416     if (base_mem_kb == 0)
    417         return 0;
    418 
    419     base_mem_kb--; /* Allocate one block. */
    420     virtio_seg = (((uint32_t)base_mem_kb * 1024) >> 4); /* Calculate start segment. */
    421 
    422     write_word(0x00, 0x0413, base_mem_kb);
    423 
    424     return virtio_seg;
    425 }
    426 
    427 /**
    428373 * Converts a segment:offset pair into a 32bit physical address.
    429374 */
     
    433378}
    434379
    435 int virtio_scsi_cmd_data_out(virtio_t __far *virtio, uint8_t idTgt, uint8_t __far *aCDB,
    436                             uint8_t cbCDB, uint8_t __far *buffer, uint32_t length)
    437 {
     380int virtio_scsi_cmd_data_out(void __far *pvHba, uint8_t idTgt, uint8_t __far *aCDB,
     381                             uint8_t cbCDB, uint8_t __far *buffer, uint32_t length)
     382{
     383    virtio_t __far *virtio = (virtio_t __far *)pvHba;
    438384    uint16_t idxUsedOld = virtio->Queue.UsedRing.idxNextUsed;
    439385
     
    488434}
    489435
    490 int virtio_scsi_cmd_data_in(virtio_t __far *virtio, uint8_t idTgt, uint8_t __far *aCDB,
     436int virtio_scsi_cmd_data_in(void __far *pvHba, uint8_t idTgt, uint8_t __far *aCDB,
    491437                            uint8_t cbCDB, uint8_t __far *buffer, uint32_t length, uint16_t skip_a,
    492438                            uint16_t skip_b)
    493439{
     440    virtio_t __far *virtio = (virtio_t __far *)pvHba;
    494441    uint16_t idxUsedOld = virtio->Queue.UsedRing.idxNextUsed;
    495442    uint8_t idxDesc = 0;
     
    575522
    576523/**
    577  * Read sectors from an attached VirtIO SCSI device.
    578  *
    579  * @returns status code.
    580  * @param   bios_dsk    Pointer to disk request packet (in the
    581  *                      EBDA).
    582  */
    583 int virtio_scsi_read_sectors(bio_dsk_t __far *bios_dsk)
    584 {
    585     uint8_t             rc;
    586     cdb_rw16            cdb;
    587     uint32_t            count;
    588     uint8_t             target_id;
    589     uint8_t             device_id;
    590 
    591     device_id = VBOX_GET_SCSI_DEVICE(bios_dsk->drqp.dev_id);
    592     if (device_id > BX_MAX_SCSI_DEVICES)
    593         BX_PANIC("%s: device_id out of range %d\n", __func__, device_id);
    594 
    595     count    = bios_dsk->drqp.nsect;
    596 
    597     high_bits_save(bios_dsk->virtio_seg :> 0);
    598     /* Prepare a CDB. */
    599     cdb.command = SCSI_READ_16;
    600     cdb.lba     = swap_64(bios_dsk->drqp.lba);
    601     cdb.pad1    = 0;
    602     cdb.nsect32 = swap_32(count);
    603     cdb.pad2    = 0;
    604 
    605 
    606     target_id = bios_dsk->scsidev[device_id].target_id;
    607 
    608     DBG_VIRTIO("%s: reading %u sectors, device %d, target %d\n", __func__,
    609              count, device_id, bios_dsk->scsidev[device_id].target_id);
    610 
    611     rc = virtio_scsi_cmd_data_in(bios_dsk->virtio_seg :> 0, target_id, (void __far *)&cdb, 16,
    612                                  bios_dsk->drqp.buffer, (count * 512L), 0, 0);
    613 
    614     if (!rc)
    615     {
    616         bios_dsk->drqp.trsfsectors = count;
    617         bios_dsk->drqp.trsfbytes   = count * 512L;
    618     }
    619     DBG_VIRTIO("%s: transferred %u sectors\n", __func__, bios_dsk->drqp.nsect);
    620     high_bits_restore(bios_dsk->virtio_seg :> 0);
    621 
    622     return rc;
    623 }
    624 
    625 /**
    626  * Write sectors to an attached VirtIO SCSI device.
    627  *
    628  * @returns status code.
    629  * @param   bios_dsk    Pointer to disk request packet (in the
    630  *                      EBDA).
    631  */
    632 int virtio_scsi_write_sectors(bio_dsk_t __far *bios_dsk)
    633 {
    634     uint8_t             rc;
    635     cdb_rw16            cdb;
    636     uint32_t            count;
    637     uint8_t             target_id;
    638     uint8_t             device_id;
    639 
    640     device_id = VBOX_GET_SCSI_DEVICE(bios_dsk->drqp.dev_id);
    641     if (device_id > BX_MAX_SCSI_DEVICES)
    642         BX_PANIC("%s: device_id out of range %d\n", __func__, device_id);
    643 
    644     count    = bios_dsk->drqp.nsect;
    645 
    646     high_bits_save(bios_dsk->virtio_seg :> 0);
    647 
    648     /* Prepare a CDB. */
    649     cdb.command = SCSI_WRITE_16;
    650     cdb.lba     = swap_64(bios_dsk->drqp.lba);
    651     cdb.pad1    = 0;
    652     cdb.nsect32 = swap_32(count);
    653     cdb.pad2    = 0;
    654 
    655     target_id = bios_dsk->scsidev[device_id].target_id;
    656 
    657     DBG_VIRTIO("%s: writing %u sectors, device %d, target %d\n", __func__,
    658              count, device_id, bios_dsk->scsidev[device_id].target_id);
    659 
    660     rc = virtio_scsi_cmd_data_out(bios_dsk->virtio_seg :> 0, target_id, (void __far *)&cdb, 16,
    661                                   bios_dsk->drqp.buffer, (count * 512L));
    662 
    663     if (!rc)
    664     {
    665         bios_dsk->drqp.trsfsectors = count;
    666         bios_dsk->drqp.trsfbytes   = (count * 512L);
    667     }
    668     DBG_VIRTIO("%s: transferred %u sectors\n", __func__, bios_dsk->drqp.nsect);
    669     high_bits_restore(bios_dsk->virtio_seg :> 0);
    670 
    671     return rc;
    672 }
    673 
    674 #define ATA_DATA_OUT     0x02
    675 
    676 /**
    677  * Perform a "packet style" read with supplied CDB.
    678  *
    679  * @returns status code.
    680  * @param   device_id   ID of the device to access.
    681  * @param   cmdlen      Length of the CDB.
    682  * @param   cmdbuf      The CDB buffer.
    683  * @param   skip_b      How much to skip before reading into the provided data buffer.
    684  * @param   length      How much to transfer.
    685  * @param   inout       Read/Write direction indicator.
    686  * @param   buffer      Data buffer to store the data from the device in.
    687  */
    688 uint16_t virtio_scsi_cmd_packet(uint16_t device_id, uint8_t cmdlen, char __far *cmdbuf,
    689                                 uint16_t skip_b, uint32_t length, uint8_t inout, char __far *buffer)
    690 {
    691     bio_dsk_t __far *bios_dsk = read_word(0x0040, 0x000E) :> &EbdaData->bdisk;
    692     uint8_t         rc;
    693     uint8_t         target_id;
    694 
    695     /* Data out is currently not supported. */
    696     if (inout == ATA_DATA_OUT) {
    697         BX_INFO("%s: DATA_OUT not supported yet\n", __func__);
    698         return 1;
    699     }
    700 
    701     /* The skip length must be even. */
    702     if (skip_b & 1) {
    703         DBG_VIRTIO("%s: skip must be even (%04x)\n", __func__, skip_b);
    704         return 1;
    705     }
    706 
    707     /* Convert to SCSI specific device number. */
    708     device_id = VBOX_GET_SCSI_DEVICE(device_id);
    709 
    710     DBG_VIRTIO("%s: reading %lu bytes, skip %u/%u, device %d, target %d\n", __func__,
    711                length, bios_dsk->drqp.skip_b, bios_dsk->drqp.skip_a,
    712                device_id, bios_dsk->scsidev[device_id].target_id);
    713     DBG_VIRTIO("%s: reading %u %u-byte sectors\n", __func__,
    714                bios_dsk->drqp.nsect, bios_dsk->drqp.sect_sz);
    715 
    716     high_bits_save(bios_dsk->virtio_seg :> 0);
    717     target_id = bios_dsk->scsidev[device_id].target_id;
    718 
    719     bios_dsk->drqp.lba     = length << 8;     /// @todo xfer length limit
    720     bios_dsk->drqp.buffer  = buffer;
    721     bios_dsk->drqp.nsect   = length / bios_dsk->drqp.sect_sz;
    722 
    723     DBG_VIRTIO("%s: reading %u bytes, device %d, target %d\n", __func__,
    724                length, device_id, bios_dsk->scsidev[device_id].target_id);
    725 
    726     rc = virtio_scsi_cmd_data_in(bios_dsk->virtio_seg :> 0, target_id, (void __far *)cmdbuf, cmdlen,
    727                                  bios_dsk->drqp.buffer, length, skip_b, bios_dsk->drqp.skip_a);
    728     if (!rc)
    729         bios_dsk->drqp.trsfbytes = length;
    730 
    731     DBG_VIRTIO("%s: transferred %u bytes\n", __func__, length);
    732     high_bits_restore(bios_dsk->virtio_seg :> 0);
    733 
    734     return rc;
    735 }
    736 
    737 static int virtio_scsi_detect_devices(virtio_t __far *virtio)
    738 {
    739     int                 i;
    740     uint8_t             buffer[0x0200];
    741     bio_dsk_t __far     *bios_dsk;
    742 
    743     bios_dsk = read_word(0x0040, 0x000E) :> &EbdaData->bdisk;
    744 
    745     /* Go through target devices. */
    746     for (i = 0; i < VBSCSI_MAX_DEVICES; i++)
    747     {
    748         uint8_t     rc;
    749         uint8_t     aCDB[16];
    750         uint8_t     hd_index, devcount_scsi;
    751 
    752         aCDB[0] = SCSI_INQUIRY;
    753         aCDB[1] = 0;
    754         aCDB[2] = 0;
    755         aCDB[3] = 0;
    756         aCDB[4] = 5; /* Allocation length. */
    757         aCDB[5] = 0;
    758 
    759         _fmemset(buffer, 0, sizeof(buffer));
    760 
    761         rc = virtio_scsi_cmd_data_in(virtio, i, aCDB, 6, buffer, 5, 0, 0);
    762         if (!rc)
    763         {
    764             devcount_scsi = bios_dsk->scsi_devcount;
    765 
    766             /* Check the attached device. */
    767             if (   ((buffer[0] & 0xe0) == 0)
    768                 && ((buffer[0] & 0x1f) == 0x00))
    769             {
    770                 DBG_VIRTIO("%s: Disk detected at %d\n", __func__, i);
    771 
    772                 /* We add the disk only if the maximum is not reached yet. */
    773                 if (devcount_scsi < BX_MAX_SCSI_DEVICES)
    774                 {
    775                     uint64_t    sectors, t;
    776                     uint32_t    sector_size, cylinders;
    777                     uint16_t    heads, sectors_per_track;
    778                     uint8_t     hdcount;
    779                     uint8_t     cmos_base;
    780 
    781                     /* Issue a read capacity command now. */
    782                     _fmemset(aCDB, 0, sizeof(aCDB));
    783                     aCDB[0] = SCSI_SERVICE_ACT;
    784                     aCDB[1] = SCSI_READ_CAP_16;
    785                     aCDB[13] = 32; /* Allocation length. */
    786 
    787                     rc = virtio_scsi_cmd_data_in(virtio, i, aCDB, 16, buffer, 32, 0, 0);
    788                     if (rc != 0)
    789                         BX_PANIC("%s: SCSI_READ_CAPACITY failed\n", __func__);
    790 
    791                     /* The value returned is the last addressable LBA, not
    792                      * the size, which what "+ 1" is for.
    793                      */
    794                     sectors = swap_64(*(uint64_t *)buffer) + 1;
    795 
    796                     sector_size =   ((uint32_t)buffer[8] << 24)
    797                                   | ((uint32_t)buffer[9] << 16)
    798                                   | ((uint32_t)buffer[10] << 8)
    799                                   | ((uint32_t)buffer[11]);
    800 
    801                     /* We only support the disk if sector size is 512 bytes. */
    802                     if (sector_size != 512)
    803                     {
    804                         /* Leave a log entry. */
    805                         BX_INFO("Disk %d has an unsupported sector size of %u\n", i, sector_size);
    806                         continue;
    807                     }
    808 
    809                     /* Get logical CHS geometry. */
    810                     switch (devcount_scsi)
    811                     {
    812                         case 0:
    813                             cmos_base = 0x90;
    814                             break;
    815                         case 1:
    816                             cmos_base = 0x98;
    817                             break;
    818                         case 2:
    819                             cmos_base = 0xA0;
    820                             break;
    821                         case 3:
    822                             cmos_base = 0xA8;
    823                             break;
    824                         default:
    825                             cmos_base = 0;
    826                     }
    827 
    828                     if (cmos_base && inb_cmos(cmos_base + 7))
    829                     {
    830                         /* If provided, grab the logical geometry from CMOS. */
    831                         cylinders         = inb_cmos(cmos_base + 0) + (inb_cmos(cmos_base + 1) << 8);
    832                         heads             = inb_cmos(cmos_base + 2);
    833                         sectors_per_track = inb_cmos(cmos_base + 7);
    834                     }
    835                     else
    836                     {
    837                         /* Calculate default logical geometry. NB: Very different
    838                          * from default ATA/SATA logical geometry!
    839                          */
    840                         if (sectors >= (uint32_t)4 * 1024 * 1024)
    841                         {
    842                             heads = 255;
    843                             sectors_per_track = 63;
    844                             /* Approximate x / (255 * 63) using shifts */
    845                             t = (sectors >> 6) + (sectors >> 12);
    846                             cylinders = (t >> 8) + (t >> 16);
    847                         }
    848                         else if (sectors >= (uint32_t)2 * 1024 * 1024)
    849                         {
    850                             heads = 128;
    851                             sectors_per_track = 32;
    852                             cylinders = sectors >> 12;
    853                         }
    854                         else
    855                         {
    856                             heads = 64;
    857                             sectors_per_track = 32;
    858                             cylinders = sectors >> 11;
    859                         }
    860                     }
    861 
    862                     /* Calculate index into the generic disk table. */
    863                     hd_index = devcount_scsi + BX_MAX_ATA_DEVICES;
    864 
    865                     bios_dsk->scsidev[devcount_scsi].target_id = i;
    866                     bios_dsk->devices[hd_index].type        = DSK_TYPE_VIRTIO_SCSI;
    867                     bios_dsk->devices[hd_index].device      = DSK_DEVICE_HD;
    868                     bios_dsk->devices[hd_index].removable   = 0;
    869                     bios_dsk->devices[hd_index].lock        = 0;
    870                     bios_dsk->devices[hd_index].blksize     = sector_size;
    871                     bios_dsk->devices[hd_index].translation = GEO_TRANSLATION_LBA;
    872 
    873                     /* Write LCHS/PCHS values. */
    874                     bios_dsk->devices[hd_index].lchs.heads = heads;
    875                     bios_dsk->devices[hd_index].lchs.spt   = sectors_per_track;
    876                     bios_dsk->devices[hd_index].pchs.heads = heads;
    877                     bios_dsk->devices[hd_index].pchs.spt   = sectors_per_track;
    878 
    879                     if (cylinders > 1024) {
    880                         bios_dsk->devices[hd_index].lchs.cylinders = 1024;
    881                         bios_dsk->devices[hd_index].pchs.cylinders = 1024;
    882                     } else {
    883                         bios_dsk->devices[hd_index].lchs.cylinders = (uint16_t)cylinders;
    884                         bios_dsk->devices[hd_index].pchs.cylinders = (uint16_t)cylinders;
    885                     }
    886 
    887                     BX_INFO("SCSI %d-ID#%d: LCHS=%lu/%u/%u 0x%llx sectors\n", devcount_scsi,
    888                             i, (uint32_t)cylinders, heads, sectors_per_track, sectors);
    889 
    890                     bios_dsk->devices[hd_index].sectors = sectors;
    891 
    892                     /* Store the id of the disk in the ata hdidmap. */
    893                     hdcount = bios_dsk->hdcount;
    894                     bios_dsk->hdidmap[hdcount] = devcount_scsi + BX_MAX_ATA_DEVICES;
    895                     hdcount++;
    896                     bios_dsk->hdcount = hdcount;
    897 
    898                     /* Update hdcount in the BDA. */
    899                     hdcount = read_byte(0x40, 0x75);
    900                     hdcount++;
    901                     write_byte(0x40, 0x75, hdcount);
    902 
    903                     devcount_scsi++;
    904                 }
    905                 else
    906                 {
    907                     /* We reached the maximum of SCSI disks we can boot from. We can quit detecting. */
    908                     break;
    909                 }
    910             }
    911             else if (   ((buffer[0] & 0xe0) == 0)
    912                      && ((buffer[0] & 0x1f) == 0x05))
    913             {
    914                 uint8_t     cdcount;
    915                 uint8_t     removable;
    916 
    917                 BX_INFO("SCSI %d-ID#%d: CD/DVD-ROM\n", devcount_scsi, i);
    918 
    919                 /* Calculate index into the generic device table. */
    920                 hd_index = devcount_scsi + BX_MAX_ATA_DEVICES;
    921 
    922                 removable = buffer[1] & 0x80 ? 1 : 0;
    923 
    924                 bios_dsk->scsidev[devcount_scsi].target_id = i;
    925                 bios_dsk->devices[hd_index].type        = DSK_TYPE_VIRTIO_SCSI;
    926                 bios_dsk->devices[hd_index].device      = DSK_DEVICE_CDROM;
    927                 bios_dsk->devices[hd_index].removable   = removable;
    928                 bios_dsk->devices[hd_index].blksize     = 2048;
    929                 bios_dsk->devices[hd_index].translation = GEO_TRANSLATION_NONE;
    930 
    931                 /* Store the ID of the device in the BIOS cdidmap. */
    932                 cdcount = bios_dsk->cdcount;
    933                 bios_dsk->cdidmap[cdcount] = devcount_scsi + BX_MAX_ATA_DEVICES;
    934                 cdcount++;
    935                 bios_dsk->cdcount = cdcount;
    936 
    937                 devcount_scsi++;
    938             }
    939             else
    940                 DBG_VIRTIO("%s: No supported device detected at %d\n", __func__, i);
    941         }
    942         else
    943             DBG_VIRTIO("%s: INQUIRY failed with %u\n", __func__, rc);
    944 
    945         bios_dsk->scsi_devcount = devcount_scsi;
    946     }
    947 
    948     return 0;
    949 }
    950 
    951 /**
    952524 * Initializes the VirtIO SCSI HBA and detects attached devices.
    953525 */
    954 static int virtio_scsi_hba_init(uint8_t u8Bus, uint8_t u8DevFn, uint8_t u8PciCapOffVirtIo)
    955 {
    956     uint8_t             u8PciCapOff;
    957     uint16_t            ebda_seg;
    958     uint16_t            virtio_seg;
    959     uint8_t             u8DevStat;
    960     bio_dsk_t __far     *bios_dsk;
    961     virtio_t __far      *virtio;
    962 
    963     ebda_seg = read_word(0x0040, 0x000E);
    964     bios_dsk = ebda_seg :> &EbdaData->bdisk;
    965 
    966     /* Allocate 1K of base memory. */
    967     virtio_seg = virtio_mem_alloc();
    968     if (virtio_seg == 0)
    969     {
    970         DBG_VIRTIO("VirtIO: Could not allocate 1K of memory, can't boot from controller\n");
    971         return 0;
    972     }
    973     DBG_VIRTIO("VirtIO: virtio_seg=%04x, size=%04x, pointer at EBDA:%04x (EBDA size=%04x)\n",
    974                virtio_seg, sizeof(virtio_t), (uint16_t)&EbdaData->bdisk.virtio_seg, sizeof(ebda_data_t));
    975 
    976     bios_dsk->virtio_seg    = virtio_seg;
    977 
    978     virtio = virtio_seg :> 0;
     526static int virtio_scsi_hba_init(virtio_t __far *virtio, uint8_t u8Bus, uint8_t u8DevFn, uint8_t u8PciCapOffVirtIo)
     527{
     528    uint8_t u8PciCapOff;
     529    uint8_t u8DevStat;
     530
    979531    virtio->u8Bus   = u8Bus;
    980532    virtio->u8DevFn = u8DevFn;
     
    1054606    {
    1055607        DBG_VIRTIO("VirtIO-SCSI: Invalid SCSI device configuration, ignoring device\n");
    1056         return 0;
     608        return 1;
    1057609    }
    1058610
     
    1067619    {
    1068620        DBG_VIRTIO("VirtIO-SCSI: Device doesn't accept our feature set, ignoring device\n");
    1069         return 0;
     621        return 1;
    1070622    }
    1071623
     
    1104656    virtio_reg_common_write_u8(virtio, VIRTIO_COMMON_REG_DEV_STS, u8DevStat);
    1105657
    1106     return virtio_scsi_detect_devices(virtio);
     658    return 0;
    1107659}
    1108660
     
    1110662 * Init the VirtIO SCSI driver and detect attached disks.
    1111663 */
    1112 void BIOSCALL virtio_scsi_init(void)
    1113 {
    1114     uint16_t    busdevfn;
    1115 
    1116     busdevfn = pci_find_device(0x1af4, 0x1048);
    1117     if (busdevfn != VBOX_VIRTIO_NO_DEVICE)
     664int virtio_scsi_init(void __far *pvHba, uint8_t u8Bus, uint8_t u8DevFn)
     665{
     666    virtio_t __far *virtio = (virtio_t __far *)pvHba;
     667    uint8_t     u8PciCapOff;
     668    uint8_t     u8PciCapOffVirtIo = VBOX_VIRTIO_NIL_CFG;
     669    uint8_t     u8PciCapVirtioSeen = 0;
     670
     671    /* Examine the capability list and search for the VirtIO specific capabilities. */
     672    u8PciCapOff = pci_read_config_byte(u8Bus, u8DevFn, PCI_CONFIG_CAP);
     673
     674    while (u8PciCapOff != 0)
    1118675    {
    1119         uint8_t     u8Bus, u8DevFn;
    1120         uint8_t     u8PciCapOff;
    1121         uint8_t     u8PciCapOffVirtIo = VBOX_VIRTIO_NIL_CFG;
    1122         uint8_t     u8PciCapVirtioSeen = 0;
    1123 
    1124         u8Bus = (busdevfn & 0xff00) >> 8;
    1125         u8DevFn = busdevfn & 0x00ff;
    1126 
    1127         DBG_VIRTIO("VirtIO SCSI HBA at Bus %u DevFn 0x%x (raw 0x%x)\n", u8Bus, u8DevFn, busdevfn);
    1128 
    1129         /* Examine the capability list and search for the VirtIO specific capabilities. */
    1130         u8PciCapOff = pci_read_config_byte(u8Bus, u8DevFn, PCI_CONFIG_CAP);
    1131 
    1132         while (u8PciCapOff != 0)
     676        uint8_t u8PciCapId = pci_read_config_byte(u8Bus, u8DevFn, u8PciCapOff);
     677        uint8_t cbPciCap   = pci_read_config_byte(u8Bus, u8DevFn, u8PciCapOff + 2); /* Capability length. */
     678
     679        DBG_VIRTIO("Capability ID 0x%x at 0x%x\n", u8PciCapId, u8PciCapOff);
     680
     681        if (   u8PciCapId == PCI_CAP_ID_VNDR
     682            && cbPciCap >= sizeof(virtio_pci_cap_t))
    1133683        {
    1134             uint8_t u8PciCapId = pci_read_config_byte(u8Bus, u8DevFn, u8PciCapOff);
    1135             uint8_t cbPciCap   = pci_read_config_byte(u8Bus, u8DevFn, u8PciCapOff + 2); /* Capability length. */
    1136 
    1137             DBG_VIRTIO("Capability ID 0x%x at 0x%x\n", u8PciCapId, u8PciCapOff);
    1138 
    1139             if (   u8PciCapId == PCI_CAP_ID_VNDR
    1140                 && cbPciCap >= sizeof(virtio_pci_cap_t))
     684            /* Read in the config type and see what we got. */
     685            uint8_t u8PciVirtioCfg = pci_read_config_byte(u8Bus, u8DevFn, u8PciCapOff + 3);
     686
     687            if (u8PciCapOffVirtIo == VBOX_VIRTIO_NIL_CFG)
     688                u8PciCapOffVirtIo = u8PciCapOff;
     689
     690            DBG_VIRTIO("VirtIO: CFG ID 0x%x\n", u8PciVirtioCfg);
     691            switch (u8PciVirtioCfg)
    1141692            {
    1142                 /* Read in the config type and see what we got. */
    1143                 uint8_t u8PciVirtioCfg = pci_read_config_byte(u8Bus, u8DevFn, u8PciCapOff + 3);
    1144 
    1145                 if (u8PciCapOffVirtIo == VBOX_VIRTIO_NIL_CFG)
    1146                     u8PciCapOffVirtIo = u8PciCapOff;
    1147 
    1148                 DBG_VIRTIO("VirtIO: CFG ID 0x%x\n", u8PciVirtioCfg);
    1149                 switch (u8PciVirtioCfg)
    1150                 {
    1151                     case VIRTIO_PCI_CAP_COMMON_CFG:
    1152                     case VIRTIO_PCI_CAP_NOTIFY_CFG:
    1153                     case VIRTIO_PCI_CAP_ISR_CFG:
    1154                     case VIRTIO_PCI_CAP_DEVICE_CFG:
    1155                     case VIRTIO_PCI_CAP_PCI_CFG:
    1156                         u8PciCapVirtioSeen |= 1 << (u8PciVirtioCfg - 1);
    1157                         break;
    1158                     default:
    1159                         DBG_VIRTIO("VirtIO SCSI HBA with unknown PCI capability type 0x%x\n", u8PciVirtioCfg);
    1160                 }
     693                case VIRTIO_PCI_CAP_COMMON_CFG:
     694                case VIRTIO_PCI_CAP_NOTIFY_CFG:
     695                case VIRTIO_PCI_CAP_ISR_CFG:
     696                case VIRTIO_PCI_CAP_DEVICE_CFG:
     697                case VIRTIO_PCI_CAP_PCI_CFG:
     698                    u8PciCapVirtioSeen |= 1 << (u8PciVirtioCfg - 1);
     699                    break;
     700                default:
     701                    DBG_VIRTIO("VirtIO SCSI HBA with unknown PCI capability type 0x%x\n", u8PciVirtioCfg);
    1161702            }
    1162 
    1163             u8PciCapOff = pci_read_config_byte(u8Bus, u8DevFn, u8PciCapOff + 1);
    1164703        }
    1165704
    1166         /* Initialize the controller if all required PCI capabilities where found. */
    1167         if (   u8PciCapOffVirtIo != VBOX_VIRTIO_NIL_CFG
    1168             && u8PciCapVirtioSeen == 0x1f)
    1169         {
    1170             int rc;
    1171 
    1172             DBG_VIRTIO("VirtIO SCSI HBA with all required capabilities at 0x%x\n", u8PciCapOffVirtIo);
    1173 
    1174             /* Enable PCI memory, I/O, bus mastering access in command register. */
    1175             pci_write_config_word(u8Bus, u8DevFn, 4, 0x7);
    1176 
    1177             rc = virtio_scsi_hba_init(u8Bus, u8DevFn, u8PciCapOffVirtIo);
    1178         }
    1179         else
    1180             DBG_VIRTIO("VirtIO SCSI HBA with no usable PCI config access!\n");
     705        u8PciCapOff = pci_read_config_byte(u8Bus, u8DevFn, u8PciCapOff + 1);
     706    }
     707
     708    /* Initialize the controller if all required PCI capabilities where found. */
     709    if (   u8PciCapOffVirtIo != VBOX_VIRTIO_NIL_CFG
     710        && u8PciCapVirtioSeen == 0x1f)
     711    {
     712        DBG_VIRTIO("VirtIO SCSI HBA with all required capabilities at 0x%x\n", u8PciCapOffVirtIo);
     713
     714        /* Enable PCI memory, I/O, bus mastering access in command register. */
     715        pci_write_config_word(u8Bus, u8DevFn, 4, 0x7);
     716
     717        return virtio_scsi_hba_init(virtio, u8Bus, u8DevFn, u8PciCapOffVirtIo);
    1181718    }
    1182719    else
    1183         DBG_VIRTIO("No VirtIO SCSI HBA!\n");
    1184 }
     720        DBG_VIRTIO("VirtIO SCSI HBA with no usable PCI config access!\n");
     721
     722    return 1;
     723}
Note: See TracChangeset for help on using the changeset viewer.

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