mirror of https://github.com/xemu-project/xemu.git
maybe slightly less racey
This commit is contained in:
parent
0ca0cc251d
commit
e91dff0bed
145
hw/xbox/nv2a.c
145
hw/xbox/nv2a.c
|
@ -246,6 +246,10 @@
|
||||||
# define NV_PGRAPH_TRAPPED_ADDR_CHID 0x01F00000
|
# define NV_PGRAPH_TRAPPED_ADDR_CHID 0x01F00000
|
||||||
# define NV_PGRAPH_TRAPPED_ADDR_DHV 0x10000000
|
# define NV_PGRAPH_TRAPPED_ADDR_DHV 0x10000000
|
||||||
#define NV_PGRAPH_TRAPPED_DATA_LOW 0x00000708
|
#define NV_PGRAPH_TRAPPED_DATA_LOW 0x00000708
|
||||||
|
#define NV_PGRAPH_SURFACE 0x00000710
|
||||||
|
# define NV_PGRAPH_SURFACE_WRITE_3D 0x00700000
|
||||||
|
# define NV_PGRAPH_SURFACE_READ_3D 0x07000000
|
||||||
|
# define NV_PGRAPH_SURFACE_MODULO_3D 0x70000000
|
||||||
#define NV_PGRAPH_INCREMENT 0x0000071C
|
#define NV_PGRAPH_INCREMENT 0x0000071C
|
||||||
# define NV_PGRAPH_INCREMENT_READ_BLIT (1 << 0)
|
# define NV_PGRAPH_INCREMENT_READ_BLIT (1 << 0)
|
||||||
# define NV_PGRAPH_INCREMENT_READ_3D (1 << 1)
|
# define NV_PGRAPH_INCREMENT_READ_3D (1 << 1)
|
||||||
|
@ -489,6 +493,10 @@
|
||||||
#define NV_KELVIN_PRIMITIVE 0x0097
|
#define NV_KELVIN_PRIMITIVE 0x0097
|
||||||
# define NV097_NO_OPERATION 0x00970100
|
# define NV097_NO_OPERATION 0x00970100
|
||||||
# define NV097_WAIT_FOR_IDLE 0x00970110
|
# define NV097_WAIT_FOR_IDLE 0x00970110
|
||||||
|
# define NV097_SET_FLIP_READ 0x00970120
|
||||||
|
# define NV097_SET_FLIP_WRITE 0x00970124
|
||||||
|
# define NV097_SET_FLIP_MODULO 0x00970128
|
||||||
|
# define NV097_FLIP_INCREMENT_WRITE 0x0097012C
|
||||||
# define NV097_FLIP_STALL 0x00970130
|
# define NV097_FLIP_STALL 0x00970130
|
||||||
# define NV097_SET_CONTEXT_DMA_NOTIFIES 0x00970180
|
# define NV097_SET_CONTEXT_DMA_NOTIFIES 0x00970180
|
||||||
# define NV097_SET_CONTEXT_DMA_A 0x00970184
|
# define NV097_SET_CONTEXT_DMA_A 0x00970184
|
||||||
|
@ -1019,10 +1027,6 @@ typedef struct Cache1State {
|
||||||
uint32_t data_shadow;
|
uint32_t data_shadow;
|
||||||
uint32_t error;
|
uint32_t error;
|
||||||
|
|
||||||
|
|
||||||
/* Puller state */
|
|
||||||
QemuMutex pull_lock;
|
|
||||||
|
|
||||||
bool pull_enabled;
|
bool pull_enabled;
|
||||||
enum FIFOEngine bound_engines[NV2A_NUM_SUBCHANNELS];
|
enum FIFOEngine bound_engines[NV2A_NUM_SUBCHANNELS];
|
||||||
enum FIFOEngine last_engine;
|
enum FIFOEngine last_engine;
|
||||||
|
@ -1045,10 +1049,14 @@ typedef struct ChannelControl {
|
||||||
typedef struct NV2AState {
|
typedef struct NV2AState {
|
||||||
PCIDevice dev;
|
PCIDevice dev;
|
||||||
qemu_irq irq;
|
qemu_irq irq;
|
||||||
|
|
||||||
|
bool exiting;
|
||||||
|
|
||||||
VGACommonState vga;
|
VGACommonState vga;
|
||||||
GraphicHwOps hw_ops;
|
GraphicHwOps hw_ops;
|
||||||
|
|
||||||
|
QEMUTimer *vblank_timer;
|
||||||
|
|
||||||
MemoryRegion *vram;
|
MemoryRegion *vram;
|
||||||
MemoryRegion vram_pci;
|
MemoryRegion vram_pci;
|
||||||
uint8_t *vram_ptr;
|
uint8_t *vram_ptr;
|
||||||
|
@ -1160,6 +1168,7 @@ static void update_irq(NV2AState *d)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (d->pmc.pending_interrupts && d->pmc.enabled_interrupts) {
|
if (d->pmc.pending_interrupts && d->pmc.enabled_interrupts) {
|
||||||
|
NV2A_DPRINTF("raise irq\n");
|
||||||
pci_irq_assert(&d->dev);
|
pci_irq_assert(&d->dev);
|
||||||
} else {
|
} else {
|
||||||
pci_irq_deassert(&d->dev);
|
pci_irq_deassert(&d->dev);
|
||||||
|
@ -2381,12 +2390,45 @@ static void pgraph_method(NV2AState *d,
|
||||||
pgraph_update_surface(d, false);
|
pgraph_update_surface(d, false);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
||||||
|
case NV097_SET_FLIP_READ:
|
||||||
|
SET_MASK(pg->regs[NV_PGRAPH_SURFACE], NV_PGRAPH_SURFACE_READ_3D,
|
||||||
|
parameter);
|
||||||
|
break;
|
||||||
|
case NV097_SET_FLIP_WRITE:
|
||||||
|
SET_MASK(pg->regs[NV_PGRAPH_SURFACE], NV_PGRAPH_SURFACE_WRITE_3D,
|
||||||
|
parameter);
|
||||||
|
break;
|
||||||
|
case NV097_SET_FLIP_MODULO:
|
||||||
|
SET_MASK(pg->regs[NV_PGRAPH_SURFACE], NV_PGRAPH_SURFACE_MODULO_3D,
|
||||||
|
parameter);
|
||||||
|
break;
|
||||||
|
case NV097_FLIP_INCREMENT_WRITE: {
|
||||||
|
SET_MASK(pg->regs[NV_PGRAPH_SURFACE],
|
||||||
|
NV_PGRAPH_SURFACE_WRITE_3D,
|
||||||
|
(GET_MASK(pg->regs[NV_PGRAPH_SURFACE],
|
||||||
|
NV_PGRAPH_SURFACE_WRITE_3D)+1)
|
||||||
|
% GET_MASK(pg->regs[NV_PGRAPH_SURFACE],
|
||||||
|
NV_PGRAPH_SURFACE_MODULO_3D) );
|
||||||
|
break;
|
||||||
|
}
|
||||||
case NV097_FLIP_STALL:
|
case NV097_FLIP_STALL:
|
||||||
pgraph_update_surface(d, false);
|
pgraph_update_surface(d, false);
|
||||||
|
|
||||||
qemu_mutex_unlock(&pg->lock);
|
qemu_mutex_unlock(&pg->lock);
|
||||||
qemu_sem_wait(&pg->read_3d);
|
|
||||||
qemu_mutex_lock(&pg->lock);
|
// busy-wait for now...
|
||||||
|
while (true) {
|
||||||
|
qemu_mutex_lock(&pg->lock);
|
||||||
|
|
||||||
|
uint32_t s = pg->regs[NV_PGRAPH_SURFACE];
|
||||||
|
if (GET_MASK(s, NV_PGRAPH_SURFACE_READ_3D)
|
||||||
|
== GET_MASK(s, NV_PGRAPH_SURFACE_WRITE_3D)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
qemu_mutex_unlock(&pg->lock);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case NV097_SET_CONTEXT_DMA_NOTIFIES:
|
case NV097_SET_CONTEXT_DMA_NOTIFIES:
|
||||||
|
@ -3044,7 +3086,7 @@ static void pgraph_wait_fifo_access(NV2AState *d) {
|
||||||
qemu_mutex_unlock(&d->pgraph.lock);
|
qemu_mutex_unlock(&d->pgraph.lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void *pfifo_puller_thread(void *arg)
|
static void* pfifo_puller_thread(void *arg)
|
||||||
{
|
{
|
||||||
NV2AState *d = arg;
|
NV2AState *d = arg;
|
||||||
Cache1State *state = &d->pfifo.cache1;
|
Cache1State *state = &d->pfifo.cache1;
|
||||||
|
@ -3052,25 +3094,14 @@ static void *pfifo_puller_thread(void *arg)
|
||||||
RAMHTEntry entry;
|
RAMHTEntry entry;
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
qemu_mutex_lock(&state->pull_lock);
|
|
||||||
if (!state->pull_enabled) {
|
|
||||||
qemu_mutex_unlock(&state->pull_lock);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
qemu_mutex_unlock(&state->pull_lock);
|
|
||||||
|
|
||||||
qemu_mutex_lock(&state->cache_lock);
|
qemu_mutex_lock(&state->cache_lock);
|
||||||
while (QSIMPLEQ_EMPTY(&state->cache)) {
|
while (QSIMPLEQ_EMPTY(&state->cache) || !state->pull_enabled) {
|
||||||
qemu_cond_wait(&state->cache_cond, &state->cache_lock);
|
qemu_cond_wait(&state->cache_cond, &state->cache_lock);
|
||||||
|
|
||||||
/* we could have been woken up to tell us we should die */
|
if (d->exiting) {
|
||||||
qemu_mutex_lock(&state->pull_lock);
|
|
||||||
if (!state->pull_enabled) {
|
|
||||||
qemu_mutex_unlock(&state->pull_lock);
|
|
||||||
qemu_mutex_unlock(&state->cache_lock);
|
qemu_mutex_unlock(&state->cache_lock);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
qemu_mutex_unlock(&state->pull_lock);
|
|
||||||
}
|
}
|
||||||
command = QSIMPLEQ_FIRST(&state->cache);
|
command = QSIMPLEQ_FIRST(&state->cache);
|
||||||
QSIMPLEQ_REMOVE_HEAD(&state->cache, entry);
|
QSIMPLEQ_REMOVE_HEAD(&state->cache, entry);
|
||||||
|
@ -3097,10 +3128,10 @@ static void *pfifo_puller_thread(void *arg)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* the engine is bound to the subchannel */
|
/* the engine is bound to the subchannel */
|
||||||
qemu_mutex_lock(&state->pull_lock);
|
qemu_mutex_lock(&state->cache_lock);
|
||||||
state->bound_engines[command->subchannel] = entry.engine;
|
state->bound_engines[command->subchannel] = entry.engine;
|
||||||
state->last_engine = entry.engine;
|
state->last_engine = entry.engine;
|
||||||
qemu_mutex_unlock(&state->pull_lock);
|
qemu_mutex_unlock(&state->cache_lock);
|
||||||
} else if (command->method >= 0x100) {
|
} else if (command->method >= 0x100) {
|
||||||
/* method passed to engine */
|
/* method passed to engine */
|
||||||
|
|
||||||
|
@ -3117,9 +3148,9 @@ static void *pfifo_puller_thread(void *arg)
|
||||||
//qemu_mutex_unlock_iothread();
|
//qemu_mutex_unlock_iothread();
|
||||||
}
|
}
|
||||||
|
|
||||||
qemu_mutex_lock(&state->pull_lock);
|
qemu_mutex_lock(&state->cache_lock);
|
||||||
enum FIFOEngine engine = state->bound_engines[command->subchannel];
|
enum FIFOEngine engine = state->bound_engines[command->subchannel];
|
||||||
qemu_mutex_unlock(&state->pull_lock);
|
qemu_mutex_unlock(&state->cache_lock);
|
||||||
|
|
||||||
switch (engine) {
|
switch (engine) {
|
||||||
case ENGINE_GRAPHICS:
|
case ENGINE_GRAPHICS:
|
||||||
|
@ -3132,9 +3163,9 @@ static void *pfifo_puller_thread(void *arg)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
qemu_mutex_lock(&state->pull_lock);
|
qemu_mutex_lock(&state->cache_lock);
|
||||||
state->last_engine = state->bound_engines[command->subchannel];
|
state->last_engine = state->bound_engines[command->subchannel];
|
||||||
qemu_mutex_unlock(&state->pull_lock);
|
qemu_mutex_unlock(&state->cache_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
g_free(command);
|
g_free(command);
|
||||||
|
@ -3266,6 +3297,9 @@ static void pfifo_run_pusher(NV2AState *d) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NV2A_DPRINTF("DMA pusher done: max 0x%llx, 0x%llx - 0x%llx\n",
|
||||||
|
dma_len, control->dma_get, control->dma_put);
|
||||||
|
|
||||||
if (state->error) {
|
if (state->error) {
|
||||||
NV2A_DPRINTF("pb error: %d\n", state->error);
|
NV2A_DPRINTF("pb error: %d\n", state->error);
|
||||||
assert(false);
|
assert(false);
|
||||||
|
@ -3459,16 +3493,16 @@ static uint64_t pfifo_read(void *opaque,
|
||||||
| d->pfifo.cache1.subroutine_active;
|
| d->pfifo.cache1.subroutine_active;
|
||||||
break;
|
break;
|
||||||
case NV_PFIFO_CACHE1_PULL0:
|
case NV_PFIFO_CACHE1_PULL0:
|
||||||
qemu_mutex_lock(&d->pfifo.cache1.pull_lock);
|
qemu_mutex_lock(&d->pfifo.cache1.cache_lock);
|
||||||
r = d->pfifo.cache1.pull_enabled;
|
r = d->pfifo.cache1.pull_enabled;
|
||||||
qemu_mutex_unlock(&d->pfifo.cache1.pull_lock);
|
qemu_mutex_unlock(&d->pfifo.cache1.cache_lock);
|
||||||
break;
|
break;
|
||||||
case NV_PFIFO_CACHE1_ENGINE:
|
case NV_PFIFO_CACHE1_ENGINE:
|
||||||
qemu_mutex_lock(&d->pfifo.cache1.pull_lock);
|
qemu_mutex_lock(&d->pfifo.cache1.cache_lock);
|
||||||
for (i=0; i<NV2A_NUM_SUBCHANNELS; i++) {
|
for (i=0; i<NV2A_NUM_SUBCHANNELS; i++) {
|
||||||
r |= d->pfifo.cache1.bound_engines[i] << (i*2);
|
r |= d->pfifo.cache1.bound_engines[i] << (i*2);
|
||||||
}
|
}
|
||||||
qemu_mutex_unlock(&d->pfifo.cache1.pull_lock);
|
qemu_mutex_unlock(&d->pfifo.cache1.cache_lock);
|
||||||
break;
|
break;
|
||||||
case NV_PFIFO_CACHE1_DMA_DCOUNT:
|
case NV_PFIFO_CACHE1_DMA_DCOUNT:
|
||||||
r = d->pfifo.cache1.dcount;
|
r = d->pfifo.cache1.dcount;
|
||||||
|
@ -3574,30 +3608,25 @@ static void pfifo_write(void *opaque, hwaddr addr,
|
||||||
(val & NV_PFIFO_CACHE1_DMA_SUBROUTINE_STATE);
|
(val & NV_PFIFO_CACHE1_DMA_SUBROUTINE_STATE);
|
||||||
break;
|
break;
|
||||||
case NV_PFIFO_CACHE1_PULL0:
|
case NV_PFIFO_CACHE1_PULL0:
|
||||||
qemu_mutex_lock(&d->pfifo.cache1.pull_lock);
|
qemu_mutex_lock(&d->pfifo.cache1.cache_lock);
|
||||||
if ((val & NV_PFIFO_CACHE1_PULL0_ACCESS)
|
if ((val & NV_PFIFO_CACHE1_PULL0_ACCESS)
|
||||||
&& !d->pfifo.cache1.pull_enabled) {
|
&& !d->pfifo.cache1.pull_enabled) {
|
||||||
d->pfifo.cache1.pull_enabled = true;
|
d->pfifo.cache1.pull_enabled = true;
|
||||||
|
|
||||||
/* fire up puller thread */
|
/* the puller thread should wake up */
|
||||||
qemu_thread_create(&d->pfifo.puller_thread,
|
qemu_cond_signal(&d->pfifo.cache1.cache_cond);
|
||||||
pfifo_puller_thread,
|
|
||||||
d, QEMU_THREAD_DETACHED);
|
|
||||||
} else if (!(val & NV_PFIFO_CACHE1_PULL0_ACCESS)
|
} else if (!(val & NV_PFIFO_CACHE1_PULL0_ACCESS)
|
||||||
&& d->pfifo.cache1.pull_enabled) {
|
&& d->pfifo.cache1.pull_enabled) {
|
||||||
d->pfifo.cache1.pull_enabled = false;
|
d->pfifo.cache1.pull_enabled = false;
|
||||||
|
|
||||||
/* the puller thread should die, wake it up. */
|
|
||||||
qemu_cond_broadcast(&d->pfifo.cache1.cache_cond);
|
|
||||||
}
|
}
|
||||||
qemu_mutex_unlock(&d->pfifo.cache1.pull_lock);
|
qemu_mutex_unlock(&d->pfifo.cache1.cache_lock);
|
||||||
break;
|
break;
|
||||||
case NV_PFIFO_CACHE1_ENGINE:
|
case NV_PFIFO_CACHE1_ENGINE:
|
||||||
qemu_mutex_lock(&d->pfifo.cache1.pull_lock);
|
qemu_mutex_lock(&d->pfifo.cache1.cache_lock);
|
||||||
for (i=0; i<NV2A_NUM_SUBCHANNELS; i++) {
|
for (i=0; i<NV2A_NUM_SUBCHANNELS; i++) {
|
||||||
d->pfifo.cache1.bound_engines[i] = (val >> (i*2)) & 3;
|
d->pfifo.cache1.bound_engines[i] = (val >> (i*2)) & 3;
|
||||||
}
|
}
|
||||||
qemu_mutex_unlock(&d->pfifo.cache1.pull_lock);
|
qemu_mutex_unlock(&d->pfifo.cache1.cache_lock);
|
||||||
break;
|
break;
|
||||||
case NV_PFIFO_CACHE1_DMA_DCOUNT:
|
case NV_PFIFO_CACHE1_DMA_DCOUNT:
|
||||||
d->pfifo.cache1.dcount =
|
d->pfifo.cache1.dcount =
|
||||||
|
@ -3891,7 +3920,9 @@ static uint64_t pgraph_read(void *opaque,
|
||||||
uint64_t r = 0;
|
uint64_t r = 0;
|
||||||
switch (addr) {
|
switch (addr) {
|
||||||
case NV_PGRAPH_INTR:
|
case NV_PGRAPH_INTR:
|
||||||
|
qemu_mutex_lock(&d->pgraph.lock);
|
||||||
r = d->pgraph.pending_interrupts;
|
r = d->pgraph.pending_interrupts;
|
||||||
|
qemu_mutex_unlock(&d->pgraph.lock);
|
||||||
break;
|
break;
|
||||||
case NV_PGRAPH_INTR_EN:
|
case NV_PGRAPH_INTR_EN:
|
||||||
r = d->pgraph.enabled_interrupts;
|
r = d->pgraph.enabled_interrupts;
|
||||||
|
@ -3950,36 +3981,35 @@ static void pgraph_write(void *opaque, hwaddr addr,
|
||||||
|
|
||||||
reg_log_write(NV_PGRAPH, addr, val);
|
reg_log_write(NV_PGRAPH, addr, val);
|
||||||
|
|
||||||
|
qemu_mutex_lock(&d->pgraph.lock);
|
||||||
|
|
||||||
switch (addr) {
|
switch (addr) {
|
||||||
case NV_PGRAPH_INTR:
|
case NV_PGRAPH_INTR:
|
||||||
qemu_mutex_lock(&d->pgraph.lock);
|
|
||||||
d->pgraph.pending_interrupts &= ~val;
|
d->pgraph.pending_interrupts &= ~val;
|
||||||
qemu_cond_broadcast(&d->pgraph.interrupt_cond);
|
qemu_cond_broadcast(&d->pgraph.interrupt_cond);
|
||||||
qemu_mutex_unlock(&d->pgraph.lock);
|
|
||||||
break;
|
break;
|
||||||
case NV_PGRAPH_INTR_EN:
|
case NV_PGRAPH_INTR_EN:
|
||||||
d->pgraph.enabled_interrupts = val;
|
d->pgraph.enabled_interrupts = val;
|
||||||
break;
|
break;
|
||||||
case NV_PGRAPH_CTX_CONTROL:
|
case NV_PGRAPH_CTX_CONTROL:
|
||||||
qemu_mutex_lock(&d->pgraph.lock);
|
|
||||||
d->pgraph.channel_valid = (val & NV_PGRAPH_CTX_CONTROL_CHID);
|
d->pgraph.channel_valid = (val & NV_PGRAPH_CTX_CONTROL_CHID);
|
||||||
qemu_mutex_unlock(&d->pgraph.lock);
|
|
||||||
break;
|
break;
|
||||||
case NV_PGRAPH_CTX_USER:
|
case NV_PGRAPH_CTX_USER:
|
||||||
qemu_mutex_lock(&d->pgraph.lock);
|
|
||||||
pgraph_set_context_user(d, val);
|
pgraph_set_context_user(d, val);
|
||||||
qemu_mutex_unlock(&d->pgraph.lock);
|
|
||||||
break;
|
break;
|
||||||
case NV_PGRAPH_INCREMENT:
|
case NV_PGRAPH_INCREMENT:
|
||||||
if (val & NV_PGRAPH_INCREMENT_READ_3D) {
|
if (val & NV_PGRAPH_INCREMENT_READ_3D) {
|
||||||
qemu_sem_post(&d->pgraph.read_3d);
|
SET_MASK(d->pgraph.regs[NV_PGRAPH_SURFACE],
|
||||||
|
NV_PGRAPH_SURFACE_READ_3D,
|
||||||
|
(GET_MASK(d->pgraph.regs[NV_PGRAPH_SURFACE],
|
||||||
|
NV_PGRAPH_SURFACE_READ_3D)+1)
|
||||||
|
% GET_MASK(d->pgraph.regs[NV_PGRAPH_SURFACE],
|
||||||
|
NV_PGRAPH_SURFACE_MODULO_3D) );
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case NV_PGRAPH_FIFO:
|
case NV_PGRAPH_FIFO:
|
||||||
qemu_mutex_lock(&d->pgraph.lock);
|
|
||||||
d->pgraph.fifo_access = GET_MASK(val, NV_PGRAPH_FIFO_ACCESS);
|
d->pgraph.fifo_access = GET_MASK(val, NV_PGRAPH_FIFO_ACCESS);
|
||||||
qemu_cond_broadcast(&d->pgraph.fifo_access_cond);
|
qemu_cond_broadcast(&d->pgraph.fifo_access_cond);
|
||||||
qemu_mutex_unlock(&d->pgraph.lock);
|
|
||||||
break;
|
break;
|
||||||
case NV_PGRAPH_CHANNEL_CTX_TABLE:
|
case NV_PGRAPH_CHANNEL_CTX_TABLE:
|
||||||
d->pgraph.context_table =
|
d->pgraph.context_table =
|
||||||
|
@ -3990,7 +4020,6 @@ static void pgraph_write(void *opaque, hwaddr addr,
|
||||||
(val & NV_PGRAPH_CHANNEL_CTX_POINTER_INST) << 4;
|
(val & NV_PGRAPH_CHANNEL_CTX_POINTER_INST) << 4;
|
||||||
break;
|
break;
|
||||||
case NV_PGRAPH_CHANNEL_CTX_TRIGGER:
|
case NV_PGRAPH_CHANNEL_CTX_TRIGGER:
|
||||||
qemu_mutex_lock(&d->pgraph.lock);
|
|
||||||
|
|
||||||
if (val & NV_PGRAPH_CHANNEL_CTX_TRIGGER_READ_IN) {
|
if (val & NV_PGRAPH_CHANNEL_CTX_TRIGGER_READ_IN) {
|
||||||
NV2A_DPRINTF("PGRAPH: read channel %d context from %llx\n",
|
NV2A_DPRINTF("PGRAPH: read channel %d context from %llx\n",
|
||||||
|
@ -4008,12 +4037,13 @@ static void pgraph_write(void *opaque, hwaddr addr,
|
||||||
/* do stuff ... */
|
/* do stuff ... */
|
||||||
}
|
}
|
||||||
|
|
||||||
qemu_mutex_unlock(&d->pgraph.lock);
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
d->pgraph.regs[addr] = val;
|
d->pgraph.regs[addr] = val;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
qemu_mutex_unlock(&d->pgraph.lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -4762,13 +4792,17 @@ static int nv2a_initfn(PCIDevice *dev)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* init fifo cache1 */
|
/* init fifo cache1 */
|
||||||
qemu_mutex_init(&d->pfifo.cache1.pull_lock);
|
|
||||||
qemu_mutex_init(&d->pfifo.cache1.cache_lock);
|
qemu_mutex_init(&d->pfifo.cache1.cache_lock);
|
||||||
qemu_cond_init(&d->pfifo.cache1.cache_cond);
|
qemu_cond_init(&d->pfifo.cache1.cache_cond);
|
||||||
QSIMPLEQ_INIT(&d->pfifo.cache1.cache);
|
QSIMPLEQ_INIT(&d->pfifo.cache1.cache);
|
||||||
|
|
||||||
pgraph_init(&d->pgraph);
|
pgraph_init(&d->pgraph);
|
||||||
|
|
||||||
|
/* fire up puller */
|
||||||
|
qemu_thread_create(&d->pfifo.puller_thread,
|
||||||
|
pfifo_puller_thread,
|
||||||
|
d, QEMU_THREAD_DETACHED);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4777,7 +4811,10 @@ static void nv2a_exitfn(PCIDevice *dev)
|
||||||
NV2AState *d;
|
NV2AState *d;
|
||||||
d = NV2A_DEVICE(dev);
|
d = NV2A_DEVICE(dev);
|
||||||
|
|
||||||
qemu_mutex_destroy(&d->pfifo.cache1.pull_lock);
|
d->exiting = true;
|
||||||
|
qemu_cond_signal(&d->pfifo.cache1.cache_cond);
|
||||||
|
qemu_thread_join(&d->pfifo.puller_thread);
|
||||||
|
|
||||||
qemu_mutex_destroy(&d->pfifo.cache1.cache_lock);
|
qemu_mutex_destroy(&d->pfifo.cache1.cache_lock);
|
||||||
qemu_cond_destroy(&d->pfifo.cache1.cache_cond);
|
qemu_cond_destroy(&d->pfifo.cache1.cache_cond);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue