Пример #1
0
static status_t
device_ioctl(void* dev, uint32 msg, void* buffer, size_t bufferLength)
{
	DeviceInfo& di = *((DeviceInfo*)dev);

//	TRACE("device_ioctl(); ioctl: %lu, buffer: 0x%08lx, bufLen: %lu\n", msg,
//		(uint32)buffer, bufferLength);

	switch (msg) {
		case B_GET_ACCELERANT_SIGNATURE:
			strcpy((char*)buffer, ATI_ACCELERANT_NAME);
			return B_OK;

		case ATI_DEVICE_NAME:
			strncpy((char*)buffer, di.name, B_OS_NAME_LENGTH);
			((char*)buffer)[B_OS_NAME_LENGTH -1] = '\0';
			return B_OK;

		case ATI_GET_SHARED_DATA:
			if (bufferLength != sizeof(area_id))
				return B_BAD_DATA;

			*((area_id*)buffer) = di.sharedArea;
			return B_OK;

		case ATI_GET_EDID:
		{
			if (bufferLength != sizeof(edid1_raw))
				return B_BAD_DATA;

			edid1_raw rawEdid;
			status_t status = GetEdidFromBIOS(rawEdid);
			if (status == B_OK)
				user_memcpy((edid1_raw*)buffer, &rawEdid, sizeof(rawEdid));
			return status;
		}

		case ATI_SET_VESA_DISPLAY_MODE:
			if (bufferLength != sizeof(uint16))
				return B_BAD_DATA;

			return SetVesaDisplayMode(*((uint16*)buffer));

		case ATI_RUN_INTERRUPTS:
			if (bufferLength != sizeof(bool))
				return B_BAD_DATA;

			if (*((bool*)buffer))
				EnableVBI();
			else
				DisableVBI();

			return B_OK;
	}

	return B_DEV_INVALID_IOCTL;
}
Пример #2
0
static void
InitInterruptHandler(DeviceInfo& di)
{
	SharedInfo& si = *(di.sharedInfo);

	TRACE("enter InitInterruptHandler()\n");

	DisableVBI();					// disable & clear any pending interrupts
	si.bInterruptAssigned = false;	// indicate interrupt not assigned yet

	// Create a semaphore for vertical blank management.
	si.vertBlankSem = create_sem(0, di.name);
	if (si.vertBlankSem < 0)
		return;

	// Change the owner of the semaphores to the calling team (usually the
	// app_server).  This is required because apps can't aquire kernel
	// semaphores.

	thread_id threadID = find_thread(NULL);
	thread_info threadInfo;
	status_t status = get_thread_info(threadID, &threadInfo);
	if (status == B_OK)
		status = set_sem_owner(si.vertBlankSem, threadInfo.team);

	// If there is a valid interrupt assigned, set up interrupts.

	if (status == B_OK && di.pciInfo.u.h0.interrupt_pin != 0x00
		&& di.pciInfo.u.h0.interrupt_line != 0xff) {
		// We have a interrupt line to use.

		status = install_io_interrupt_handler(di.pciInfo.u.h0.interrupt_line,
			InterruptHandler, (void*)(&di), 0);

		if (status == B_OK)
			si.bInterruptAssigned = true;	// we can use interrupt related functions
	}

	if (status != B_OK) {
		// Interrupt does not exist; thus delete semaphore as it won't be used.
		delete_sem(si.vertBlankSem);
		si.vertBlankSem = -1;
	}
}
Пример #3
0
static status_t
device_free(void* dev)
{
	DeviceInfo& di = *((DeviceInfo*)dev);
	SharedInfo& si = *(di.sharedInfo);
	pci_info& pciInfo = di.pciInfo;

	TRACE("enter device_free()\n");

	gLock.Acquire();		// lock driver

	// If opened multiple times, merely decrement the open count and exit.

	if (di.openCount <= 1) {
		DisableVBI();		// disable & clear any pending interrupts

		if (si.bInterruptAssigned) {
			remove_io_interrupt_handler(pciInfo.u.h0.interrupt_line,
				InterruptHandler, &di);
		}

		// Delete the semaphores, ignoring any errors because the owning team
		// may have died.
		if (si.vertBlankSem >= 0)
			delete_sem(si.vertBlankSem);
		si.vertBlankSem = -1;

		UnmapDevice(di);	// free regs and frame buffer areas

		delete_area(di.sharedArea);
		di.sharedArea = -1;
		di.sharedInfo = NULL;
	}

	if (di.openCount > 0)
		di.openCount--;		// mark device available

	gLock.Release();	// unlock driver

	TRACE("exit device_free() openCount: %ld\n", di.openCount);
	return B_OK;
}
Пример #4
0
static status_t
device_ioctl(void* dev, uint32 msg, void* buf, size_t len)
{
	DeviceInfo& di = *((DeviceInfo*)dev);

	(void)len;		// avoid compiler warning for unused arg

//	TRACE("device_ioctl(); ioctl: %lu, buf: 0x%08lx, len: %lu\n", msg, (uint32)buf, len);

	switch (msg) {
		case B_GET_ACCELERANT_SIGNATURE:
			strcpy((char*)buf, "s3.accelerant");
			return B_OK;

		case S3_DEVICE_NAME:
			strncpy((char*)buf, di.name, B_OS_NAME_LENGTH);
			((char*)buf)[B_OS_NAME_LENGTH -1] = '\0';
			return B_OK;

		case S3_GET_PRIVATE_DATA:
		{
			S3GetPrivateData* gpd = (S3GetPrivateData*)buf;
			if (gpd->magic == S3_PRIVATE_DATA_MAGIC) {
				gpd->sharedInfoArea = di.sharedArea;
				return B_OK;
			}
			break;
		}

		case S3_GET_EDID:
		{
#ifdef __HAIKU__
			S3GetEDID* ged = (S3GetEDID*)buf;
			if (ged->magic == S3_PRIVATE_DATA_MAGIC) {
				edid1_raw rawEdid;
				status_t status = GetEdidFromBIOS(rawEdid);
				if (status == B_OK)
					user_memcpy(&ged->rawEdid, &rawEdid, sizeof(rawEdid));
				return status;
			}
#else
			return B_UNSUPPORTED;
#endif
			break;
		}

		case S3_GET_PIO:
		{
			S3GetSetPIO* gsp = (S3GetSetPIO*)buf;
			if (gsp->magic == S3_PRIVATE_DATA_MAGIC) {
				switch (gsp->size) {
					case 1:
						gsp->value = gPCI->read_io_8(gsp->offset);
						break;
					case 2:
						gsp->value = gPCI->read_io_16(gsp->offset);
						break;
					case 4:
						gsp->value = gPCI->read_io_32(gsp->offset);
						break;
					default:
						TRACE("device_ioctl() S3_GET_PIO invalid size: %ld\n", gsp->size);
						return B_ERROR;
				}
				return B_OK;
			}
			break;
		}

		case S3_SET_PIO:
		{
			S3GetSetPIO* gsp = (S3GetSetPIO*)buf;
			if (gsp->magic == S3_PRIVATE_DATA_MAGIC) {
				switch (gsp->size) {
					case 1:
						gPCI->write_io_8(gsp->offset, gsp->value);
						break;
					case 2:
						gPCI->write_io_16(gsp->offset, gsp->value);
						break;
					case 4:
						gPCI->write_io_32(gsp->offset, gsp->value);
						break;
					default:
						TRACE("device_ioctl() S3_SET_PIO invalid size: %ld\n", gsp->size);
						return B_ERROR;
				}
				return B_OK;
			}
			break;
		}

		case S3_RUN_INTERRUPTS:
		{
			S3SetBoolState* ri = (S3SetBoolState*)buf;
			if (ri->magic == S3_PRIVATE_DATA_MAGIC) {
				if (ri->bEnable)
					EnableVBI();
				else
					DisableVBI();
			}
			return B_OK;
		}
	}

	return B_DEV_INVALID_IOCTL;
}