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; }
static bool_t is_gaps_sector(struct sib *sib) { uint16_t dsz = data_sz(sib); return ((dsz & (dsz-1)) || (dsz & 0x7f)); }
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 {
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); }
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