/[qemu]/qemu/hw/esp.c
ViewVC logotype

Diff of /qemu/hw/esp.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.2 by bellard, Wed Apr 6 20:31:50 2005 UTC revision 1.3 by bellard, Sun Oct 30 17:24:05 2005 UTC
# Line 36  do { printf("ESP: " fmt , ##args); } whi Line 36  do { printf("ESP: " fmt , ##args); } whi
36  #define ESPDMA_REGS 4  #define ESPDMA_REGS 4
37  #define ESPDMA_MAXADDR (ESPDMA_REGS * 4 - 1)  #define ESPDMA_MAXADDR (ESPDMA_REGS * 4 - 1)
38  #define ESP_MAXREG 0x3f  #define ESP_MAXREG 0x3f
39    #define TI_BUFSZ 65536
40    #define DMA_VER 0xa0000000
41    #define DMA_LOADED 0x04000000
42    
43  typedef struct ESPState {  typedef struct ESPState {
44      BlockDriverState **bd;      BlockDriverState **bd;
# Line 44  typedef struct ESPState { Line 47  typedef struct ESPState {
47      int irq;      int irq;
48      uint32_t espdmaregs[ESPDMA_REGS];      uint32_t espdmaregs[ESPDMA_REGS];
49      uint32_t ti_size;      uint32_t ti_size;
50        uint32_t ti_rptr, ti_wptr;
51      int ti_dir;      int ti_dir;
52      uint8_t ti_buf[65536];      uint8_t ti_buf[TI_BUFSZ];
53        int dma;
54  } ESPState;  } ESPState;
55    
56  #define STAT_DO 0x00  #define STAT_DO 0x00
# Line 73  static void handle_satn(ESPState *s) Line 78  static void handle_satn(ESPState *s)
78      int64_t nb_sectors;      int64_t nb_sectors;
79      int target;      int target;
80    
     dmaptr = iommu_translate(s->espdmaregs[1]);  
81      dmalen = s->wregs[0] | (s->wregs[1] << 8);      dmalen = s->wregs[0] | (s->wregs[1] << 8);
82      DPRINTF("Select with ATN at %8.8x len %d\n", dmaptr, dmalen);      target = s->wregs[4] & 7;
83      DPRINTF("DMA Direction: %c\n", s->espdmaregs[0] & 0x100? 'w': 'r');      DPRINTF("Select with ATN len %d target %d\n", dmalen, target);
84      cpu_physical_memory_read(dmaptr, buf, dmalen);      if (s->dma) {
85            dmaptr = iommu_translate(s->espdmaregs[1]);
86            DPRINTF("DMA Direction: %c, addr 0x%8.8x\n", s->espdmaregs[0] & 0x100? 'w': 'r', dmaptr);
87            cpu_physical_memory_read(dmaptr, buf, dmalen);
88        } else {
89            buf[0] = 0;
90            memcpy(&buf[1], s->ti_buf, dmalen);
91            dmalen++;
92        }
93      for (i = 0; i < dmalen; i++) {      for (i = 0; i < dmalen; i++) {
94          DPRINTF("Command %2.2x\n", buf[i]);          DPRINTF("Command %2.2x\n", buf[i]);
95      }      }
96      s->ti_dir = 0;      s->ti_dir = 0;
97      s->ti_size = 0;      s->ti_size = 0;
98      target = s->wregs[4] & 7;      s->ti_rptr = 0;
99        s->ti_wptr = 0;
100    
101      if (target > 4 || !s->bd[target]) { // No such drive      if (target > 4 || !s->bd[target]) { // No such drive
102          s->rregs[4] = STAT_IN;          s->rregs[4] = STAT_IN;
# Line 126  static void handle_satn(ESPState *s) Line 139  static void handle_satn(ESPState *s)
139          s->ti_buf[3] = nb_sectors & 0xff;          s->ti_buf[3] = nb_sectors & 0xff;
140          s->ti_buf[4] = 0;          s->ti_buf[4] = 0;
141          s->ti_buf[5] = 0;          s->ti_buf[5] = 0;
142          s->ti_buf[6] = 2;          if (bdrv_get_type_hint(s->bd[target]) == BDRV_TYPE_CDROM)
143                s->ti_buf[6] = 8; // sector size 2048
144            else
145                s->ti_buf[6] = 2; // sector size 512
146          s->ti_buf[7] = 0;          s->ti_buf[7] = 0;
147          s->ti_dir = 1;          s->ti_dir = 1;
148          s->ti_size = 8;          s->ti_size = 8;
# Line 135  static void handle_satn(ESPState *s) Line 151  static void handle_satn(ESPState *s)
151          {          {
152              int64_t offset, len;              int64_t offset, len;
153    
154              offset = (buf[3] << 24) | (buf[4] << 16) | (buf[5] << 8) | buf[6];              if (bdrv_get_type_hint(s->bd[target]) == BDRV_TYPE_CDROM) {
155              len = (buf[8] << 8) | buf[9];                  offset = ((buf[3] << 24) | (buf[4] << 16) | (buf[5] << 8) | buf[6]) * 4;
156                    len = ((buf[8] << 8) | buf[9]) * 4;
157                    s->ti_size = len * 2048;
158                } else {
159                    offset = (buf[3] << 24) | (buf[4] << 16) | (buf[5] << 8) | buf[6];
160                    len = (buf[8] << 8) | buf[9];
161                    s->ti_size = len * 512;
162                }
163              DPRINTF("Read (10) (offset %lld len %lld)\n", offset, len);              DPRINTF("Read (10) (offset %lld len %lld)\n", offset, len);
164              bdrv_read(s->bd[target], offset, s->ti_buf, len);              bdrv_read(s->bd[target], offset, s->ti_buf, len);
165                // XXX error handling
166              s->ti_dir = 1;              s->ti_dir = 1;
             s->ti_size = len * 512;  
167              break;              break;
168          }          }
169      case 0x2a:      case 0x2a:
170          {          {
171              int64_t offset, len;              int64_t offset, len;
172    
173              offset = (buf[3] << 24) | (buf[4] << 16) | (buf[5] << 8) | buf[6];              if (bdrv_get_type_hint(s->bd[target]) == BDRV_TYPE_CDROM) {
174              len = (buf[8] << 8) | buf[9];                  offset = ((buf[3] << 24) | (buf[4] << 16) | (buf[5] << 8) | buf[6]) * 4;
175                    len = ((buf[8] << 8) | buf[9]) * 4;
176                    s->ti_size = len * 2048;
177                } else {
178                    offset = (buf[3] << 24) | (buf[4] << 16) | (buf[5] << 8) | buf[6];
179                    len = (buf[8] << 8) | buf[9];
180                    s->ti_size = len * 512;
181                }
182              DPRINTF("Write (10) (offset %lld len %lld)\n", offset, len);              DPRINTF("Write (10) (offset %lld len %lld)\n", offset, len);
183              bdrv_write(s->bd[target], offset, s->ti_buf, len);              bdrv_write(s->bd[target], offset, s->ti_buf, len);
184                // XXX error handling
185              s->ti_dir = 0;              s->ti_dir = 0;
             s->ti_size = len * 512;  
186              break;              break;
187          }          }
188      default:      default:
189          DPRINTF("Unknown command (%2.2x)\n", buf[1]);          DPRINTF("Unknown SCSI command (%2.2x)\n", buf[1]);
190          break;          break;
191      }      }
192      s->rregs[4] = STAT_IN | STAT_TC | STAT_DI;      s->rregs[4] = STAT_IN | STAT_TC | STAT_DI;
# Line 170  static void dma_write(ESPState *s, const Line 200  static void dma_write(ESPState *s, const
200  {  {
201      uint32_t dmaptr, dmalen;      uint32_t dmaptr, dmalen;
202    
     dmaptr = iommu_translate(s->espdmaregs[1]);  
203      dmalen = s->wregs[0] | (s->wregs[1] << 8);      dmalen = s->wregs[0] | (s->wregs[1] << 8);
204      DPRINTF("DMA Direction: %c\n", s->espdmaregs[0] & 0x100? 'w': 'r');      DPRINTF("Transfer status len %d\n", dmalen);
205      cpu_physical_memory_write(dmaptr, buf, len);      if (s->dma) {
206      s->rregs[4] = STAT_IN | STAT_TC | STAT_ST;          dmaptr = iommu_translate(s->espdmaregs[1]);
207      s->rregs[5] = INTR_BS | INTR_FC;          DPRINTF("DMA Direction: %c\n", s->espdmaregs[0] & 0x100? 'w': 'r');
208      s->rregs[6] = SEQ_CD;          cpu_physical_memory_write(dmaptr, buf, len);
209      s->espdmaregs[0] |= 1;          s->rregs[4] = STAT_IN | STAT_TC | STAT_ST;
210            s->rregs[5] = INTR_BS | INTR_FC;
211            s->rregs[6] = SEQ_CD;
212            s->espdmaregs[0] |= 1;
213        } else {
214            memcpy(s->ti_buf, buf, len);
215            s->ti_size = dmalen;
216            s->ti_rptr = 0;
217            s->ti_wptr = 0;
218        }
219      pic_set_irq(s->irq, 1);      pic_set_irq(s->irq, 1);
220    
221  }  }
222    
223  static const uint8_t okbuf[] = {0, 0};  static const uint8_t okbuf[] = {0, 0};
224    
225  static void handle_ti(ESPState *s)  static void handle_ti(ESPState *s)
# Line 188  static void handle_ti(ESPState *s) Line 227  static void handle_ti(ESPState *s)
227      uint32_t dmaptr, dmalen;      uint32_t dmaptr, dmalen;
228      unsigned int i;      unsigned int i;
229    
     dmaptr = iommu_translate(s->espdmaregs[1]);  
230      dmalen = s->wregs[0] | (s->wregs[1] << 8);      dmalen = s->wregs[0] | (s->wregs[1] << 8);
231      DPRINTF("Transfer Information at %8.8x len %d\n", dmaptr, dmalen);      DPRINTF("Transfer Information len %d\n", dmalen);
232      DPRINTF("DMA Direction: %c\n", s->espdmaregs[0] & 0x100? 'w': 'r');      if (s->dma) {
233      for (i = 0; i < s->ti_size; i++) {          dmaptr = iommu_translate(s->espdmaregs[1]);
234          dmaptr = iommu_translate(s->espdmaregs[1] + i);          DPRINTF("DMA Direction: %c, addr 0x%8.8x\n", s->espdmaregs[0] & 0x100? 'w': 'r', dmaptr);
235          if (s->ti_dir)          for (i = 0; i < s->ti_size; i++) {
236              cpu_physical_memory_write(dmaptr, &s->ti_buf[i], 1);              dmaptr = iommu_translate(s->espdmaregs[1] + i);
237          else              if (s->ti_dir)
238              cpu_physical_memory_read(dmaptr, &s->ti_buf[i], 1);                  cpu_physical_memory_write(dmaptr, &s->ti_buf[i], 1);
239      }              else
240      s->rregs[4] = STAT_IN | STAT_TC | STAT_ST;                  cpu_physical_memory_read(dmaptr, &s->ti_buf[i], 1);
241      s->rregs[5] = INTR_BS;          }
242      s->rregs[6] = 0;          s->rregs[4] = STAT_IN | STAT_TC | STAT_ST;
243      s->espdmaregs[0] |= 1;          s->rregs[5] = INTR_BS;
244            s->rregs[6] = 0;
245            s->espdmaregs[0] |= 1;
246        } else {
247            s->ti_size = dmalen;
248            s->ti_rptr = 0;
249            s->ti_wptr = 0;
250        }  
251      pic_set_irq(s->irq, 1);      pic_set_irq(s->irq, 1);
252  }  }
253    
# Line 221  static uint32_t esp_mem_readb(void *opaq Line 266  static uint32_t esp_mem_readb(void *opaq
266    
267      saddr = (addr & ESP_MAXREG) >> 2;      saddr = (addr & ESP_MAXREG) >> 2;
268      switch (saddr) {      switch (saddr) {
269        case 2:
270            // FIFO
271            if (s->ti_size > 0) {
272                s->ti_size--;
273                s->rregs[saddr] = s->ti_buf[s->ti_rptr++];
274                pic_set_irq(s->irq, 1);
275            }
276            if (s->ti_size == 0) {
277                s->ti_rptr = 0;
278                s->ti_wptr = 0;
279            }
280            break;
281      default:      default:
282          break;          break;
283      }      }
284      DPRINTF("read reg[%d]: 0x%2.2x\n", saddr, s->rregs[saddr]);      DPRINTF("read reg[%d]: 0x%2.2x\n", saddr, s->rregs[saddr]);
285    
286      return s->rregs[saddr];      return s->rregs[saddr];
287  }  }
288    
# Line 236  static void esp_mem_writeb(void *opaque, Line 294  static void esp_mem_writeb(void *opaque,
294      saddr = (addr & ESP_MAXREG) >> 2;      saddr = (addr & ESP_MAXREG) >> 2;
295      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);
296      switch (saddr) {      switch (saddr) {
297        case 0:
298        case 1:
299            s->rregs[saddr] = val;
300            break;
301        case 2:
302            // FIFO
303            s->ti_size++;
304            s->ti_buf[s->ti_wptr++] = val & 0xff;
305            break;
306      case 3:      case 3:
307            s->rregs[saddr] = val;
308          // Command          // Command
309            if (val & 0x80) {
310                s->dma = 1;
311            } else {
312                s->dma = 0;
313            }
314          switch(val & 0x7f) {          switch(val & 0x7f) {
315          case 0:          case 0:
316              DPRINTF("NOP (%2.2x)\n", val);              DPRINTF("NOP (%2.2x)\n", val);
# Line 278  static void esp_mem_writeb(void *opaque, Line 351  static void esp_mem_writeb(void *opaque,
351              handle_satn(s);              handle_satn(s);
352              break;              break;
353          default:          default:
354              DPRINTF("Unhandled command (%2.2x)\n", val);              DPRINTF("Unhandled ESP command (%2.2x)\n", val);
355              break;              break;
356          }          }
357          break;          break;
358      case 4 ... 7:      case 4 ... 7:
     case 9 ... 0xf:  
359          break;          break;
360        case 8:
361            s->rregs[saddr] = val;
362            break;
363        case 9 ... 10:
364            break;
365        case 11 ... 15:
366            s->rregs[saddr] = val;
367            break;
368      default:      default:
369          break;          break;
370      }      }
# Line 309  static uint32_t espdma_mem_readl(void *o Line 389  static uint32_t espdma_mem_readl(void *o
389      uint32_t saddr;      uint32_t saddr;
390    
391      saddr = (addr & ESPDMA_MAXADDR) >> 2;      saddr = (addr & ESPDMA_MAXADDR) >> 2;
392      DPRINTF("read dmareg[%d]: 0x%2.2x\n", saddr, s->espdmaregs[saddr]);      DPRINTF("read dmareg[%d]: 0x%8.8x\n", saddr, s->espdmaregs[saddr]);
393    
394      return s->espdmaregs[saddr];      return s->espdmaregs[saddr];
395  }  }
396    
# Line 319  static void espdma_mem_writel(void *opaq Line 400  static void espdma_mem_writel(void *opaq
400      uint32_t saddr;      uint32_t saddr;
401    
402      saddr = (addr & ESPDMA_MAXADDR) >> 2;      saddr = (addr & ESPDMA_MAXADDR) >> 2;
403      DPRINTF("write dmareg[%d]: 0x%2.2x -> 0x%2.2x\n", saddr, s->espdmaregs[saddr], val);      DPRINTF("write dmareg[%d]: 0x%8.8x -> 0x%8.8x\n", saddr, s->espdmaregs[saddr], val);
404      switch (saddr) {      switch (saddr) {
405      case 0:      case 0:
406          if (!(val & 0x10))          if (!(val & 0x10))
407              pic_set_irq(s->irq, 0);              pic_set_irq(s->irq, 0);
408          break;          if (val & 0x80) {
409                esp_reset(s);
410            } else if (val & 0x40) {
411                val &= ~0x40;
412            } else if (val == 0)
413                val = 0x40;
414            val &= 0x0fffffff;
415            val |= DMA_VER;
416            break;
417        case 1:
418            s->espdmaregs[0] = DMA_LOADED;
419            break;
420      default:      default:
421          break;          break;
422      }      }
# Line 353  static void esp_save(QEMUFile *f, void * Line 445  static void esp_save(QEMUFile *f, void *
445      qemu_put_be32s(f, &s->irq);      qemu_put_be32s(f, &s->irq);
446      for (i = 0; i < ESPDMA_REGS; i++)      for (i = 0; i < ESPDMA_REGS; i++)
447          qemu_put_be32s(f, &s->espdmaregs[i]);          qemu_put_be32s(f, &s->espdmaregs[i]);
448        qemu_put_be32s(f, &s->ti_size);
449        qemu_put_be32s(f, &s->ti_rptr);
450        qemu_put_be32s(f, &s->ti_wptr);
451        qemu_put_be32s(f, &s->ti_dir);
452        qemu_put_buffer(f, s->ti_buf, TI_BUFSZ);
453        qemu_put_be32s(f, &s->dma);
454  }  }
455    
456  static int esp_load(QEMUFile *f, void *opaque, int version_id)  static int esp_load(QEMUFile *f, void *opaque, int version_id)
# Line 368  static int esp_load(QEMUFile *f, void *o Line 466  static int esp_load(QEMUFile *f, void *o
466      qemu_get_be32s(f, &s->irq);      qemu_get_be32s(f, &s->irq);
467      for (i = 0; i < ESPDMA_REGS; i++)      for (i = 0; i < ESPDMA_REGS; i++)
468          qemu_get_be32s(f, &s->espdmaregs[i]);          qemu_get_be32s(f, &s->espdmaregs[i]);
469        qemu_get_be32s(f, &s->ti_size);
470        qemu_get_be32s(f, &s->ti_rptr);
471        qemu_get_be32s(f, &s->ti_wptr);
472        qemu_get_be32s(f, &s->ti_dir);
473        qemu_get_buffer(f, s->ti_buf, TI_BUFSZ);
474        qemu_get_be32s(f, &s->dma);
475    
476      return 0;      return 0;
477  }  }

Legend:
Removed from v.1.2  
changed lines
  Added in v.1.3

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26