Commit 4f6200f03b32d1cb166c2b85c97e857109dd8f9d

Authored by bellard
1 parent aea3ce4c

ESP PIO mode, 2k CDROM sector size (Blue Swirl)


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1577 c046a42c-6fe2-441c-8c8c-71466251a162
Showing 1 changed file with 143 additions and 39 deletions
hw/esp.c
@@ -36,6 +36,9 @@ do { printf("ESP: " fmt , ##args); } while (0) @@ -36,6 +36,9 @@ do { printf("ESP: " fmt , ##args); } while (0)
36 #define ESPDMA_REGS 4 36 #define ESPDMA_REGS 4
37 #define ESPDMA_MAXADDR (ESPDMA_REGS * 4 - 1) 37 #define ESPDMA_MAXADDR (ESPDMA_REGS * 4 - 1)
38 #define ESP_MAXREG 0x3f 38 #define ESP_MAXREG 0x3f
  39 +#define TI_BUFSZ 65536
  40 +#define DMA_VER 0xa0000000
  41 +#define DMA_LOADED 0x04000000
39 42
40 typedef struct ESPState { 43 typedef struct ESPState {
41 BlockDriverState **bd; 44 BlockDriverState **bd;
@@ -44,8 +47,10 @@ typedef struct ESPState { @@ -44,8 +47,10 @@ typedef struct ESPState {
44 int irq; 47 int irq;
45 uint32_t espdmaregs[ESPDMA_REGS]; 48 uint32_t espdmaregs[ESPDMA_REGS];
46 uint32_t ti_size; 49 uint32_t ti_size;
  50 + uint32_t ti_rptr, ti_wptr;
47 int ti_dir; 51 int ti_dir;
48 - uint8_t ti_buf[65536]; 52 + uint8_t ti_buf[TI_BUFSZ];
  53 + int dma;
49 } ESPState; 54 } ESPState;
50 55
51 #define STAT_DO 0x00 56 #define STAT_DO 0x00
@@ -73,17 +78,25 @@ static void handle_satn(ESPState *s) @@ -73,17 +78,25 @@ static void handle_satn(ESPState *s)
73 int64_t nb_sectors; 78 int64_t nb_sectors;
74 int target; 79 int target;
75 80
76 - dmaptr = iommu_translate(s->espdmaregs[1]);  
77 dmalen = s->wregs[0] | (s->wregs[1] << 8); 81 dmalen = s->wregs[0] | (s->wregs[1] << 8);
78 - DPRINTF("Select with ATN at %8.8x len %d\n", dmaptr, dmalen);  
79 - DPRINTF("DMA Direction: %c\n", s->espdmaregs[0] & 0x100? 'w': 'r');  
80 - cpu_physical_memory_read(dmaptr, buf, dmalen); 82 + target = s->wregs[4] & 7;
  83 + DPRINTF("Select with ATN len %d target %d\n", dmalen, target);
  84 + 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 + }
81 for (i = 0; i < dmalen; i++) { 93 for (i = 0; i < dmalen; i++) {
82 DPRINTF("Command %2.2x\n", buf[i]); 94 DPRINTF("Command %2.2x\n", buf[i]);
83 } 95 }
84 s->ti_dir = 0; 96 s->ti_dir = 0;
85 s->ti_size = 0; 97 s->ti_size = 0;
86 - target = s->wregs[4] & 7; 98 + s->ti_rptr = 0;
  99 + s->ti_wptr = 0;
87 100
88 if (target > 4 || !s->bd[target]) { // No such drive 101 if (target > 4 || !s->bd[target]) { // No such drive
89 s->rregs[4] = STAT_IN; 102 s->rregs[4] = STAT_IN;
@@ -126,7 +139,10 @@ static void handle_satn(ESPState *s) @@ -126,7 +139,10 @@ static void handle_satn(ESPState *s)
126 s->ti_buf[3] = nb_sectors & 0xff; 139 s->ti_buf[3] = nb_sectors & 0xff;
127 s->ti_buf[4] = 0; 140 s->ti_buf[4] = 0;
128 s->ti_buf[5] = 0; 141 s->ti_buf[5] = 0;
129 - s->ti_buf[6] = 2; 142 + 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
130 s->ti_buf[7] = 0; 146 s->ti_buf[7] = 0;
131 s->ti_dir = 1; 147 s->ti_dir = 1;
132 s->ti_size = 8; 148 s->ti_size = 8;
@@ -135,28 +151,42 @@ static void handle_satn(ESPState *s) @@ -135,28 +151,42 @@ static void handle_satn(ESPState *s)
135 { 151 {
136 int64_t offset, len; 152 int64_t offset, len;
137 153
138 - offset = (buf[3] << 24) | (buf[4] << 16) | (buf[5] << 8) | buf[6];  
139 - len = (buf[8] << 8) | buf[9]; 154 + if (bdrv_get_type_hint(s->bd[target]) == BDRV_TYPE_CDROM) {
  155 + 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 + }
140 DPRINTF("Read (10) (offset %lld len %lld)\n", offset, len); 163 DPRINTF("Read (10) (offset %lld len %lld)\n", offset, len);
141 bdrv_read(s->bd[target], offset, s->ti_buf, len); 164 bdrv_read(s->bd[target], offset, s->ti_buf, len);
  165 + // XXX error handling
142 s->ti_dir = 1; 166 s->ti_dir = 1;
143 - s->ti_size = len * 512;  
144 break; 167 break;
145 } 168 }
146 case 0x2a: 169 case 0x2a:
147 { 170 {
148 int64_t offset, len; 171 int64_t offset, len;
149 172
150 - offset = (buf[3] << 24) | (buf[4] << 16) | (buf[5] << 8) | buf[6];  
151 - len = (buf[8] << 8) | buf[9]; 173 + if (bdrv_get_type_hint(s->bd[target]) == BDRV_TYPE_CDROM) {
  174 + 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 + }
152 DPRINTF("Write (10) (offset %lld len %lld)\n", offset, len); 182 DPRINTF("Write (10) (offset %lld len %lld)\n", offset, len);
153 bdrv_write(s->bd[target], offset, s->ti_buf, len); 183 bdrv_write(s->bd[target], offset, s->ti_buf, len);
  184 + // XXX error handling
154 s->ti_dir = 0; 185 s->ti_dir = 0;
155 - s->ti_size = len * 512;  
156 break; 186 break;
157 } 187 }
158 default: 188 default:
159 - DPRINTF("Unknown command (%2.2x)\n", buf[1]); 189 + DPRINTF("Unknown SCSI command (%2.2x)\n", buf[1]);
160 break; 190 break;
161 } 191 }
162 s->rregs[4] = STAT_IN | STAT_TC | STAT_DI; 192 s->rregs[4] = STAT_IN | STAT_TC | STAT_DI;
@@ -170,17 +200,26 @@ static void dma_write(ESPState *s, const uint8_t *buf, uint32_t len) @@ -170,17 +200,26 @@ static void dma_write(ESPState *s, const uint8_t *buf, uint32_t len)
170 { 200 {
171 uint32_t dmaptr, dmalen; 201 uint32_t dmaptr, dmalen;
172 202
173 - dmaptr = iommu_translate(s->espdmaregs[1]);  
174 dmalen = s->wregs[0] | (s->wregs[1] << 8); 203 dmalen = s->wregs[0] | (s->wregs[1] << 8);
175 - DPRINTF("DMA Direction: %c\n", s->espdmaregs[0] & 0x100? 'w': 'r');  
176 - cpu_physical_memory_write(dmaptr, buf, len);  
177 - s->rregs[4] = STAT_IN | STAT_TC | STAT_ST;  
178 - s->rregs[5] = INTR_BS | INTR_FC;  
179 - s->rregs[6] = SEQ_CD;  
180 - s->espdmaregs[0] |= 1; 204 + DPRINTF("Transfer status len %d\n", dmalen);
  205 + if (s->dma) {
  206 + dmaptr = iommu_translate(s->espdmaregs[1]);
  207 + DPRINTF("DMA Direction: %c\n", s->espdmaregs[0] & 0x100? 'w': 'r');
  208 + cpu_physical_memory_write(dmaptr, buf, len);
  209 + 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 + }
181 pic_set_irq(s->irq, 1); 219 pic_set_irq(s->irq, 1);
182 220
183 } 221 }
  222 +
184 static const uint8_t okbuf[] = {0, 0}; 223 static const uint8_t okbuf[] = {0, 0};
185 224
186 static void handle_ti(ESPState *s) 225 static void handle_ti(ESPState *s)
@@ -188,21 +227,27 @@ static void handle_ti(ESPState *s) @@ -188,21 +227,27 @@ static void handle_ti(ESPState *s)
188 uint32_t dmaptr, dmalen; 227 uint32_t dmaptr, dmalen;
189 unsigned int i; 228 unsigned int i;
190 229
191 - dmaptr = iommu_translate(s->espdmaregs[1]);  
192 dmalen = s->wregs[0] | (s->wregs[1] << 8); 230 dmalen = s->wregs[0] | (s->wregs[1] << 8);
193 - DPRINTF("Transfer Information at %8.8x len %d\n", dmaptr, dmalen);  
194 - DPRINTF("DMA Direction: %c\n", s->espdmaregs[0] & 0x100? 'w': 'r');  
195 - for (i = 0; i < s->ti_size; i++) {  
196 - dmaptr = iommu_translate(s->espdmaregs[1] + i);  
197 - if (s->ti_dir)  
198 - cpu_physical_memory_write(dmaptr, &s->ti_buf[i], 1);  
199 - else  
200 - cpu_physical_memory_read(dmaptr, &s->ti_buf[i], 1);  
201 - }  
202 - s->rregs[4] = STAT_IN | STAT_TC | STAT_ST;  
203 - s->rregs[5] = INTR_BS;  
204 - s->rregs[6] = 0;  
205 - s->espdmaregs[0] |= 1; 231 + DPRINTF("Transfer Information len %d\n", dmalen);
  232 + if (s->dma) {
  233 + dmaptr = iommu_translate(s->espdmaregs[1]);
  234 + DPRINTF("DMA Direction: %c, addr 0x%8.8x\n", s->espdmaregs[0] & 0x100? 'w': 'r', dmaptr);
  235 + for (i = 0; i < s->ti_size; i++) {
  236 + dmaptr = iommu_translate(s->espdmaregs[1] + i);
  237 + if (s->ti_dir)
  238 + cpu_physical_memory_write(dmaptr, &s->ti_buf[i], 1);
  239 + else
  240 + cpu_physical_memory_read(dmaptr, &s->ti_buf[i], 1);
  241 + }
  242 + s->rregs[4] = STAT_IN | STAT_TC | STAT_ST;
  243 + 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 + }
206 pic_set_irq(s->irq, 1); 251 pic_set_irq(s->irq, 1);
207 } 252 }
208 253
@@ -221,10 +266,23 @@ static uint32_t esp_mem_readb(void *opaque, target_phys_addr_t addr) @@ -221,10 +266,23 @@ static uint32_t esp_mem_readb(void *opaque, target_phys_addr_t addr)
221 266
222 saddr = (addr & ESP_MAXREG) >> 2; 267 saddr = (addr & ESP_MAXREG) >> 2;
223 switch (saddr) { 268 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;
224 default: 281 default:
225 break; 282 break;
226 } 283 }
227 DPRINTF("read reg[%d]: 0x%2.2x\n", saddr, s->rregs[saddr]); 284 DPRINTF("read reg[%d]: 0x%2.2x\n", saddr, s->rregs[saddr]);
  285 +
228 return s->rregs[saddr]; 286 return s->rregs[saddr];
229 } 287 }
230 288
@@ -236,8 +294,23 @@ static void esp_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val) @@ -236,8 +294,23 @@ static void esp_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
236 saddr = (addr & ESP_MAXREG) >> 2; 294 saddr = (addr & ESP_MAXREG) >> 2;
237 DPRINTF("write reg[%d]: 0x%2.2x -> 0x%2.2x\n", saddr, s->wregs[saddr], val); 295 DPRINTF("write reg[%d]: 0x%2.2x -> 0x%2.2x\n", saddr, s->wregs[saddr], val);
238 switch (saddr) { 296 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;
239 case 3: 306 case 3:
  307 + s->rregs[saddr] = val;
240 // Command 308 // Command
  309 + if (val & 0x80) {
  310 + s->dma = 1;
  311 + } else {
  312 + s->dma = 0;
  313 + }
241 switch(val & 0x7f) { 314 switch(val & 0x7f) {
242 case 0: 315 case 0:
243 DPRINTF("NOP (%2.2x)\n", val); 316 DPRINTF("NOP (%2.2x)\n", val);
@@ -278,13 +351,20 @@ static void esp_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val) @@ -278,13 +351,20 @@ static void esp_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
278 handle_satn(s); 351 handle_satn(s);
279 break; 352 break;
280 default: 353 default:
281 - DPRINTF("Unhandled command (%2.2x)\n", val); 354 + DPRINTF("Unhandled ESP command (%2.2x)\n", val);
282 break; 355 break;
283 } 356 }
284 break; 357 break;
285 case 4 ... 7: 358 case 4 ... 7:
286 - case 9 ... 0xf:  
287 break; 359 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;
288 default: 368 default:
289 break; 369 break;
290 } 370 }
@@ -309,7 +389,8 @@ static uint32_t espdma_mem_readl(void *opaque, target_phys_addr_t addr) @@ -309,7 +389,8 @@ static uint32_t espdma_mem_readl(void *opaque, target_phys_addr_t addr)
309 uint32_t saddr; 389 uint32_t saddr;
310 390
311 saddr = (addr & ESPDMA_MAXADDR) >> 2; 391 saddr = (addr & ESPDMA_MAXADDR) >> 2;
312 - DPRINTF("read dmareg[%d]: 0x%2.2x\n", saddr, s->espdmaregs[saddr]); 392 + DPRINTF("read dmareg[%d]: 0x%8.8x\n", saddr, s->espdmaregs[saddr]);
  393 +
313 return s->espdmaregs[saddr]; 394 return s->espdmaregs[saddr];
314 } 395 }
315 396
@@ -319,12 +400,23 @@ static void espdma_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t va @@ -319,12 +400,23 @@ static void espdma_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t va
319 uint32_t saddr; 400 uint32_t saddr;
320 401
321 saddr = (addr & ESPDMA_MAXADDR) >> 2; 402 saddr = (addr & ESPDMA_MAXADDR) >> 2;
322 - DPRINTF("write dmareg[%d]: 0x%2.2x -> 0x%2.2x\n", saddr, s->espdmaregs[saddr], val); 403 + DPRINTF("write dmareg[%d]: 0x%8.8x -> 0x%8.8x\n", saddr, s->espdmaregs[saddr], val);
323 switch (saddr) { 404 switch (saddr) {
324 case 0: 405 case 0:
325 if (!(val & 0x10)) 406 if (!(val & 0x10))
326 pic_set_irq(s->irq, 0); 407 pic_set_irq(s->irq, 0);
  408 + 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;
327 break; 416 break;
  417 + case 1:
  418 + s->espdmaregs[0] = DMA_LOADED;
  419 + break;
328 default: 420 default:
329 break; 421 break;
330 } 422 }
@@ -353,6 +445,12 @@ static void esp_save(QEMUFile *f, void *opaque) @@ -353,6 +445,12 @@ static void esp_save(QEMUFile *f, void *opaque)
353 qemu_put_be32s(f, &s->irq); 445 qemu_put_be32s(f, &s->irq);
354 for (i = 0; i < ESPDMA_REGS; i++) 446 for (i = 0; i < ESPDMA_REGS; i++)
355 qemu_put_be32s(f, &s->espdmaregs[i]); 447 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);
356 } 454 }
357 455
358 static int esp_load(QEMUFile *f, void *opaque, int version_id) 456 static int esp_load(QEMUFile *f, void *opaque, int version_id)
@@ -368,6 +466,12 @@ static int esp_load(QEMUFile *f, void *opaque, int version_id) @@ -368,6 +466,12 @@ static int esp_load(QEMUFile *f, void *opaque, int version_id)
368 qemu_get_be32s(f, &s->irq); 466 qemu_get_be32s(f, &s->irq);
369 for (i = 0; i < ESPDMA_REGS; i++) 467 for (i = 0; i < ESPDMA_REGS; i++)
370 qemu_get_be32s(f, &s->espdmaregs[i]); 468 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);
371 475
372 return 0; 476 return 0;
373 } 477 }