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

version 1.1.1.11, 2018/04/24 18:39:39 version 1.1.1.12, 2018/04/24 19:01:38
Line 61  struct ESPState { Line 61  struct ESPState {
     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];      uint8_t ti_buf[TI_BUFSZ];
     uint32_t sense;      uint32_t status;
     uint32_t dma;      uint32_t dma;
     SCSIBus bus;      SCSIBus bus;
     SCSIDevice *current_dev;      SCSIDevice *current_dev;
       SCSIRequest *current_req;
     uint8_t cmdbuf[TI_BUFSZ];      uint8_t cmdbuf[TI_BUFSZ];
     uint32_t cmdlen;      uint32_t cmdlen;
     uint32_t do_cmd;      uint32_t do_cmd;
Line 187  static void esp_dma_enable(void *opaque, Line 188  static void esp_dma_enable(void *opaque,
     }      }
 }  }
   
   static void esp_request_cancelled(SCSIRequest *req)
   {
       ESPState *s = DO_UPCAST(ESPState, busdev.qdev, req->bus->qbus.parent);
   
       if (req == s->current_req) {
           scsi_req_unref(s->current_req);
           s->current_req = NULL;
           s->current_dev = NULL;
       }
   }
   
 static uint32_t get_cmd(ESPState *s, uint8_t *buf)  static uint32_t get_cmd(ESPState *s, uint8_t *buf)
 {  {
     uint32_t dmalen;      uint32_t dmalen;
Line 199  static uint32_t get_cmd(ESPState *s, uin Line 211  static uint32_t get_cmd(ESPState *s, uin
     } else {      } else {
         dmalen = s->ti_size;          dmalen = s->ti_size;
         memcpy(buf, s->ti_buf, dmalen);          memcpy(buf, s->ti_buf, dmalen);
         buf[0] = 0;          buf[0] = buf[2] >> 5;
     }      }
     DPRINTF("get_cmd: len %d target %d\n", dmalen, target);      DPRINTF("get_cmd: len %d target %d\n", dmalen, target);
   
Line 207  static uint32_t get_cmd(ESPState *s, uin Line 219  static uint32_t get_cmd(ESPState *s, uin
     s->ti_rptr = 0;      s->ti_rptr = 0;
     s->ti_wptr = 0;      s->ti_wptr = 0;
   
     if (s->current_dev) {      if (s->current_req) {
         /* Started a new command before the old one finished.  Cancel it.  */          /* Started a new command before the old one finished.  Cancel it.  */
         s->current_dev->info->cancel_io(s->current_dev, 0);          scsi_req_cancel(s->current_req);
         s->async_len = 0;          s->async_len = 0;
     }      }
   
Line 232  static void do_busid_cmd(ESPState *s, ui Line 244  static void do_busid_cmd(ESPState *s, ui
   
     DPRINTF("do_busid_cmd: busid 0x%x\n", busid);      DPRINTF("do_busid_cmd: busid 0x%x\n", busid);
     lun = busid & 7;      lun = busid & 7;
     datalen = s->current_dev->info->send_command(s->current_dev, 0, buf, lun);      s->current_req = scsi_req_new(s->current_dev, 0, lun, NULL);
       datalen = scsi_req_enqueue(s->current_req, buf);
     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 240  static void do_busid_cmd(ESPState *s, ui Line 253  static void do_busid_cmd(ESPState *s, ui
         s->dma_counter = 0;          s->dma_counter = 0;
         if (datalen > 0) {          if (datalen > 0) {
             s->rregs[ESP_RSTAT] |= STAT_DI;              s->rregs[ESP_RSTAT] |= STAT_DI;
             s->current_dev->info->read_data(s->current_dev, 0);  
         } else {          } else {
             s->rregs[ESP_RSTAT] |= STAT_DO;              s->rregs[ESP_RSTAT] |= STAT_DO;
             s->current_dev->info->write_data(s->current_dev, 0);  
         }          }
           scsi_req_continue(s->current_req);
     }      }
     s->rregs[ESP_RINTR] = INTR_BS | INTR_FC;      s->rregs[ESP_RINTR] = INTR_BS | INTR_FC;
     s->rregs[ESP_RSEQ] = SEQ_CD;      s->rregs[ESP_RSEQ] = SEQ_CD;
Line 306  static void handle_satn_stop(ESPState *s Line 318  static void handle_satn_stop(ESPState *s
   
 static void write_response(ESPState *s)  static void write_response(ESPState *s)
 {  {
     DPRINTF("Transfer status (sense=%d)\n", s->sense);      DPRINTF("Transfer status (status=%d)\n", s->status);
     s->ti_buf[0] = s->sense;      s->ti_buf[0] = s->status;
     s->ti_buf[1] = 0;      s->ti_buf[1] = 0;
     if (s->dma) {      if (s->dma) {
         s->dma_memory_write(s->dma_opaque, s->ti_buf, 2);          s->dma_memory_write(s->dma_opaque, s->ti_buf, 2);
Line 370  static void esp_do_dma(ESPState *s) Line 382  static void esp_do_dma(ESPState *s)
     else      else
         s->ti_size -= len;          s->ti_size -= len;
     if (s->async_len == 0) {      if (s->async_len == 0) {
         if (to_device) {          scsi_req_continue(s->current_req);
             // ti_size is negative          /* If there is still data to be read from the device then
             s->current_dev->info->write_data(s->current_dev, 0);             complete the DMA operation immediately.  Otherwise defer
         } else {             until the scsi layer has completed.  */
             s->current_dev->info->read_data(s->current_dev, 0);          if (to_device || s->dma_left != 0 || s->ti_size == 0) {
             /* If there is still data to be read from the device then              return;
                complete the DMA operation immediately.  Otherwise defer  
                until the scsi layer has completed.  */  
             if (s->dma_left == 0 && s->ti_size > 0) {  
                 esp_dma_done(s);  
             }  
         }          }
     } else {  
         /* Partially filled a scsi buffer. Complete immediately.  */  
         esp_dma_done(s);  
     }      }
   
       /* Partially filled a scsi buffer. Complete immediately.  */
       esp_dma_done(s);
 }  }
   
 static void esp_command_complete(SCSIBus *bus, int reason, uint32_t tag,  static void esp_command_complete(SCSIRequest *req, uint32_t status)
                                  uint32_t arg)  
 {  {
     ESPState *s = DO_UPCAST(ESPState, busdev.qdev, bus->qbus.parent);      ESPState *s = DO_UPCAST(ESPState, busdev.qdev, req->bus->qbus.parent);
   
     if (reason == SCSI_REASON_DONE) {      DPRINTF("SCSI Command complete\n");
         DPRINTF("SCSI Command complete\n");      if (s->ti_size != 0) {
         if (s->ti_size != 0)          DPRINTF("SCSI command completed unexpectedly\n");
             DPRINTF("SCSI command completed unexpectedly\n");      }
         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 (arg)      if (status) {
             DPRINTF("Command failed\n");          DPRINTF("Command failed\n");
         s->sense = arg;      }
         s->rregs[ESP_RSTAT] = STAT_ST;      s->status = status;
         esp_dma_done(s);      s->rregs[ESP_RSTAT] = STAT_ST;
       esp_dma_done(s);
       if (s->current_req) {
           scsi_req_unref(s->current_req);
           s->current_req = NULL;
         s->current_dev = NULL;          s->current_dev = NULL;
     } else {      }
         DPRINTF("transfer %d/%d\n", s->dma_left, s->ti_size);  }
         s->async_len = arg;  
         s->async_buf = s->current_dev->info->get_buf(s->current_dev, 0);  static void esp_transfer_data(SCSIRequest *req, uint32_t len)
         if (s->dma_left) {  {
             esp_do_dma(s);      ESPState *s = DO_UPCAST(ESPState, busdev.qdev, req->bus->qbus.parent);
         } else if (s->dma_counter != 0 && s->ti_size <= 0) {  
             /* If this was the last part of a DMA transfer then the      DPRINTF("transfer %d/%d\n", s->dma_left, s->ti_size);
                completion interrupt is deferred to here.  */      s->async_len = len;
             esp_dma_done(s);      s->async_buf = scsi_req_get_buf(req);
         }      if (s->dma_left) {
           esp_do_dma(s);
       } else if (s->dma_counter != 0 && s->ti_size <= 0) {
           /* If this was the last part of a DMA transfer then the
              completion interrupt is deferred to here.  */
           esp_dma_done(s);
     }      }
 }  }
   
Line 678  static const VMStateDescription vmstate_ Line 693  static const VMStateDescription vmstate_
         VMSTATE_UINT32(ti_rptr, ESPState),          VMSTATE_UINT32(ti_rptr, ESPState),
         VMSTATE_UINT32(ti_wptr, ESPState),          VMSTATE_UINT32(ti_wptr, ESPState),
         VMSTATE_BUFFER(ti_buf, ESPState),          VMSTATE_BUFFER(ti_buf, ESPState),
         VMSTATE_UINT32(sense, ESPState),          VMSTATE_UINT32(status, ESPState),
         VMSTATE_UINT32(dma, ESPState),          VMSTATE_UINT32(dma, ESPState),
         VMSTATE_BUFFER(cmdbuf, ESPState),          VMSTATE_BUFFER(cmdbuf, ESPState),
         VMSTATE_UINT32(cmdlen, ESPState),          VMSTATE_UINT32(cmdlen, ESPState),
Line 714  void esp_init(target_phys_addr_t espaddr Line 729  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 = {
       .transfer_data = esp_transfer_data,
       .complete = esp_command_complete,
       .cancel = esp_request_cancelled
   };
   
 static int esp_init1(SysBusDevice *dev)  static int esp_init1(SysBusDevice *dev)
 {  {
     ESPState *s = FROM_SYSBUS(ESPState, dev);      ESPState *s = FROM_SYSBUS(ESPState, dev);
Line 728  static int esp_init1(SysBusDevice *dev) Line 749  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_command_complete);      scsi_bus_new(&s->bus, &dev->qdev, 0, ESP_MAX_DEVS, &esp_scsi_ops);
     return scsi_bus_legacy_handle_cmdline(&s->bus);      return scsi_bus_legacy_handle_cmdline(&s->bus);
 }  }
   

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


unix.superglobalmegacorp.com