Diff for /qemu/hw/esp.c between versions 1.1.1.5 and 1.1.1.6

version 1.1.1.5, 2018/04/24 16:46:05 version 1.1.1.6, 2018/04/24 16:48:52
Line 1 Line 1
 /*  /*
  * QEMU ESP/NCR53C9x emulation   * QEMU ESP/NCR53C9x emulation
  *    *
  * Copyright (c) 2005-2006 Fabrice Bellard   * Copyright (c) 2005-2006 Fabrice Bellard
  *    *
  * Permission is hereby granted, free of charge, to any person obtaining a copy   * Permission is hereby granted, free of charge, to any person obtaining a copy
  * of this software and associated documentation files (the "Software"), to deal   * of this software and associated documentation files (the "Software"), to deal
  * in the Software without restriction, including without limitation the rights   * in the Software without restriction, including without limitation the rights
Line 21 Line 21
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN   * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  * THE SOFTWARE.   * THE SOFTWARE.
  */   */
 #include "vl.h"  #include "hw.h"
   #include "block.h"
   #include "scsi-disk.h"
   #include "sun4m.h"
   /* FIXME: Only needed for MAX_DISKS, which is probably wrong.  */
   #include "sysemu.h"
   
 /* debug ESP card */  /* debug ESP card */
 //#define DEBUG_ESP  //#define DEBUG_ESP
   
 /*  /*
  * On Sparc32, this is the ESP (NCR53C90) part of chip STP2000 (Master I/O), also   * On Sparc32, this is the ESP (NCR53C90) part of chip STP2000 (Master I/O),
  * produced as NCR89C100. See   * also produced as NCR89C100. See
  * http://www.ibiblio.org/pub/historic-linux/early-ports/Sparc/NCR/NCR89C100.txt   * http://www.ibiblio.org/pub/historic-linux/early-ports/Sparc/NCR/NCR89C100.txt
  * and   * and
  * 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
Line 41  do { printf("ESP: " fmt , ##args); } whi Line 46  do { printf("ESP: " fmt , ##args); } whi
 #define DPRINTF(fmt, args...)  #define DPRINTF(fmt, args...)
 #endif  #endif
   
 #define ESP_MAXREG 0x3f  #define ESP_MASK 0x3f
   #define ESP_REGS 16
   #define ESP_SIZE (ESP_REGS * 4)
 #define TI_BUFSZ 32  #define TI_BUFSZ 32
 /* The HBA is ID 7, so for simplicitly limit to 7 devices.  */  
 #define ESP_MAX_DEVS      7  
   
 typedef struct ESPState ESPState;  typedef struct ESPState ESPState;
   
 struct ESPState {  struct ESPState {
     BlockDriverState **bd;      qemu_irq irq;
     uint8_t rregs[ESP_MAXREG];      uint8_t rregs[ESP_REGS];
     uint8_t wregs[ESP_MAXREG];      uint8_t wregs[ESP_REGS];
     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];
     int sense;      int sense;
     int dma;      int dma;
     SCSIDevice *scsi_dev[MAX_DISKS];      SCSIDevice *scsi_dev[ESP_MAX_DEVS];
     SCSIDevice *current_dev;      SCSIDevice *current_dev;
     uint8_t cmdbuf[TI_BUFSZ];      uint8_t cmdbuf[TI_BUFSZ];
     int cmdlen;      int cmdlen;
Line 73  struct ESPState { Line 78  struct ESPState {
     void *dma_opaque;      void *dma_opaque;
 };  };
   
   #define ESP_TCLO   0x0
   #define ESP_TCMID  0x1
   #define ESP_FIFO   0x2
   #define ESP_CMD    0x3
   #define ESP_RSTAT  0x4
   #define ESP_WBUSID 0x4
   #define ESP_RINTR  0x5
   #define ESP_WSEL   0x5
   #define ESP_RSEQ   0x6
   #define ESP_WSYNTP 0x6
   #define ESP_RFLAGS 0x7
   #define ESP_WSYNO  0x7
   #define ESP_CFG1   0x8
   #define ESP_RRES1  0x9
   #define ESP_WCCF   0x9
   #define ESP_RRES2  0xa
   #define ESP_WTEST  0xa
   #define ESP_CFG2   0xb
   #define ESP_CFG3   0xc
   #define ESP_RES3   0xd
   #define ESP_TCHI   0xe
   #define ESP_RES4   0xf
   
   #define CMD_DMA 0x80
   #define CMD_CMD 0x7f
   
   #define CMD_NOP      0x00
   #define CMD_FLUSH    0x01
   #define CMD_RESET    0x02
   #define CMD_BUSRESET 0x03
   #define CMD_TI       0x10
   #define CMD_ICCS     0x11
   #define CMD_MSGACC   0x12
   #define CMD_SATN     0x1a
   #define CMD_SELATN   0x42
   #define CMD_SELATNS  0x43
   #define CMD_ENSEL    0x44
   
 #define STAT_DO 0x00  #define STAT_DO 0x00
 #define STAT_DI 0x01  #define STAT_DI 0x01
 #define STAT_CD 0x02  #define STAT_CD 0x02
 #define STAT_ST 0x03  #define STAT_ST 0x03
 #define STAT_MI 0x06  #define STAT_MI 0x06
 #define STAT_MO 0x07  #define STAT_MO 0x07
   #define STAT_PIO_MASK 0x06
   
 #define STAT_TC 0x10  #define STAT_TC 0x10
 #define STAT_PE 0x20  #define STAT_PE 0x20
Line 93  struct ESPState { Line 137  struct ESPState {
 #define SEQ_0 0x0  #define SEQ_0 0x0
 #define SEQ_CD 0x4  #define SEQ_CD 0x4
   
   #define CFG1_RESREPT 0x40
   
   #define CFG2_MASK 0x15
   
   #define TCHI_FAS100A 0x4
   
 static int get_cmd(ESPState *s, uint8_t *buf)  static int get_cmd(ESPState *s, uint8_t *buf)
 {  {
     uint32_t dmalen;      uint32_t dmalen;
     int target;      int target;
   
     dmalen = s->rregs[0] | (s->rregs[1] << 8);      dmalen = s->rregs[ESP_TCLO] | (s->rregs[ESP_TCMID] << 8);
     target = s->wregs[4] & 7;      target = s->wregs[ESP_WBUSID] & 7;
     DPRINTF("get_cmd: len %d target %d\n", dmalen, target);      DPRINTF("get_cmd: len %d target %d\n", dmalen, target);
     if (s->dma) {      if (s->dma) {
         espdma_memory_read(s->dma_opaque, buf, dmalen);          espdma_memory_read(s->dma_opaque, buf, dmalen);
     } else {      } else {
         buf[0] = 0;          buf[0] = 0;
         memcpy(&buf[1], s->ti_buf, dmalen);          memcpy(&buf[1], s->ti_buf, dmalen);
         dmalen++;          dmalen++;
     }      }
   
     s->ti_size = 0;      s->ti_size = 0;
Line 115  static int get_cmd(ESPState *s, uint8_t  Line 165  static int get_cmd(ESPState *s, uint8_t 
   
     if (s->current_dev) {      if (s->current_dev) {
         /* Started a new command before the old one finished.  Cancel it.  */          /* Started a new command before the old one finished.  Cancel it.  */
         scsi_cancel_io(s->current_dev, 0);          s->current_dev->cancel_io(s->current_dev, 0);
         s->async_len = 0;          s->async_len = 0;
     }      }
   
     if (target >= MAX_DISKS || !s->scsi_dev[target]) {      if (target >= ESP_MAX_DEVS || !s->scsi_dev[target]) {
         // No such drive          // No such drive
         s->rregs[4] = STAT_IN;          s->rregs[ESP_RSTAT] = STAT_IN;
         s->rregs[5] = INTR_DC;          s->rregs[ESP_RINTR] = INTR_DC;
         s->rregs[6] = SEQ_0;          s->rregs[ESP_RSEQ] = SEQ_0;
         espdma_raise_irq(s->dma_opaque);          qemu_irq_raise(s->irq);
         return 0;          return 0;
     }      }
     s->current_dev = s->scsi_dev[target];      s->current_dev = s->scsi_dev[target];
     return dmalen;      return dmalen;
Line 138  static void do_cmd(ESPState *s, uint8_t  Line 188  static void do_cmd(ESPState *s, uint8_t 
   
     DPRINTF("do_cmd: busid 0x%x\n", buf[0]);      DPRINTF("do_cmd: busid 0x%x\n", buf[0]);
     lun = buf[0] & 7;      lun = buf[0] & 7;
     datalen = scsi_send_command(s->current_dev, 0, &buf[1], lun);      datalen = s->current_dev->send_command(s->current_dev, 0, &buf[1], lun);
     s->ti_size = datalen;      s->ti_size = datalen;
     if (datalen != 0) {      if (datalen != 0) {
         s->rregs[4] = STAT_IN | STAT_TC;          s->rregs[ESP_RSTAT] = STAT_IN | STAT_TC;
         s->dma_left = 0;          s->dma_left = 0;
         s->dma_counter = 0;          s->dma_counter = 0;
         if (datalen > 0) {          if (datalen > 0) {
             s->rregs[4] |= STAT_DI;              s->rregs[ESP_RSTAT] |= STAT_DI;
             scsi_read_data(s->current_dev, 0);              s->current_dev->read_data(s->current_dev, 0);
         } else {          } else {
             s->rregs[4] |= STAT_DO;              s->rregs[ESP_RSTAT] |= STAT_DO;
             scsi_write_data(s->current_dev, 0);              s->current_dev->write_data(s->current_dev, 0);
         }          }
     }      }
     s->rregs[5] = INTR_BS | INTR_FC;      s->rregs[ESP_RINTR] = INTR_BS | INTR_FC;
     s->rregs[6] = SEQ_CD;      s->rregs[ESP_RSEQ] = SEQ_CD;
     espdma_raise_irq(s->dma_opaque);      qemu_irq_raise(s->irq);
 }  }
   
 static void handle_satn(ESPState *s)  static void handle_satn(ESPState *s)
Line 173  static void handle_satn_stop(ESPState *s Line 223  static void handle_satn_stop(ESPState *s
     if (s->cmdlen) {      if (s->cmdlen) {
         DPRINTF("Set ATN & Stop: cmdlen %d\n", s->cmdlen);          DPRINTF("Set ATN & Stop: cmdlen %d\n", s->cmdlen);
         s->do_cmd = 1;          s->do_cmd = 1;
         s->rregs[4] = STAT_IN | STAT_TC | STAT_CD;          s->rregs[ESP_RSTAT] = STAT_IN | STAT_TC | STAT_CD;
         s->rregs[5] = INTR_BS | INTR_FC;          s->rregs[ESP_RINTR] = INTR_BS | INTR_FC;
         s->rregs[6] = SEQ_CD;          s->rregs[ESP_RSEQ] = SEQ_CD;
         espdma_raise_irq(s->dma_opaque);          qemu_irq_raise(s->irq);
     }      }
 }  }
   
Line 187  static void write_response(ESPState *s) Line 237  static void write_response(ESPState *s)
     s->ti_buf[1] = 0;      s->ti_buf[1] = 0;
     if (s->dma) {      if (s->dma) {
         espdma_memory_write(s->dma_opaque, s->ti_buf, 2);          espdma_memory_write(s->dma_opaque, s->ti_buf, 2);
         s->rregs[4] = STAT_IN | STAT_TC | STAT_ST;          s->rregs[ESP_RSTAT] = STAT_IN | STAT_TC | STAT_ST;
         s->rregs[5] = INTR_BS | INTR_FC;          s->rregs[ESP_RINTR] = INTR_BS | INTR_FC;
         s->rregs[6] = SEQ_CD;          s->rregs[ESP_RSEQ] = SEQ_CD;
     } else {      } else {
         s->ti_size = 2;          s->ti_size = 2;
         s->ti_rptr = 0;          s->ti_rptr = 0;
         s->ti_wptr = 0;          s->ti_wptr = 0;
         s->rregs[7] = 2;          s->rregs[ESP_RFLAGS] = 2;
     }      }
     espdma_raise_irq(s->dma_opaque);      qemu_irq_raise(s->irq);
 }  }
   
 static void esp_dma_done(ESPState *s)  static void esp_dma_done(ESPState *s)
 {  {
     s->rregs[4] |= STAT_IN | STAT_TC;      s->rregs[ESP_RSTAT] |= STAT_IN | STAT_TC;
     s->rregs[5] = INTR_BS;      s->rregs[ESP_RINTR] = INTR_BS;
     s->rregs[6] = 0;      s->rregs[ESP_RSEQ] = 0;
     s->rregs[7] = 0;      s->rregs[ESP_RFLAGS] = 0;
     s->rregs[0] = 0;      s->rregs[ESP_TCLO] = 0;
     s->rregs[1] = 0;      s->rregs[ESP_TCMID] = 0;
     espdma_raise_irq(s->dma_opaque);      qemu_irq_raise(s->irq);
 }  }
   
 static void esp_do_dma(ESPState *s)  static void esp_do_dma(ESPState *s)
Line 248  static void esp_do_dma(ESPState *s) Line 298  static void esp_do_dma(ESPState *s)
     if (s->async_len == 0) {      if (s->async_len == 0) {
         if (to_device) {          if (to_device) {
             // ti_size is negative              // ti_size is negative
             scsi_write_data(s->current_dev, 0);              s->current_dev->write_data(s->current_dev, 0);
         } else {          } else {
             scsi_read_data(s->current_dev, 0);              s->current_dev->read_data(s->current_dev, 0);
             /* If there is still data to be read from the device then              /* If there is still data to be read from the device then
                complete the DMA operation immeriately.  Otherwise defer                 complete the DMA operation immeriately.  Otherwise defer
                until the scsi layer has completed.  */                 until the scsi layer has completed.  */
Line 279  static void esp_command_complete(void *o Line 329  static void esp_command_complete(void *o
         if (arg)          if (arg)
             DPRINTF("Command failed\n");              DPRINTF("Command failed\n");
         s->sense = arg;          s->sense = arg;
         s->rregs[4] = STAT_ST;          s->rregs[ESP_RSTAT] = STAT_ST;
         esp_dma_done(s);          esp_dma_done(s);
         s->current_dev = NULL;          s->current_dev = NULL;
     } else {      } else {
         DPRINTF("transfer %d/%d\n", s->dma_left, s->ti_size);          DPRINTF("transfer %d/%d\n", s->dma_left, s->ti_size);
         s->async_len = arg;          s->async_len = arg;
         s->async_buf = scsi_get_buf(s->current_dev, 0);          s->async_buf = s->current_dev->get_buf(s->current_dev, 0);
         if (s->dma_left) {          if (s->dma_left) {
             esp_do_dma(s);              esp_do_dma(s);
         } else if (s->dma_counter != 0 && s->ti_size <= 0) {          } else if (s->dma_counter != 0 && s->ti_size <= 0) {
Line 300  static void handle_ti(ESPState *s) Line 350  static void handle_ti(ESPState *s)
 {  {
     uint32_t dmalen, minlen;      uint32_t dmalen, minlen;
   
     dmalen = s->rregs[0] | (s->rregs[1] << 8);      dmalen = s->rregs[ESP_TCLO] | (s->rregs[ESP_TCMID] << 8);
     if (dmalen==0) {      if (dmalen==0) {
       dmalen=0x10000;        dmalen=0x10000;
     }      }
Line 315  static void handle_ti(ESPState *s) Line 365  static void handle_ti(ESPState *s)
     DPRINTF("Transfer Information len %d\n", minlen);      DPRINTF("Transfer Information len %d\n", minlen);
     if (s->dma) {      if (s->dma) {
         s->dma_left = minlen;          s->dma_left = minlen;
         s->rregs[4] &= ~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);          DPRINTF("command len %d\n", s->cmdlen);
Line 327  static void handle_ti(ESPState *s) Line 377  static void handle_ti(ESPState *s)
     }      }
 }  }
   
 void esp_reset(void *opaque)  static void esp_reset(void *opaque)
 {  {
     ESPState *s = opaque;      ESPState *s = opaque;
   
     memset(s->rregs, 0, ESP_MAXREG);      memset(s->rregs, 0, ESP_REGS);
     memset(s->wregs, 0, ESP_MAXREG);      memset(s->wregs, 0, ESP_REGS);
     s->rregs[0x0e] = 0x4; // Indicate fas100a      s->rregs[ESP_TCHI] = TCHI_FAS100A; // Indicate fas100a
     s->ti_size = 0;      s->ti_size = 0;
     s->ti_rptr = 0;      s->ti_rptr = 0;
     s->ti_wptr = 0;      s->ti_wptr = 0;
Line 341  void esp_reset(void *opaque) Line 391  void esp_reset(void *opaque)
     s->do_cmd = 0;      s->do_cmd = 0;
 }  }
   
   static void parent_esp_reset(void *opaque, int irq, int level)
   {
       if (level)
           esp_reset(opaque);
   }
   
 static uint32_t esp_mem_readb(void *opaque, target_phys_addr_t addr)  static uint32_t esp_mem_readb(void *opaque, target_phys_addr_t addr)
 {  {
     ESPState *s = opaque;      ESPState *s = opaque;
     uint32_t saddr;      uint32_t saddr;
   
     saddr = (addr & ESP_MAXREG) >> 2;      saddr = (addr & ESP_MASK) >> 2;
     DPRINTF("read reg[%d]: 0x%2.2x\n", saddr, s->rregs[saddr]);      DPRINTF("read reg[%d]: 0x%2.2x\n", saddr, s->rregs[saddr]);
     switch (saddr) {      switch (saddr) {
     case 2:      case ESP_FIFO:
         // FIFO          if (s->ti_size > 0) {
         if (s->ti_size > 0) {              s->ti_size--;
             s->ti_size--;              if ((s->rregs[ESP_RSTAT] & STAT_PIO_MASK) == 0) {
             if ((s->rregs[4] & 6) == 0) {  
                 /* Data in/out.  */                  /* Data in/out.  */
                 fprintf(stderr, "esp: PIO data read not implemented\n");                  fprintf(stderr, "esp: PIO data read not implemented\n");
                 s->rregs[2] = 0;                  s->rregs[ESP_FIFO] = 0;
             } else {              } else {
                 s->rregs[2] = s->ti_buf[s->ti_rptr++];                  s->rregs[ESP_FIFO] = s->ti_buf[s->ti_rptr++];
             }              }
             espdma_raise_irq(s->dma_opaque);              qemu_irq_raise(s->irq);
         }          }
         if (s->ti_size == 0) {          if (s->ti_size == 0) {
             s->ti_rptr = 0;              s->ti_rptr = 0;
             s->ti_wptr = 0;              s->ti_wptr = 0;
         }          }
         break;          break;
     case 5:      case ESP_RINTR:
         // interrupt  
         // Clear interrupt/error status bits          // Clear interrupt/error status bits
         s->rregs[4] &= ~(STAT_IN | STAT_GE | STAT_PE);          s->rregs[ESP_RSTAT] &= ~(STAT_IN | STAT_GE | STAT_PE);
         espdma_clear_irq(s->dma_opaque);          qemu_irq_lower(s->irq);
         break;          break;
     default:      default:
         break;          break;
     }      }
     return s->rregs[saddr];      return s->rregs[saddr];
 }  }
Line 384  static void esp_mem_writeb(void *opaque, Line 438  static void esp_mem_writeb(void *opaque,
     ESPState *s = opaque;      ESPState *s = opaque;
     uint32_t saddr;      uint32_t saddr;
   
     saddr = (addr & ESP_MAXREG) >> 2;      saddr = (addr & ESP_MASK) >> 2;
     DPRINTF("write reg[%d]: 0x%2.2x -> 0x%2.2x\n", saddr, s->wregs[saddr], val);      DPRINTF("write reg[%d]: 0x%2.2x -> 0x%2.2x\n", saddr, s->wregs[saddr],
               val);
     switch (saddr) {      switch (saddr) {
     case 0:      case ESP_TCLO:
     case 1:      case ESP_TCMID:
         s->rregs[4] &= ~STAT_TC;          s->rregs[ESP_RSTAT] &= ~STAT_TC;
         break;          break;
     case 2:      case ESP_FIFO:
         // FIFO  
         if (s->do_cmd) {          if (s->do_cmd) {
             s->cmdbuf[s->cmdlen++] = val & 0xff;              s->cmdbuf[s->cmdlen++] = val & 0xff;
         } else if ((s->rregs[4] & 6) == 0) {          } else if ((s->rregs[ESP_RSTAT] & STAT_PIO_MASK) == 0) {
             uint8_t buf;              uint8_t buf;
             buf = val & 0xff;              buf = val & 0xff;
             s->ti_size--;              s->ti_size--;
Line 404  static void esp_mem_writeb(void *opaque, Line 458  static void esp_mem_writeb(void *opaque,
             s->ti_size++;              s->ti_size++;
             s->ti_buf[s->ti_wptr++] = val & 0xff;              s->ti_buf[s->ti_wptr++] = val & 0xff;
         }          }
         break;          break;
     case 3:      case ESP_CMD:
         s->rregs[saddr] = val;          s->rregs[saddr] = val;
         // Command          if (val & CMD_DMA) {
         if (val & 0x80) {              s->dma = 1;
             s->dma = 1;  
             /* Reload DMA counter.  */              /* Reload DMA counter.  */
             s->rregs[0] = s->wregs[0];              s->rregs[ESP_TCLO] = s->wregs[ESP_TCLO];
             s->rregs[1] = s->wregs[1];              s->rregs[ESP_TCMID] = s->wregs[ESP_TCMID];
         } else {          } else {
             s->dma = 0;              s->dma = 0;
         }          }
         switch(val & 0x7f) {          switch(val & CMD_CMD) {
         case 0:          case CMD_NOP:
             DPRINTF("NOP (%2.2x)\n", val);              DPRINTF("NOP (%2.2x)\n", val);
             break;              break;
         case 1:          case CMD_FLUSH:
             DPRINTF("Flush FIFO (%2.2x)\n", val);              DPRINTF("Flush FIFO (%2.2x)\n", val);
             //s->ti_size = 0;              //s->ti_size = 0;
             s->rregs[5] = INTR_FC;              s->rregs[ESP_RINTR] = INTR_FC;
             s->rregs[6] = 0;              s->rregs[ESP_RSEQ] = 0;
             break;              break;
         case 2:          case CMD_RESET:
             DPRINTF("Chip reset (%2.2x)\n", val);              DPRINTF("Chip reset (%2.2x)\n", val);
             esp_reset(s);              esp_reset(s);
             break;              break;
         case 3:          case CMD_BUSRESET:
             DPRINTF("Bus reset (%2.2x)\n", val);              DPRINTF("Bus reset (%2.2x)\n", val);
             s->rregs[5] = INTR_RST;              s->rregs[ESP_RINTR] = INTR_RST;
             if (!(s->wregs[8] & 0x40)) {              if (!(s->wregs[ESP_CFG1] & CFG1_RESREPT)) {
                 espdma_raise_irq(s->dma_opaque);                  qemu_irq_raise(s->irq);
             }              }
             break;              break;
         case 0x10:          case CMD_TI:
             handle_ti(s);              handle_ti(s);
             break;              break;
         case 0x11:          case CMD_ICCS:
             DPRINTF("Initiator Command Complete Sequence (%2.2x)\n", val);              DPRINTF("Initiator Command Complete Sequence (%2.2x)\n", val);
             write_response(s);              write_response(s);
             break;              break;
         case 0x12:          case CMD_MSGACC:
             DPRINTF("Message Accepted (%2.2x)\n", val);              DPRINTF("Message Accepted (%2.2x)\n", val);
             write_response(s);              write_response(s);
             s->rregs[5] = INTR_DC;              s->rregs[ESP_RINTR] = INTR_DC;
             s->rregs[6] = 0;              s->rregs[ESP_RSEQ] = 0;
             break;              break;
         case 0x1a:          case CMD_SATN:
             DPRINTF("Set ATN (%2.2x)\n", val);              DPRINTF("Set ATN (%2.2x)\n", val);
             break;              break;
         case 0x42:          case CMD_SELATN:
             DPRINTF("Set ATN (%2.2x)\n", val);              DPRINTF("Set ATN (%2.2x)\n", val);
             handle_satn(s);              handle_satn(s);
             break;              break;
         case 0x43:          case CMD_SELATNS:
             DPRINTF("Set ATN & stop (%2.2x)\n", val);              DPRINTF("Set ATN & stop (%2.2x)\n", val);
             handle_satn_stop(s);              handle_satn_stop(s);
             break;              break;
         default:          case CMD_ENSEL:
             DPRINTF("Unhandled ESP command (%2.2x)\n", val);              DPRINTF("Enable selection (%2.2x)\n", val);
             break;              break;
         }          default:
         break;              DPRINTF("Unhandled ESP command (%2.2x)\n", val);
     case 4 ... 7:              break;
         break;          }
     case 8:          break;
       case ESP_WBUSID ... ESP_WSYNO:
           break;
       case ESP_CFG1:
         s->rregs[saddr] = val;          s->rregs[saddr] = val;
         break;          break;
     case 9 ... 10:      case ESP_WCCF ... ESP_WTEST:
         break;          break;
     case 11:      case ESP_CFG2:
         s->rregs[saddr] = val & 0x15;          s->rregs[saddr] = val & CFG2_MASK;
         break;          break;
     case 12 ... 15:      case ESP_CFG3 ... ESP_RES4:
         s->rregs[saddr] = val;          s->rregs[saddr] = val;
         break;          break;
     default:      default:
         break;          break;
     }      }
     s->wregs[saddr] = val;      s->wregs[saddr] = val;
 }  }
   
 static CPUReadMemoryFunc *esp_mem_read[3] = {  static CPUReadMemoryFunc *esp_mem_read[3] = {
     esp_mem_readb,      esp_mem_readb,
     esp_mem_readb,      NULL,
     esp_mem_readb,      NULL,
 };  };
   
 static CPUWriteMemoryFunc *esp_mem_write[3] = {  static CPUWriteMemoryFunc *esp_mem_write[3] = {
     esp_mem_writeb,      esp_mem_writeb,
     esp_mem_writeb,      NULL,
     esp_mem_writeb,      NULL,
 };  };
   
 static void esp_save(QEMUFile *f, void *opaque)  static void esp_save(QEMUFile *f, void *opaque)
 {  {
     ESPState *s = opaque;      ESPState *s = opaque;
   
     qemu_put_buffer(f, s->rregs, ESP_MAXREG);      qemu_put_buffer(f, s->rregs, ESP_REGS);
     qemu_put_buffer(f, s->wregs, ESP_MAXREG);      qemu_put_buffer(f, s->wregs, ESP_REGS);
     qemu_put_be32s(f, &s->ti_size);      qemu_put_be32s(f, &s->ti_size);
     qemu_put_be32s(f, &s->ti_rptr);      qemu_put_be32s(f, &s->ti_rptr);
     qemu_put_be32s(f, &s->ti_wptr);      qemu_put_be32s(f, &s->ti_wptr);
     qemu_put_buffer(f, s->ti_buf, TI_BUFSZ);      qemu_put_buffer(f, s->ti_buf, TI_BUFSZ);
       qemu_put_be32s(f, &s->sense);
     qemu_put_be32s(f, &s->dma);      qemu_put_be32s(f, &s->dma);
       qemu_put_buffer(f, s->cmdbuf, TI_BUFSZ);
       qemu_put_be32s(f, &s->cmdlen);
       qemu_put_be32s(f, &s->do_cmd);
       qemu_put_be32s(f, &s->dma_left);
       // There should be no transfers in progress, so dma_counter is not saved
 }  }
   
 static int esp_load(QEMUFile *f, void *opaque, int version_id)  static int esp_load(QEMUFile *f, void *opaque, int version_id)
 {  {
     ESPState *s = opaque;      ESPState *s = opaque;
       
     if (version_id != 2)  
         return -EINVAL; // Cannot emulate 1  
   
     qemu_get_buffer(f, s->rregs, ESP_MAXREG);      if (version_id != 3)
     qemu_get_buffer(f, s->wregs, ESP_MAXREG);          return -EINVAL; // Cannot emulate 2
   
       qemu_get_buffer(f, s->rregs, ESP_REGS);
       qemu_get_buffer(f, s->wregs, ESP_REGS);
     qemu_get_be32s(f, &s->ti_size);      qemu_get_be32s(f, &s->ti_size);
     qemu_get_be32s(f, &s->ti_rptr);      qemu_get_be32s(f, &s->ti_rptr);
     qemu_get_be32s(f, &s->ti_wptr);      qemu_get_be32s(f, &s->ti_wptr);
     qemu_get_buffer(f, s->ti_buf, TI_BUFSZ);      qemu_get_buffer(f, s->ti_buf, TI_BUFSZ);
       qemu_get_be32s(f, &s->sense);
     qemu_get_be32s(f, &s->dma);      qemu_get_be32s(f, &s->dma);
       qemu_get_buffer(f, s->cmdbuf, TI_BUFSZ);
       qemu_get_be32s(f, &s->cmdlen);
       qemu_get_be32s(f, &s->do_cmd);
       qemu_get_be32s(f, &s->dma_left);
   
     return 0;      return 0;
 }  }
Line 544  void esp_scsi_attach(void *opaque, Block Line 611  void esp_scsi_attach(void *opaque, Block
     }      }
     if (s->scsi_dev[id]) {      if (s->scsi_dev[id]) {
         DPRINTF("Destroying device %d\n", id);          DPRINTF("Destroying device %d\n", id);
         scsi_disk_destroy(s->scsi_dev[id]);          s->scsi_dev[id]->destroy(s->scsi_dev[id]);
     }      }
     DPRINTF("Attaching block device %d\n", id);      DPRINTF("Attaching block device %d\n", id);
     /* Command queueing is not implemented.  */      /* Command queueing is not implemented.  */
     s->scsi_dev[id] = scsi_disk_init(bd, 0, esp_command_complete, s);      s->scsi_dev[id] = scsi_generic_init(bd, 0, esp_command_complete, s);
       if (s->scsi_dev[id] == NULL)
           s->scsi_dev[id] = scsi_disk_init(bd, 0, esp_command_complete, s);
 }  }
   
 void *esp_init(BlockDriverState **bd, uint32_t espaddr, void *dma_opaque)  void *esp_init(target_phys_addr_t espaddr,
                  void *dma_opaque, qemu_irq irq, qemu_irq *reset)
 {  {
     ESPState *s;      ESPState *s;
     int esp_io_memory;      int esp_io_memory;
Line 560  void *esp_init(BlockDriverState **bd, ui Line 630  void *esp_init(BlockDriverState **bd, ui
     if (!s)      if (!s)
         return NULL;          return NULL;
   
     s->bd = bd;      s->irq = irq;
     s->dma_opaque = dma_opaque;      s->dma_opaque = dma_opaque;
   
     esp_io_memory = cpu_register_io_memory(0, esp_mem_read, esp_mem_write, s);      esp_io_memory = cpu_register_io_memory(0, esp_mem_read, esp_mem_write, s);
     cpu_register_physical_memory(espaddr, ESP_MAXREG*4, esp_io_memory);      cpu_register_physical_memory(espaddr, ESP_SIZE, esp_io_memory);
   
     esp_reset(s);      esp_reset(s);
   
     register_savevm("esp", espaddr, 2, esp_save, esp_load, s);      register_savevm("esp", espaddr, 3, esp_save, esp_load, s);
     qemu_register_reset(esp_reset, s);      qemu_register_reset(esp_reset, s);
   
       *reset = *qemu_allocate_irqs(parent_esp_reset, s, 1);
   
     return s;      return s;
 }  }

Removed from v.1.1.1.5  
changed lines
  Added in v.1.1.1.6


unix.superglobalmegacorp.com