Diff for /qemu/hw/esp.c between versions 1.1.1.12 and 1.1.1.13

version 1.1.1.12, 2018/04/24 19:01:38 version 1.1.1.13, 2018/04/24 19:29:33
Line 25 Line 25
 #include "sysbus.h"  #include "sysbus.h"
 #include "scsi.h"  #include "scsi.h"
 #include "esp.h"  #include "esp.h"
   #include "trace.h"
 /* debug ESP card */  
 //#define DEBUG_ESP  
   
 /*  /*
  * On Sparc32, this is the ESP (NCR53C90) part of chip STP2000 (Master I/O),   * On Sparc32, this is the ESP (NCR53C90) part of chip STP2000 (Master I/O),
Line 37 Line 35
  * http://www.ibiblio.org/pub/historic-linux/early-ports/Sparc/NCR/NCR53C9X.txt   * http://www.ibiblio.org/pub/historic-linux/early-ports/Sparc/NCR/NCR53C9X.txt
  */   */
   
 #ifdef DEBUG_ESP  
 #define DPRINTF(fmt, ...)                                       \  
     do { printf("ESP: " fmt , ## __VA_ARGS__); } while (0)  
 #else  
 #define DPRINTF(fmt, ...) do {} while (0)  
 #endif  
   
 #define ESP_ERROR(fmt, ...)                                             \  #define ESP_ERROR(fmt, ...)                                             \
     do { printf("ESP ERROR: %s: " fmt, __func__ , ## __VA_ARGS__); } while (0)      do { printf("ESP ERROR: %s: " fmt, __func__ , ## __VA_ARGS__); } while (0)
   
Line 54  typedef struct ESPState ESPState; Line 45  typedef struct ESPState ESPState;
   
 struct ESPState {  struct ESPState {
     SysBusDevice busdev;      SysBusDevice busdev;
     uint32_t it_shift;  
     qemu_irq irq;  
     uint8_t rregs[ESP_REGS];      uint8_t rregs[ESP_REGS];
     uint8_t wregs[ESP_REGS];      uint8_t wregs[ESP_REGS];
       qemu_irq irq;
       uint32_t it_shift;
     int32_t ti_size;      int32_t ti_size;
     uint32_t ti_rptr, ti_wptr;      uint32_t ti_rptr, ti_wptr;
     uint8_t ti_buf[TI_BUFSZ];  
     uint32_t status;      uint32_t status;
     uint32_t dma;      uint32_t dma;
       uint8_t ti_buf[TI_BUFSZ];
     SCSIBus bus;      SCSIBus bus;
     SCSIDevice *current_dev;      SCSIDevice *current_dev;
     SCSIRequest *current_req;      SCSIRequest *current_req;
Line 75  struct ESPState { Line 66  struct ESPState {
     /* The size of the current DMA transfer.  Zero if no transfer is in      /* The size of the current DMA transfer.  Zero if no transfer is in
        progress.  */         progress.  */
     uint32_t dma_counter;      uint32_t dma_counter;
     uint8_t *async_buf;      int dma_enabled;
   
     uint32_t async_len;      uint32_t async_len;
       uint8_t *async_buf;
   
     ESPDMAMemoryReadWriteFunc dma_memory_read;      ESPDMAMemoryReadWriteFunc dma_memory_read;
     ESPDMAMemoryReadWriteFunc dma_memory_write;      ESPDMAMemoryReadWriteFunc dma_memory_write;
     void *dma_opaque;      void *dma_opaque;
     int dma_enabled;  
     void (*dma_cb)(ESPState *s);      void (*dma_cb)(ESPState *s);
 };  };
   
Line 157  static void esp_raise_irq(ESPState *s) Line 149  static void esp_raise_irq(ESPState *s)
     if (!(s->rregs[ESP_RSTAT] & STAT_INT)) {      if (!(s->rregs[ESP_RSTAT] & STAT_INT)) {
         s->rregs[ESP_RSTAT] |= STAT_INT;          s->rregs[ESP_RSTAT] |= STAT_INT;
         qemu_irq_raise(s->irq);          qemu_irq_raise(s->irq);
         DPRINTF("Raise IRQ\n");          trace_esp_raise_irq();
     }      }
 }  }
   
Line 166  static void esp_lower_irq(ESPState *s) Line 158  static void esp_lower_irq(ESPState *s)
     if (s->rregs[ESP_RSTAT] & STAT_INT) {      if (s->rregs[ESP_RSTAT] & STAT_INT) {
         s->rregs[ESP_RSTAT] &= ~STAT_INT;          s->rregs[ESP_RSTAT] &= ~STAT_INT;
         qemu_irq_lower(s->irq);          qemu_irq_lower(s->irq);
         DPRINTF("Lower IRQ\n");          trace_esp_lower_irq();
     }      }
 }  }
   
Line 177  static void esp_dma_enable(void *opaque, Line 169  static void esp_dma_enable(void *opaque,
   
     if (level) {      if (level) {
         s->dma_enabled = 1;          s->dma_enabled = 1;
         DPRINTF("Raise enable\n");          trace_esp_dma_enable();
         if (s->dma_cb) {          if (s->dma_cb) {
             s->dma_cb(s);              s->dma_cb(s);
             s->dma_cb = NULL;              s->dma_cb = NULL;
         }          }
     } else {      } else {
         DPRINTF("Lower enable\n");          trace_esp_dma_disable();
         s->dma_enabled = 0;          s->dma_enabled = 0;
     }      }
 }  }
Line 213  static uint32_t get_cmd(ESPState *s, uin Line 205  static uint32_t get_cmd(ESPState *s, uin
         memcpy(buf, s->ti_buf, dmalen);          memcpy(buf, s->ti_buf, dmalen);
         buf[0] = buf[2] >> 5;          buf[0] = buf[2] >> 5;
     }      }
     DPRINTF("get_cmd: len %d target %d\n", dmalen, target);      trace_esp_get_cmd(dmalen, target);
   
     s->ti_size = 0;      s->ti_size = 0;
     s->ti_rptr = 0;      s->ti_rptr = 0;
Line 225  static uint32_t get_cmd(ESPState *s, uin Line 217  static uint32_t get_cmd(ESPState *s, uin
         s->async_len = 0;          s->async_len = 0;
     }      }
   
     if (target >= ESP_MAX_DEVS || !s->bus.devs[target]) {      s->current_dev = scsi_device_find(&s->bus, 0, target, 0);
       if (!s->current_dev) {
         // No such drive          // No such drive
         s->rregs[ESP_RSTAT] = 0;          s->rregs[ESP_RSTAT] = 0;
         s->rregs[ESP_RINTR] = INTR_DC;          s->rregs[ESP_RINTR] = INTR_DC;
Line 233  static uint32_t get_cmd(ESPState *s, uin Line 226  static uint32_t get_cmd(ESPState *s, uin
         esp_raise_irq(s);          esp_raise_irq(s);
         return 0;          return 0;
     }      }
     s->current_dev = s->bus.devs[target];  
     return dmalen;      return dmalen;
 }  }
   
Line 241  static void do_busid_cmd(ESPState *s, ui Line 233  static void do_busid_cmd(ESPState *s, ui
 {  {
     int32_t datalen;      int32_t datalen;
     int lun;      int lun;
       SCSIDevice *current_lun;
   
     DPRINTF("do_busid_cmd: busid 0x%x\n", busid);      trace_esp_do_busid_cmd(busid);
     lun = busid & 7;      lun = busid & 7;
     s->current_req = scsi_req_new(s->current_dev, 0, lun, NULL);      current_lun = scsi_device_find(&s->bus, 0, s->current_dev->id, lun);
     datalen = scsi_req_enqueue(s->current_req, buf);      s->current_req = scsi_req_new(current_lun, 0, lun, buf, NULL);
       datalen = scsi_req_enqueue(s->current_req);
     s->ti_size = datalen;      s->ti_size = datalen;
     if (datalen != 0) {      if (datalen != 0) {
         s->rregs[ESP_RSTAT] = STAT_TC;          s->rregs[ESP_RSTAT] = STAT_TC;
Line 307  static void handle_satn_stop(ESPState *s Line 301  static void handle_satn_stop(ESPState *s
     }      }
     s->cmdlen = get_cmd(s, s->cmdbuf);      s->cmdlen = get_cmd(s, s->cmdbuf);
     if (s->cmdlen) {      if (s->cmdlen) {
         DPRINTF("Set ATN & Stop: cmdlen %d\n", s->cmdlen);          trace_esp_handle_satn_stop(s->cmdlen);
         s->do_cmd = 1;          s->do_cmd = 1;
         s->rregs[ESP_RSTAT] = STAT_TC | STAT_CD;          s->rregs[ESP_RSTAT] = STAT_TC | STAT_CD;
         s->rregs[ESP_RINTR] = INTR_BS | INTR_FC;          s->rregs[ESP_RINTR] = INTR_BS | INTR_FC;
Line 318  static void handle_satn_stop(ESPState *s Line 312  static void handle_satn_stop(ESPState *s
   
 static void write_response(ESPState *s)  static void write_response(ESPState *s)
 {  {
     DPRINTF("Transfer status (status=%d)\n", s->status);      trace_esp_write_response(s->status);
     s->ti_buf[0] = s->status;      s->ti_buf[0] = s->status;
     s->ti_buf[1] = 0;      s->ti_buf[1] = 0;
     if (s->dma) {      if (s->dma) {
Line 354  static void esp_do_dma(ESPState *s) Line 348  static void esp_do_dma(ESPState *s)
     to_device = (s->ti_size < 0);      to_device = (s->ti_size < 0);
     len = s->dma_left;      len = s->dma_left;
     if (s->do_cmd) {      if (s->do_cmd) {
         DPRINTF("command len %d + %d\n", s->cmdlen, len);          trace_esp_do_dma(s->cmdlen, len);
         s->dma_memory_read(s->dma_opaque, &s->cmdbuf[s->cmdlen], len);          s->dma_memory_read(s->dma_opaque, &s->cmdbuf[s->cmdlen], len);
         s->ti_size = 0;          s->ti_size = 0;
         s->cmdlen = 0;          s->cmdlen = 0;
Line 399  static void esp_command_complete(SCSIReq Line 393  static void esp_command_complete(SCSIReq
 {  {
     ESPState *s = DO_UPCAST(ESPState, busdev.qdev, req->bus->qbus.parent);      ESPState *s = DO_UPCAST(ESPState, busdev.qdev, req->bus->qbus.parent);
   
     DPRINTF("SCSI Command complete\n");      trace_esp_command_complete();
     if (s->ti_size != 0) {      if (s->ti_size != 0) {
         DPRINTF("SCSI command completed unexpectedly\n");          trace_esp_command_complete_unexpected();
     }      }
     s->ti_size = 0;      s->ti_size = 0;
     s->dma_left = 0;      s->dma_left = 0;
     s->async_len = 0;      s->async_len = 0;
     if (status) {      if (status) {
         DPRINTF("Command failed\n");          trace_esp_command_complete_fail();
     }      }
     s->status = status;      s->status = status;
     s->rregs[ESP_RSTAT] = STAT_ST;      s->rregs[ESP_RSTAT] = STAT_ST;
Line 423  static void esp_transfer_data(SCSIReques Line 417  static void esp_transfer_data(SCSIReques
 {  {
     ESPState *s = DO_UPCAST(ESPState, busdev.qdev, req->bus->qbus.parent);      ESPState *s = DO_UPCAST(ESPState, busdev.qdev, req->bus->qbus.parent);
   
     DPRINTF("transfer %d/%d\n", s->dma_left, s->ti_size);      trace_esp_transfer_data(s->dma_left, s->ti_size);
     s->async_len = len;      s->async_len = len;
     s->async_buf = scsi_req_get_buf(req);      s->async_buf = scsi_req_get_buf(req);
     if (s->dma_left) {      if (s->dma_left) {
Line 451  static void handle_ti(ESPState *s) Line 445  static void handle_ti(ESPState *s)
         minlen = (dmalen < -s->ti_size) ? dmalen : -s->ti_size;          minlen = (dmalen < -s->ti_size) ? dmalen : -s->ti_size;
     else      else
         minlen = (dmalen < s->ti_size) ? dmalen : s->ti_size;          minlen = (dmalen < s->ti_size) ? dmalen : s->ti_size;
     DPRINTF("Transfer Information len %d\n", minlen);      trace_esp_handle_ti(minlen);
     if (s->dma) {      if (s->dma) {
         s->dma_left = minlen;          s->dma_left = minlen;
         s->rregs[ESP_RSTAT] &= ~STAT_TC;          s->rregs[ESP_RSTAT] &= ~STAT_TC;
         esp_do_dma(s);          esp_do_dma(s);
     } else if (s->do_cmd) {      } else if (s->do_cmd) {
         DPRINTF("command len %d\n", s->cmdlen);          trace_esp_handle_ti_cmd(s->cmdlen);
         s->ti_size = 0;          s->ti_size = 0;
         s->cmdlen = 0;          s->cmdlen = 0;
         s->do_cmd = 0;          s->do_cmd = 0;
Line 516  static uint32_t esp_mem_readb(void *opaq Line 510  static uint32_t esp_mem_readb(void *opaq
     uint32_t saddr, old_val;      uint32_t saddr, old_val;
   
     saddr = addr >> s->it_shift;      saddr = addr >> s->it_shift;
     DPRINTF("read reg[%d]: 0x%2.2x\n", saddr, s->rregs[saddr]);      trace_esp_mem_readb(saddr, s->rregs[saddr]);
     switch (saddr) {      switch (saddr) {
     case ESP_FIFO:      case ESP_FIFO:
         if (s->ti_size > 0) {          if (s->ti_size > 0) {
Line 557  static void esp_mem_writeb(void *opaque, Line 551  static void esp_mem_writeb(void *opaque,
     uint32_t saddr;      uint32_t saddr;
   
     saddr = addr >> s->it_shift;      saddr = addr >> s->it_shift;
     DPRINTF("write reg[%d]: 0x%2.2x -> 0x%2.2x\n", saddr, s->wregs[saddr],      trace_esp_mem_writeb(saddr, s->wregs[saddr], val);
             val);  
     switch (saddr) {      switch (saddr) {
     case ESP_TCLO:      case ESP_TCLO:
     case ESP_TCMID:      case ESP_TCMID:
Line 586  static void esp_mem_writeb(void *opaque, Line 579  static void esp_mem_writeb(void *opaque,
         }          }
         switch(val & CMD_CMD) {          switch(val & CMD_CMD) {
         case CMD_NOP:          case CMD_NOP:
             DPRINTF("NOP (%2.2x)\n", val);              trace_esp_mem_writeb_cmd_nop(val);
             break;              break;
         case CMD_FLUSH:          case CMD_FLUSH:
             DPRINTF("Flush FIFO (%2.2x)\n", val);              trace_esp_mem_writeb_cmd_flush(val);
             //s->ti_size = 0;              //s->ti_size = 0;
             s->rregs[ESP_RINTR] = INTR_FC;              s->rregs[ESP_RINTR] = INTR_FC;
             s->rregs[ESP_RSEQ] = 0;              s->rregs[ESP_RSEQ] = 0;
             s->rregs[ESP_RFLAGS] = 0;              s->rregs[ESP_RFLAGS] = 0;
             break;              break;
         case CMD_RESET:          case CMD_RESET:
             DPRINTF("Chip reset (%2.2x)\n", val);              trace_esp_mem_writeb_cmd_reset(val);
             esp_soft_reset(&s->busdev.qdev);              esp_soft_reset(&s->busdev.qdev);
             break;              break;
         case CMD_BUSRESET:          case CMD_BUSRESET:
             DPRINTF("Bus reset (%2.2x)\n", val);              trace_esp_mem_writeb_cmd_bus_reset(val);
             s->rregs[ESP_RINTR] = INTR_RST;              s->rregs[ESP_RINTR] = INTR_RST;
             if (!(s->wregs[ESP_CFG1] & CFG1_RESREPT)) {              if (!(s->wregs[ESP_CFG1] & CFG1_RESREPT)) {
                 esp_raise_irq(s);                  esp_raise_irq(s);
Line 610  static void esp_mem_writeb(void *opaque, Line 603  static void esp_mem_writeb(void *opaque,
             handle_ti(s);              handle_ti(s);
             break;              break;
         case CMD_ICCS:          case CMD_ICCS:
             DPRINTF("Initiator Command Complete Sequence (%2.2x)\n", val);              trace_esp_mem_writeb_cmd_iccs(val);
             write_response(s);              write_response(s);
             s->rregs[ESP_RINTR] = INTR_FC;              s->rregs[ESP_RINTR] = INTR_FC;
             s->rregs[ESP_RSTAT] |= STAT_MI;              s->rregs[ESP_RSTAT] |= STAT_MI;
             break;              break;
         case CMD_MSGACC:          case CMD_MSGACC:
             DPRINTF("Message Accepted (%2.2x)\n", val);              trace_esp_mem_writeb_cmd_msgacc(val);
             s->rregs[ESP_RINTR] = INTR_DC;              s->rregs[ESP_RINTR] = INTR_DC;
             s->rregs[ESP_RSEQ] = 0;              s->rregs[ESP_RSEQ] = 0;
             s->rregs[ESP_RFLAGS] = 0;              s->rregs[ESP_RFLAGS] = 0;
             esp_raise_irq(s);              esp_raise_irq(s);
             break;              break;
         case CMD_PAD:          case CMD_PAD:
             DPRINTF("Transfer padding (%2.2x)\n", val);              trace_esp_mem_writeb_cmd_pad(val);
             s->rregs[ESP_RSTAT] = STAT_TC;              s->rregs[ESP_RSTAT] = STAT_TC;
             s->rregs[ESP_RINTR] = INTR_FC;              s->rregs[ESP_RINTR] = INTR_FC;
             s->rregs[ESP_RSEQ] = 0;              s->rregs[ESP_RSEQ] = 0;
             break;              break;
         case CMD_SATN:          case CMD_SATN:
             DPRINTF("Set ATN (%2.2x)\n", val);              trace_esp_mem_writeb_cmd_satn(val);
             break;              break;
         case CMD_SEL:          case CMD_SEL:
             DPRINTF("Select without ATN (%2.2x)\n", val);              trace_esp_mem_writeb_cmd_sel(val);
             handle_s_without_atn(s);              handle_s_without_atn(s);
             break;              break;
         case CMD_SELATN:          case CMD_SELATN:
             DPRINTF("Select with ATN (%2.2x)\n", val);              trace_esp_mem_writeb_cmd_selatn(val);
             handle_satn(s);              handle_satn(s);
             break;              break;
         case CMD_SELATNS:          case CMD_SELATNS:
             DPRINTF("Select with ATN & stop (%2.2x)\n", val);              trace_esp_mem_writeb_cmd_selatns(val);
             handle_satn_stop(s);              handle_satn_stop(s);
             break;              break;
         case CMD_ENSEL:          case CMD_ENSEL:
             DPRINTF("Enable selection (%2.2x)\n", val);              trace_esp_mem_writeb_cmd_ensel(val);
             s->rregs[ESP_RINTR] = 0;              s->rregs[ESP_RINTR] = 0;
             break;              break;
         default:          default:
Line 729  void esp_init(target_phys_addr_t espaddr Line 722  void esp_init(target_phys_addr_t espaddr
     *dma_enable = qdev_get_gpio_in(dev, 1);      *dma_enable = qdev_get_gpio_in(dev, 1);
 }  }
   
 static const struct SCSIBusOps esp_scsi_ops = {  static const struct SCSIBusInfo esp_scsi_info = {
       .tcq = false,
       .max_target = ESP_MAX_DEVS,
       .max_lun = 7,
   
     .transfer_data = esp_transfer_data,      .transfer_data = esp_transfer_data,
     .complete = esp_command_complete,      .complete = esp_command_complete,
     .cancel = esp_request_cancelled      .cancel = esp_request_cancelled
Line 749  static int esp_init1(SysBusDevice *dev) Line 746  static int esp_init1(SysBusDevice *dev)
   
     qdev_init_gpio_in(&dev->qdev, esp_gpio_demux, 2);      qdev_init_gpio_in(&dev->qdev, esp_gpio_demux, 2);
   
     scsi_bus_new(&s->bus, &dev->qdev, 0, ESP_MAX_DEVS, &esp_scsi_ops);      scsi_bus_new(&s->bus, &dev->qdev, &esp_scsi_info);
     return scsi_bus_legacy_handle_cmdline(&s->bus);      return scsi_bus_legacy_handle_cmdline(&s->bus);
 }  }
   

Removed from v.1.1.1.12  
changed lines
  Added in v.1.1.1.13


unix.superglobalmegacorp.com