summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author Patrick Mackinlay <pmackinlay@hotmail.com>2018-10-02 13:55:48 +0700
committer Patrick Mackinlay <pmackinlay@hotmail.com>2018-10-02 13:55:48 +0700
commitdacf82932a9f6a1113d019e0532b618ee8fdbf3a (patch)
treef5f49f4b81006f042ae4aa8464298ef2c62f5b53
parent6f54f6aa974ac325cb83d5189adcbfc94373cb6e (diff)
nscsi_cd: set block size with mode select (nw)
Solaris 2.3 uses MODE SELECT (6) to specify a 512-byte block size during boot from CD-ROM on sun4_40. This patch is very limited (only a single mode parameter block, and no other parameters are supported), but sufficient to make sun4 happy.
-rw-r--r--src/devices/machine/nscsi_cd.cpp30
-rw-r--r--src/devices/machine/nscsi_cd.h2
2 files changed, 31 insertions, 1 deletions
diff --git a/src/devices/machine/nscsi_cd.cpp b/src/devices/machine/nscsi_cd.cpp
index 4a6a6712c14..32989426b68 100644
--- a/src/devices/machine/nscsi_cd.cpp
+++ b/src/devices/machine/nscsi_cd.cpp
@@ -37,7 +37,6 @@ MACHINE_CONFIG_END
void nscsi_cdrom_device::set_block_size(u32 block_size)
{
- assert_always(!started(), "block size should not be set after device start");
assert_always(bytes_per_sector % block_size == 0, "block size must be a factor of sector size");
bytes_per_block = block_size;
@@ -60,6 +59,25 @@ uint8_t nscsi_cdrom_device::scsi_get_data(int id, int pos)
return sector_buffer[(pos + extra_pos) & (bytes_per_sector - 1)];
}
+void nscsi_cdrom_device::scsi_put_data(int id, int pos, uint8_t data)
+{
+ if(id != 2) {
+ nscsi_full_device::scsi_put_data(id, pos, data);
+ return;
+ }
+
+ // process mode parameter header and one block descriptor
+ if(pos < sizeof(mode_data)) {
+ mode_data[pos] = data;
+
+ // is this the last byte of the mode parameter block descriptor?
+ if(pos == sizeof(mode_data) - 1)
+ // is there exactly one block descriptor?
+ if(mode_data[3] == 8)
+ set_block_size((mode_data[9] << 16) | (mode_data[10] << 8) | (mode_data[11] << 0));
+ }
+}
+
void nscsi_cdrom_device::return_no_cd()
{
sense(false, 3);
@@ -162,6 +180,16 @@ void nscsi_cdrom_device::scsi_command()
break;
}
+ case SC_MODE_SELECT_6:
+ LOG("command MODE SELECT 6 length %d\n", scsi_cmdbuf[4]);
+
+ // accept mode select parameter data
+ if(scsi_cmdbuf[4])
+ scsi_data_out(2, scsi_cmdbuf[4]);
+
+ scsi_status_complete(SS_GOOD);
+ break;
+
case SC_START_STOP_UNIT:
LOG("command %s UNIT%s\n", (scsi_cmdbuf[4] & 0x1) ? "START" : "STOP",
(scsi_cmdbuf[4] & 0x2) ? (scsi_cmdbuf[4] & 0x1) ? " (LOAD)" : " (EJECT)" : "");
diff --git a/src/devices/machine/nscsi_cd.h b/src/devices/machine/nscsi_cd.h
index 45e470b4c32..2f7c111c2d6 100644
--- a/src/devices/machine/nscsi_cd.h
+++ b/src/devices/machine/nscsi_cd.h
@@ -23,6 +23,7 @@ protected:
virtual void scsi_command() override;
virtual uint8_t scsi_get_data(int id, int pos) override;
+ virtual void scsi_put_data(int buf, int offset, uint8_t data) override;
private:
static constexpr uint32_t bytes_per_sector = 2048;
@@ -32,6 +33,7 @@ private:
uint32_t bytes_per_block;
int lba, cur_sector;
required_device<cdrom_image_device> image;
+ uint8_t mode_data[12];
void return_no_cd();
};