VirtualBox

Changeset 48081 in vbox for trunk/src/VBox


Ignore:
Timestamp:
Aug 27, 2013 1:03:34 PM (11 years ago)
Author:
vboxsync
Message:

DevFdc: Allow reformatting a floppy.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Devices/Storage/DevFdc.cpp

    r48059 r48081  
    177177    uint8_t track;
    178178    uint8_t sect;
     179    uint8_t ltrk;             /* Logical track */
    179180    /* Media */
    180181    fdrive_flags_t flags;
     
    287288        drv->sect = sect;
    288289    }
     290    drv->ltrk = drv->track;
    289291
    290292    return ret;
     
    297299    drv->head = 0;
    298300    drv->track = 0;
     301    drv->ltrk = 0;
    299302    drv->sect = 1;
    300303}
     
    535538    FD_DIR_SCANE   = 2,
    536539    FD_DIR_SCANL   = 3,
    537     FD_DIR_SCANH   = 4
     540    FD_DIR_SCANH   = 4,
     541    FD_DIR_FORMAT  = 5
    538542};
    539543
     
    11651169            } else {
    11661170                cur_drv->head = 0;
    1167                 cur_drv->track++;
     1171                cur_drv->ltrk++;
    11681172                if ((cur_drv->flags & FDISK_DBL_SIDES) == 0)
    11691173                    return 0;
    11701174            }
    11711175        } else {
    1172             cur_drv->track++;
     1176            cur_drv->ltrk++;
    11731177            return 0;
    11741178        }
     
    11951199    fdctrl->fifo[1] = status1;
    11961200    fdctrl->fifo[2] = status2;
    1197     fdctrl->fifo[3] = cur_drv->track;
     1201    fdctrl->fifo[3] = cur_drv->ltrk;
    11981202    fdctrl->fifo[4] = cur_drv->head;
    11991203    fdctrl->fifo[5] = cur_drv->sect;
     
    13161320              direction == FD_DIR_SCANH) && dma_mode == 0) ||
    13171321            (direction == FD_DIR_WRITE && dma_mode == 2) ||
    1318             (direction == FD_DIR_READ && dma_mode == 1)) {
     1322            (direction == FD_DIR_READ && (dma_mode == 1 || dma_mode == 0))) {
    13191323            /* No access is allowed until DMA transfer has completed */
    13201324            fdctrl->msr &= ~FD_MSR_RQM;
     
    13441348}
    13451349
     1350/* Prepare a format data transfer (either DMA or FIFO) */
     1351static void fdctrl_start_format(fdctrl_t *fdctrl)
     1352{
     1353    fdrive_t *cur_drv;
     1354    uint8_t ns, dp, kh, kt, ks;
     1355
     1356    SET_CUR_DRV(fdctrl, fdctrl->fifo[1] & FD_DOR_SELMASK);
     1357    cur_drv = get_cur_drv(fdctrl);
     1358    kt = cur_drv->track;
     1359    kh = (fdctrl->fifo[1] & 0x04) >> 2;
     1360    ns = fdctrl->fifo[3];
     1361    dp = fdctrl->fifo[5];
     1362    ks = 1;
     1363    FLOPPY_DPRINTF("Start format at %d %d %02x, %d sect, pat %02x (%d)\n",
     1364                   GET_CUR_DRV(fdctrl), kh, kt, ns, dp,
     1365                   fd_sector_calc(kh, kt, ks, cur_drv->last_sect, NUM_SIDES(cur_drv)));
     1366    switch (fd_seek(cur_drv, kh, kt, ks, false)) {
     1367    case 2:
     1368        /* sect too big */
     1369        fdctrl_stop_transfer(fdctrl, FD_SR0_ABNTERM, 0x00, 0x00);
     1370        fdctrl->fifo[3] = kt;
     1371        fdctrl->fifo[4] = kh;
     1372        fdctrl->fifo[5] = ks;
     1373        return;
     1374    case 3:
     1375        /* track too big */
     1376        fdctrl_stop_transfer(fdctrl, FD_SR0_ABNTERM, FD_SR1_EC, 0x00);
     1377        fdctrl->fifo[3] = kt;
     1378        fdctrl->fifo[4] = kh;
     1379        fdctrl->fifo[5] = ks;
     1380        return;
     1381    case 4:
     1382        /* No seek enabled */
     1383        fdctrl_stop_transfer(fdctrl, FD_SR0_ABNTERM, 0x00, 0x00);
     1384        fdctrl->fifo[3] = kt;
     1385        fdctrl->fifo[4] = kh;
     1386        fdctrl->fifo[5] = ks;
     1387        return;
     1388    case 1:
     1389        break;
     1390    default:
     1391        break;
     1392    }
     1393    /* It's not clear what should happen if the data rate does not match. */
     1394#if 0
     1395    /* Check the data rate. If the programmed data rate does not match
     1396     * the currently inserted medium, the operation has to fail.
     1397     */
     1398    if ((fdctrl->dsr & FD_DSR_DRATEMASK) != cur_drv->media_rate) {
     1399        FLOPPY_DPRINTF("data rate mismatch (fdc=%d, media=%d)\n",
     1400                       fdctrl->dsr & FD_DSR_DRATEMASK, cur_drv->media_rate);
     1401        fdctrl_stop_transfer(fdctrl, FD_SR0_ABNTERM, FD_SR1_MA, FD_SR2_MD);
     1402        fdctrl->fifo[3] = kt;
     1403        fdctrl->fifo[4] = kh;
     1404        fdctrl->fifo[5] = ks;
     1405        return;
     1406    }
     1407#endif
     1408    /* Set the FIFO state */
     1409    fdctrl->data_dir = FD_DIR_FORMAT;
     1410    fdctrl->data_pos = 0;
     1411    fdctrl->msr |= FD_MSR_CMDBUSY;
     1412    fdctrl->data_state &= ~(FD_STATE_MULTI | FD_STATE_SEEK);
     1413    fdctrl->data_len = ns * 4;
     1414    fdctrl->eot = ns;
     1415    if (fdctrl->dor & FD_DOR_DMAEN) {
     1416        int dma_mode;
     1417        /* DMA transfer are enabled. Check if DMA channel is well programmed */
     1418#ifndef VBOX
     1419        dma_mode = DMA_get_channel_mode(fdctrl->dma_chann);
     1420#else
     1421        dma_mode = PDMDevHlpDMAGetChannelMode (fdctrl->pDevIns, fdctrl->dma_chann);
     1422#endif
     1423        dma_mode = (dma_mode >> 2) & 3;
     1424        FLOPPY_DPRINTF("dma_mode=%d direction=%d (%d - %d)\n",
     1425                       dma_mode, fdctrl->data_dir,
     1426                       (128 << fdctrl->fifo[2]) *
     1427                       (cur_drv->last_sect + 1), fdctrl->data_len);
     1428        if (fdctrl->data_dir == FD_DIR_FORMAT && dma_mode == 2) {
     1429            /* No access is allowed until DMA transfer has completed */
     1430            fdctrl->msr &= ~FD_MSR_RQM;
     1431            /* Now, we just have to wait for the DMA controller to
     1432             * recall us...
     1433             */
     1434#ifndef VBOX
     1435            DMA_hold_DREQ(fdctrl->dma_chann);
     1436            DMA_schedule(fdctrl->dma_chann);
     1437#else
     1438            PDMDevHlpDMASetDREQ (fdctrl->pDevIns, fdctrl->dma_chann, 1);
     1439            PDMDevHlpDMASchedule (fdctrl->pDevIns);
     1440#endif
     1441            return;
     1442        } else {
     1443            FLOPPY_ERROR("dma_mode=%d direction=%d\n", dma_mode, fdctrl->data_dir);
     1444        }
     1445    }
     1446    FLOPPY_DPRINTF("start non-DMA format\n");
     1447    fdctrl->msr |= FD_MSR_NONDMA;
     1448    /* IO based transfer: calculate len */
     1449    fdctrl_raise_irq(fdctrl, 0x00);
     1450
     1451    return;
     1452}
     1453
    13461454/* Prepare a transfer of deleted data */
    13471455static void fdctrl_start_transfer_del(fdctrl_t *fdctrl, int direction)
     
    14391547        goto transfer_error;
    14401548    }
     1549
     1550#ifdef VBOX
     1551        if (cur_drv->ro)
     1552        {
     1553            if (fdctrl->data_dir == FD_DIR_WRITE || fdctrl->data_dir == FD_DIR_FORMAT)
     1554            {
     1555                /* Handle readonly medium early, no need to do DMA, touch the
     1556                 * LED or attempt any writes. A real floppy doesn't attempt
     1557                 * to write to readonly media either. */
     1558                fdctrl_stop_transfer(fdctrl, FD_SR0_ABNTERM | FD_SR0_SEEK, FD_SR1_NW,
     1559                                     0x00);
     1560                goto transfer_error;
     1561            }
     1562        }
     1563#endif
     1564
     1565
    14411566    rel_pos = fdctrl->data_pos % FD_SECTOR_LEN;
    14421567    for (start_pos = fdctrl->data_pos; fdctrl->data_pos < dma_len;) {
     
    14491574                       cur_drv->track, cur_drv->sect, fd_sector(cur_drv),
    14501575                       fd_sector(cur_drv) * FD_SECTOR_LEN);
    1451         if (fdctrl->data_dir != FD_DIR_WRITE ||
    1452             len < FD_SECTOR_LEN || rel_pos != 0) {
     1576        if (fdctrl->data_dir != FD_DIR_FORMAT &&
     1577            (fdctrl->data_dir != FD_DIR_WRITE ||
     1578            len < FD_SECTOR_LEN || rel_pos != 0)) {
    14531579            /* READ & SCAN commands and realign to a sector for WRITE */
    14541580#ifdef VBOX
     
    14881614            /* WRITE commands */
    14891615#ifdef VBOX
    1490             if (cur_drv->ro)
    1491             {
    1492                 /* Handle readonly medium early, no need to do DMA, touch the
    1493                  * LED or attempt any writes. A real floppy doesn't attempt
    1494                  * to write to readonly media either. */
    1495                 fdctrl_stop_transfer(fdctrl, FD_SR0_ABNTERM | FD_SR0_SEEK, FD_SR1_NW,
    1496                                      0x00);
    1497                 goto transfer_error;
    1498             }
    1499 
    15001616            {
    15011617                uint32_t written;
     
    15211637            }
    15221638            break;
     1639#ifdef VBOX
     1640        case FD_DIR_FORMAT:
     1641            /* FORMAT command */
     1642            {
     1643                uint8_t  eot    = fdctrl->fifo[3];
     1644                uint8_t  filler = fdctrl->fifo[5];
     1645                uint32_t written;
     1646                int      sct;
     1647                int rc2 = PDMDevHlpDMAReadMemory(fdctrl->pDevIns, nchan,
     1648                                                 fdctrl->fifo + rel_pos,
     1649                                                 fdctrl->data_pos,
     1650                                                 len, &written);
     1651                AssertMsgRC (rc2, ("DMAReadMemory -> %Rrc\n", rc2));
     1652
     1653                /* Fill the entire track with desired data pattern. */
     1654                FLOPPY_DPRINTF("formatting track: %d sectors, pattern %02x\n",
     1655                               eot, filler);
     1656                memset(fdctrl->fifo, filler, FD_SECTOR_LEN);
     1657                for (sct = 0; sct < eot; ++sct)
     1658                {
     1659                    rc = blk_write(cur_drv, fd_sector(cur_drv), fdctrl->fifo, 1);
     1660                    if (RT_FAILURE(rc))
     1661                    {
     1662                        FLOPPY_ERROR("formatting sector %d\n", fd_sector(cur_drv));
     1663                        fdctrl_stop_transfer(fdctrl, FD_SR0_ABNTERM | FD_SR0_SEEK, 0x00, 0x00);
     1664                        goto transfer_error;
     1665                    }
     1666                    fdctrl_seek_to_next_sect(fdctrl, cur_drv);
     1667                }
     1668            }
     1669            break;
     1670#endif
    15231671        default:
    15241672            /* SCAN commands */
     
    18261974    fdrive_t *cur_drv;
    18271975    uint8_t ns, dp;
    1828     int did_seek = 0;
    18291976
    18301977    SET_CUR_DRV(fdctrl, fdctrl->fifo[1] & FD_DOR_SELMASK);
    18311978    cur_drv = get_cur_drv(fdctrl);
     1979    fdctrl->data_state &= ~(FD_STATE_MULTI | FD_STATE_SEEK);
    18321980    ns = fdctrl->fifo[3];
    18331981    dp = fdctrl->fifo[5];
     
    18391987                   fdctrl->fifo[3], fdctrl->fifo[4], fdctrl->fifo[5]);
    18401988
    1841     fdctrl->data_state |= FD_STATE_FORMAT;
    1842     if (fdctrl->fifo[0] & 0x80)
    1843         fdctrl->data_state |= FD_STATE_MULTI;
     1989    /* Since we cannot actually format anything, we have to make sure that
     1990     * whatever new format the guest is trying to establish matches the
     1991     * existing format of the medium.
     1992     */
     1993    if (cur_drv->last_sect != ns || fdctrl->fifo[2] != 2)
     1994        fdctrl_stop_transfer(fdctrl, FD_SR0_ABNTERM, FD_SR1_NW, 0);
    18441995    else
    1845         fdctrl->data_state &= ~FD_STATE_MULTI;
    1846     fdctrl->data_state &= ~FD_STATE_SEEK;
    1847     cur_drv->bps =
    1848         fdctrl->fifo[2] > 7 ? 16384 : 128 << fdctrl->fifo[2];
    1849 #if 0
    1850     cur_drv->last_sect =
    1851         cur_drv->flags & FDISK_DBL_SIDES ? fdctrl->fifo[3] :
    1852         fdctrl->fifo[3] / 2;
    1853 #else
    1854     cur_drv->last_sect = fdctrl->fifo[3];
    1855 #endif
    1856     /* TODO: implement format using DMA expected by the Bochs BIOS
    1857      * and Linux fdformat (read 3 bytes per sector via DMA and fill
    1858      * the sector with the specified fill byte
    1859      */
    1860     fdctrl->data_state &= ~FD_STATE_FORMAT;
    1861     fdctrl_stop_transfer(fdctrl, 0x00, 0x00, 0x00);
     1996    {
     1997        cur_drv->bps = fdctrl->fifo[2] > 7 ? 16384 : 128 << fdctrl->fifo[2];
     1998        cur_drv->last_sect = ns;
     1999   
     2000        fdctrl_start_format(fdctrl);
     2001    }
    18622002}
    18632003
     
    19482088     */
    19492089    cur_drv->track = fdctrl->fifo[2];
     2090    cur_drv->ltrk = cur_drv->track;
    19502091    /* Raise Interrupt */
    19512092    fdctrl_raise_irq(fdctrl, FD_SR0_SEEK | GET_CUR_DRV(fdctrl));
     
    21742315        FLOPPY_DPRINTF("read id rate mismatch (fdc=%d, media=%d)\n",
    21752316                       fdctrl->dsr & FD_DSR_DRATEMASK, cur_drv->media_rate);
     2317        fdctrl_stop_transfer(fdctrl, FD_SR0_ABNTERM, FD_SR1_MA | FD_SR1_ND, FD_SR2_MD);
     2318    } else if (cur_drv->track >= cur_drv->max_track) {
     2319        FLOPPY_DPRINTF("read id past last track (%d >= %d)\n",
     2320                       cur_drv->track, cur_drv->max_track);
     2321        cur_drv->ltrk = 0;
    21762322        fdctrl_stop_transfer(fdctrl, FD_SR0_ABNTERM, FD_SR1_MA | FD_SR1_ND, FD_SR2_MD);
    21772323    }
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