コード例 #1
0
ファイル: driver.c プロジェクト: luciang/haiku
static status_t
free_hook(void* dev)
{
	device_info *di = (device_info *)dev;
	shared_info	*si = di->si;
	vuint32 *regs = di->regs;

	/* lock the driver */
	AQUIRE_BEN(pd->kernel);

	/* if opened multiple times, decrement the open count and exit */
	if (di->is_open > 1)
		goto unlock_and_exit;

	/* disable and clear any pending interrupts */
	//fixme:
	//distinquish between crtc1/crtc2 once all heads get seperate driver instances!
	disable_vbi_all(regs);

	if (si->ps.int_assigned) {
		/* remove interrupt handler */
		remove_io_interrupt_handler(di->pcii.u.h0.interrupt_line, nv_interrupt, di);

		/* delete the semaphores, ignoring any errors ('cause the owning
		   team may have died on us) */
		delete_sem(si->vblank);
		si->vblank = -1;
	}

	/* free regs and framebuffer areas */
	unmap_device(di);

	/* 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);
	di->shared_area = -1;
	di->si = NULL;

unlock_and_exit:
	/* mark the device available */
	di->is_open--;
	/* unlock the driver */
	RELEASE_BEN(pd->kernel);
	/* all done */
	return B_OK;
}
コード例 #2
0
ファイル: driver.c プロジェクト: DonCN/haiku
/* -----------
	free_hook - close down the device
----------- */
static status_t
free_hook (void* dev) {
	device_info *di = (device_info *)dev;
	shared_info	*si = di->si;
	vuint32 *regs = di->regs;

	/* lock the driver */
	AQUIRE_BEN(pd->kernel);

	/* if opened multiple times, decrement the open count and exit */
	if (di->is_open > 1)
		goto unlock_and_exit;

	/* disable and clear any pending interrupts */
	disable_vbi(regs);

	/* remove interrupt handler */
	remove_io_interrupt_handler(di->pcii.u.h0.interrupt_line, eng_interrupt, di);

	/* delete the semaphores, ignoring any errors ('cause the owning team may have died on us) */
	delete_sem(si->vblank);
	si->vblank = -1;

	/* free regs and framebuffer areas */
	unmap_device(di);

	/* clean up our shared area */
	delete_area(di->shared_area);
	di->shared_area = -1;
	di->si = NULL;

unlock_and_exit:
	/* mark the device available */
	di->is_open--;
	/* unlock the driver */
	RELEASE_BEN(pd->kernel);
	/* all done */
	return B_OK;
}
コード例 #3
0
ファイル: driver.c プロジェクト: looncraz/haiku
/*
 * et6000FreeHook - close down the device
 */
static status_t et6000FreeHook(void* dev) {
ET6000DeviceInfo *di = (ET6000DeviceInfo *)dev;
ET6000SharedInfo *si = di->si;

    ddprintf(("SKD et6000FreeHook() begins...\n"));
    /* lock the driver */
    AQUIRE_BEN(pd->kernel);

    /* if opened multiple times, decrement the open count and exit */
    if (di->isOpen > 1)
        goto unlock_and_exit;

    /* Clear any pending interrupts and disable interrupts. */
    et6000aclReadInterruptClear(si->mmRegs);
    et6000aclWriteInterruptClear(si->mmRegs);
    et6000aclMasterInterruptDisable(si->mmRegs);

    /* Remove the interrupt handler */
    remove_io_interrupt_handler(di->pcii.u.h0.interrupt_line, et6000Interrupt, di);

    /* free framebuffer area */
    et6000UnmapDevice(di);

    /* clean up our shared area */
    delete_area(di->sharedArea);
    di->sharedArea = -1;
    di->si = NULL;

unlock_and_exit:
    /* mark the device available */
    di->isOpen--;
    /* unlock the driver */
    RELEASE_BEN(pd->kernel);
    ddprintf(("SKD et6000FreeHook() ends.\n"));
    /* all done */
    return B_OK;
}
コード例 #4
0
ファイル: driver.c プロジェクト: DonCN/haiku
/* -----------
	control_hook - where the real work is done
----------- */
static status_t
control_hook (void* dev, uint32 msg, void *buf, size_t len) {
	device_info *di = (device_info *)dev;
	status_t result = B_DEV_INVALID_IOCTL;
	uint32 tmpUlong;

	switch (msg) {
		/* the only PUBLIC ioctl */
		case B_GET_ACCELERANT_SIGNATURE: {
			char *sig = (char *)buf;
			strcpy(sig, current_settings.accelerant);
			result = B_OK;
		} break;

		/* PRIVATE ioctl from here on */
		case ENG_GET_PRIVATE_DATA: {
			eng_get_private_data *gpd = (eng_get_private_data *)buf;
			if (gpd->magic == VIA_PRIVATE_DATA_MAGIC) {
				gpd->shared_info_area = di->shared_area;
				result = B_OK;
			}
		} break;
		case ENG_GET_PCI: {
			eng_get_set_pci *gsp = (eng_get_set_pci *)buf;
			if (gsp->magic == VIA_PRIVATE_DATA_MAGIC) {
				pci_info *pcii = &(di->pcii);
				gsp->value = get_pci(gsp->offset, gsp->size);
				result = B_OK;
			}
		} break;
		case ENG_SET_PCI: {
			eng_get_set_pci *gsp = (eng_get_set_pci *)buf;
			if (gsp->magic == VIA_PRIVATE_DATA_MAGIC) {
				pci_info *pcii = &(di->pcii);
				set_pci(gsp->offset, gsp->size, gsp->value);
				result = B_OK;
			}
		} break;
		case ENG_DEVICE_NAME: { // apsed
			eng_device_name *dn = (eng_device_name *)buf;
			if (dn->magic == VIA_PRIVATE_DATA_MAGIC) {
				strcpy(dn->name, di->name);
				result = B_OK;
			}
		} break;
		case ENG_RUN_INTERRUPTS: {
			eng_set_bool_state *ri = (eng_set_bool_state *)buf;
			if (ri->magic == VIA_PRIVATE_DATA_MAGIC) {
				vuint32 *regs = di->regs;
				if (ri->do_it) {
					enable_vbi(regs);
				} else {
					disable_vbi(regs);
				}
				result = B_OK;
			}
		} break;
		case ENG_GET_NTH_AGP_INFO: {
			eng_nth_agp_info *nai = (eng_nth_agp_info *)buf;
			if (nai->magic == VIA_PRIVATE_DATA_MAGIC) {
				nai->exist = false;
				nai->agp_bus = false;
				if (agp_bus) {
					nai->agp_bus = true;
					if ((*agp_bus->get_nth_agp_info)(nai->index, &(nai->agpi)) == B_NO_ERROR) {
						nai->exist = true;
					}
				}
				result = B_OK;
			}
		} break;
		case ENG_ENABLE_AGP: {
			eng_cmd_agp *nca = (eng_cmd_agp *)buf;
			if (nca->magic == VIA_PRIVATE_DATA_MAGIC) {
				if (agp_bus) {
					nca->agp_bus = true;
					nca->cmd = agp_bus->set_agp_mode(nca->cmd);
				} else {
					nca->agp_bus = false;
					nca->cmd = 0;
				}
				result = B_OK;
			}
		} break;
		case ENG_ISA_OUT: {
			eng_in_out_isa *io_isa = (eng_in_out_isa *)buf;
			if (io_isa->magic == VIA_PRIVATE_DATA_MAGIC) {
				pci_info *pcii = &(di->pcii);

				/* lock the driver:
				 * no other graphics card may have ISA I/O enabled when we enter */
				AQUIRE_BEN(pd->kernel);

				/* enable ISA I/O access */
				tmpUlong = get_pci(PCI_command, 2);
				tmpUlong |= PCI_command_io;
				set_pci(PCI_command, 2, tmpUlong);

				if (io_isa->size == 1)
  					isa_bus->write_io_8(io_isa->adress, (uint8)io_isa->data);
   				else
   					isa_bus->write_io_16(io_isa->adress, io_isa->data);
  				result = B_OK;

				/* disable ISA I/O access */
				tmpUlong = get_pci(PCI_command, 2);
				tmpUlong &= ~PCI_command_io;
				set_pci(PCI_command, 2, tmpUlong);

				/* end of critical section */
				RELEASE_BEN(pd->kernel);
   			}
		} break;
		case ENG_ISA_IN: {
			eng_in_out_isa *io_isa = (eng_in_out_isa *)buf;
			if (io_isa->magic == VIA_PRIVATE_DATA_MAGIC) {
				pci_info *pcii = &(di->pcii);

				/* lock the driver:
				 * no other graphics card may have ISA I/O enabled when we enter */
				AQUIRE_BEN(pd->kernel);

				/* enable ISA I/O access */
				tmpUlong = get_pci(PCI_command, 2);
				tmpUlong |= PCI_command_io;
				set_pci(PCI_command, 2, tmpUlong);

				if (io_isa->size == 1)
	   				io_isa->data = isa_bus->read_io_8(io_isa->adress);
	   			else
	   				io_isa->data = isa_bus->read_io_16(io_isa->adress);
   				result = B_OK;

				/* disable ISA I/O access */
				tmpUlong = get_pci(PCI_command, 2);
				tmpUlong &= ~PCI_command_io;
				set_pci(PCI_command, 2, tmpUlong);

				/* end of critical section */
				RELEASE_BEN(pd->kernel);
   			}
		} break;
	}
	return result;
}
コード例 #5
0
ファイル: driver.c プロジェクト: DonCN/haiku
static status_t open_hook (const char* name, uint32 flags, void** cookie) {
	int32 index = 0;
	device_info *di;
	shared_info *si;
	thread_id	thid;
	thread_info	thinfo;
	status_t	result = B_OK;
	vuint32		*regs;
	char shared_name[B_OS_NAME_LENGTH];

	/* find the device name in the list of devices */
	/* we're never passed a name we didn't publish */
	while (pd->device_names[index] && (strcmp(name, pd->device_names[index]) != 0)) index++;

	/* for convienience */
	di = &(pd->di[index]);

	/* make sure no one else has write access to the common data */
	AQUIRE_BEN(pd->kernel);

	/* if it's already open for writing */
	if (di->is_open) {
		/* mark it open another time */
		goto mark_as_open;
	}
	/* create the shared area */
	sprintf(shared_name, DEVICE_FORMAT " shared",
		di->pcii.vendor_id, di->pcii.device_id,
		di->pcii.bus, di->pcii.device, di->pcii.function);
	/* create this area with NO user-space read or write permissions, to prevent accidental dammage */
	di->shared_area = create_area(shared_name, (void **)&(di->si), B_ANY_KERNEL_ADDRESS, ((sizeof(shared_info) + (B_PAGE_SIZE - 1)) & ~(B_PAGE_SIZE - 1)), B_FULL_LOCK, 0);
	if (di->shared_area < 0) {
		/* return the error */
		result = di->shared_area;
		goto done;
	}

	/* save a few dereferences */
	si = di->si;

	/* save the vendor and device IDs */
	si->vendor_id = di->pcii.vendor_id;
	si->device_id = di->pcii.device_id;
	si->revision = di->pcii.revision;
	si->bus = di->pcii.bus;
	si->device = di->pcii.device;
	si->function = di->pcii.function;

	/* device at bus #0, device #0, function #0 holds byte value at byte-index 0xf6 */
	si->ps.chip_rev = ((*pci_bus->read_pci_config)(0, 0, 0, 0xf6, 1));

	/* map the device */
	result = map_device(di);
	if (result < 0) goto free_shared;
	result = B_OK;

	/* create a semaphore for vertical blank management */
	si->vblank = create_sem(0, di->name);
	if (si->vblank < 0) {
		result = si->vblank;
		goto unmap;
	}

	/* change the owner of the semaphores to the opener's team */
	/* this is required because apps can't aquire kernel semaphores */
	thid = find_thread(NULL);
	get_thread_info(thid, &thinfo);
	set_sem_owner(si->vblank, thinfo.team);

	/* assign local regs pointer for SAMPLExx() macros */
	regs = di->regs;

	/* disable and clear any pending interrupts */
	disable_vbi(regs);

	/* If there is a valid interrupt line assigned then set up interrupts */
	if ((di->pcii.u.h0.interrupt_pin == 0x00) ||
	    (di->pcii.u.h0.interrupt_line == 0xff) || /* no IRQ assigned */
	    (di->pcii.u.h0.interrupt_line <= 0x02))   /* system IRQ assigned */
	{
		/* we are aborting! */
		/* Note: the R4 graphics driver kit lacks this statement!! */
		result = B_ERROR;
		/* interrupt does not exist so exit without installing our handler */
		goto delete_the_sem;
	}
	else
	{
		/* otherwise install our interrupt handler */
		result = install_io_interrupt_handler(di->pcii.u.h0.interrupt_line, eng_interrupt, (void *)di, 0);
		/* bail if we couldn't install the handler */
		if (result != B_OK) goto delete_the_sem;
	}

mark_as_open:
	/* mark the device open */
	di->is_open++;

	/* send the cookie to the opener */
	*cookie = di;

	goto done;


delete_the_sem:
	delete_sem(si->vblank);

unmap:
	unmap_device(di);

free_shared:
	/* clean up our shared area */
	delete_area(di->shared_area);
	di->shared_area = -1;
	di->si = NULL;

done:
	/* end of critical section */
	RELEASE_BEN(pd->kernel);

	/* all done, return the status */
	return result;
}
コード例 #6
0
ファイル: Overlay.c プロジェクト: AmirAbrams/haiku
const overlay_buffer *ALLOCATE_OVERLAY_BUFFER(color_space cs, uint16 width, uint16 height)
{
	int offset = 0;					/* used to determine next buffer to create */
	uint32 adress, adress2, temp32;	/* used to calculate buffer adresses */
	uint32 oldsize = 0;				/* used to 'squeeze' new buffers between already existing ones */
	int cnt;						/* loopcounter */

	/* acquire the shared benaphore */
	AQUIRE_BEN(si->overlay.lock)

	LOG(4,("Overlay: cardRAM_start = $%08x\n",(uint32)((uint8*)si->framebuffer)));
	LOG(4,("Overlay: cardRAM_start_DMA = $%08x\n",(uint32)((uint8*)si->framebuffer_pci)));
	LOG(4,("Overlay: cardRAM_size = %3.3fMb\n",(si->ps.memory_size / (1024.0 * 1024.0))));

	/* find first empty slot (room for another buffer?) */
	for (offset = 0; offset < MAXBUFFERS; offset++)
	{
		if (si->overlay.myBuffer[offset].buffer == NULL) break;
	}

	LOG(4,("Overlay: Allocate_buffer offset = %d\n",offset));

	if (offset < MAXBUFFERS)
	/* setup new scaler input buffer */
	{
		switch (cs)
		{
			case B_YCbCr422:
					if (si->ps.card_arch < NV10A)
					{
						/* check if slopspace is needed: RIVA128 and TNT need ~0x000f. */
						si->overlay.myBuffer[offset].width = ((width + 0x000f) & ~0x000f);
					}
					else
					{
						/* check if slopspace is needed: GeForce need ~0x001f. */
						/* fixme:
						 * update needed for GF DVDmax support to adhere to CRTC2 constraints?? */
						si->overlay.myBuffer[offset].width = ((width + 0x001f) & ~0x001f);
					}
					si->overlay.myBuffer[offset].bytes_per_row = 2 * si->overlay.myBuffer[offset].width;

					/* check if the requested horizontal pitch is supported: */
					//fixme: tune for GF and TNT...
					if (si->overlay.myBuffer[offset].width > 4088)
					{
						LOG(4,("Overlay: Sorry, requested buffer pitch not supported, aborted\n"));

						/* release the shared benaphore */
						RELEASE_BEN(si->overlay.lock)

						return NULL;
					}
					break;
			default:
					/* unsupported colorspace! */
					LOG(4,("Overlay: Sorry, colorspace $%08x not supported, aborted\n",cs));

					/* release the shared benaphore */
					RELEASE_BEN(si->overlay.lock)

					return NULL;
					break;
		}

		/* check if the requested buffer width is supported */
		if (si->overlay.myBuffer[offset].width > 1024)
		{
			LOG(4,("Overlay: Sorry, requested buffer width not supported, aborted\n"));

			/* release the shared benaphore */
			RELEASE_BEN(si->overlay.lock)

			return NULL;
		}
コード例 #7
0
ファイル: driver.c プロジェクト: luciang/haiku
static status_t
control_hook(void* dev, uint32 msg, void *buf, size_t len)
{
	device_info *di = (device_info *)dev;
	status_t result = B_DEV_INVALID_IOCTL;
	uint32 tmpUlong;

	switch (msg) {
		/* the only PUBLIC ioctl */
		case B_GET_ACCELERANT_SIGNATURE:
		{
			strcpy((char* )buf, sSettings.accelerant);
			result = B_OK;
			break;
		}

		/* PRIVATE ioctl from here on */
		case NV_GET_PRIVATE_DATA:
		{
			nv_get_private_data *gpd = (nv_get_private_data *)buf;
			if (gpd->magic == NV_PRIVATE_DATA_MAGIC) {
				gpd->shared_info_area = di->shared_area;
				result = B_OK;
			}
			break;
		}

		case NV_GET_PCI:
		{
			nv_get_set_pci *gsp = (nv_get_set_pci *)buf;
			if (gsp->magic == NV_PRIVATE_DATA_MAGIC) {
				pci_info *pcii = &(di->pcii);
				gsp->value = get_pci(gsp->offset, gsp->size);
				result = B_OK;
			}
			break;
		}

		case NV_SET_PCI:
		{
			nv_get_set_pci *gsp = (nv_get_set_pci *)buf;
			if (gsp->magic == NV_PRIVATE_DATA_MAGIC) {
				pci_info *pcii = &(di->pcii);
				set_pci(gsp->offset, gsp->size, gsp->value);
				result = B_OK;
			}
			break;
		}

		case NV_DEVICE_NAME:
		{
			nv_device_name *dn = (nv_device_name *)buf;
			if (dn->magic == NV_PRIVATE_DATA_MAGIC) {
				strcpy(dn->name, di->name);
				result = B_OK;
			}
			break;
		}

		case NV_RUN_INTERRUPTS:
		{
			nv_set_vblank_int *vi = (nv_set_vblank_int *)buf;
			if (vi->magic == NV_PRIVATE_DATA_MAGIC) {
				vuint32 *regs = di->regs;
				if (!(vi->crtc)) {
					if (vi->do_it) {
						enable_vbi_crtc1(regs);
					} else {
						disable_vbi_crtc1(regs);
					}
				} else {
					if (vi->do_it) {
						enable_vbi_crtc2(regs);
					} else {
						disable_vbi_crtc2(regs);
					}
				}
				result = B_OK;
			}
			break;
		}

		case NV_ISA_OUT:
		{
			nv_in_out_isa *io_isa = (nv_in_out_isa *)buf;
			if (io_isa->magic == NV_PRIVATE_DATA_MAGIC) {
				pci_info *pcii = &(di->pcii);

				/* lock the driver:
				 * no other graphics card may have ISA I/O enabled when we enter */
				AQUIRE_BEN(pd->kernel);

				/* enable ISA I/O access */
				tmpUlong = get_pci(PCI_command, 2);
				tmpUlong |= PCI_command_io;
				set_pci(PCI_command, 2, tmpUlong);

				if (io_isa->size == 1)
  					isa_bus->write_io_8(io_isa->adress, (uint8)io_isa->data);
   				else
   					isa_bus->write_io_16(io_isa->adress, io_isa->data);
  				result = B_OK;

				/* disable ISA I/O access */
				tmpUlong = get_pci(PCI_command, 2);
				tmpUlong &= ~PCI_command_io;
				set_pci(PCI_command, 2, tmpUlong);

				/* end of critical section */
				RELEASE_BEN(pd->kernel);
   			}
			break;
		}

		case NV_ISA_IN:
		{
			nv_in_out_isa *io_isa = (nv_in_out_isa *)buf;
			if (io_isa->magic == NV_PRIVATE_DATA_MAGIC) {
				pci_info *pcii = &(di->pcii);

				/* lock the driver:
				 * no other graphics card may have ISA I/O enabled when we enter */
				AQUIRE_BEN(pd->kernel);

				/* enable ISA I/O access */
				tmpUlong = get_pci(PCI_command, 2);
				tmpUlong |= PCI_command_io;
				set_pci(PCI_command, 2, tmpUlong);

				if (io_isa->size == 1)
	   				io_isa->data = isa_bus->read_io_8(io_isa->adress);
	   			else
	   				io_isa->data = isa_bus->read_io_16(io_isa->adress);
   				result = B_OK;

				/* disable ISA I/O access */
				tmpUlong = get_pci(PCI_command, 2);
				tmpUlong &= ~PCI_command_io;
				set_pci(PCI_command, 2, tmpUlong);

				/* end of critical section */
				RELEASE_BEN(pd->kernel);
   			}
			break;
		}
	}

	return result;
}
コード例 #8
0
ファイル: driver.c プロジェクト: luciang/haiku
static status_t
open_hook(const char* name, uint32 flags, void** cookie)
{
	int32 index = 0;
	device_info *di;
	shared_info *si;
	thread_id	thid;
	thread_info	thinfo;
	status_t	result = B_OK;
	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 */
	while (pd->device_names[index]
		&& (strcmp(name, pd->device_names[index]) != 0))
		index++;

	/* for convienience */
	di = &(pd->di[index]);

	/* make sure no one else has write access to the common data */
	AQUIRE_BEN(pd->kernel);

	/* if it's already open for writing */
	if (di->is_open) {
		/* mark it open another time */
		goto mark_as_open;
	}
	/* create the shared_info area */
	sprintf(shared_name, DEVICE_FORMAT " shared",
		di->pcii.vendor_id, di->pcii.device_id,
		di->pcii.bus, di->pcii.device, di->pcii.function);
	/* create this area with NO user-space read or write permissions, to prevent accidental damage */
	di->shared_area = create_area(shared_name, (void **)&(di->si), B_ANY_KERNEL_ADDRESS,
		((sizeof(shared_info) + (B_PAGE_SIZE - 1)) & ~(B_PAGE_SIZE - 1)), B_FULL_LOCK,
		B_USER_CLONEABLE_AREA);
	if (di->shared_area < 0) {
		/* return the error */
		result = di->shared_area;
		goto done;
	}

	/* save a few dereferences */
	si = di->si;

	/* create the DMA command buffer area */
	//fixme? for R4.5 a workaround for cloning would be needed!
	/* 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->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_32_BIT_CONTIGUOUS, /* GPU always needs access */
			B_USER_CLONEABLE_AREA | B_READ_AREA | B_WRITE_AREA);
			// TODO: Physical aligning can be done without waste using the
			// private create_area_etc().
	/* on error, abort */
	if (si->unaligned_dma_area < 0)
	{
		/* free the already created shared_info area, and return the error */
		result = si->unaligned_dma_area;
		goto free_shared;
	}
	/* 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*)
		((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", (addr_t)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", (addr_t)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;
	si->device_id = di->pcii.device_id;
	si->revision = di->pcii.revision;
	si->bus = di->pcii.bus;
	si->device = di->pcii.device;
	si->function = di->pcii.function;

	/* ensure that the accelerant's INIT_ACCELERANT function can be executed */
	si->accelerant_in_use = false;
	/* preset singlehead card to prevent early INT routine calls (once installed) to
	 * wrongly identify the INT request coming from us! */
	si->ps.secondary_head = false;

	/* note the amount of system RAM the system BIOS assigned to the card if applicable:
	 * unified memory architecture (UMA) */
	switch ((((uint32)(si->device_id)) << 16) | si->vendor_id)
	{
	case 0x01a010de: /* Nvidia GeForce2 Integrated GPU */
		/* device at bus #0, device #0, function #1 holds value at byte-index 0x7C */
		si->ps.memory_size = 1024 * 1024 *
			(((((*pci_bus->read_pci_config)(0, 0, 1, 0x7c, 4)) & 0x000007c0) >> 6) + 1);
		/* last 64kB RAM is used for the BIOS (or something else?) */
		si->ps.memory_size -= (64 * 1024);
		break;
	case 0x01f010de: /* Nvidia GeForce4 MX Integrated GPU */
		/* device at bus #0, device #0, function #1 holds value at byte-index 0x84 */
		si->ps.memory_size = 1024 * 1024 *
			(((((*pci_bus->read_pci_config)(0, 0, 1, 0x84, 4)) & 0x000007f0) >> 4) + 1);
		/* last 64kB RAM is used for the BIOS (or something else?) */
		si->ps.memory_size -= (64 * 1024);
		break;
	default:
		/* all other cards have own RAM: the amount of which is determined in the
		 * accelerant. */
		break;
	}

	/* map the device */
	result = map_device(di);
	if (result < 0) goto free_shared_and_alldma;

	/* we will be returning OK status for sure now */
	result = B_OK;

	/* disable and clear any pending interrupts */
	//fixme:
	//distinquish between crtc1/crtc2 once all heads get seperate driver instances!
	disable_vbi_all(di->regs);

	/* preset we can't use INT related functions */
	si->ps.int_assigned = false;

	/* create a semaphore for vertical blank management */
	si->vblank = create_sem(0, di->name);
	if (si->vblank < 0) goto mark_as_open;

	/* change the owner of the semaphores to the opener's team */
	/* this is required because apps can't aquire kernel semaphores */
	thid = find_thread(NULL);
	get_thread_info(thid, &thinfo);
	set_sem_owner(si->vblank, thinfo.team);

	/* If there is a valid interrupt line assigned then set up interrupts */
	if ((di->pcii.u.h0.interrupt_pin == 0x00) ||
	    (di->pcii.u.h0.interrupt_line == 0xff) || /* no IRQ assigned */
	    (di->pcii.u.h0.interrupt_line <= 0x02))   /* system IRQ assigned */
	{
		/* delete the semaphore as it won't be used */
		delete_sem(si->vblank);
		si->vblank = -1;
	}
	else
	{
		/* otherwise install our interrupt handler */
		result = install_io_interrupt_handler(di->pcii.u.h0.interrupt_line, nv_interrupt, (void *)di, 0);
		/* bail if we couldn't install the handler */
		if (result != B_OK)
		{
			/* delete the semaphore as it won't be used */
			delete_sem(si->vblank);
			si->vblank = -1;
		}
		else
		{
			/* inform accelerant(s) we can use INT related functions */
			si->ps.int_assigned = true;
		}
	}

mark_as_open:
	/* mark the device open */
	di->is_open++;

	/* send the cookie to the opener */
	*cookie = di;

	goto done;


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 */
	delete_area(di->shared_area);
	di->shared_area = -1;
	di->si = NULL;

done:
	/* end of critical section */
	RELEASE_BEN(pd->kernel);

	/* all done, return the status */
	return result;
}
コード例 #9
0
ファイル: Overlay.c プロジェクト: AmirAbrams/haiku
const overlay_buffer *ALLOCATE_OVERLAY_BUFFER(color_space cs, uint16 width, uint16 height)
{
	int offset = 0;					/* used to determine next buffer to create */
	uintptr_t adress, adress2, temp32;	/* used to calculate buffer adresses */
	uint32 oldsize = 0;				/* used to 'squeeze' new buffers between already existing ones */
	int cnt;						/* loopcounter */

	/* acquire the shared benaphore */
	AQUIRE_BEN(si->overlay.lock)

	LOG(4,("Overlay: cardRAM_start = $%p\n", (uint8*)si->framebuffer));
	LOG(4,("Overlay: cardRAM_start_DMA = $%p\n", (uint8*)si->framebuffer_pci));
	LOG(4,("Overlay: cardRAM_size = %3.3fMb\n",(si->ps.memory_size / (1024.0 * 1024.0))));

	/* find first empty slot (room for another buffer?) */
	for (offset = 0; offset < MAXBUFFERS; offset++)
	{
		if (si->overlay.myBuffer[offset].buffer == NULL) break;
	}

	LOG(4,("Overlay: Allocate_buffer offset = %d\n",offset));

	if (offset < MAXBUFFERS)
	/* setup new scaler input buffer */
	{
		switch (cs)
		{
			case B_YCbCr422:
					/* check if slopspace is needed: VIA CLE266 needs ~0x0007. */
					si->overlay.myBuffer[offset].width = ((width + 0x0007) & ~0x0007);
					si->overlay.myBuffer[offset].bytes_per_row = 2 * si->overlay.myBuffer[offset].width;

					/* check if the requested horizontal pitch is supported: */
					//fixme: tune for VIA... (overruled below, this should probably be a bytes_per_row check)
					if (si->overlay.myBuffer[offset].width > 4088)
					{
						LOG(4,("Overlay: Sorry, requested buffer pitch not supported, aborted\n"));

						/* release the shared benaphore */
						RELEASE_BEN(si->overlay.lock)

						return NULL;
					}
					break;
			default:
					/* unsupported colorspace! */
					LOG(4,("Overlay: Sorry, colorspace $%08x not supported, aborted\n",cs));

					/* release the shared benaphore */
					RELEASE_BEN(si->overlay.lock)

					return NULL;
					break;
		}

		/* check if the requested buffer width is supported */
		if (si->overlay.myBuffer[offset].width > 1024)
		{
			LOG(4,("Overlay: Sorry, requested buffer width not supported, aborted\n"));

			/* release the shared benaphore */
			RELEASE_BEN(si->overlay.lock)

			return NULL;
		}
コード例 #10
0
ファイル: driver.c プロジェクト: looncraz/haiku
static status_t et6000OpenHook(const char* name, uint32 flags, void** cookie) {
int32 index = 0;
ET6000DeviceInfo *di;
ET6000SharedInfo *si;
status_t        result = B_OK;
char shared_name[B_OS_NAME_LENGTH];

    ddprintf(("SKD et6000OpenHook(%s, %ld, 0x%08lx)\n", name, flags, (uint32)cookie));

    /* find the device name in the list of devices */
    /* we're never passed a name we didn't publish */
    while(pd->deviceNames[index] &&
         (strcmp(name, pd->deviceNames[index]) != 0))
    {
        index++;
    }

    /* for convienience */
    di = &(pd->di[index]);

    /* make sure no one else has write access to the common data */
    AQUIRE_BEN(pd->kernel);

    /* if it's already open for writing */
    if (di->isOpen) {
        /* mark it open another time */
        goto mark_as_open;
    }
    /* create the shared area */
    sprintf(shared_name, "%04X_%04X_%02X%02X%02X shared",
        di->pcii.vendor_id, di->pcii.device_id,
        di->pcii.bus, di->pcii.device, di->pcii.function);
    /* create this area with NO user-space read or write permissions, to prevent accidental dammage */
    di->sharedArea = create_area(shared_name, (void **)&(di->si), B_ANY_KERNEL_ADDRESS, ((sizeof(ET6000SharedInfo) + (B_PAGE_SIZE - 1)) & ~(B_PAGE_SIZE - 1)), B_FULL_LOCK,
		B_FULL_LOCK, B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA | B_USER_CLONEABLE_AREA);
    if (di->sharedArea < 0) {
        /* return the error */
        result = di->sharedArea;
        goto done;
    }

    /* save a few dereferences */
    si = di->si;

    /* save the vendor and device IDs */
    si->vendor_id = di->pcii.vendor_id;
    si->device_id = di->pcii.device_id;
    si->revision = di->pcii.revision;

    si->pixelClockMax16 = 135000;
    si->pixelClockMax24 = 135000;
    if (si->vendor_id == 0x100C) { /* Tseng Labs, Inc. */
        switch (si->device_id) {
        case 0x3208:/* ET6000/ET6100 */
            if (si->revision < 0x70) { /* ET6000 */
                si->pixelClockMax16 = 135000;
                si->pixelClockMax24 = 135000;
            }
            else { /* ET6100 */
                si->pixelClockMax16 = 175000;
                si->pixelClockMax24 = 175000;
            }
            break;
        case 0x4702: /* ET6300 */
            si->pixelClockMax16 = 220000;
            si->pixelClockMax24 = 220000;
            break;
        }
    }

    /* map the device */
    result = et6000MapDevice(di);
    if (result < 0)
        goto free_shared;
    result = B_OK;

    /*
     * Clear any pending interrupts and disable interrupts. Driver
     * currently does not use interrupts and unlikely will in future.
     */
    et6000aclReadInterruptClear(si->mmRegs);
    et6000aclWriteInterruptClear(si->mmRegs);
    et6000aclMasterInterruptDisable(si->mmRegs);

    /* Install the interrupt handler */
    result = install_io_interrupt_handler(di->pcii.u.h0.interrupt_line,
                                       et6000Interrupt, (void *)di, 0);
    /* bail if we couldn't install the handler */
    if (result != B_OK)
        goto unmap;

mark_as_open:
    /* mark the device open */
    di->isOpen++;

    /* send the cookie to the opener */
    *cookie = di;

    goto done;

unmap:
    et6000UnmapDevice(di);

free_shared:
    /* clean up our shared area */
    delete_area(di->sharedArea);
    di->sharedArea = -1;
    di->si = NULL;

done:
    /* end of critical section */
    RELEASE_BEN(pd->kernel);

    /* all done, return the status */
    ddprintf(("et6000OpenHook returning 0x%08lx\n", result));

    return result;
}