Esempio n. 1
0
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;
}
Esempio n. 2
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;
}
Esempio n. 3
0
/*
	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);
}
Esempio n. 4
0
/*
    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));
}
Esempio n. 5
0
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(&sector[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, &sector[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;
	}
}
Esempio n. 6
0
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);
	}
}