VirtualBox

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


Ignore:
Timestamp:
May 7, 2019 10:02:20 AM (6 years ago)
Author:
vboxsync
Message:

BIOS: Reworked ATA device detection, old code relied on bugs in ATA emulation.

File:
1 edited

Legend:

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

    r78052 r78423  
    374374// ---------------------------------------------------------------------------
    375375
     376int ata_signature(uint16_t iobase1, uint8_t channel, uint8_t slave)
     377{
     378    int         dsk_type = DSK_TYPE_NONE;
     379    uint8_t     sc, sn, st, cl, ch;
     380
     381    /*
     382     * Wait for BSY=0 so that the signature can be read. We already determined that
     383     * an ATA interface is present, and rely on the fact that for non-existent
     384     * devices, the BSY bit will always be clear.
     385     */
     386    outb(iobase1+ATA_CB_DH, slave ? ATA_CB_DH_DEV1 : ATA_CB_DH_DEV0);
     387    do {
     388        st = inb(iobase1+ATA_CB_STAT);
     389    } while (st & ATA_CB_STAT_BSY);
     390
     391    /*
     392     * Look for ATA/ATAPI signature. Fun Fact #1: If there's a Device 1 but no
     393     * Device 0, Device 1 can't tell and does not respond for it. Accessing
     394     * non-existent Device 0 behaves the same regardless of whether Device 1
     395     * is present or not.
     396     */
     397    sc = inb(iobase1+ATA_CB_SC);
     398    sn = inb(iobase1+ATA_CB_SN);
     399    if ((sc == 1) && (sn == 1)) {
     400        cl = inb(iobase1+ATA_CB_CL);
     401        ch = inb(iobase1+ATA_CB_CH);
     402
     403        /*
     404         * Fun fact #2: If Device 0 responds for Device 1, an ATA device generally
     405         * returns the values of its own registers, while an ATAPI device returns
     406         * zeros. In both cases, the Status register is read as zero.
     407         */
     408        if ((cl == 0x14) && (ch == 0xEB)) {
     409            dsk_type = DSK_TYPE_ATAPI;
     410            BX_DEBUG_ATA("ata%d-%d: ATAPI device\n", channel, slave);
     411        } else if ((cl == 0) && (ch == 0)) {
     412            if (st != 0) {
     413                dsk_type = DSK_TYPE_ATA;
     414                BX_DEBUG_ATA("ata%d-%d: ATA device\n", channel, slave);
     415            } else {
     416                BX_DEBUG_ATA("ata%d-%d: ATA master responding for slave\n", channel, slave);
     417            }
     418        } else {
     419            dsk_type = DSK_TYPE_UNKNOWN;
     420            BX_DEBUG_ATA("ata%d-%d: something else (%02X/%02X/%02X)\n", channel, slave, cl, ch, st);
     421        }
     422    } else  /* Possibly ATAPI Device 0 responding for Device 1. */
     423        BX_DEBUG_ATA("ata%d-%d: bad sc/sn signature (%02X/%02X)\n", channel, slave, sc, sn);
     424
     425    return dsk_type;
     426}
     427
    376428void BIOSCALL ata_detect(void)
    377429{
     
    411463    bios_dsk->channels[1].irq     = 15;
    412464#endif
    413 #if 0   /// @todo - temporarily removed to avoid conflict with AHCI
    414465#if BX_MAX_ATA_INTERFACES > 2
    415466    bios_dsk->channels[2].iface   = ATA_IFACE_ISA;
     
    424475    bios_dsk->channels[3].irq     = 11;
    425476#endif
    426 #endif
    427477#if BX_MAX_ATA_INTERFACES > 4
    428 #error Please fill the ATA interface informations
     478#error Please fill the ATA interface information
    429479#endif
    430480
     
    434484    for (device = 0; device < BX_MAX_ATA_DEVICES; device++) {
    435485        uint16_t    iobase1, iobase2;
     486        uint16_t    retries;
    436487        uint8_t     channel, slave;
    437         uint8_t     sc, sn, cl, ch, st;
     488        uint8_t     st;
    438489
    439490        channel = device / 2;
     
    443494        iobase2 = bios_dsk->channels[channel].iobase2;
    444495
    445         // Disable interrupts
    446         outb(iobase2+ATA_CB_DC, ATA_CB_DC_HD15 | ATA_CB_DC_NIEN);
    447 
    448         // Look for device
    449         outb(iobase1+ATA_CB_DH, slave ? ATA_CB_DH_DEV1 : ATA_CB_DH_DEV0);
    450         outb(iobase1+ATA_CB_SC, 0x55);
    451         outb(iobase1+ATA_CB_SN, 0xaa);
    452         outb(iobase1+ATA_CB_SC, 0xaa);
    453         outb(iobase1+ATA_CB_SN, 0x55);
    454         outb(iobase1+ATA_CB_SC, 0x55);
    455         outb(iobase1+ATA_CB_SN, 0xaa);
    456 
    457         // If we found something
    458         sc = inb(iobase1+ATA_CB_SC);
    459         sn = inb(iobase1+ATA_CB_SN);
    460 
    461         if ( (sc == 0x55) && (sn == 0xaa) ) {
    462             bios_dsk->devices[device].type = DSK_TYPE_UNKNOWN;
    463 
    464             // reset the channel
    465             ata_reset(device);
    466 
    467             // check for ATA or ATAPI
    468             outb(iobase1+ATA_CB_DH, slave ? ATA_CB_DH_DEV1 : ATA_CB_DH_DEV0);
    469             sc = inb(iobase1+ATA_CB_SC);
    470             sn = inb(iobase1+ATA_CB_SN);
    471             if ((sc==0x01) && (sn==0x01)) {
    472                 cl = inb(iobase1+ATA_CB_CL);
    473                 ch = inb(iobase1+ATA_CB_CH);
     496        /*
     497         * Here we are in a tricky situation. We do not know if an ATA
     498         * interface is even present at a given address. If it is present,
     499         * we don't know if a device is present. We also need to consider
     500         * the case of only a slave device being present, which does not
     501         * respond for the missing master device. If a device is present,
     502         * it may be still powering up or processing reset, which means it
     503         * may be busy.
     504         *
     505         * If a device is busy, we can't reliably write any registers, and
     506         * reads will return the Status register. If the Status register
     507         * value is 0FFh, there might be no ATA controller at all, or it
     508         * might be a busy drive. Fortunately we know that our own devices
     509         * never return such a value when busy, and we use that knowledge
     510         * to detect non-existent interfaces.
     511         *
     512         * We also know that our ATA interface will not return 0FFh even when
     513         * no device is present on a given channel. This knowledge is handy
     514         * when only a slave device exists because we won't read 0FFh and
     515         * think there is no ATA interface at all.
     516         */
     517
     518        st = inb(iobase1+ATA_CB_STAT);
     519        BX_DEBUG_ATA("ata%d-%d: Status=%02X\n", channel, slave, st);
     520        if (st == 0xff)
     521            continue;
     522
     523        /*
     524         * Perform a software reset by setting and clearing the SRST bit. This
     525         * can be done at any time, and forces device signature into the task file
     526         * registers. If present, both devices are reset at once, so we only do
     527         * this once per channel.
     528         */
     529        if (!slave) {
     530            outb(iobase2+ATA_CB_DC, ATA_CB_DC_HD15 | ATA_CB_DC_NIEN | ATA_CB_DC_SRST);
     531
     532            /*
     533             * Ensure reasonable SRST pulse width, but do not wait long for
     534             * non-existent devices.
     535             */
     536            retries = 32;
     537            while (--retries > 0) {
    474538                st = inb(iobase1+ATA_CB_STAT);
    475 
    476                 if ((cl==0x14) && (ch==0xeb)) {
    477                     bios_dsk->devices[device].type = DSK_TYPE_ATAPI;
    478                 } else if ((cl==0x00) && (ch==0x00) && (st!=0x00)) {
    479                     bios_dsk->devices[device].type = DSK_TYPE_ATA;
    480                 } else if ((cl==0xff) && (ch==0xff)) {
    481                     bios_dsk->devices[device].type = DSK_TYPE_NONE;
    482                 }
    483             }
     539                if (st & ATA_CB_STAT_BSY)
     540                    break;
     541            }
     542
     543            outb(iobase2+ATA_CB_DC, ATA_CB_DC_HD15 | ATA_CB_DC_NIEN);
     544
     545            /* After reset, device signature will be placed in registers. But
     546             * executing any commands will overwrite it for Device 1. So that
     547             * we don't have to reset twice, look for both Device 0 and Device 1
     548             * signatures here right after reset.
     549             */
     550            bios_dsk->devices[device + 0].type = ata_signature(iobase1, channel, 0);
     551            bios_dsk->devices[device + 1].type = ata_signature(iobase1, channel, 1);
    484552        }
    485553
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