VirtualBox

Ticket #7415: virtualbox_5_0_0_64bit_edd.rev2.2.diff

File virtualbox_5_0_0_64bit_edd.rev2.2.diff, 28.8 KB (added by sobomax, 9 years ago)

Patch to implement 64-bit EDD in BIOS for v5.0.0 (revised to keep VBoxSCSI API compatible)

  • src/VBox/Devices/PC/BIOS/Makefile.kmk

    diff --git a/src/VBox/Devices/PC/BIOS/Makefile.kmk b/src/VBox/Devices/PC/BIOS/Makefile.kmk
    index fa9cb6f..6655ecb 100644
    a b ifdef VBOX_WITH_OPEN_WATCOM  
    6868        pcibio32.asm \
    6969        apm_pm.asm \
    7070        $(VBoxPcBios32_1_TARGET) \
    71         orgs.asm
     71        orgs.asm \
     72        ow_glue64.asm
    7273
    7374 # For 32-bit C code in PC BIOS.
    7475 LIBRARIES += VBoxPcBios32
  • src/VBox/Devices/PC/BIOS/ahci.c

    diff --git a/src/VBox/Devices/PC/BIOS/ahci.c b/src/VBox/Devices/PC/BIOS/ahci.c
    index fd638c9..4f3a4c8 100644
    a b static uint16_t ahci_cmd_data(bio_dsk_t __far *bios_dsk, uint8_t cmd)  
    359359    ahci->abCmd[7]  = RT_BIT_32(6); /* LBA access. */
    360360
    361361    ahci->abCmd[8]  = (bios_dsk->drqp.lba >> 24) & 0xff;
    362     ahci->abCmd[9]  = 0;
    363     ahci->abCmd[10] = 0;
     362    ahci->abCmd[9]  = (bios_dsk->drqp.lba >> 32) & 0xff;
     363    ahci->abCmd[10] = (bios_dsk->drqp.lba >> 40) & 0xff;
    364364    ahci->abCmd[11] = 0;
    365365
    366366    ahci->abCmd[12] = (uint8_t)(n_sect & 0xff);
    int ahci_read_sectors(bio_dsk_t __far *bios_dsk)  
    524524    if (device_id > BX_MAX_AHCI_DEVICES)
    525525        BX_PANIC("%s: device_id out of range %d\n", __func__, device_id);
    526526
    527     DBG_AHCI("%s: %u sectors @ LBA %lu, device %d, port %d\n", __func__,
    528              bios_dsk->drqp.nsect, bios_dsk->drqp.lba, device_id,
    529              bios_dsk->ahcidev[device_id].port);
     527    DBG_AHCI("%s: %u sectors @ LBA 0x%llx, device %d, port %d\n", __func__,
     528             bios_dsk->drqp.nsect, bios_dsk->drqp.lba,
     529             device_id, bios_dsk->ahcidev[device_id].port);
    530530
    531531    high_bits_save(bios_dsk->ahci_seg :> 0);
    532532    ahci_port_init(bios_dsk->ahci_seg :> 0, bios_dsk->ahcidev[device_id].port);
    int ahci_write_sectors(bio_dsk_t __far *bios_dsk)  
    556556    if (device_id > BX_MAX_AHCI_DEVICES)
    557557        BX_PANIC("%s: device_id out of range %d\n", __func__, device_id);
    558558
    559     DBG_AHCI("%s: %u sectors @ LBA %lu, device %d, port %d\n", __func__,
     559    DBG_AHCI("%s: %u sectors @ LBA 0x%llx, device %d, port %d\n", __func__,
    560560             bios_dsk->drqp.nsect, bios_dsk->drqp.lba, device_id,
    561561             bios_dsk->ahcidev[device_id].port);
    562562
    uint16_t ahci_cmd_packet(uint16_t device_id, uint8_t cmdlen, char __far *cmdbuf,  
    601601    DBG_AHCI("%s: reading %u %u-byte sectors\n", __func__,
    602602             bios_dsk->drqp.nsect, bios_dsk->drqp.sect_sz);
    603603
    604     bios_dsk->drqp.lba     = (uint32_t)length << 8;     //@todo: xfer length limit
     604    bios_dsk->drqp.lba     = length << 8;     //@todo: xfer length limit
    605605    bios_dsk->drqp.buffer  = buffer;
    606606    bios_dsk->drqp.nsect   = length / bios_dsk->drqp.sect_sz;
    607607//    bios_dsk->drqp.sect_sz = 2048;
    void ahci_port_detect_device(ahci_t __far *ahci, uint8_t u8Port)  
    689689            VBOXAHCI_PORT_READ_REG(ahci->iobase, u8Port, AHCI_REG_PORT_SIG, val);
    690690            if (val == 0x101)
    691691            {
    692                 uint32_t    sectors;
     692                uint64_t    sectors;
    693693                uint16_t    cylinders, heads, spt;
    694694                chs_t       lgeo;
    695695                uint8_t     idxCmosChsBase;
    void ahci_port_detect_device(ahci_t __far *ahci, uint8_t u8Port)  
    712712                spt       = *(uint16_t *)(abBuffer+(6*2));  // word 6
    713713                sectors   = *(uint32_t *)(abBuffer+(60*2)); // word 60 and word 61
    714714
    715                 /** @todo update sectors to be a 64 bit number (also lba...). */
    716715                if (sectors == 0x0FFFFFFF)  /* For disks bigger than ~128GB */
    717                     sectors = *(uint32_t *)(abBuffer+(100*2)); // words 100 to 103 (someday)
     716                    sectors = *(uint64_t *)(abBuffer+(100*2)); // words 100 to 103
    718717
    719                 DBG_AHCI("AHCI: %ld sectors\n", sectors);
     718                DBG_AHCI("AHCI: 0x%llx sectors\n", sectors);
    720719
    721720                bios_dsk->ahcidev[devcount_ahci].port = u8Port;
    722721                bios_dsk->devices[hd_index].type        = DSK_TYPE_AHCI;
    void ahci_port_detect_device(ahci_t __far *ahci, uint8_t u8Port)  
    758757                else
    759758                    set_geom_lba(&lgeo, sectors);   /* Default EDD-style translated LBA geometry. */
    760759
    761                 BX_INFO("AHCI %d-P#%d: PCHS=%u/%u/%u LCHS=%u/%u/%u %lu sectors\n", devcount_ahci,
    762                         u8Port, cylinders, heads, spt, lgeo.cylinders, lgeo.heads, lgeo.spt, sectors);
     760                BX_INFO("AHCI %d-P#%d: PCHS=%u/%u/%u LCHS=%u/%u/%u 0x%llx sectors\n", devcount_ahci,
     761                        u8Port, cylinders, heads, spt, lgeo.cylinders, lgeo.heads, lgeo.spt,
     762                        sectors);
    763763
    764764                bios_dsk->devices[hd_index].lchs = lgeo;
    765765
  • src/VBox/Devices/PC/BIOS/ata.c

    diff --git a/src/VBox/Devices/PC/BIOS/ata.c b/src/VBox/Devices/PC/BIOS/ata.c
    index 45b79e9..af3e9fe 100644
    a b void BIOSCALL ata_init(void)  
    108108        bios_dsk->devices[device].pchs.heads     = 0;
    109109        bios_dsk->devices[device].pchs.cylinders = 0;
    110110        bios_dsk->devices[device].pchs.spt       = 0;
    111         bios_dsk->devices[device].sectors     = 0;
     111        bios_dsk->devices[device].sectors        = 0;
    112112    }
    113113
    114114    // hdidmap  and cdidmap init.
    void ata_reset(uint16_t device)  
    206206      // 7 : more sectors to write
    207207uint16_t ata_cmd_data_in(bio_dsk_t __far *bios_dsk, uint16_t command, uint16_t count)
    208208{
    209     uint32_t        lba;
     209    uint64_t        lba;
    210210    uint16_t        iobase1, iobase2, blksize, mult_blk_cnt;
    211211    uint16_t        cylinder;
    212212    uint16_t        head;
    uint16_t ata_cmd_data_in(bio_dsk_t __far *bios_dsk, uint16_t command, uint16_t c  
    255255    if (sector == 0) {
    256256        if (lba + count >= 268435456)
    257257        {
    258             sector = (lba & 0xff000000L) >> 24;
    259             cylinder = 0; /* The parameter lba is just a 32 bit value. */
     258            sector = (lba >> 24) & 0x00ff;
     259            cylinder = (lba >> 32) & 0xffff;
    260260            outb(iobase1 + ATA_CB_SC, (count & 0xff00) >> 8);
    261261            outb(iobase1 + ATA_CB_SN, sector);
    262262            outb(iobase1 + ATA_CB_CL, cylinder & 0x00ff);
    void BIOSCALL ata_detect(void)  
    459459
    460460        // Now we send a IDENTIFY command to ATA device
    461461        if (type == DSK_TYPE_ATA) {
    462             uint32_t    sectors;
     462            uint64_t    sectors;
    463463            uint16_t    cylinders, heads, spt, blksize;
    464464            chs_t       lgeo;
    465465            uint8_t     chsgeo_base;
    void BIOSCALL ata_detect(void)  
    483483            spt       = *(uint16_t *)(buffer+(6*2)); // word 6
    484484
    485485            sectors   = *(uint32_t *)(buffer+(60*2)); // word 60 and word 61
    486             /** @todo update sectors to be a 64 bit number (also lba...). */
    487486            if (sectors == 0x0FFFFFFF)  /* For disks bigger than ~128GB */
    488                 sectors = *(uint32_t *)(buffer+(100*2)); // words 100 to 103 (someday)
     487                sectors = *(uint64_t *)(buffer+(100*2)); // words 100 to 103
    489488            switch (device)
    490489            {
    491490            case 0:
    void BIOSCALL ata_detect(void)  
    594593
    595594            switch (type) {
    596595            case DSK_TYPE_ATA:
    597                 sizeinmb = bios_dsk->devices[device].sectors;
    598                 sizeinmb >>= 11;
     596                sizeinmb = (bios_dsk->devices[device].sectors >> 11);
    599597            case DSK_TYPE_ATAPI:
    600598                // Read ATA/ATAPI version
    601599                ataversion = ((uint16_t)(*(buffer+161))<<8) | *(buffer+160);
    void BIOSCALL ata_detect(void)  
    682680      // 7 : more sectors to write
    683681uint16_t ata_cmd_data_out(bio_dsk_t __far *bios_dsk, uint16_t command, uint16_t count)
    684682{
    685     uint32_t        lba;
     683    uint64_t        lba;
    686684    char __far      *buffer;
    687685    uint16_t        iobase1, iobase2, blksize;
    688686    uint16_t        cylinder;
    uint16_t ata_cmd_data_out(bio_dsk_t __far *bios_dsk, uint16_t command, uint16_t  
    723721    if (sector == 0) {
    724722        if (lba + count >= 268435456)
    725723        {
    726             sector = (lba & 0xff000000L) >> 24;
    727             cylinder = 0; /* The parameter lba is just a 32 bit value. */
     724            sector = (lba >> 24) & 0x00ff;
     725            cylinder = (lba >> 32) & 0xffff;
    728726            outb(iobase1 + ATA_CB_SC, (count & 0xff00) >> 8);
    729727            outb(iobase1 + ATA_CB_SN, sector);
    730728            outb(iobase1 + ATA_CB_CL, cylinder & 0x00ff);
    int ata_read_sectors(bio_dsk_t __far *bios_dsk)  
    836834    if (bios_dsk->drqp.sector) {
    837835        /* CHS addressing. */
    838836        bios_dsk->devices[device_id].blksize = n_sect * 0x200;
     837        BX_DEBUG_ATA("%s: reading %u sectors (CHS)\n", __func__, n_sect);
    839838        status = ata_cmd_data_in(bios_dsk, ATA_CMD_READ_MULTIPLE, n_sect);
    840839        bios_dsk->devices[device_id].blksize = 0x200;
    841840    } else {
    842841        /* LBA addressing. */
    843         if (bios_dsk->drqp.lba + n_sect >= 268435456)
     842        if (bios_dsk->drqp.lba + n_sect >= 268435456) {
     843            BX_DEBUG_ATA("%s: reading %u sector (LBA,EXT)\n", __func__, n_sect);
    844844            status = ata_cmd_data_in(bios_dsk, ATA_CMD_READ_SECTORS_EXT, n_sect);
    845         else {
     845        } else {
    846846            bios_dsk->devices[device_id].blksize = n_sect * 0x200;
     847            BX_DEBUG_ATA("%s: reading %u sector (LBA,MULT)\n", __func__, n_sect);
    847848            status = ata_cmd_data_in(bios_dsk, ATA_CMD_READ_MULTIPLE, n_sect);
    848849            bios_dsk->devices[device_id].blksize = 0x200;
    849850        }
  • src/VBox/Devices/PC/BIOS/disk.c

    diff --git a/src/VBox/Devices/PC/BIOS/disk.c b/src/VBox/Devices/PC/BIOS/disk.c
    index 355a976..ecfb49f 100644
    a b dsk_acc_t dskacc[DSKTYP_CNT] = {  
    9898 * Phoenix EDD 3.0. This is used as a fallback to generate sane logical
    9999 * geometry in case none was provided in CMOS.
    100100 */
    101 void set_geom_lba(chs_t __far *lgeo, uint32_t nsectors)
     101void set_geom_lba(chs_t __far *lgeo, uint64_t nsectors64)
    102102{
    103103    uint32_t    limit = 8257536;    /* 1024 * 128 * 63 */
     104    uint32_t    nsectors;
    104105    unsigned    heads = 255;
    105106    int         i;
    106107
     108    nsectors = (nsectors64 >> 32) ? 0xFFFFFFFFL : (uint32_t)nsectors64;
    107109    /* Start with ~4GB limit, go down to 504MB. */
    108110    for (i = 0; i < 4; ++i) {
    109111        if (nsectors <= limit)
    int13_success_noah:  
    330332
    331333void BIOSCALL int13_harddisk_ext(disk_regs_t r)
    332334{
    333     uint32_t            lba;
     335    uint64_t            lba;
    334336    uint16_t            ebda_seg = read_word(0x0040,0x000E);
    335337    uint16_t            segment, offset;
    336338    uint16_t            npc, nph, npspt;
    void BIOSCALL int13_harddisk_ext(disk_regs_t r)  
    383385        segment = i13_ext->segment;
    384386        offset  = i13_ext->offset;
    385387
    386         BX_DEBUG_INT13_HD("%s: %d sectors from lba %lu @ %04x:%04x\n", __func__,
    387                           count, i13_ext->lba1, segment, offset);
    388 
    389         // Can't use 64 bits lba
     388        // Get 64 bits lba and check
    390389        lba = i13_ext->lba2;
    391         if (lba != 0L) {
    392             BX_PANIC("%s: function %02x. Can't use 64bits lba\n", __func__, GET_AH());
    393             goto int13x_fail;
    394         }
     390        lba <<= 32;
     391        lba |= i13_ext->lba1;
    395392
    396         // Get 32 bits lba and check
    397         lba = i13_ext->lba1;
     393        BX_DEBUG_INT13_HD("%s: %d sectors from LBA 0x%llx @ %04x:%04x\n", __func__,
     394                          count, lba, segment, offset);
    398395
    399396        type = bios_dsk->devices[device].type;
    400397        if (lba >= bios_dsk->devices[device].sectors) {
    void BIOSCALL int13_harddisk_ext(disk_regs_t r)  
    466463            dpt->heads     = nph;
    467464            dpt->spt       = npspt;
    468465            dpt->blksize   = blksize;
    469             dpt->sector_count1 = lba;   // FIXME should be Bit64
    470             dpt->sector_count2 = 0;
     466            dpt->sector_count1 = lba;
     467            dpt->sector_count2 = lba >> 32;
    471468        }
    472469
    473470        /* Fill in EDD 2.x table. */
  • src/VBox/Devices/PC/BIOS/ebda.h

    diff --git a/src/VBox/Devices/PC/BIOS/ebda.h b/src/VBox/Devices/PC/BIOS/ebda.h
    index dd9352d..a1cd5df 100644
    a b typedef struct {  
    192192    uint16_t    blksize;      /* Disk block size. */
    193193    chs_t       lchs;         /* Logical CHS geometry. */
    194194    chs_t       pchs;         /* Physical CHS geometry. */
    195     uint32_t    sectors;      /* Total sector count. */
     195    uint64_t    sectors;      /* Total sector count. */
    196196} disk_dev_t;
    197197
    198198/* A structure for passing disk request information around. This structure
    typedef struct {  
    200200 * one such structure is sufficient.
    201201 */
    202202typedef struct {
    203     uint32_t    lba;                /* Starting LBA. */
     203    uint64_t    lba;                /* Starting LBA. */
    204204    void __far  *buffer;            /* Read/write data buffer pointer. */
    205205    uint8_t     dev_id;             /* Device ID; index into devices array. */
    206206    uint16_t    nsect;              /* Number of sectors to be transferred. */
    int __fastcall scsi_write_sectors(bio_dsk_t __far *bios_dsk);  
    317317int __fastcall ahci_read_sectors(bio_dsk_t __far *bios_dsk);
    318318int __fastcall ahci_write_sectors(bio_dsk_t __far *bios_dsk);
    319319
    320 extern void set_geom_lba(chs_t __far *lgeo, uint32_t nsectors);
     320extern void set_geom_lba(chs_t __far *lgeo, uint64_t nsectors);
    321321
    322322// @todo: put this elsewhere (and change/eliminate?)
    323323#define SET_DISK_RET_STATUS(status) write_byte(0x0040, 0x0074, status)
  • new file src/VBox/Devices/PC/BIOS/ow_glue64.asm

    diff --git a/src/VBox/Devices/PC/BIOS/ow_glue64.asm b/src/VBox/Devices/PC/BIOS/ow_glue64.asm
    new file mode 100644
    index 0000000..cde216f
    - +  
     1;;
     2;; Copyright (C) 2006-2015 Oracle Corporation
     3;;
     4;; This file is part of VirtualBox Open Source Edition (OSE), as
     5;; available from http://www.virtualbox.org. This file is free software;
     6;; you can redistribute it and/or modify it under the terms of the GNU
     7;; General Public License (GPL) as published by the Free Software
     8;; Foundation, in version 2 as it comes in the "COPYING" file of the
     9;; VirtualBox OSE distribution. VirtualBox OSE is distributed in the
     10;; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
     11;;
     12;; --------------------------------------------------------------------
     13;;
     14;; Shift routines necessary for the OpenWatcom compiler to link code
     15;; that uses shifts on 64-bit integers
     16;;
     17
     18 name    ow_glue64
     19
     20_TEXT segment word public 'CODE'
     21      assume  cs:_TEXT
     22
     23public __U8LS
     24public __U8RS
     25
     26__U8LS proc near
     27        test si, si
     28        je short out1
     29loop1:
     30        sal dx, 1
     31        rcl cx, 1
     32        rcl bx, 1
     33        rcl ax, 1
     34        dec si
     35        jne short loop1
     36out1:
     37        retn
     38__U8LS endp
     39
     40__U8RS proc near
     41        test si, si
     42        je short out2
     43loop2:
     44        shr ax, 1
     45        rcr bx, 1
     46        rcr cx, 1
     47        rcr dx, 1
     48        dec si
     49        jne short loop2
     50out2:
     51        retn
     52__U8RS endp
     53
     54_TEXT ends
     55
     56 end
  • src/VBox/Devices/PC/BIOS/print.c

    diff --git a/src/VBox/Devices/PC/BIOS/print.c b/src/VBox/Devices/PC/BIOS/print.c
    index af5e85f..1d09471 100644
    a b void put_str_near(uint16_t action, const char __near *s)  
    144144//
    145145//   Supports %[format_width][length]format
    146146//   where format can be x,X,u,d,s,S,c
    147 //   and the optional length modifier is l (ell)
     147//   and the optional length modifier is l (ell, long 32-bit) or ll
     148//   (long long, 64-bit).
     149//   Only x,X work with ll
    148150//--------------------------------------------------------------------------
    149151void bios_printf(uint16_t action, const char *s, ...)
    150152{
    void bios_printf(uint16_t action, const char *s, ...)  
    189191                else if (c == 'u') {
    190192                    put_uint(action, arg, format_width, 0);
    191193                }
     194                else if (c == 'l' && s[1] == 'l') {
     195                    uint64_t llval;
     196                    uint16_t *cp16;
     197
     198                    s += 2;
     199                    c = *s;
     200                    cp16 = (uint16_t *)&llval;
     201                    cp16[0] = arg;
     202                    cp16[1] = va_arg( args, uint16_t );
     203                    cp16[2] = va_arg( args, uint16_t );
     204                    cp16[3] = va_arg( args, uint16_t );
     205                    if (c == 'x' || c == 'X') {
     206                        if (format_width == 0)
     207                            format_width = 16;
     208                        if (c == 'x')
     209                            hexadd = 'a';
     210                        else
     211                            hexadd = 'A';
     212                        for (i=format_width-1; i>=0; i--) {
     213                            nibble =  (llval >> (i * 4)) & 0x000f;
     214                            send (action, (nibble<=9)? (nibble+'0') : (nibble-10+hexadd));
     215                        }
     216                    } else {
     217                        BX_PANIC("bios_printf: unknown %ll format\n");
     218                    }
     219                }
    192220                else if (c == 'l') {
    193221                    s++;
    194222                    c = *s; /* is it ld,lx,lu? */
  • src/VBox/Devices/PC/BIOS/scsi.c

    diff --git a/src/VBox/Devices/PC/BIOS/scsi.c b/src/VBox/Devices/PC/BIOS/scsi.c
    index 36393de..1df60c8 100644
    a b  
    4848#define VBSCSI_MAX_DEVICES 16 /* Maximum number of devices a SCSI device can have. */
    4949
    5050/* Command opcodes. */
     51#define SCSI_SERVICE_ACT   0x9e
    5152#define SCSI_INQUIRY       0x12
    52 #define SCSI_READ_CAPACITY 0x25
     53#define SCSI_READ_CAP_10  0x25
    5354#define SCSI_READ_10       0x28
    5455#define SCSI_WRITE_10      0x2a
     56#define SCSI_READ_CAP_16   0x10    /* Not an opcode by itself, sub-action for the "Service Action" */
     57#define SCSI_READ_16       0x88
     58#define SCSI_WRITE_16      0x8a
    5559
    5660/* Data transfer direction. */
    5761#define SCSI_TXDIR_FROM_DEVICE 0
    typedef struct {  
    6872    uint8_t     pad2;       /* Unused. */
    6973} cdb_rw10;
    7074
     75/* READ_16/WRITE_16 CDB layout. */
     76typedef struct {
     77    uint16_t    command;    /* Command. */
     78    uint64_t    lba;        /* LBA, MSB first! */
     79    uint32_t    nsect32;    /* Sector count, MSB first! */
     80    uint8_t     pad1;       /* Unused. */
     81    uint8_t     pad2;       /* Unused. */
     82} cdb_rw16;
     83
    7184#pragma pack()
    7285
    7386ct_assert(sizeof(cdb_rw10) == 10);
    74 
     87ct_assert(sizeof(cdb_rw16) == 16);
    7588
    7689void insb_discard(unsigned nbytes, unsigned port);
    7790#pragma aux insb_discard =  \
    int scsi_cmd_data_in(uint16_t io_base, uint8_t target_id, uint8_t __far *aCDB,  
    93106        status = inb(io_base + VBSCSI_REGISTER_STATUS);
    94107    while (status & VBSCSI_BUSY);
    95108
    96 
    97     sizes = ((length >> 12) & 0xF0) | cbCDB;
     109    sizes = ((length >> 12) & 0xF0) | (cbCDB == 16) ? 0 : cbCDB;
    98110    outb(io_base + VBSCSI_REGISTER_COMMAND, target_id);                 /* Write the target ID. */
    99111    outb(io_base + VBSCSI_REGISTER_COMMAND, SCSI_TXDIR_FROM_DEVICE);    /* Write the transfer direction. */
    100112    outb(io_base + VBSCSI_REGISTER_COMMAND, sizes);                     /* Write CDB size and top bufsize bits. */
    int scsi_cmd_data_out(uint16_t io_base, uint8_t target_id, uint8_t __far *aCDB,  
    145157    while (status & VBSCSI_BUSY);
    146158
    147159
    148     sizes = ((length >> 12) & 0xF0) | cbCDB;
     160    sizes = ((length >> 12) & 0xF0) | (cbCDB == 16) ? 0 : cbCDB;
    149161    outb(io_base + VBSCSI_REGISTER_COMMAND, target_id);                 /* Write the target ID. */
    150162    outb(io_base + VBSCSI_REGISTER_COMMAND, SCSI_TXDIR_TO_DEVICE);      /* Write the transfer direction. */
    151163    outb(io_base + VBSCSI_REGISTER_COMMAND, sizes);                     /* Write CDB size and top bufsize bits. */
    int scsi_cmd_data_out(uint16_t io_base, uint8_t target_id, uint8_t __far *aCDB,  
    184196    return 0;
    185197}
    186198
     199static uint64_t swap_64(uint64_t val)
     200{
     201    uint64_t rval;
     202
     203    rval = swap_32(val & 0xffffffff);
     204    rval <<= 32;
     205    rval |= swap_32(val >> 32);
     206
     207    return rval;
     208}
     209
    187210/**
    188211 * Read sectors from an attached SCSI device.
    189212 *
    int scsi_cmd_data_out(uint16_t io_base, uint8_t target_id, uint8_t __far *aCDB,  
    194217int scsi_read_sectors(bio_dsk_t __far *bios_dsk)
    195218{
    196219    uint8_t             rc;
    197     cdb_rw10            cdb;
    198     uint16_t            count;
     220    cdb_rw16            cdb;
     221    uint32_t            count;
    199222    uint16_t            io_base;
    200223    uint8_t             target_id;
    201224    uint8_t             device_id;
    int scsi_read_sectors(bio_dsk_t __far *bios_dsk)  
    207230    count    = bios_dsk->drqp.nsect;
    208231
    209232    /* Prepare a CDB. */
    210     cdb.command = SCSI_READ_10;
    211     cdb.lba     = swap_32(bios_dsk->drqp.lba);
     233    cdb.command = SCSI_READ_16;
     234    cdb.lba     = swap_64(bios_dsk->drqp.lba);
    212235    cdb.pad1    = 0;
    213     cdb.nsect   = swap_16(count);
     236    cdb.nsect32 = swap_32(count);
    214237    cdb.pad2    = 0;
    215238
    216239
    int scsi_read_sectors(bio_dsk_t __far *bios_dsk)  
    220243    DBG_SCSI("%s: reading %u sectors, device %d, target %d\n", __func__,
    221244             count, device_id, bios_dsk->scsidev[device_id].target_id);
    222245
    223     rc = scsi_cmd_data_in(io_base, target_id, (void __far *)&cdb, 10,
     246    rc = scsi_cmd_data_in(io_base, target_id, (void __far *)&cdb, 16,
    224247                          bios_dsk->drqp.buffer, (count * 512L));
    225248
    226249    if (!rc)
    int scsi_read_sectors(bio_dsk_t __far *bios_dsk)  
    243266int scsi_write_sectors(bio_dsk_t __far *bios_dsk)
    244267{
    245268    uint8_t             rc;
    246     cdb_rw10            cdb;
    247     uint16_t            count;
     269    cdb_rw16            cdb;
     270    uint32_t            count;
    248271    uint16_t            io_base;
    249272    uint8_t             target_id;
    250273    uint8_t             device_id;
    int scsi_write_sectors(bio_dsk_t __far *bios_dsk)  
    256279    count    = bios_dsk->drqp.nsect;
    257280
    258281    /* Prepare a CDB. */
    259     cdb.command = SCSI_WRITE_10;
    260     cdb.lba     = swap_32(bios_dsk->drqp.lba);
     282    cdb.command = SCSI_WRITE_16;
     283    cdb.lba     = swap_64(bios_dsk->drqp.lba);
    261284    cdb.pad1    = 0;
    262     cdb.nsect   = swap_16(count);
     285    cdb.nsect32 = swap_32(count);
    263286    cdb.pad2    = 0;
    264287
    265288    io_base   = bios_dsk->scsidev[device_id].io_base;
    int scsi_write_sectors(bio_dsk_t __far *bios_dsk)  
    268291    DBG_SCSI("%s: writing %u sectors, device %d, target %d\n", __func__,
    269292             count, device_id, bios_dsk->scsidev[device_id].target_id);
    270293
    271     rc = scsi_cmd_data_out(io_base, target_id, (void __far *)&cdb, 10,
     294    rc = scsi_cmd_data_out(io_base, target_id, (void __far *)&cdb, 16,
    272295                           bios_dsk->drqp.buffer, (count * 512L));
    273296
    274297    if (!rc)
    void scsi_enumerate_attached_devices(uint16_t io_base)  
    402425    for (i = 0; i < VBSCSI_MAX_DEVICES; i++)
    403426    {
    404427        uint8_t     rc;
    405         uint8_t     aCDB[10];
     428        uint8_t     aCDB[16];
    406429        uint8_t     hd_index, devcount_scsi;
    407430
    408431        aCDB[0] = SCSI_INQUIRY;
    void scsi_enumerate_attached_devices(uint16_t io_base)  
    427450            /* We add the disk only if the maximum is not reached yet. */
    428451            if (devcount_scsi < BX_MAX_SCSI_DEVICES)
    429452            {
    430                 uint32_t    sectors, sector_size, cylinders;
     453                uint64_t    sectors, t;
     454                uint32_t    sector_size, cylinders;
    431455                uint16_t    heads, sectors_per_track;
    432456                uint8_t     hdcount;
    433457                uint8_t     cmos_base;
    434458
    435459                /* Issue a read capacity command now. */
    436460                _fmemset(aCDB, 0, sizeof(aCDB));
    437                 aCDB[0] = SCSI_READ_CAPACITY;
     461                aCDB[0] = SCSI_SERVICE_ACT;
     462                aCDB[1] = SCSI_READ_CAP_16;
     463                aCDB[13] = 32; /* Allocation length. */
    438464
    439                 rc = scsi_cmd_data_in(io_base, i, aCDB, 10, buffer, 8);
     465                rc = scsi_cmd_data_in(io_base, i, aCDB, 16, buffer, 32);
    440466                if (rc != 0)
    441467                    BX_PANIC("%s: SCSI_READ_CAPACITY failed\n", __func__);
    442468
    443                 /* Build sector number and size from the buffer. */
    444                 //@todo: byte swapping for dword sized items should be farmed out...
    445                 sectors =   ((uint32_t)buffer[0] << 24)
    446                           | ((uint32_t)buffer[1] << 16)
    447                           | ((uint32_t)buffer[2] << 8)
    448                           | ((uint32_t)buffer[3]);
    449                 ++sectors;  /* Returned value is the last LBA, zero-based. */
     469                /* The value returned is the last addressable LBA, not
     470                 * the size, which what "+ 1" is for.
     471                 */
     472                sectors = swap_64(*(uint64_t *)buffer) + 1;
    450473
    451                 sector_size =   ((uint32_t)buffer[4] << 24)
    452                               | ((uint32_t)buffer[5] << 16)
    453                               | ((uint32_t)buffer[6] << 8)
    454                               | ((uint32_t)buffer[7]);
     474                sector_size =   ((uint32_t)buffer[8] << 24)
     475                              | ((uint32_t)buffer[9] << 16)
     476                              | ((uint32_t)buffer[10] << 8)
     477                              | ((uint32_t)buffer[11]);
    455478
    456479                /* We only support the disk if sector size is 512 bytes. */
    457480                if (sector_size != 512)
    void scsi_enumerate_attached_devices(uint16_t io_base)  
    496519                    {
    497520                        heads = 255;
    498521                        sectors_per_track = 63;
     522                        /* Approximate x / (255 * 63) using shifts */
     523                        t = (sectors >> 6) + (sectors >> 12);
     524                        cylinders = (t >> 8) + (t >> 16);
    499525                    }
    500526                    else if (sectors >= (uint32_t)2 * 1024 * 1024)
    501527                    {
    502528                        heads = 128;
    503529                        sectors_per_track = 32;
     530                        cylinders = sectors >> 12;
    504531                    }
    505532                    else
    506533                    {
    507534                        heads = 64;
    508535                        sectors_per_track = 32;
     536                        cylinders = sectors >> 11;
    509537                    }
    510                     cylinders = (uint32_t)(sectors / (heads * sectors_per_track));
    511538                }
    512539
    513540                /* Calculate index into the generic disk table. */
    void scsi_enumerate_attached_devices(uint16_t io_base)  
    522549                bios_dsk->devices[hd_index].blksize     = sector_size;
    523550                bios_dsk->devices[hd_index].translation = GEO_TRANSLATION_LBA;
    524551
    525                 /* Write LCHS values. */
     552                /* Write LCHS/PCHS values. */
    526553                bios_dsk->devices[hd_index].lchs.heads = heads;
    527554                bios_dsk->devices[hd_index].lchs.spt   = sectors_per_track;
    528                 if (cylinders > 1024)
    529                     bios_dsk->devices[hd_index].lchs.cylinders = 1024;
    530                 else
    531                     bios_dsk->devices[hd_index].lchs.cylinders = (uint16_t)cylinders;
    532 
    533                 BX_INFO("SCSI %d-ID#%d: LCHS=%u/%u/%u %lu sectors\n", devcount_scsi,
    534                         i, (uint16_t)cylinders, heads, sectors_per_track, sectors);
    535 
    536                 /* Write PCHS values. */
    537555                bios_dsk->devices[hd_index].pchs.heads = heads;
    538556                bios_dsk->devices[hd_index].pchs.spt   = sectors_per_track;
    539                 if (cylinders > 1024)
     557
     558                if (cylinders > 1024) {
     559                    bios_dsk->devices[hd_index].lchs.cylinders = 1024;
    540560                    bios_dsk->devices[hd_index].pchs.cylinders = 1024;
    541                 else
     561                } else {
     562                    bios_dsk->devices[hd_index].lchs.cylinders = (uint16_t)cylinders;
    542563                    bios_dsk->devices[hd_index].pchs.cylinders = (uint16_t)cylinders;
     564                }
     565
     566                BX_INFO("SCSI %d-ID#%d: LCHS=%lu/%u/%u 0x%llx sectors\n", devcount_scsi,
     567                        i, (uint32_t)cylinders, heads, sectors_per_track, sectors);
    543568
    544569                bios_dsk->devices[hd_index].sectors = sectors;
    545570
  • src/VBox/Devices/Storage/VBoxSCSI.cpp

    diff --git a/src/VBox/Devices/Storage/VBoxSCSI.cpp b/src/VBox/Devices/Storage/VBoxSCSI.cpp
    index 04fefa5..d638d50 100644
    a b int vboxscsiWriteRegister(PVBOXSCSI pVBoxSCSI, uint8_t iRegister, uint8_t uVal)  
    173173            }
    174174            else if (pVBoxSCSI->enmState == VBOXSCSISTATE_READ_CDB_SIZE_BUFHI)
    175175            {
    176                 uint8_t cbCDB = uVal & 0x0F;
     176                uint8_t cbCDB = (uVal & 0x0F);
     177
     178                if (cbCDB == 0)
     179                    cbCDB = 16;
    177180                if (cbCDB > VBOXSCSI_CDB_SIZE_MAX)
    178181                    vboxscsiReset(pVBoxSCSI, true /*fEverything*/);
    179182                else
  • src/VBox/Devices/Storage/VBoxSCSI.h

    diff --git a/src/VBox/Devices/Storage/VBoxSCSI.h b/src/VBox/Devices/Storage/VBoxSCSI.h
    index 4f4b5e2..776dff5 100644
    a b typedef enum VBOXSCSISTATE  
    8787#define VBOXSCSI_TXDIR_TO_DEVICE   1
    8888
    8989/** Maximum CDB size the BIOS driver sends. */
    90 #define VBOXSCSI_CDB_SIZE_MAX     10
     90#define VBOXSCSI_CDB_SIZE_MAX     16
    9191
    9292typedef struct VBOXSCSI
    9393{
    typedef struct VBOXSCSI  
    100100    /** The size of the CDB we are issuing. */
    101101    uint8_t              cbCDB;
    102102    /** The command to issue. */
    103     uint8_t              abCDB[12];
     103    uint8_t              abCDB[VBOXSCSI_CDB_SIZE_MAX + 4];
    104104    /** Current position in the array. */
    105105    uint8_t              iCDB;
    106106

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