UINT32 hard_disk_write(struct hard_disk_file *file, UINT32 lbasector, UINT32 numsectors, const void *buffer) { UINT32 hunknum = lbasector / file->hunksectors; UINT32 sectoroffs = lbasector % file->hunksectors; /* for now, just break down multisector writes into single sectors */ if (numsectors > 1) { UINT32 total = 0; while (numsectors--) { if (hard_disk_write(file, lbasector++, 1, (const UINT8 *)buffer + total * file->info.sectorbytes)) total++; else break; } return total; } /* if we haven't cached this hunk, read it now */ if (file->cachehunk != hunknum) { if (!chd_read(file->chd, hunknum, 1, file->cache)) return 0; file->cachehunk = hunknum; } /* copy in the requested data */ memcpy(&file->cache[sectoroffs * file->info.sectorbytes], buffer, file->info.sectorbytes); /* write it back out */ if (chd_write(file->chd, hunknum, 1, file->cache)) return 1; return 0; }
// // Corvus_Write_Sector // // Write a variably-sized chunk of data to the CHD file // // Pass: // drv: Corvus drive id (1..15) // sector: Physical sector number to write to // buffer: Buffer to write // len: Length of the buffer (amount of data to write) // // Returns: // status: Command status // UINT8 corvus_hdc_t::corvus_write_sector(UINT8 drv, UINT32 sector, UINT8 *buffer, int len) { hard_disk_file *disk; // Structures for interface to CHD routines UINT8 tbuffer[512]; // Buffer to hold an entire sector UINT16 cylinder; // Cylinder this sector resides on LOG(("corvus_write_sector: Write Drive: %d, physical sector: 0x%5.5x\n", drv, sector)); disk = corvus_hdc_file(drv); if(!disk) { logerror("corvus_write_sector: Failure returned by corvus_hdc_file(%d)\n", drv); return STAT_FATAL_ERR | STAT_DRIVE_NOT_ONLINE; } // // Calculate what cylinder the sector resides on for timing purposes // cylinder = (double) sector / (double) m_sectors_per_track / (double) m_tracks_per_cylinder; m_delay = abs(m_last_cylinder - cylinder) * TRACK_SEEK_TIME + INTERSECTOR_DELAY; // // Corvus supports write sizes of 128, 256 and 512 bytes. In the case of a write smaller than // the sector size of 512 bytes, the sector is read, the provided data is overlayed and then the // sector is written back out. See pp. 5 of the Mass Storage Systems GTI for the details of this // wonderful functionality. // if(len == 512) { hard_disk_write(disk, sector, buffer); } else { hard_disk_read(disk, sector, tbuffer); // Read the existing data into our temporary buffer memcpy(tbuffer, buffer, len); // Overlay the data with the buffer passed m_delay += INTERSECTOR_DELAY; // Add another delay because of the Read / Write hard_disk_write(disk, sector, tbuffer); // Re-write the data } m_last_cylinder = cylinder; LOG(("corvus_write_sector: Full sector dump on a write of %d bytes follows:\n", len)); LOG_BUFFER(len == 512 ? buffer : tbuffer, 512); return STAT_SUCCESS; }
/* imghd_write() Write sector(s) from MAME HD image */ imgtoolerr_t imghd_write(struct mess_hard_disk_file *disk, UINT32 lbasector, const void *buffer) { chd_interface interface_save; UINT32 reply; chd_save_interface(&interface_save); chd_set_interface(&imgtool_chd_interface); reply = hard_disk_write(disk->hard_disk, lbasector, buffer); chd_set_interface(&interface_save); return reply ? IMGTOOLERR_SUCCESS : map_chd_error(reply); }
/* imghd_write() Write sector(s) from MAME HD image */ imgtoolerr_t imghd_write(struct mess_hard_disk_file *disk, UINT32 lbasector, const void *buffer) { UINT32 reply; reply = hard_disk_write(disk->hard_disk, lbasector, buffer); return (imgtoolerr_t)(reply ? IMGTOOLERR_SUCCESS : map_chd_error((chd_error)reply)); }
void omti5100_device::ExecCommand() { int drive = (command[1] >> 5) & 1; hard_disk_file *image = (drive ? m_image1 : m_image0)->get_hard_disk_file(); if(!image) { if(command[0] == T10SPC_CMD_REQUEST_SENSE) return scsihd_device::ExecCommand(); m_phase = SCSI_PHASE_STATUS; m_status_code = SCSI_STATUS_CODE_CHECK_CONDITION; m_sense_asc = OMTI_STATUS_NOT_READY; m_transfer_length = 0; return; } hard_disk_info *info = hard_disk_get_info(image); switch(command[0]) { case OMTI_READ_DATA_BUFFER: m_phase = SCSI_PHASE_DATAIN; m_status_code = SCSI_STATUS_CODE_GOOD; m_transfer_length = 512; break; case OMTI_ASSIGN_DISK_PARAM: m_phase = SCSI_PHASE_DATAOUT; m_status_code = SCSI_STATUS_CODE_GOOD; m_transfer_length = 10; break; case OMTI_CHECK_TRACK_FORMAT: m_phase = SCSI_PHASE_STATUS; m_status_code = SCSI_STATUS_CODE_GOOD; m_transfer_length = 0; break; case T10SBC_CMD_READ_6: { int track = ((command[1]&0x1f)<<16 | command[2]<<8 | command[3]) / (m_param[drive].sectors ? m_param[drive].sectors : 1); int heads = m_param[drive].heads ? m_param[drive].heads : 1; if(((track % heads) > info->heads) || (track >= (info->cylinders * heads))) { m_phase = SCSI_PHASE_STATUS; m_status_code = SCSI_STATUS_CODE_CHECK_CONDITION; m_sense_asc = OMTI_STATUS_SEEK_FAIL; m_transfer_length = 0; } else { SetDevice(image); scsihd_device::ExecCommand(); } break; } case OMTI_FORMAT_TRACK: { int track = ((command[1]&0x1f)<<16 | command[2]<<8 | command[3]) / m_param[drive].sectors; if(((track % m_param[drive].heads) <= info->heads) && (track < (info->cylinders * m_param[drive].heads))) { dynamic_buffer sector(info->sectorbytes); memset(§or[0], 0xe5, info->sectorbytes); m_phase = SCSI_PHASE_STATUS; m_status_code = SCSI_STATUS_CODE_GOOD; m_transfer_length = 0; for(int i = 0; i < info->sectors; i++) hard_disk_write(image, track * info->sectors + i, §or[0]); } else { m_phase = SCSI_PHASE_STATUS; m_status_code = SCSI_STATUS_CODE_CHECK_CONDITION; m_sense_asc = OMTI_STATUS_SEEK_FAIL; m_transfer_length = 0; } break; } default: SetDevice(image); scsihd_device::ExecCommand(); break; } }
static void write_sector_done(int which) { struct ide_state *ide = &idestate[which]; int lba = lba_address(ide), count = 0; /* now do the write */ if (ide->disk) count = hard_disk_write(ide->disk, lba, 1, ide->buffer); /* by default, mark the buffer ready and the seek complete */ ide->status |= IDE_STATUS_BUFFER_READY; ide->status |= IDE_STATUS_SEEK_COMPLETE; /* and clear the busy adn error flags */ ide->status &= ~IDE_STATUS_ERROR; ide->status &= ~IDE_STATUS_BUSY; /* if we succeeded, advance to the next sector and set the nice bits */ if (count == 1) { /* advance the pointers, unless this is the last sector */ /* Gauntlet: Dark Legacy checks to make sure we stop on the last sector */ if (ide->sector_count != 1) next_sector(ide); /* clear the error value */ ide->error = IDE_ERROR_NONE; /* signal an interrupt */ if (--ide->sectors_until_int == 0 || ide->sector_count == 1) { ide->sectors_until_int = ((ide->command == IDE_COMMAND_WRITE_MULTIPLE_BLOCK) ? ide->block_count : 1); signal_interrupt(ide); } /* signal an interrupt if there's more data needed */ if (ide->sector_count > 0) ide->sector_count--; if (ide->sector_count == 0) ide->status &= ~IDE_STATUS_BUFFER_READY; /* keep going for DMA */ if (ide->dma_active && ide->sector_count != 0) { read_buffer_from_dma(ide); continue_write(ide); } else ide->dma_active = 0; } /* if we got an error, we need to report it */ else { /* set the error flag and the error */ ide->status |= IDE_STATUS_ERROR; ide->error = IDE_ERROR_BAD_SECTOR; ide->bus_master_status |= IDE_BUSMASTER_STATUS_ERROR; ide->bus_master_status &= ~IDE_BUSMASTER_STATUS_ACTIVE; /* signal an interrupt */ signal_interrupt(ide); } }