Revision def93791 hw/ide/pci.c
b/hw/ide/pci.c | ||
---|---|---|
183 | 183 |
bmdma_start_dma(&bm->dma, s, bm->dma_cb); |
184 | 184 |
} |
185 | 185 |
|
186 |
/* TODO This should be common IDE code */ |
|
186 | 187 |
static void bmdma_restart_bh(void *opaque) |
187 | 188 |
{ |
188 | 189 |
BMDMAState *bm = opaque; |
190 |
IDEBus *bus = bm->bus; |
|
189 | 191 |
int is_read; |
190 | 192 |
|
191 | 193 |
qemu_bh_delete(bm->bh); |
192 | 194 |
bm->bh = NULL; |
193 | 195 |
|
194 |
is_read = !!(bm->status & BM_STATUS_RETRY_READ); |
|
196 |
if (bm->unit == (uint8_t) -1) { |
|
197 |
return; |
|
198 |
} |
|
195 | 199 |
|
196 |
if (bm->status & BM_STATUS_DMA_RETRY) { |
|
197 |
bm->status &= ~(BM_STATUS_DMA_RETRY | BM_STATUS_RETRY_READ); |
|
200 |
is_read = !!(bus->error_status & BM_STATUS_RETRY_READ); |
|
201 |
|
|
202 |
if (bus->error_status & BM_STATUS_DMA_RETRY) { |
|
203 |
bus->error_status &= ~(BM_STATUS_DMA_RETRY | BM_STATUS_RETRY_READ); |
|
198 | 204 |
bmdma_restart_dma(bm, is_read); |
199 |
} else if (bm->status & BM_STATUS_PIO_RETRY) {
|
|
200 |
bm->status &= ~(BM_STATUS_PIO_RETRY | BM_STATUS_RETRY_READ);
|
|
205 |
} else if (bus->error_status & BM_STATUS_PIO_RETRY) {
|
|
206 |
bus->error_status &= ~(BM_STATUS_PIO_RETRY | BM_STATUS_RETRY_READ);
|
|
201 | 207 |
if (is_read) { |
202 | 208 |
ide_sector_read(bmdma_active_if(bm)); |
203 | 209 |
} else { |
204 | 210 |
ide_sector_write(bmdma_active_if(bm)); |
205 | 211 |
} |
206 |
} else if (bm->status & BM_STATUS_RETRY_FLUSH) {
|
|
212 |
} else if (bus->error_status & BM_STATUS_RETRY_FLUSH) {
|
|
207 | 213 |
ide_flush_cache(bmdma_active_if(bm)); |
208 | 214 |
} |
209 | 215 |
} |
... | ... | |
351 | 357 |
return (bm->cur_prd_len != 0); |
352 | 358 |
} |
353 | 359 |
|
360 |
static bool ide_bmdma_status_needed(void *opaque) |
|
361 |
{ |
|
362 |
BMDMAState *bm = opaque; |
|
363 |
|
|
364 |
/* Older versions abused some bits in the status register for internal |
|
365 |
* error state. If any of these bits are set, we must add a subsection to |
|
366 |
* transfer the real status register */ |
|
367 |
uint8_t abused_bits = BM_MIGRATION_COMPAT_STATUS_BITS; |
|
368 |
|
|
369 |
return ((bm->status & abused_bits) != 0); |
|
370 |
} |
|
371 |
|
|
372 |
static void ide_bmdma_pre_save(void *opaque) |
|
373 |
{ |
|
374 |
BMDMAState *bm = opaque; |
|
375 |
uint8_t abused_bits = BM_MIGRATION_COMPAT_STATUS_BITS; |
|
376 |
|
|
377 |
bm->migration_compat_status = |
|
378 |
(bm->status & ~abused_bits) | (bm->bus->error_status & abused_bits); |
|
379 |
} |
|
380 |
|
|
381 |
/* This function accesses bm->bus->error_status which is loaded only after |
|
382 |
* BMDMA itself. This is why the function is called from ide_pci_post_load |
|
383 |
* instead of being registered with VMState where it would run too early. */ |
|
384 |
static int ide_bmdma_post_load(void *opaque, int version_id) |
|
385 |
{ |
|
386 |
BMDMAState *bm = opaque; |
|
387 |
uint8_t abused_bits = BM_MIGRATION_COMPAT_STATUS_BITS; |
|
388 |
|
|
389 |
if (bm->status == 0) { |
|
390 |
bm->status = bm->migration_compat_status & ~abused_bits; |
|
391 |
bm->bus->error_status |= bm->migration_compat_status & abused_bits; |
|
392 |
} |
|
393 |
|
|
394 |
return 0; |
|
395 |
} |
|
396 |
|
|
354 | 397 |
static const VMStateDescription vmstate_bmdma_current = { |
355 | 398 |
.name = "ide bmdma_current", |
356 | 399 |
.version_id = 1, |
... | ... | |
365 | 408 |
} |
366 | 409 |
}; |
367 | 410 |
|
411 |
const VMStateDescription vmstate_bmdma_status = { |
|
412 |
.name ="ide bmdma/status", |
|
413 |
.version_id = 1, |
|
414 |
.minimum_version_id = 1, |
|
415 |
.minimum_version_id_old = 1, |
|
416 |
.fields = (VMStateField []) { |
|
417 |
VMSTATE_UINT8(status, BMDMAState), |
|
418 |
VMSTATE_END_OF_LIST() |
|
419 |
} |
|
420 |
}; |
|
368 | 421 |
|
369 | 422 |
static const VMStateDescription vmstate_bmdma = { |
370 | 423 |
.name = "ide bmdma", |
371 | 424 |
.version_id = 3, |
372 | 425 |
.minimum_version_id = 0, |
373 | 426 |
.minimum_version_id_old = 0, |
427 |
.pre_save = ide_bmdma_pre_save, |
|
374 | 428 |
.fields = (VMStateField []) { |
375 | 429 |
VMSTATE_UINT8(cmd, BMDMAState), |
376 |
VMSTATE_UINT8(status, BMDMAState), |
|
430 |
VMSTATE_UINT8(migration_compat_status, BMDMAState),
|
|
377 | 431 |
VMSTATE_UINT32(addr, BMDMAState), |
378 | 432 |
VMSTATE_INT64(sector_num, BMDMAState), |
379 | 433 |
VMSTATE_UINT32(nsector, BMDMAState), |
... | ... | |
385 | 439 |
.vmsd = &vmstate_bmdma_current, |
386 | 440 |
.needed = ide_bmdma_current_needed, |
387 | 441 |
}, { |
442 |
.vmsd = &vmstate_bmdma_status, |
|
443 |
.needed = ide_bmdma_status_needed, |
|
444 |
}, { |
|
388 | 445 |
/* empty */ |
389 | 446 |
} |
390 | 447 |
} |
... | ... | |
399 | 456 |
/* current versions always store 0/1, but older version |
400 | 457 |
stored bigger values. We only need last bit */ |
401 | 458 |
d->bmdma[i].unit &= 1; |
459 |
ide_bmdma_post_load(&d->bmdma[i], -1); |
|
402 | 460 |
} |
461 |
|
|
403 | 462 |
return 0; |
404 | 463 |
} |
405 | 464 |
|
Also available in: Unified diff