RL02: read header
This commit is contained in:
parent
fd8bb6a60b
commit
a623c0ab67
2 changed files with 54 additions and 26 deletions
77
rl02.cpp
77
rl02.cpp
|
@ -20,6 +20,17 @@ static const char * const regnames[] = {
|
||||||
"multipurpose "
|
"multipurpose "
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const char * const commands[] = {
|
||||||
|
"no-op",
|
||||||
|
"write check",
|
||||||
|
"get status",
|
||||||
|
"seek",
|
||||||
|
"read header",
|
||||||
|
"write data",
|
||||||
|
"read data",
|
||||||
|
"read data w/o header check"
|
||||||
|
};
|
||||||
|
|
||||||
rl02::rl02(const std::vector<disk_backend *> & files, bus *const b, std::atomic_bool *const disk_read_acitivity, std::atomic_bool *const disk_write_acitivity) :
|
rl02::rl02(const std::vector<disk_backend *> & files, bus *const b, std::atomic_bool *const disk_read_acitivity, std::atomic_bool *const disk_write_acitivity) :
|
||||||
b(b),
|
b(b),
|
||||||
disk_read_acitivity(disk_read_acitivity),
|
disk_read_acitivity(disk_read_acitivity),
|
||||||
|
@ -70,13 +81,15 @@ uint16_t rl02::readWord(const uint16_t addr)
|
||||||
|
|
||||||
if (addr == RL02_MPR) { // multi purpose register
|
if (addr == RL02_MPR) { // multi purpose register
|
||||||
value = mpr[0];
|
value = mpr[0];
|
||||||
memcpy(&mpr[0], &mpr[1], sizeof(mpr[0]) * 2);
|
mpr[0] = mpr[1];
|
||||||
|
mpr[1] = mpr[2];
|
||||||
|
mpr[2] = 0;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
value = registers[reg];
|
value = registers[reg];
|
||||||
}
|
}
|
||||||
|
|
||||||
DOLOG(debug, false, "RL02 read %s/%o: %06o", regnames[reg], addr, value);
|
DOLOG(debug, false, "RL02 read \"%s\"/%o: %06o", regnames[reg], addr, value);
|
||||||
|
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
@ -110,17 +123,22 @@ void rl02::update_bus_address(const uint32_t a)
|
||||||
registers[(RL02_CSR - RL02_BASE) / 2] |= ((a >> 16) & 3) << 4;
|
registers[(RL02_CSR - RL02_BASE) / 2] |= ((a >> 16) & 3) << 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t rl02::calcOffset() const
|
uint32_t rl02::calc_offset() const
|
||||||
{
|
{
|
||||||
return (rl02_sectors_per_track * track * 2 + head * rl02_sectors_per_track + sector) * rl02_bytes_per_sector;
|
return (rl02_sectors_per_track * track * 2 + head * rl02_sectors_per_track + sector) * rl02_bytes_per_sector;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void rl02::update_dar()
|
||||||
|
{
|
||||||
|
registers[(RL02_DAR - RL02_BASE) / 2] = (sector & 63) | (head << 6) | (track << 7);
|
||||||
|
}
|
||||||
|
|
||||||
void rl02::writeWord(const uint16_t addr, uint16_t v)
|
void rl02::writeWord(const uint16_t addr, uint16_t v)
|
||||||
{
|
{
|
||||||
DOLOG(debug, false, "RL02 write %06o: %06o", addr, v);
|
|
||||||
|
|
||||||
const int reg = (addr - RL02_BASE) / 2;
|
const int reg = (addr - RL02_BASE) / 2;
|
||||||
|
|
||||||
|
DOLOG(debug, false, "RL02 write \"%s\"/%06o: %06o", regnames[reg], addr, v);
|
||||||
|
|
||||||
registers[reg] = v;
|
registers[reg] = v;
|
||||||
|
|
||||||
if (addr == RL02_CSR) { // control status
|
if (addr == RL02_CSR) { // control status
|
||||||
|
@ -128,7 +146,7 @@ void rl02::writeWord(const uint16_t addr, uint16_t v)
|
||||||
|
|
||||||
const bool do_exec = !(v & 128);
|
const bool do_exec = !(v & 128);
|
||||||
|
|
||||||
DOLOG(debug, false, "RL02 set command %d, exec: %d", command, do_exec);
|
DOLOG(debug, false, "RL02 set command %d, exec: %d (%s)", command, do_exec, commands[command]);
|
||||||
|
|
||||||
int device = 0; // TODO
|
int device = 0; // TODO
|
||||||
|
|
||||||
|
@ -142,33 +160,31 @@ void rl02::writeWord(const uint16_t addr, uint16_t v)
|
||||||
else if (command == 3) { // seek
|
else if (command == 3) { // seek
|
||||||
uint16_t temp = registers[(RL02_DAR - RL02_BASE) / 2];
|
uint16_t temp = registers[(RL02_DAR - RL02_BASE) / 2];
|
||||||
|
|
||||||
int cylinder_count = (((temp >> 7) & 255) + 1) * (temp & 4 ? 1 : -1);
|
int cylinder_count = (temp >> 7) * (temp & 4 ? 1 : -1);
|
||||||
|
|
||||||
int32_t new_track = 0; // when bit 4 is set, a reset is performed
|
int16_t new_track = track + cylinder_count;
|
||||||
|
|
||||||
if ((temp & 8) == 0) {
|
if (new_track < 0)
|
||||||
new_track = track + cylinder_count;
|
new_track = 0;
|
||||||
|
else if (new_track >= rl02_track_count)
|
||||||
if (new_track < 0)
|
new_track = rl02_track_count - 1;
|
||||||
new_track = 0;
|
|
||||||
else if (new_track >= rl02_track_count)
|
|
||||||
new_track = rl02_track_count;
|
|
||||||
}
|
|
||||||
|
|
||||||
DOLOG(debug, false, "RL02: seek from cylinder %d to %d (distance: %d, DAR: %06o)", track, new_track, cylinder_count, temp);
|
DOLOG(debug, false, "RL02: seek from cylinder %d to %d (distance: %d, DAR: %06o)", track, new_track, cylinder_count, temp);
|
||||||
track = new_track;
|
track = new_track;
|
||||||
|
|
||||||
|
update_dar();
|
||||||
|
|
||||||
do_int = true;
|
do_int = true;
|
||||||
}
|
}
|
||||||
else if (command == 4) { // read header
|
else if (command == 4) { // read header
|
||||||
|
mpr[0] = (sector & 63) | (head << 6) | (track << 7);
|
||||||
|
mpr[1] = 0; // zero
|
||||||
|
mpr[2] = 0; // TODO: CRC
|
||||||
|
|
||||||
|
do_int = true;
|
||||||
}
|
}
|
||||||
else if (command == 6 || command == 7) { // read data / read data without header check
|
else if (command == 6 || command == 7) { // read data / read data without header check
|
||||||
uint16_t temp = registers[(RL02_DAR - RL02_BASE) / 2];
|
uint32_t temp_disk_offset = calc_offset();
|
||||||
sector = temp & 63;
|
|
||||||
head = !!(temp & 64);
|
|
||||||
track = temp >> 7;
|
|
||||||
|
|
||||||
uint32_t temp_disk_offset = calcOffset();
|
|
||||||
|
|
||||||
uint32_t memory_address = get_bus_address();
|
uint32_t memory_address = get_bus_address();
|
||||||
|
|
||||||
|
@ -176,18 +192,24 @@ void rl02::writeWord(const uint16_t addr, uint16_t v)
|
||||||
|
|
||||||
DOLOG(debug, false, "RL02 read %d bytes (dec) from %d (dec) to %06o (oct) [cylinder: %d, head: %d, sector: %d]", count, temp_disk_offset, memory_address, track, head, sector);
|
DOLOG(debug, false, "RL02 read %d bytes (dec) from %d (dec) to %06o (oct) [cylinder: %d, head: %d, sector: %d]", count, temp_disk_offset, memory_address, track, head, sector);
|
||||||
|
|
||||||
|
update_dar();
|
||||||
|
|
||||||
while(count > 0) {
|
while(count > 0) {
|
||||||
uint32_t cur = std::min(uint32_t(sizeof xfer_buffer), count);
|
uint32_t cur = std::min(uint32_t(sizeof xfer_buffer), count);
|
||||||
|
|
||||||
if (!fhs.at(device)->read(temp_disk_offset, cur, xfer_buffer)) {
|
if (!fhs.at(device)->read(temp_disk_offset, cur, xfer_buffer)) {
|
||||||
DOLOG(ll_error, true, "RL02 read error %s", strerror(errno));
|
DOLOG(ll_error, true, "RL02 read error %s, disk offset %u, read size %u, cylinder %d, head %d, sector %d", strerror(errno), temp_disk_offset, cur, track, head, sector);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
for(uint32_t i=0; i<cur; i++, memory_address++) {
|
for(uint32_t i=0; i<cur;) {
|
||||||
b->writeUnibusByte(memory_address, xfer_buffer[i]);
|
// BA and MPR are increased by 2
|
||||||
|
b->writeUnibusByte(memory_address++, xfer_buffer[i++]);
|
||||||
|
b->writeUnibusByte(memory_address++, xfer_buffer[i++]);
|
||||||
|
|
||||||
update_bus_address(memory_address);
|
update_bus_address(memory_address);
|
||||||
|
|
||||||
|
(*reinterpret_cast<int16_t *>(®isters[(RL02_MPR - RL02_BASE) / 2]))++;
|
||||||
}
|
}
|
||||||
|
|
||||||
temp_disk_offset += cur;
|
temp_disk_offset += cur;
|
||||||
|
@ -205,8 +227,13 @@ void rl02::writeWord(const uint16_t addr, uint16_t v)
|
||||||
track++;
|
track++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
update_dar();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (registers[(RL02_MPR - RL02_BASE) / 2])
|
||||||
|
DOLOG(warning, false, "RL02: unexpected MPR value after read (%06o)", registers[(RL02_MPR - RL02_BASE) / 2]);
|
||||||
|
|
||||||
do_int = true;
|
do_int = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
3
rl02.h
3
rl02.h
|
@ -42,7 +42,8 @@ private:
|
||||||
|
|
||||||
uint32_t get_bus_address() const;
|
uint32_t get_bus_address() const;
|
||||||
void update_bus_address(const uint32_t a);
|
void update_bus_address(const uint32_t a);
|
||||||
uint32_t calcOffset() const;
|
void update_dar();
|
||||||
|
uint32_t calc_offset() const;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
rl02(const std::vector<disk_backend *> & files, bus *const b, std::atomic_bool *const disk_read_acitivity, std::atomic_bool *const disk_write_acitivity);
|
rl02(const std::vector<disk_backend *> & files, bus *const b, std::atomic_bool *const disk_read_acitivity, std::atomic_bool *const disk_write_acitivity);
|
||||||
|
|
Loading…
Add table
Reference in a new issue