diff --git a/hw/scsi/esp.c b/hw/scsi/esp.c index 2d3c649567..aa11a6c041 100644 --- a/hw/scsi/esp.c +++ b/hw/scsi/esp.c @@ -235,6 +235,8 @@ static uint32_t get_cmd(ESPState *s, uint32_t maxlen) uint32_t dmalen, n; int target; + memset (buf, 0, ESP_CMDFIFO_SZ); + if (s->current_req) { /* Started a new command before the old one finished. Cancel it. */ scsi_req_cancel(s->current_req); @@ -284,6 +286,8 @@ static void do_command_phase(ESPState *s) SCSIDevice *current_lun; uint8_t buf[ESP_CMDFIFO_SZ]; + memset (buf, 0, ESP_CMDFIFO_SZ); + trace_esp_do_command_phase(s->lun); cmdlen = fifo8_num_used(&s->cmdfifo); if (!cmdlen || !s->current_dev) { @@ -596,6 +600,8 @@ static void esp_do_dma(ESPState *s) int to_device = ((s->rregs[ESP_RSTAT] & 7) == STAT_DO); uint8_t buf[ESP_CMDFIFO_SZ]; + memset (buf, 0, ESP_CMDFIFO_SZ); + len = esp_get_tc(s); if (s->do_cmd) { /* @@ -1066,6 +1072,31 @@ void esp_reg_write(ESPState *s, uint32_t saddr, uint64_t val) esp_soft_reset(s); break; case CMD_BUSRESET: + + /* + * As far as I can ascertain, the bus reset command + * asserts the SCSI RSTO (reset output) pin on the + * bus, and asserting this signal is supposed to have + * the effect of kicking all targets off the bus and + * returning them to their initial conditions such + * that the host must renogotiate with them. The + * SunOS 4.1.x esp driver sends a bus reset command + * when the kernel boots, presumably to ensure all + * devices have been returned to a known initial state + * so that it can reliably probe them. After the bus + * reset, SunOS sends a TEST_UNIT_READY command, which + * it expects will yield a CHECK_CONDITION response. + * This only happens if the device is in the + * UNIT_ATTENTION state, which it only would be when + * it has just been powered up or reset. If we don't + * actually reset the device here, then the device will + * be in the NO_SENSE state instead, and SunOS gets back + * a GOOD response instead, which may result in the + * target being detected as a "non-CCS" device. + */ + + qbus_reset_all(BUS(&s->bus)); + trace_esp_mem_writeb_cmd_bus_reset(val); if (!(s->wregs[ESP_CFG1] & CFG1_RESREPT)) { s->rregs[ESP_RINTR] |= INTR_RST;