diff options
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 |
commit | dacf82932a9f6a1113d019e0532b618ee8fdbf3a (patch) | |
tree | f5f49f4b81006f042ae4aa8464298ef2c62f5b53 | |
parent | 6f54f6aa974ac325cb83d5189adcbfc94373cb6e (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.cpp | 30 | ||||
-rw-r--r-- | src/devices/machine/nscsi_cd.h | 2 |
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(); }; |