mirror of
https://github.com/TomHarte/CLK.git
synced 2024-11-29 12:50:28 +00:00
Separates the 8272's drive selection signalling from actual drive ownership.
Thereby returns working motor control to the CPC.
This commit is contained in:
parent
96bf133924
commit
d3c385b471
@ -119,11 +119,12 @@ void i8272::run_for(Cycles cycles) {
|
|||||||
// Perform a step.
|
// Perform a step.
|
||||||
int direction = (drives_[c].target_head_position < drives_[c].head_position) ? -1 : 1;
|
int direction = (drives_[c].target_head_position < drives_[c].head_position) ? -1 : 1;
|
||||||
printf("Target %d versus believed %d\n", drives_[c].target_head_position, drives_[c].head_position);
|
printf("Target %d versus believed %d\n", drives_[c].target_head_position, drives_[c].head_position);
|
||||||
drives_[c].drive->step(direction);
|
select_drive(c);
|
||||||
|
get_drive().step(direction);
|
||||||
if(drives_[c].target_head_position >= 0) drives_[c].head_position += direction;
|
if(drives_[c].target_head_position >= 0) drives_[c].head_position += direction;
|
||||||
|
|
||||||
// Check for completion.
|
// Check for completion.
|
||||||
if(drives_[c].seek_is_satisfied()) {
|
if(seek_is_satisfied(c)) {
|
||||||
drives_[c].phase = Drive::CompletedSeeking;
|
drives_[c].phase = Drive::CompletedSeeking;
|
||||||
drives_seeking_--;
|
drives_seeking_--;
|
||||||
break;
|
break;
|
||||||
@ -192,12 +193,6 @@ uint8_t i8272::get_register(int address) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void i8272::set_disk(std::shared_ptr<Storage::Disk::Disk> disk, int drive) {
|
|
||||||
if(drive < 4 && drive >= 0) {
|
|
||||||
drives_[drive].drive->set_disk(disk);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#define BEGIN_SECTION() switch(resume_point_) { default:
|
#define BEGIN_SECTION() switch(resume_point_) { default:
|
||||||
#define END_SECTION() }
|
#define END_SECTION() }
|
||||||
|
|
||||||
@ -235,7 +230,7 @@ void i8272::set_disk(std::shared_ptr<Storage::Disk::Disk> disk, int drive) {
|
|||||||
#define SET_DRIVE_HEAD_MFM() \
|
#define SET_DRIVE_HEAD_MFM() \
|
||||||
active_drive_ = command_[1]&3; \
|
active_drive_ = command_[1]&3; \
|
||||||
active_head_ = (command_[1] >> 2)&1; \
|
active_head_ = (command_[1] >> 2)&1; \
|
||||||
set_drive(drives_[active_drive_].drive); \
|
select_drive(active_drive_); \
|
||||||
get_drive().set_head((unsigned int)active_head_); \
|
get_drive().set_head((unsigned int)active_head_); \
|
||||||
set_is_double_density(command_[0] & 0x40);
|
set_is_double_density(command_[0] & 0x40);
|
||||||
|
|
||||||
@ -503,7 +498,7 @@ void i8272::posit_event(int event_type) {
|
|||||||
write_data:
|
write_data:
|
||||||
printf("Write [deleted] data [%02x %02x %02x %02x ... %02x %02x]\n", command_[2], command_[3], command_[4], command_[5], command_[6], command_[8]);
|
printf("Write [deleted] data [%02x %02x %02x %02x ... %02x %02x]\n", command_[2], command_[3], command_[4], command_[5], command_[6], command_[8]);
|
||||||
|
|
||||||
if(drives_[active_drive_].drive->get_is_read_only()) {
|
if(get_drive().get_is_read_only()) {
|
||||||
SetNotWriteable();
|
SetNotWriteable();
|
||||||
goto abort;
|
goto abort;
|
||||||
}
|
}
|
||||||
@ -618,7 +613,7 @@ void i8272::posit_event(int event_type) {
|
|||||||
// Performs format [/write] track.
|
// Performs format [/write] track.
|
||||||
format_track:
|
format_track:
|
||||||
printf("Format track\n");
|
printf("Format track\n");
|
||||||
if(drives_[active_drive_].drive->get_is_read_only()) {
|
if(get_drive().get_is_read_only()) {
|
||||||
SetNotWriteable();
|
SetNotWriteable();
|
||||||
goto abort;
|
goto abort;
|
||||||
}
|
}
|
||||||
@ -711,6 +706,7 @@ void i8272::posit_event(int event_type) {
|
|||||||
seek:
|
seek:
|
||||||
{
|
{
|
||||||
int drive = command_[1]&3;
|
int drive = command_[1]&3;
|
||||||
|
select_drive(drive);
|
||||||
|
|
||||||
// Increment the seeking count if this drive wasn't already seeking.
|
// Increment the seeking count if this drive wasn't already seeking.
|
||||||
if(drives_[drive].phase != Drive::Seeking) {
|
if(drives_[drive].phase != Drive::Seeking) {
|
||||||
@ -740,7 +736,7 @@ void i8272::posit_event(int event_type) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check whether any steps are even needed; if not then mark as completed already.
|
// Check whether any steps are even needed; if not then mark as completed already.
|
||||||
if(drives_[drive].seek_is_satisfied()) {
|
if(seek_is_satisfied(drive)) {
|
||||||
drives_[drive].phase = Drive::CompletedSeeking;
|
drives_[drive].phase = Drive::CompletedSeeking;
|
||||||
drives_seeking_--;
|
drives_seeking_--;
|
||||||
}
|
}
|
||||||
@ -792,12 +788,13 @@ void i8272::posit_event(int event_type) {
|
|||||||
printf("Sense drive status\n");
|
printf("Sense drive status\n");
|
||||||
{
|
{
|
||||||
int drive = command_[1] & 3;
|
int drive = command_[1] & 3;
|
||||||
|
select_drive(drive);
|
||||||
result_stack_.push_back(
|
result_stack_.push_back(
|
||||||
(command_[1] & 7) | // drive and head number
|
(command_[1] & 7) | // drive and head number
|
||||||
0x08 | // single sided
|
0x08 | // single sided
|
||||||
(drives_[drive].drive->get_is_track_zero() ? 0x10 : 0x00) |
|
(get_drive().get_is_track_zero() ? 0x10 : 0x00) |
|
||||||
(drives_[drive].drive->get_is_ready() ? 0x20 : 0x00) |
|
(get_drive().get_is_ready() ? 0x20 : 0x00) |
|
||||||
(drives_[drive].drive->get_is_read_only() ? 0x40 : 0x00)
|
(get_drive().get_is_read_only() ? 0x40 : 0x00)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
goto post_result;
|
goto post_result;
|
||||||
@ -852,9 +849,9 @@ void i8272::posit_event(int event_type) {
|
|||||||
END_SECTION()
|
END_SECTION()
|
||||||
}
|
}
|
||||||
|
|
||||||
bool i8272::Drive::seek_is_satisfied() {
|
bool i8272::seek_is_satisfied(int drive) {
|
||||||
return (target_head_position == head_position) ||
|
return (drives_[drive].target_head_position == drives_[drive].head_position) ||
|
||||||
(target_head_position == -1 && drive->get_is_track_zero());
|
(drives_[drive].target_head_position == -1 && get_drive().get_is_track_zero());
|
||||||
}
|
}
|
||||||
|
|
||||||
void i8272::set_dma_acknowledge(bool dack) {
|
void i8272::set_dma_acknowledge(bool dack) {
|
||||||
|
@ -39,10 +39,11 @@ class i8272: public Storage::Disk::MFMController {
|
|||||||
void set_dma_acknowledge(bool dack);
|
void set_dma_acknowledge(bool dack);
|
||||||
void set_terminal_count(bool tc);
|
void set_terminal_count(bool tc);
|
||||||
|
|
||||||
void set_disk(std::shared_ptr<Storage::Disk::Disk> disk, int drive);
|
|
||||||
|
|
||||||
bool is_sleeping();
|
bool is_sleeping();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual void select_drive(int number) = 0;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// The bus handler, for interrupt and DMA-driven usage.
|
// The bus handler, for interrupt and DMA-driven usage.
|
||||||
BusHandler &bus_handler_;
|
BusHandler &bus_handler_;
|
||||||
@ -91,24 +92,20 @@ class i8272: public Storage::Disk::MFMController {
|
|||||||
int steps_taken;
|
int steps_taken;
|
||||||
int target_head_position; // either an actual number, or -1 to indicate to step until track zero
|
int target_head_position; // either an actual number, or -1 to indicate to step until track zero
|
||||||
|
|
||||||
/// @returns @c true if the currently queued-up seek or recalibrate has reached where it should be.
|
|
||||||
bool seek_is_satisfied();
|
|
||||||
|
|
||||||
// Head state.
|
// Head state.
|
||||||
int head_unload_delay[2];
|
int head_unload_delay[2];
|
||||||
bool head_is_loaded[2];
|
bool head_is_loaded[2];
|
||||||
|
|
||||||
// The connected drive.
|
|
||||||
std::shared_ptr<Storage::Disk::Drive> drive;
|
|
||||||
|
|
||||||
Drive() :
|
Drive() :
|
||||||
head_position(0), phase(NotSeeking),
|
head_position(0), phase(NotSeeking),
|
||||||
drive(new Storage::Disk::Drive(8000000, 300)), // TODO: these constants can't live here.
|
|
||||||
head_is_loaded{false, false},
|
head_is_loaded{false, false},
|
||||||
head_unload_delay{0, 0} {};
|
head_unload_delay{0, 0} {};
|
||||||
} drives_[4];
|
} drives_[4];
|
||||||
int drives_seeking_;
|
int drives_seeking_;
|
||||||
|
|
||||||
|
/// @returns @c true if the selected drive, which is number @c drive, can stop seeking.
|
||||||
|
bool seek_is_satisfied(int drive);
|
||||||
|
|
||||||
// User-supplied parameters; as per the specify command.
|
// User-supplied parameters; as per the specify command.
|
||||||
int step_rate_time_;
|
int step_rate_time_;
|
||||||
int head_unload_time_;
|
int head_unload_time_;
|
||||||
|
@ -582,13 +582,25 @@ class KeyboardState: public GI::AY38910::PortHandler {
|
|||||||
class FDC: public Intel::i8272::i8272 {
|
class FDC: public Intel::i8272::i8272 {
|
||||||
private:
|
private:
|
||||||
Intel::i8272::BusHandler bus_handler_;
|
Intel::i8272::BusHandler bus_handler_;
|
||||||
|
std::shared_ptr<Storage::Disk::Drive> drive_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
FDC() : i8272(bus_handler_, Cycles(8000000)) {}
|
FDC() :
|
||||||
|
i8272(bus_handler_, Cycles(8000000)),
|
||||||
|
drive_(new Storage::Disk::Drive(8000000, 300)) {
|
||||||
|
set_drive(drive_);
|
||||||
|
}
|
||||||
|
|
||||||
void set_motor_on(bool on) {
|
void set_motor_on(bool on) {
|
||||||
// TODO: should set all motors on, not 8272.hjust the one active drive.
|
drive_->set_motor_on(on);
|
||||||
get_drive().set_motor_on(on);
|
}
|
||||||
|
|
||||||
|
void select_drive(int c) {
|
||||||
|
// TODO: support more than one drive.
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_disk(std::shared_ptr<Storage::Disk::Disk> disk, int drive) {
|
||||||
|
drive_->set_disk(disk);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user