VirtualBox

Changeset 46241 in vbox for trunk/src/VBox/Devices


Ignore:
Timestamp:
May 23, 2013 3:15:39 PM (12 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
85970
Message:

BIOS: Properly handle SCSI disk reads of 64K or more.

File:
1 edited

Legend:

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

    r46240 r46241  
    8484
    8585int scsi_cmd_data_in(uint16_t io_base, uint8_t target_id, uint8_t __far *aCDB,
    86                      uint8_t cbCDB, uint8_t __far *buffer, uint32_t cbBuffer)
     86                     uint8_t cbCDB, uint8_t __far *buffer, uint32_t length)
    8787{
    8888    /* Check that the adapter is ready. */
     
    9595
    9696   
    97     sizes = ((cbBuffer >> 12) & 0xF0) | cbCDB;
     97    sizes = ((length >> 12) & 0xF0) | cbCDB;
    9898    outb(io_base + VBSCSI_REGISTER_COMMAND, target_id);                 /* Write the target ID. */
    9999    outb(io_base + VBSCSI_REGISTER_COMMAND, SCSI_TXDIR_FROM_DEVICE);    /* Write the transfer direction. */
    100100    outb(io_base + VBSCSI_REGISTER_COMMAND, sizes);                     /* Write CDB size and top bufsize bits. */
    101     outb(io_base + VBSCSI_REGISTER_COMMAND, cbBuffer);                  /* Write the buffer size. */
    102     outb(io_base + VBSCSI_REGISTER_COMMAND, (cbBuffer >> 8));   
     101    outb(io_base + VBSCSI_REGISTER_COMMAND, length);                    /* Write the buffer size. */
     102    outb(io_base + VBSCSI_REGISTER_COMMAND, (length >> 8));   
    103103    for (i = 0; i < cbCDB; i++)                                         /* Write the CDB. */
    104104        outb(io_base + VBSCSI_REGISTER_COMMAND, aCDB[i]);
     
    109109    while (status & VBSCSI_BUSY);
    110110
    111     /* Get the read data. */
    112     rep_insb(buffer, cbBuffer, io_base + VBSCSI_REGISTER_DATA_IN);
     111    /* Read in the data. The transfer length may be exactly 64K or more,
     112     * which needs a bit of care when we're using 16-bit 'rep ins'.
     113     */
     114    while (length > 32768) {
     115        DBG_SCSI("%s: reading 32K to %X:%X\n", __func__, FP_SEG(buffer), FP_OFF(buffer));
     116        rep_insb(buffer, 32768, io_base + VBSCSI_REGISTER_DATA_IN);
     117        length -= 32768;
     118        buffer = (FP_SEG(buffer) + (32768 >> 4)) :> FP_OFF(buffer);
     119    }
     120
     121    DBG_SCSI("%s: reading %ld bytes to %X:%X\n", __func__, length, FP_SEG(buffer), FP_OFF(buffer));
     122    rep_insb(buffer, length, io_base + VBSCSI_REGISTER_DATA_IN);
    113123
    114124    return 0;
     
    116126
    117127int scsi_cmd_data_out(uint16_t io_base, uint8_t target_id, uint8_t __far *aCDB,
    118                       uint8_t cbCDB, uint8_t __far *buffer, uint32_t cbBuffer)
     128                      uint8_t cbCDB, uint8_t __far *buffer, uint32_t length)
    119129{
    120130    /* Check that the adapter is ready. */
     
    127137
    128138   
    129     sizes = ((cbBuffer >> 12) & 0xF0) | cbCDB;
     139    sizes = ((length >> 12) & 0xF0) | cbCDB;
    130140    outb(io_base + VBSCSI_REGISTER_COMMAND, target_id);                 /* Write the target ID. */
    131141    outb(io_base + VBSCSI_REGISTER_COMMAND, SCSI_TXDIR_TO_DEVICE);      /* Write the transfer direction. */
    132142    outb(io_base + VBSCSI_REGISTER_COMMAND, sizes);                     /* Write CDB size and top bufsize bits. */
    133     outb(io_base + VBSCSI_REGISTER_COMMAND, cbBuffer);                  /* Write the buffer size. */
    134     outb(io_base + VBSCSI_REGISTER_COMMAND, (cbBuffer >> 8));
     143    outb(io_base + VBSCSI_REGISTER_COMMAND, length);                    /* Write the buffer size. */
     144    outb(io_base + VBSCSI_REGISTER_COMMAND, (length >> 8));
    135145    for (i = 0; i < cbCDB; i++)                                         /* Write the CDB. */
    136146        outb(io_base + VBSCSI_REGISTER_COMMAND, aCDB[i]);
    137147
    138     /* Write data to I/O port. */
    139     rep_outsb(buffer, cbBuffer, io_base+VBSCSI_REGISTER_DATA_IN);
     148    /* Write out the data. The transfer length may be exactly 64K or more,
     149     * which needs a bit of care when we're using 16-bit 'rep outs'.
     150     */
     151    while (length > 32768) {
     152        DBG_SCSI("%s: writing 32K from %X:%X\n", __func__, FP_SEG(buffer), FP_OFF(buffer));
     153        rep_outsb(buffer, 32768, io_base + VBSCSI_REGISTER_DATA_IN);
     154        length -= 32768;
     155        buffer = (FP_SEG(buffer) + (32768 >> 4)) :> FP_OFF(buffer);
     156    }
     157
     158    DBG_SCSI("%s: writing %ld bytes from %X:%X\n", __func__, length, FP_SEG(buffer), FP_OFF(buffer));
     159    rep_outsb(buffer, length, io_base + VBSCSI_REGISTER_DATA_IN);
    140160
    141161    /* Now wait for the command to complete. */
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