// // Corvus_Read_Sector // // Read a variably-sized chunk of data from the CHD file // // Pass: // drv: Corvus drive id (1..15) // sector: Physical sector number to read from // buffer: Buffer to hold the data read from the disk // len: Length of the buffer // // Returns: // status: Corvus status // UINT8 corvus_hdc_t::corvus_read_sector(UINT8 drv, UINT32 sector, UINT8 *buffer, int len) { hard_disk_file *disk; // Structures for interface to CHD routines UINT8 tbuffer[512]; // Buffer to store full sector results in UINT16 cylinder; LOG(("corvus_read_sector: Read Drive: %d, physical sector: 0x%5.5x\n", drv, sector)); disk = corvus_hdc_file(drv); if(!disk) { logerror("corvus_read_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; hard_disk_read(disk, sector, tbuffer); memcpy(buffer, tbuffer, len); m_last_cylinder = cylinder; LOG(("corvus_read_sector: Data read follows:\n")); LOG_BUFFER(tbuffer, len); return STAT_SUCCESS; }
UINT32 hard_disk_read(struct hard_disk_file *file, UINT32 lbasector, UINT32 numsectors, void *buffer) { UINT32 hunknum = lbasector / file->hunksectors; UINT32 sectoroffs = lbasector % file->hunksectors; /* for now, just break down multisector reads into single sectors */ if (numsectors > 1) { UINT32 total = 0; while (numsectors--) { if (hard_disk_read(file, lbasector++, 1, (UINT8 *)buffer + total * file->info.sectorbytes)) total++; else break; } return total; } // printf("HDD: rd lba %x\n", lbasector); /* 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 out the requested sector */ memcpy(buffer, &file->cache[sectoroffs * file->info.sectorbytes], file->info.sectorbytes); return 1; }
static void read_sector_done(int which) { struct ide_state *ide = &idestate[which]; int lba = lba_address(ide), count = 0; /* now do the read */ if (ide->disk) count = hard_disk_read(ide->disk, lba, 1, ide->buffer); /* by default, mark the buffer ready and the seek complete */ if (!ide->verify_only) ide->status |= IDE_STATUS_BUFFER_READY; ide->status |= IDE_STATUS_SEEK_COMPLETE; /* and clear the busy and 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->verify_only) ide->sectors_until_int--; if (ide->sectors_until_int == 0 || ide->sector_count == 1) { ide->sectors_until_int = ((ide->command == IDE_COMMAND_READ_MULTIPLE_BLOCK) ? ide->block_count : 1); signal_interrupt(ide); } /* handle DMA */ if (ide->dma_active) write_buffer_to_dma(ide); /* if we're just verifying or if we DMA'ed the data, we can read the next sector */ if (ide->verify_only || ide->dma_active) continue_read(ide); } /* 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); } }
// retrieve data from the SCSI controller void am53cf96_read_data(int bytes, data8_t *pData) { int i; scsi_regs[REG_STATUS] |= 0x10; // indicate DMA finished switch (last_cmd) { case 0x03: // REQUEST SENSE pData[0] = 0x80; // valid sense for (i = 1; i < 12; i++) { pData[i] = 0; } break; case 0x28: // READ (10 byte) if ((disk) && (blocks)) { while (bytes > 0) { if (!hard_disk_read(disk, lba, 1, pData)) { logerror("53cf96: HD read error!\n"); } lba++; blocks--; bytes -= 512; pData += 512; } } break; } }
/* imghd_read() Read sector(s) from MAME HD image */ imgtoolerr_t imghd_read(struct mess_hard_disk_file *disk, UINT32 lbasector, void *buffer) { chd_interface interface_save; UINT32 reply; chd_save_interface(&interface_save); chd_set_interface(&imgtool_chd_interface); reply = hard_disk_read(disk->hard_disk, lbasector, buffer); chd_set_interface(&interface_save); return reply ? IMGTOOLERR_SUCCESS : map_chd_error(reply); }
// // 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_read() Read sector(s) from MAME HD image */ imgtoolerr_t imghd_read(struct mess_hard_disk_file *disk, UINT32 lbasector, void *buffer) { UINT32 reply; reply = hard_disk_read(disk->hard_disk, lbasector, buffer); return (imgtoolerr_t)(reply ? IMGTOOLERR_SUCCESS : map_chd_error((chd_error)reply)); }