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); } }
static UINT32 ide_controller_read(struct ide_state *ide, offs_t offset, int size) { UINT32 result = 0; /* logit */ if (offset != IDE_ADDR_DATA && offset != IDE_ADDR_STATUS_COMMAND && offset != IDE_ADDR_STATUS_CONTROL) LOG(("%08X:IDE read at %03X, size=%d\n", activecpu_get_previouspc(), offset, size)); switch (offset) { /* unknown config register */ case IDE_ADDR_CONFIG_UNK: return ide->config_unknown; /* active config register */ case IDE_ADDR_CONFIG_REGISTER: return ide->config_register_num; /* data from active config register */ case IDE_ADDR_CONFIG_DATA: if (ide->config_register_num < IDE_CONFIG_REGISTERS) return ide->config_register[ide->config_register_num]; return 0; /* read data if there's data to be read */ case IDE_ADDR_DATA: if (ide->status & IDE_STATUS_BUFFER_READY) { /* fetch the correct amount of data */ result = ide->buffer[ide->buffer_offset++]; if (size > 1) result |= ide->buffer[ide->buffer_offset++] << 8; if (size > 2) { result |= ide->buffer[ide->buffer_offset++] << 16; result |= ide->buffer[ide->buffer_offset++] << 24; } /* if we're at the end of the buffer, handle it */ if (ide->buffer_offset >= IDE_DISK_SECTOR_SIZE) continue_read(ide); } break; /* return the current error */ case IDE_ADDR_ERROR: return ide->error; /* return the current sector count */ case IDE_ADDR_SECTOR_COUNT: return ide->sector_count; /* return the current sector */ case IDE_ADDR_SECTOR_NUMBER: return ide->cur_sector; /* return the current cylinder LSB */ case IDE_ADDR_CYLINDER_LSB: return ide->cur_cylinder & 0xff; /* return the current cylinder MSB */ case IDE_ADDR_CYLINDER_MSB: return ide->cur_cylinder >> 8; /* return the current head */ case IDE_ADDR_HEAD_NUMBER: return ide->cur_head_reg; /* return the current status and clear any pending interrupts */ case IDE_ADDR_STATUS_COMMAND: /* return the current status but don't clear interrupts */ case IDE_ADDR_STATUS_CONTROL: result = ide->status; if (timer_timeelapsed(ide->last_status_timer) > TIME_PER_ROTATION) { result |= IDE_STATUS_HIT_INDEX; timer_adjust(ide->last_status_timer, TIME_NEVER, 0, 0); } /* clear interrutps only when reading the real status */ if (offset == IDE_ADDR_STATUS_COMMAND) { if (ide->interrupt_pending) clear_interrupt(ide); } /* take a bit of time to speed up people who poll hard */ activecpu_adjust_icount(-100); break; /* log anything else */ default: logerror("%08X:unknown IDE read at %03X, size=%d\n", activecpu_get_previouspc(), offset, size); break; } /* return the result */ return result; }