diff --git a/src/add-ons/kernel/drivers/graphics/nvidia/driver.c b/src/add-ons/kernel/drivers/graphics/nvidia/driver.c index 50b298b804..60900b3067 100644 --- a/src/add-ons/kernel/drivers/graphics/nvidia/driver.c +++ b/src/add-ons/kernel/drivers/graphics/nvidia/driver.c @@ -843,6 +843,7 @@ static status_t open_hook (const char* name, uint32 flags, void** cookie) { char shared_name[B_OS_NAME_LENGTH]; physical_entry map[1]; size_t net_buf_size; + void *unaligned_dma_buffer; /* find the device name in the list of devices */ /* we're never passed a name we didn't publish */ @@ -881,28 +882,46 @@ static status_t open_hook (const char* name, uint32 flags, void** cookie) { /* we want to setup a 1Mb buffer (size must be multiple of B_PAGE_SIZE) */ net_buf_size = ((1 * 1024 * 1024) + (B_PAGE_SIZE-1)) & ~(B_PAGE_SIZE-1); /* create the area that will hold the DMA command buffer */ - si->dma_buffer_area = - create_area("NV accelerant DMA cmd buffer", - (void **)&(si->dma_buffer), + si->unaligned_dma_area = + create_area("NV DMA cmd buffer", + (void **)&unaligned_dma_buffer, B_ANY_KERNEL_ADDRESS, 2 * net_buf_size, /* take twice the net size so we can have MTRR-WC even on old systems */ B_FULL_LOCK | B_CONTIGUOUS, /* both properties needed: GPU always needs access */ - B_USER_CLONEABLE_AREA); + B_USER_CLONEABLE_AREA | B_READ_AREA | B_WRITE_AREA); /* on error, abort */ - if (si->dma_buffer_area < 0) + if (si->unaligned_dma_area < 0) { /* free the already created shared_info area, and return the error */ - result = si->dma_buffer_area; + result = si->unaligned_dma_area; goto free_shared; } - /* we also need the physical adress our DMA buffer resides in, as this needs to be - * fed into the GPU's engine later on. So get the first page of our assigned buffer */ - get_memory_map(si->dma_buffer, B_PAGE_SIZE, map, 1); - si->dma_buffer_pci = (void*)((uint32)(map[0].address)); - /* set our net buffer at an aligned adress for MTRR-WC mapping even by older CPU's */ - /* (using MTRR-WC mapping will speed-up placing commands..) */ - si->engine.dma.cmdbuffer = (uint32*) - ((((uint32)(si->dma_buffer_pci)) + net_buf_size - 1) & ~(net_buf_size - 1)); + /* we (also) need the physical adress our DMA buffer is at, as this needs to be + * fed into the GPU's engine later on. Get an aligned adress so we can use MTRR-WC + * even on older CPU's. */ + get_memory_map(unaligned_dma_buffer, B_PAGE_SIZE, map, 1); + si->dma_buffer_pci = (void*) + ((((uint32)(map[0].address)) + net_buf_size - 1) & ~(net_buf_size - 1)); + + /* map the net DMA command buffer into vmem, using Write Combining */ + si->dma_area = map_physical_memory( + "NV aligned DMA cmd buffer", si->dma_buffer_pci, net_buf_size, + B_ANY_KERNEL_BLOCK_ADDRESS | B_MTR_WC, + B_READ_AREA | B_WRITE_AREA, &(si->dma_buffer)); + /* if failed with write combining try again without */ + if (si->dma_area < 0) { + si->dma_area = map_physical_memory( + "NV aligned DMA cmd buffer", si->dma_buffer_pci, net_buf_size, + B_ANY_KERNEL_BLOCK_ADDRESS, + B_READ_AREA | B_WRITE_AREA, &(si->dma_buffer)); + } + /* if there was an error, delete our other areas and pass on error*/ + if (si->dma_area < 0) + { + /* free the already created areas, and return the error */ + result = si->dma_area; + goto free_shared_and_uadma; + } /* save the vendor and device IDs */ si->vendor_id = di->pcii.vendor_id; @@ -938,7 +957,7 @@ static status_t open_hook (const char* name, uint32 flags, void** cookie) { /* map the device */ result = map_device(di); - if (result < 0) goto free_shared_and_dma; + if (result < 0) goto free_shared_and_alldma; result = B_OK; /* create a semaphore for vertical blank management */ @@ -995,11 +1014,17 @@ delete_the_sem: unmap: unmap_device(di); -free_shared_and_dma: - /* clean up our DMA area */ - delete_area(si->dma_buffer_area); - si->dma_buffer_area = -1; - si->dma_buffer = si->dma_buffer_pci = si->engine.dma.cmdbuffer = NULL; +free_shared_and_alldma: + /* clean up our aligned DMA area */ + delete_area(si->dma_area); + si->dma_area = -1; + si->dma_buffer = NULL; + +free_shared_and_uadma: + /* clean up our unaligned DMA area */ + delete_area(si->unaligned_dma_area); + si->unaligned_dma_area = -1; + si->dma_buffer_pci = NULL; free_shared: /* clean up our shared area */ @@ -1074,10 +1099,15 @@ free_hook (void* dev) { /* free regs and framebuffer areas */ unmap_device(di); - /* clean up our DMA area */ - delete_area(si->dma_buffer_area); - si->dma_buffer_area = -1; - si->dma_buffer = si->dma_buffer_pci = si->engine.dma.cmdbuffer = NULL; + /* clean up our aligned DMA area */ + delete_area(si->dma_area); + si->dma_area = -1; + si->dma_buffer = NULL; + + /* clean up our unaligned DMA area */ + delete_area(si->unaligned_dma_area); + si->unaligned_dma_area = -1; + si->dma_buffer_pci = NULL; /* clean up our shared area */ delete_area(di->shared_area);