Commit 9f149aa9c1a04117d03de16bb0f8d2dad8c4f8c1

Authored by pbrook
1 parent 7d8406be

SATN fixes (Blue Swirl).


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1947 c046a42c-6fe2-441c-8c8c-71466251a162
Showing 1 changed file with 75 additions and 18 deletions
hw/esp.c
@@ -59,6 +59,9 @@ struct ESPState { @@ -59,6 +59,9 @@ struct ESPState {
59 int dma; 59 int dma;
60 SCSIDevice *scsi_dev[MAX_DISKS]; 60 SCSIDevice *scsi_dev[MAX_DISKS];
61 SCSIDevice *current_dev; 61 SCSIDevice *current_dev;
  62 + uint8_t cmdbuf[TI_BUFSZ];
  63 + int cmdlen;
  64 + int do_cmd;
62 }; 65 };
63 66
64 #define STAT_DO 0x00 67 #define STAT_DO 0x00
@@ -79,17 +82,14 @@ struct ESPState { @@ -79,17 +82,14 @@ struct ESPState {
79 #define SEQ_0 0x0 82 #define SEQ_0 0x0
80 #define SEQ_CD 0x4 83 #define SEQ_CD 0x4
81 84
82 -static void handle_satn(ESPState *s) 85 +static int get_cmd(ESPState *s, uint8_t *buf)
83 { 86 {
84 - uint8_t buf[32];  
85 uint32_t dmaptr, dmalen; 87 uint32_t dmaptr, dmalen;
86 int target; 88 int target;
87 - int32_t datalen;  
88 - int lun;  
89 89
90 dmalen = s->wregs[0] | (s->wregs[1] << 8); 90 dmalen = s->wregs[0] | (s->wregs[1] << 8);
91 target = s->wregs[4] & 7; 91 target = s->wregs[4] & 7;
92 - DPRINTF("Select with ATN len %d target %d\n", dmalen, target); 92 + DPRINTF("get_cmd: len %d target %d\n", dmalen, target);
93 if (s->dma) { 93 if (s->dma) {
94 dmaptr = iommu_translate(s->espdmaregs[1]); 94 dmaptr = iommu_translate(s->espdmaregs[1]);
95 DPRINTF("DMA Direction: %c, addr 0x%8.8x\n", 95 DPRINTF("DMA Direction: %c, addr 0x%8.8x\n",
@@ -100,8 +100,6 @@ static void handle_satn(ESPState *s) @@ -100,8 +100,6 @@ static void handle_satn(ESPState *s)
100 memcpy(&buf[1], s->ti_buf, dmalen); 100 memcpy(&buf[1], s->ti_buf, dmalen);
101 dmalen++; 101 dmalen++;
102 } 102 }
103 - DPRINTF("busid 0x%x\n", buf[0]);  
104 - lun = buf[0] & 7;  
105 103
106 s->ti_size = 0; 104 s->ti_size = 0;
107 s->ti_rptr = 0; 105 s->ti_rptr = 0;
@@ -114,9 +112,19 @@ static void handle_satn(ESPState *s) @@ -114,9 +112,19 @@ static void handle_satn(ESPState *s)
114 s->rregs[6] = SEQ_0; 112 s->rregs[6] = SEQ_0;
115 s->espdmaregs[0] |= DMA_INTR; 113 s->espdmaregs[0] |= DMA_INTR;
116 pic_set_irq(s->irq, 1); 114 pic_set_irq(s->irq, 1);
117 - return; 115 + return 0;
118 } 116 }
119 s->current_dev = s->scsi_dev[target]; 117 s->current_dev = s->scsi_dev[target];
  118 + return dmalen;
  119 +}
  120 +
  121 +static void do_cmd(ESPState *s, uint8_t *buf)
  122 +{
  123 + int32_t datalen;
  124 + int lun;
  125 +
  126 + DPRINTF("do_cmd: busid 0x%x\n", buf[0]);
  127 + lun = buf[0] & 7;
120 datalen = scsi_send_command(s->current_dev, 0, &buf[1], lun); 128 datalen = scsi_send_command(s->current_dev, 0, &buf[1], lun);
121 if (datalen == 0) { 129 if (datalen == 0) {
122 s->ti_size = 0; 130 s->ti_size = 0;
@@ -136,6 +144,31 @@ static void handle_satn(ESPState *s) @@ -136,6 +144,31 @@ static void handle_satn(ESPState *s)
136 pic_set_irq(s->irq, 1); 144 pic_set_irq(s->irq, 1);
137 } 145 }
138 146
  147 +static void handle_satn(ESPState *s)
  148 +{
  149 + uint8_t buf[32];
  150 + int len;
  151 +
  152 + len = get_cmd(s, buf);
  153 + if (len)
  154 + do_cmd(s, buf);
  155 +}
  156 +
  157 +static void handle_satn_stop(ESPState *s)
  158 +{
  159 + s->cmdlen = get_cmd(s, s->cmdbuf);
  160 + if (s->cmdlen) {
  161 + DPRINTF("Set ATN & Stop: cmdlen %d\n", s->cmdlen);
  162 + s->do_cmd = 1;
  163 + s->espdmaregs[1] += s->cmdlen;
  164 + s->rregs[4] = STAT_IN | STAT_TC | STAT_CD;
  165 + s->rregs[5] = INTR_BS | INTR_FC;
  166 + s->rregs[6] = SEQ_CD;
  167 + s->espdmaregs[0] |= DMA_INTR;
  168 + pic_set_irq(s->irq, 1);
  169 + }
  170 +}
  171 +
139 static void write_response(ESPState *s) 172 static void write_response(ESPState *s)
140 { 173 {
141 uint32_t dmaptr; 174 uint32_t dmaptr;
@@ -188,7 +221,10 @@ static void handle_ti(ESPState *s) @@ -188,7 +221,10 @@ static void handle_ti(ESPState *s)
188 dmalen=0x10000; 221 dmalen=0x10000;
189 } 222 }
190 223
191 - minlen = (dmalen < s->ti_size) ? dmalen : s->ti_size; 224 + if (s->do_cmd)
  225 + minlen = (dmalen < 32) ? dmalen : 32;
  226 + else
  227 + minlen = (dmalen < s->ti_size) ? dmalen : s->ti_size;
192 DPRINTF("Transfer Information len %d\n", minlen); 228 DPRINTF("Transfer Information len %d\n", minlen);
193 if (s->dma) { 229 if (s->dma) {
194 dmaptr = iommu_translate(s->espdmaregs[1]); 230 dmaptr = iommu_translate(s->espdmaregs[1]);
@@ -207,14 +243,24 @@ static void handle_ti(ESPState *s) @@ -207,14 +243,24 @@ static void handle_ti(ESPState *s)
207 } 243 }
208 DPRINTF("DMA address p %08x v %08x len %08x, from %08x, to %08x\n", dmaptr, s->espdmaregs[1] + i, len, from, to); 244 DPRINTF("DMA address p %08x v %08x len %08x, from %08x, to %08x\n", dmaptr, s->espdmaregs[1] + i, len, from, to);
209 s->ti_size -= len; 245 s->ti_size -= len;
210 - if (to_device) {  
211 - cpu_physical_memory_read(dmaptr, buf, len);  
212 - scsi_write_data(s->current_dev, buf, len); 246 + if (s->do_cmd) {
  247 + DPRINTF("command len %d + %d\n", s->cmdlen, len);
  248 + cpu_physical_memory_read(dmaptr, &s->cmdbuf[s->cmdlen], len);
  249 + s->ti_size = 0;
  250 + s->cmdlen = 0;
  251 + s->do_cmd = 0;
  252 + do_cmd(s, s->cmdbuf);
  253 + return;
213 } else { 254 } else {
214 - scsi_read_data(s->current_dev, buf, len);  
215 - cpu_physical_memory_write(dmaptr, buf, len); 255 + if (to_device) {
  256 + cpu_physical_memory_read(dmaptr, buf, len);
  257 + scsi_write_data(s->current_dev, buf, len);
  258 + } else {
  259 + scsi_read_data(s->current_dev, buf, len);
  260 + cpu_physical_memory_write(dmaptr, buf, len);
  261 + }
216 } 262 }
217 - } 263 + }
218 if (s->ti_size) { 264 if (s->ti_size) {
219 s->rregs[4] = STAT_IN | STAT_TC | (to_device ? STAT_DO : STAT_DI); 265 s->rregs[4] = STAT_IN | STAT_TC | (to_device ? STAT_DO : STAT_DI);
220 } 266 }
@@ -222,7 +268,14 @@ static void handle_ti(ESPState *s) @@ -222,7 +268,14 @@ static void handle_ti(ESPState *s)
222 s->rregs[6] = 0; 268 s->rregs[6] = 0;
223 s->rregs[7] = 0; 269 s->rregs[7] = 0;
224 s->espdmaregs[0] |= DMA_INTR; 270 s->espdmaregs[0] |= DMA_INTR;
225 - } 271 + } else if (s->do_cmd) {
  272 + DPRINTF("command len %d\n", s->cmdlen);
  273 + s->ti_size = 0;
  274 + s->cmdlen = 0;
  275 + s->do_cmd = 0;
  276 + do_cmd(s, s->cmdbuf);
  277 + return;
  278 + }
226 pic_set_irq(s->irq, 1); 279 pic_set_irq(s->irq, 1);
227 } 280 }
228 281
@@ -237,6 +290,7 @@ static void esp_reset(void *opaque) @@ -237,6 +290,7 @@ static void esp_reset(void *opaque)
237 s->ti_rptr = 0; 290 s->ti_rptr = 0;
238 s->ti_wptr = 0; 291 s->ti_wptr = 0;
239 s->dma = 0; 292 s->dma = 0;
  293 + s->do_cmd = 0;
240 } 294 }
241 295
242 static uint32_t esp_mem_readb(void *opaque, target_phys_addr_t addr) 296 static uint32_t esp_mem_readb(void *opaque, target_phys_addr_t addr)
@@ -291,7 +345,9 @@ static void esp_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val) @@ -291,7 +345,9 @@ static void esp_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
291 break; 345 break;
292 case 2: 346 case 2:
293 // FIFO 347 // FIFO
294 - if ((s->rregs[4] & 6) == 0) { 348 + if (s->do_cmd) {
  349 + s->cmdbuf[s->cmdlen++] = val & 0xff;
  350 + } else if ((s->rregs[4] & 6) == 0) {
295 uint8_t buf; 351 uint8_t buf;
296 buf = val & 0xff; 352 buf = val & 0xff;
297 s->ti_size--; 353 s->ti_size--;
@@ -348,11 +404,12 @@ static void esp_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val) @@ -348,11 +404,12 @@ static void esp_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
348 DPRINTF("Set ATN (%2.2x)\n", val); 404 DPRINTF("Set ATN (%2.2x)\n", val);
349 break; 405 break;
350 case 0x42: 406 case 0x42:
  407 + DPRINTF("Set ATN (%2.2x)\n", val);
351 handle_satn(s); 408 handle_satn(s);
352 break; 409 break;
353 case 0x43: 410 case 0x43:
354 DPRINTF("Set ATN & stop (%2.2x)\n", val); 411 DPRINTF("Set ATN & stop (%2.2x)\n", val);
355 - handle_satn(s); 412 + handle_satn_stop(s);
356 break; 413 break;
357 default: 414 default:
358 DPRINTF("Unhandled ESP command (%2.2x)\n", val); 415 DPRINTF("Unhandled ESP command (%2.2x)\n", val);