Example #1
0
static status_t
MapDevice(DeviceInfo& di)
{
	SharedInfo& si = *(di.sharedInfo);
	pci_info& pciInfo = di.pciInfo;

	// Enable memory mapped IO and bus master.

	SetPCI(pciInfo, PCI_command, 2, GetPCI(pciInfo, PCI_command, 2)
		| PCI_command_io | PCI_command_memory | PCI_command_master);

	// Map the video memory.

	phys_addr_t videoRamAddr = pciInfo.u.h0.base_registers[0];
	uint32 videoRamSize = pciInfo.u.h0.base_register_sizes[0];
	si.videoMemPCI = videoRamAddr;
	char frameBufferAreaName[] = "ATI frame buffer";

	si.videoMemArea = map_physical_memory(
		frameBufferAreaName,
		videoRamAddr,
		videoRamSize,
		B_ANY_KERNEL_BLOCK_ADDRESS | B_MTR_WC,
		B_READ_AREA + B_WRITE_AREA,
		(void**)&(si.videoMemAddr));

	if (si.videoMemArea < 0) {
		// Try to map this time without write combining.
		si.videoMemArea = map_physical_memory(
			frameBufferAreaName,
			videoRamAddr,
			videoRamSize,
			B_ANY_KERNEL_BLOCK_ADDRESS,
			B_READ_AREA + B_WRITE_AREA,
			(void**)&(si.videoMemAddr));
	}

	if (si.videoMemArea < 0)
		return si.videoMemArea;

	// Map the MMIO register area.

	phys_addr_t regsBase = pciInfo.u.h0.base_registers[2];
	uint32 regAreaSize = pciInfo.u.h0.base_register_sizes[2];

	// If the register area address or size is not in the PCI info, it should
	// be at the end of the video memory.  Check if it is there.

	if (MACH64_FAMILY(si.chipType) && (regsBase == 0 || regAreaSize == 0)) {
		uint32 regsOffset = 0x7ff000;	// offset to regs area in video memory
		uint32 regs = uint32(si.videoMemAddr) + regsOffset;
		uint32 chipInfo = *((vuint32*)(regs + M64_CONFIG_CHIP_ID));

		if (si.deviceID != (chipInfo & M64_CFG_CHIP_TYPE)) {
			// Register area not found;  delete any other areas that were
			// created.
			delete_area(si.videoMemArea);
			si.videoMemArea = -1;
			TRACE("Mach64 register area not found\n");
			return B_ERROR;
		}

		// Adjust params for creating register area below.

		regsBase = videoRamAddr + regsOffset;
		regAreaSize = 0x1000;
		TRACE("Register address is at end of frame buffer memory at 0x%lx\n",
			uint32(regsBase));
	}

	si.regsArea = map_physical_memory("ATI mmio registers",
		regsBase,
		regAreaSize,
		B_ANY_KERNEL_ADDRESS,
		0,		// neither read nor write, to hide it from user space apps
		(void**)&di.regs);

	// If there was an error, delete other areas.
	if (si.regsArea < 0) {
		delete_area(si.videoMemArea);
		si.videoMemArea = -1;
	}

	return si.regsArea;
}
static status_t
MapDevice(DeviceInfo& di)
{
	char areaName[B_OS_NAME_LENGTH];
	SharedInfo& si = *(di.sharedInfo);
	pci_info& pciInfo = di.pciInfo;

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

	// Enable memory mapped IO and bus master.

	SetPCI(pciInfo, PCI_command, 2, GetPCI(pciInfo, PCI_command, 2)
		| PCI_command_io | PCI_command_memory | PCI_command_master);

	const uint32 SavageMmioRegBaseOld	= 0x1000000;	// 16 MB
	const uint32 SavageMmioRegBaseNew	= 0x0000000;
	const uint32 SavageMmioRegSize		= 0x0080000;	// 512 KB reg area size

	const uint32 VirgeMmioRegBase		= 0x1000000;	// 16 MB
	const uint32 VirgeMmioRegSize		= 0x10000;		// 64 KB reg area size

	uint32 videoRamAddr = 0;
	uint32 videoRamSize = 0;
	uint32 regsBase = 0;
	uint32 regAreaSize = 0;

	// Since we do not know at this point the actual size of the video
	// memory, set it to the largest value that the respective chipset
	// family can have.

	if (S3_SAVAGE_FAMILY(di.pChipInfo->chipType)) {
		if (S3_SAVAGE_3D_SERIES(di.pChipInfo->chipType)) {
			// Savage 3D & Savage MX chips.

			regsBase = pciInfo.u.h0.base_registers[0] + SavageMmioRegBaseOld;
			regAreaSize = SavageMmioRegSize;

	 		videoRamAddr = pciInfo.u.h0.base_registers[0];
			videoRamSize = 16 * 1024 * 1024;	// 16 MB is max for 3D series
			si.videoMemPCI = (void *)(pciInfo.u.h0.base_registers_pci[0]);
		} else {
			// All other Savage chips.

			regsBase = pciInfo.u.h0.base_registers[0] + SavageMmioRegBaseNew;
			regAreaSize = SavageMmioRegSize;

			videoRamAddr = pciInfo.u.h0.base_registers[1];
			videoRamSize = pciInfo.u.h0.base_register_sizes[1];
			si.videoMemPCI = (void *)(pciInfo.u.h0.base_registers_pci[1]);
		}
	} else {
		// Trio/Virge chips.

		regsBase = pciInfo.u.h0.base_registers[0] + VirgeMmioRegBase;
		regAreaSize = VirgeMmioRegSize;

 		videoRamAddr = pciInfo.u.h0.base_registers[0];
		videoRamSize = 8 * 1024 * 1024;	// 8 MB is max for Trio/Virge chips
		si.videoMemPCI = (void *)(pciInfo.u.h0.base_registers_pci[0]);
	}

	// Map the MMIO register area.

	sprintf(areaName, DEVICE_FORMAT " regs",
		pciInfo.vendor_id, pciInfo.device_id,
		pciInfo.bus, pciInfo.device, pciInfo.function);

	si.regsArea = map_physical_memory(areaName, regsBase, regAreaSize,
		B_ANY_KERNEL_ADDRESS,
		0,		// neither read nor write, to hide it from user space apps
		(void**)(&(di.regs)));

	if (si.regsArea < 0)
		return si.regsArea;	// return error code

	// Map the video memory.

	sprintf(areaName, DEVICE_FORMAT " framebuffer",
		pciInfo.vendor_id, pciInfo.device_id,
		pciInfo.bus, pciInfo.device, pciInfo.function);

	si.videoMemArea = map_physical_memory(
		areaName,
		videoRamAddr,
		videoRamSize,
		B_ANY_KERNEL_BLOCK_ADDRESS | B_MTR_WC,
		B_READ_AREA + B_WRITE_AREA,
		&(si.videoMemAddr));

	if (si.videoMemArea < 0) {
		// Try to map this time without write combining.
		si.videoMemArea = map_physical_memory(
			areaName,
			videoRamAddr,
			videoRamSize,
			B_ANY_KERNEL_BLOCK_ADDRESS,
			B_READ_AREA + B_WRITE_AREA,
			&(si.videoMemAddr));
	}

	TRACE("Video memory, area: %ld,  addr: 0x%lX\n", si.videoMemArea, (uint32)(si.videoMemAddr));

	// If there was an error, delete other areas.
	if (si.videoMemArea < 0) {
		delete_area(si.regsArea);
		si.regsArea = -1;
	}

	TRACE("leave MapDevice(); result: %ld\n", si.videoMemArea);
	return si.videoMemArea;
}