Revision 9f149aa9

b/hw/esp.c
59 59
    int dma;
60 60
    SCSIDevice *scsi_dev[MAX_DISKS];
61 61
    SCSIDevice *current_dev;
62
    uint8_t cmdbuf[TI_BUFSZ];
63
    int cmdlen;
64
    int do_cmd;
62 65
};
63 66

  
64 67
#define STAT_DO 0x00
......
79 82
#define SEQ_0 0x0
80 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 87
    uint32_t dmaptr, dmalen;
86 88
    int target;
87
    int32_t datalen;
88
    int lun;
89 89

  
90 90
    dmalen = s->wregs[0] | (s->wregs[1] << 8);
91 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 93
    if (s->dma) {
94 94
	dmaptr = iommu_translate(s->espdmaregs[1]);
95 95
	DPRINTF("DMA Direction: %c, addr 0x%8.8x\n",
......
100 100
	memcpy(&buf[1], s->ti_buf, dmalen);
101 101
	dmalen++;
102 102
    }
103
    DPRINTF("busid 0x%x\n", buf[0]);
104
    lun = buf[0] & 7;
105 103

  
106 104
    s->ti_size = 0;
107 105
    s->ti_rptr = 0;
......
114 112
	s->rregs[6] = SEQ_0;
115 113
	s->espdmaregs[0] |= DMA_INTR;
116 114
	pic_set_irq(s->irq, 1);
117
	return;
115
	return 0;
118 116
    }
119 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 128
    datalen = scsi_send_command(s->current_dev, 0, &buf[1], lun);
121 129
    if (datalen == 0) {
122 130
        s->ti_size = 0;
......
136 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 172
static void write_response(ESPState *s)
140 173
{
141 174
    uint32_t dmaptr;
......
188 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 228
    DPRINTF("Transfer Information len %d\n", minlen);
193 229
    if (s->dma) {
194 230
	dmaptr = iommu_translate(s->espdmaregs[1]);
......
207 243
            }
208 244
            DPRINTF("DMA address p %08x v %08x len %08x, from %08x, to %08x\n", dmaptr, s->espdmaregs[1] + i, len, from, to);
209 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 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 264
        if (s->ti_size) {
219 265
	    s->rregs[4] = STAT_IN | STAT_TC | (to_device ? STAT_DO : STAT_DI);
220 266
        }
......
222 268
	s->rregs[6] = 0;
223 269
	s->rregs[7] = 0;
224 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 279
    pic_set_irq(s->irq, 1);
227 280
}
228 281

  
......
237 290
    s->ti_rptr = 0;
238 291
    s->ti_wptr = 0;
239 292
    s->dma = 0;
293
    s->do_cmd = 0;
240 294
}
241 295

  
242 296
static uint32_t esp_mem_readb(void *opaque, target_phys_addr_t addr)
......
291 345
        break;
292 346
    case 2:
293 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 351
            uint8_t buf;
296 352
            buf = val & 0xff;
297 353
            s->ti_size--;
......
348 404
	    DPRINTF("Set ATN (%2.2x)\n", val);
349 405
	    break;
350 406
	case 0x42:
407
	    DPRINTF("Set ATN (%2.2x)\n", val);
351 408
	    handle_satn(s);
352 409
	    break;
353 410
	case 0x43:
354 411
	    DPRINTF("Set ATN & stop (%2.2x)\n", val);
355
	    handle_satn(s);
412
	    handle_satn_stop(s);
356 413
	    break;
357 414
	default:
358 415
	    DPRINTF("Unhandled ESP command (%2.2x)\n", val);

Also available in: Unified diff