Ejemplo n.º 1
0
static uint32_t calc_start_pos(struct image *im)
{
    struct tib *tib = tib_p(im);
    uint32_t decode_off;
    unsigned int i;

    /* Calculate start position within the track. */
    im->dsk.crc = 0xffff;
    im->dsk.trk_pos = im->dsk.rd_sec_pos = im->dsk.decode_data_pos = 0;
    decode_off = im->cur_bc / 16;
    if (decode_off < im->dsk.idx_sz) {
        /* Post-index track gap */
        im->dsk.decode_pos = 0;
    } else {
        decode_off -= im->dsk.idx_sz;
        for (i = 0; i < tib->nr_secs; i++) {
            uint16_t sec_sz = im->dsk.idam_sz + im->dsk.dam_sz_pre
                + data_sz(&tib->sib[i]) + im->dsk.dam_sz_post;
            if (is_gaps_sector(&tib->sib[i]))
                sec_sz -= im->dsk.dam_sz_post;
            if (decode_off < sec_sz)
                break;
            decode_off -= sec_sz;
        }
        if (i < tib->nr_secs) {
            /* IDAM */
            im->dsk.trk_pos = i;
            im->dsk.decode_pos = i * 4 + 1;
            if (decode_off >= im->dsk.idam_sz) {
                /* DAM */
                decode_off -= im->dsk.idam_sz;
                im->dsk.decode_pos++;
                if (decode_off >= im->dsk.dam_sz_pre) {
                    /* Data or Post Data */
                    decode_off -= im->dsk.dam_sz_pre;
                    im->dsk.decode_pos++;
                    if (decode_off < data_sz(&tib->sib[i])) {
                        /* Data */
                        im->dsk.rd_sec_pos = decode_off / 1024;
                        im->dsk.decode_data_pos = im->dsk.rd_sec_pos;
                        decode_off %= 1024;
                    } else {
                        /* Post Data */
                        decode_off -= data_sz(&tib->sib[i]);
                        im->dsk.decode_pos++;
                        im->dsk.trk_pos = (i + 1) % tib->nr_secs;
                    }
                }
            }
        } else {
            /* Pre-index track gap */
            im->dsk.decode_pos = tib->nr_secs * 4 + 1;
            im->dsk.decode_data_pos = decode_off / 1024;
            decode_off %= 1024;
        }
    }

    return decode_off;
}
Ejemplo n.º 2
0
static bool_t is_gaps_sector(struct sib *sib)
{
    uint16_t dsz = data_sz(sib);
    return ((dsz & (dsz-1)) || (dsz & 0x7f));
}
Ejemplo n.º 3
0
static bool_t dsk_read_track(struct image *im)
{
    struct tib *tib = tib_p(im);
    struct image_buf *rd = &im->bufs.read_data;
    struct image_buf *bc = &im->bufs.read_bc;
    uint8_t *buf = (uint8_t *)rd->p + 512; /* skip DIB/TIB */
    uint16_t *bc_b = bc->p;
    uint32_t bc_len, bc_mask, bc_space, bc_p, bc_c;
    uint16_t pr = 0, crc;
    unsigned int i;

    if (tib->nr_secs && (rd->prod == rd->cons)) {
        uint16_t off = 0, len;
        for (i = 0; i < im->dsk.trk_pos; i++)
            off += tib->sib[i].actual_length;
        len = data_sz(&tib->sib[i]);
        if (len != tib->sib[i].actual_length) {
            /* Weak sector -- pick different data each revolution. */
            off += len * (im->dsk.rev % (tib->sib[i].actual_length / len));
        }
        off += im->dsk.rd_sec_pos * 1024;
        len -= im->dsk.rd_sec_pos * 1024;
        if (len > 1024) {
            len = 1024;
            im->dsk.rd_sec_pos++;
        } else {
            im->dsk.rd_sec_pos = 0;
            if (++im->dsk.trk_pos >= tib->nr_secs) {
                im->dsk.trk_pos = 0;
                im->dsk.rev++;
            }
        }
        F_lseek(&im->fp, im->dsk.trk_off + off);
        F_read(&im->fp, buf, len, NULL);
        rd->prod++;
    }

    /* Generate some MFM if there is space in the raw-bitcell ring buffer. */
    bc_p = bc->prod / 16; /* MFM words */
    bc_c = bc->cons / 16; /* MFM words */
    bc_len = bc->len / 2; /* MFM words */
    bc_mask = bc_len - 1;
    bc_space = bc_len - (uint16_t)(bc_p - bc_c);

#define emit_raw(r) ({                                   \
    uint16_t _r = (r);                                   \
    bc_b[bc_p++ & bc_mask] = htobe16(_r & ~(pr << 15));  \
    pr = _r; })
#define emit_byte(b) emit_raw(mfmtab[(uint8_t)(b)])

    if (im->dsk.decode_pos == 0) {
        /* Post-index track gap */
        if (bc_space < im->dsk.idx_sz)
            return FALSE;
        for (i = 0; i < GAP_4A; i++)
            emit_byte(0x4e);
        /* IAM */
        for (i = 0; i < GAP_SYNC; i++)
            emit_byte(0x00);
        for (i = 0; i < 3; i++)
            emit_raw(0x5224);
        emit_byte(0xfc);
        for (i = 0; i < GAP_1; i++)
            emit_byte(0x4e);
    } else if (im->dsk.decode_pos == (tib->nr_secs * 4 + 1)) {
        /* Pre-index track gap */
        uint16_t sz = im->dsk.gap4 - im->dsk.decode_data_pos * 1024;
        if (bc_space < min_t(unsigned int, sz, 1024))
            return FALSE;
        if (sz > 1024) {
            sz = 1024;
            im->dsk.decode_data_pos++;
            im->dsk.decode_pos--;
        } else {
            im->dsk.decode_data_pos = 0;
            im->dsk.decode_pos = -1;
        }
        for (i = 0; i < sz; i++)
            emit_byte(0x4e);
    } else {
Ejemplo n.º 4
0
static void dsk_seek_track(
    struct image *im, uint16_t track, unsigned int cyl, unsigned int side)
{
    struct dib *dib = dib_p(im);
    struct tib *tib = tib_p(im);
    unsigned int i, nr;
    uint32_t tracklen;

    im->cur_track = track;

    if (cyl >= im->nr_cyls) {
    unformatted:
        printk("T%u.%u: Empty\n", cyl, side);
        memset(tib, 0, sizeof(*tib));
        goto out;
    }

    im->dsk.trk_off = 0x100;
    nr = (unsigned int)cyl * im->nr_sides + side;
    if (im->dsk.extended) {
        if (dib->track_szs[nr] == 0)
            goto unformatted;
        for (i = 0; i < nr; i++)
            im->dsk.trk_off += dib->track_szs[i] * 256;
    } else {
        im->dsk.trk_off += nr * le16toh(dib->track_sz);
    }

    /* Read the Track Info Block and Sector Info Blocks. */
    F_lseek(&im->fp, im->dsk.trk_off);
    F_read(&im->fp, tib, 256, NULL);
    im->dsk.trk_off += 256;
    if (strncmp(tib->sig, "Track-Info", 10) || !tib->nr_secs)
        goto unformatted;

    printk("T%u.%u -> %u.%u: %u sectors\n", cyl, side, tib->track,
           tib->side, tib->nr_secs);

    /* Clamp number of sectors. */
    if (tib->nr_secs > 29)
        tib->nr_secs = 29;

    /* Compute per-sector actual length. */
    for (i = 0; i < tib->nr_secs; i++) {
        tib->sib[i].actual_length = im->dsk.extended
            ? le16toh(tib->sib[i].actual_length)
            : 128 << min_t(unsigned, tib->sec_sz, 8);
        if ((tib->sib[i].actual_length > 8192)
            || (tib->sib[i].n > 6))
            F_die(FR_BAD_IMAGE);
    }

out:
    im->dsk.idx_sz = GAP_4A;
    im->dsk.idx_sz += GAP_SYNC + 4 + GAP_1;
    im->dsk.idam_sz = GAP_SYNC + 8 + 2 + GAP_2;
    im->dsk.dam_sz_pre = GAP_SYNC + 4;
    im->dsk.dam_sz_post = 2 + tib->gap3;

    /* Work out minimum track length (with no pre-index track gap). */
    tracklen = (im->dsk.idam_sz + im->dsk.dam_sz_pre + im->dsk.dam_sz_post)
        * tib->nr_secs;
    tracklen += im->dsk.idx_sz;
    for (i = 0; i < tib->nr_secs; i++) {
        tracklen += data_sz(&tib->sib[i]);
        if (is_gaps_sector(&tib->sib[i]))
            tracklen -= im->dsk.dam_sz_post;
    }
    tracklen *= 16;

    /* Calculate and round the track length. */
    im->tracklen_bc = max_t(unsigned int, 100000, tracklen + 20*16);
    im->tracklen_bc = (im->tracklen_bc + 31) & ~31;

    /* Now calculate the pre-index track gap. */
    im->dsk.gap4 = (im->tracklen_bc - tracklen) / 16;

    /* Calculate ticks per revolution */
    im->stk_per_rev = stk_sysclk(im->tracklen_bc * im->write_bc_ticks);
}
Ejemplo n.º 5
0
void ParallelMap::communicateData()
{
    const int size = SAMRAI_MPI::getNodes();
    const int rank = SAMRAI_MPI::getRank();

    // Add items to the map.
    if (SAMRAI_MPI::maxReduction(static_cast<int>(d_pending_additions.size())) > 0)
    {
        StreamableManager* streamable_manager = StreamableManager::getManager();

        // Determine how many keys have been registered for addition on each
        // process.
        std::vector<int> num_additions(size, 0);
        num_additions[rank] = d_pending_additions.size();
        SAMRAI_MPI::sumReduction(&num_additions[0], size);

        // Get the local values to send and determine the amount of data to be
        // broadcast by each process.
        std::vector<int> keys_to_send;
        std::vector<tbox::Pointer<Streamable> > data_items_to_send;
        for (std::map<int, tbox::Pointer<Streamable> >::const_iterator cit =
                 d_pending_additions.begin();
             cit != d_pending_additions.end();
             ++cit)
        {
            keys_to_send.push_back(cit->first);
            data_items_to_send.push_back(cit->second);
        }
        std::vector<int> data_sz(size, 0);
        data_sz[rank] = tbox::AbstractStream::sizeofInt() * keys_to_send.size() +
                        streamable_manager->getDataStreamSize(data_items_to_send);
        SAMRAI_MPI::sumReduction(&data_sz[0], size);

        // Broadcast data from each process.
        for (int sending_proc = 0; sending_proc < size; ++sending_proc)
        {
            int num_keys = num_additions[sending_proc];
            if (num_keys == 0) continue;
            if (sending_proc == rank)
            {
                // Pack and broadcast data on process sending_proc.
                FixedSizedStream stream(data_sz[sending_proc]);
                stream.pack(&keys_to_send[0], keys_to_send.size());
                streamable_manager->packStream(stream, data_items_to_send);
                int data_size = stream.getCurrentSize();
#if !defined(NDEBUG)
                TBOX_ASSERT(static_cast<int>(d_pending_additions.size()) == num_keys);
                TBOX_ASSERT(data_size == data_sz[sending_proc]);
#endif
                SAMRAI_MPI::bcast(
                    static_cast<char*>(stream.getBufferStart()), data_size, sending_proc);
                for (int k = 0; k < num_keys; ++k)
                {
                    d_map[keys_to_send[k]] = data_items_to_send[k];
                }
            }
            else
            {
                // Receive and unpack data broadcast from process sending_proc.
                std::vector<char> buffer(data_sz[sending_proc]);
                int data_size = data_sz[sending_proc];
                SAMRAI_MPI::bcast(&buffer[0], data_size, sending_proc);
#if !defined(NDEBUG)
                TBOX_ASSERT(data_size == data_sz[sending_proc]);
#endif
                FixedSizedStream stream(&buffer[0], data_size);
                std::vector<int> keys_received(num_keys);
                stream.unpack(&keys_received[0], num_keys);
                std::vector<tbox::Pointer<Streamable> > data_items_received;
                hier::IntVector<NDIM> offset = 0;
                streamable_manager->unpackStream(stream, offset, data_items_received);
#if !defined(NDEBUG)
                TBOX_ASSERT(keys_received.size() == data_items_received.size());
#endif
                for (int k = 0; k < num_keys; ++k)
                {
                    d_map[keys_received[k]] = data_items_received[k];
                }
            }
        }

        // Clear the set of pending additions.
        d_pending_additions.clear();
    }

    // Remove items from the map.
    if (SAMRAI_MPI::maxReduction(static_cast<int>(d_pending_removals.size())) > 0)
    {
        // Determine how many keys have been registered for removal on each
        // process.
        std::vector<int> num_removals(size, 0);
        num_removals[rank] = d_pending_removals.size();
        SAMRAI_MPI::sumReduction(&num_removals[0], size);

        // Broadcast data from each process.
        for (int sending_proc = 0; sending_proc < size; ++sending_proc)
        {
            int num_keys = num_removals[sending_proc];
            if (num_keys == 0) continue;
            if (sending_proc == rank)
            {
// Pack and broadcast data on process sending_proc.
#if !defined(NDEBUG)
                TBOX_ASSERT(static_cast<int>(d_pending_removals.size()) == num_keys);
#endif
                SAMRAI_MPI::bcast(&d_pending_removals[0], num_keys, sending_proc);
                for (int k = 0; k < num_keys; ++k)
                {
                    d_map.erase(d_pending_removals[k]);
                }
            }
            else
            {
                // Receive and unpack data broadcast from process sending_proc.
                std::vector<int> keys_received(num_removals[sending_proc]);
                SAMRAI_MPI::bcast(&keys_received[0], num_keys, sending_proc);
                for (int k = 0; k < num_keys; ++k)
                {
                    d_map.erase(keys_received[k]);
                }
            }
        }

        // Clear the set of pending removals.
        d_pending_removals.clear();
    }
    return;
} // communicateData