Revision 9f149aa9 hw/esp.c
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