Beispiel #1
0
status_t
submit_tx_command(bt_usb_dev* bdev, snet_buffer* snbuf)
{
	uint8 bRequestType = bdev->ctrl_req;
	uint8 bRequest = 0;
	uint16 wIndex = 0;
	uint16 value = 0;
	uint16 wLength = B_HOST_TO_LENDIAN_INT16(snb_size(snbuf));
	status_t error;

	if (!GET_BIT(bdev->state, RUNNING)) {
		return B_DEV_NOT_READY;
	}

	// set cookie
	snb_set_cookie(snbuf, bdev);

	debugf("@%p\n", snb_get(snbuf));

	error = usb->queue_request(bdev->dev, bRequestType, bRequest,
		value, wIndex, wLength,	snb_get(snbuf),
#ifndef HAIKU_TARGET_PLATFORM_HAIKU
		wLength,
#endif
		command_complete, (void*) snbuf);

	if (error != B_OK) {
		bdev->stat.rejectedTX++;
	} else {
		bdev->stat.acceptedTX++;
	}

	return error;
}
Beispiel #2
0
void 
PCL6Writer::Append(uint16 value)
{
	int16 v = B_HOST_TO_LENDIAN_INT16(value);
	Append(BYTE_AT(v, 0));  
	Append(BYTE_AT(v, 1));  
}
Beispiel #3
0
ssize_t
QuickCamDevice::ReadIIC16(uint8 address, uint16 *data)
{
	status_t err;
	uint8 buffer[0x23];
	memset(buffer, 0, sizeof(buffer));
	buffer[0x20] = Sensor() ? Sensor()->IICReadAddress() : 0;
	buffer[0x21] = 1 - 1;
	buffer[0x22] = 0x03;
	buffer[0] = address;
	err = SendCommand(USB_REQTYPE_DEVICE_OUT, 0x04, STV_I2C_WRITE, 0, 0x23, buffer);
	if (err < B_OK)
		return err;

	buffer[0] = 0xaa;
	buffer[1] = 0xaa;
	err = SendCommand(USB_REQTYPE_DEVICE_IN, 0x04, STV_I2C_READ, 0, 0x2, buffer);
	PRINT((CH ": SendCommand: %s" CT, strerror(err)));
	if (err < B_OK)
		return err;

	if (fChipIsBigEndian)
		*data = B_HOST_TO_BENDIAN_INT16(*(uint16 *)(&buffer[0]));
	else
		*data = B_HOST_TO_LENDIAN_INT16(*(uint16 *)(&buffer[0]));
	PRINT((CH ": 0x%04x" CT, *data));
	return 2;
}
Beispiel #4
0
// utf8 to LENDIAN unicode
static status_t
_utf8_to_lendian_unicode(
	const char	*src,
	size_t		*srcLen,
	char		*dst,
	size_t		*dstLen)
{
	size_t srcLimit = *srcLen;
	size_t dstLimit = *dstLen - 1;
	size_t srcCount = 0;
	size_t dstCount = 0;
	status_t status = B_ERROR;

	while ((srcCount < srcLimit) && (dstCount < dstLimit)) {
		uint16	unicode;
		uint16	*UNICODE = &unicode;
		uchar	*UTF8 = (uchar *)src + srcCount;
		int     err_flag;

		if ((srcCount + utf8_char_len(src[srcCount])) > srcLimit)
			break;

		utf8_to_u_hostendian(UTF8, UNICODE, err_flag);
		if (err_flag == 1)
			return EINVAL;

		unicode = B_HOST_TO_LENDIAN_INT16(unicode);
		if ((dstCount + 1) > dstLimit) {
			status = B_BUFFER_OVERFLOW;
			break;
		}
		dst[dstCount++] = unicode & 0xFF;
		dst[dstCount++] = unicode >> 8;

		srcCount += UTF8 - ((uchar *)(src + srcCount));
		status = B_OK;
	}

	*srcLen = srcCount;
	*dstLen = dstCount;

	return status;
}
Beispiel #5
0
// utf8 to LENDIAN unicode
static status_t
_utf8_to_lendian_unicode(
	const char	*src,
	int32		*srcLen,
	char		*dst,
	uint32		*dstLen)
{
	int32 srcLimit = *srcLen;
	int32 dstLimit = *dstLen - 1;
	int32 srcCount = 0;
	int32 dstCount = 0;

	while ((srcCount < srcLimit) && (dstCount < dstLimit)) {
		uint16	unicode;
		uint16	*UNICODE = &unicode;
		uchar	*UTF8 = (uchar *)src + srcCount;
		int     err_flag;

		if ((srcCount + utf8_char_len(src[srcCount])) > srcLimit)
			break;

		utf8_to_u_hostendian(UTF8, UNICODE, err_flag);
		if(err_flag == 1)
			return EINVAL;

		unicode = B_HOST_TO_LENDIAN_INT16(unicode);
		dst[dstCount++] = unicode & 0xFF;
		dst[dstCount++] = unicode >> 8;

		srcCount += UTF8 - ((uchar *)(src + srcCount));
	}

	*srcLen = srcCount;
	*dstLen = dstCount;

	return ((dstCount > 0) ? B_NO_ERROR : B_ERROR);
}
status_t Initialize(int fatbits, const char *device, const char *label, bool noprompt, bool testmode)
{
    if (fatbits != 0 && fatbits != 12 && fatbits != 16 && fatbits != 32) {
        fprintf(stderr,"Error: don't know how to create a %d bit fat\n",fatbits);
        return B_ERROR;
    }
    //XXX the following two checks can be removed when this is fixed:
#ifndef WITH_FLOPPY_SUPPORT
    if (0 != strstr(device,"floppy")) {
        fprintf(stderr,"Error: floppy B_GET_GEOMETRY and B_GET_BIOS_GEOMETRY calls are broken, floppy not supported\n");
        return B_ERROR;
    }
    if (fatbits == 12) {
        fprintf(stderr,"Error: can't create a 12 bit fat on a device other than floppy\n");
        return B_ERROR;
    }
#endif

    printf("device = %s\n",device);

    int fd = open(device, O_RDWR);
    if (fd < 0) {
        fprintf(stderr, "Error: couldn't open file for device %s (%s)\n", device, strerror(errno));
        return B_ERROR;
    }

    bool isRawDevice;
    bool hasBiosGeometry;
    bool hasDeviceGeometry;
    bool hasPartitionInfo;
    device_geometry biosGeometry;
    device_geometry deviceGeometry;
    partition_info 	partitionInfo;

    isRawDevice = 0 != strstr(device, "/raw");
    hasBiosGeometry = B_OK == ioctl(fd, B_GET_BIOS_GEOMETRY, &biosGeometry, sizeof(biosGeometry));
    hasDeviceGeometry = B_OK == ioctl(fd, B_GET_GEOMETRY, &deviceGeometry, sizeof(deviceGeometry));
    hasPartitionInfo = B_OK == ioctl(fd, B_GET_PARTITION_INFO, &partitionInfo, sizeof(partitionInfo));

    if (!isRawDevice && !hasBiosGeometry && !hasDeviceGeometry && !hasPartitionInfo)
        isRawDevice = true;

    if (hasBiosGeometry) {
        printf("bios geometry: %ld heads, %ld cylinders, %ld sectors/track, %ld bytes/sector\n",
               biosGeometry.head_count,biosGeometry.cylinder_count,biosGeometry.sectors_per_track,biosGeometry.bytes_per_sector);
    }
    if (hasBiosGeometry) {
        printf("device geometry: %ld heads, %ld cylinders, %ld sectors/track, %ld bytes/sector\n",
               deviceGeometry.head_count,deviceGeometry.cylinder_count,deviceGeometry.sectors_per_track,deviceGeometry.bytes_per_sector);
    }
    if (hasPartitionInfo) {
        printf("partition info: start at %Ld bytes (%Ld sectors), %Ld KB, %Ld MB, %Ld GB\n",
               partitionInfo.offset,
               partitionInfo.offset / 512,
               partitionInfo.offset / 1024,
               partitionInfo.offset / (1024 * 1024),
               partitionInfo.offset / (1024 * 1024 * 1024));
        printf("partition info: size %Ld bytes, %Ld KB, %Ld MB, %Ld GB\n",
               partitionInfo.size,
               partitionInfo.size / 1024,
               partitionInfo.size / (1024 * 1024),
               partitionInfo.size / (1024 * 1024 * 1024));
    }

    if (!isRawDevice && !hasPartitionInfo) {
        fprintf(stderr,"Warning: couldn't get partition information\n");
    }
    if ((hasBiosGeometry && biosGeometry.bytes_per_sector != 512)
            ||	(hasDeviceGeometry && deviceGeometry.bytes_per_sector != 512)) {
        fprintf(stderr,"Error: geometry block size not 512 bytes\n");
        close(fd);
        return B_ERROR;
    } else if (hasPartitionInfo && partitionInfo.logical_block_size != 512) {
        printf("partition logical block size is not 512, it's %ld bytes\n",
               partitionInfo.logical_block_size);
    }

    if (hasDeviceGeometry && deviceGeometry.read_only) {
        fprintf(stderr,"Error: this is a read-only device\n");
        close(fd);
        return B_ERROR;
    }
    if (hasDeviceGeometry && deviceGeometry.write_once) {
        fprintf(stderr,"Error: this is a write-once device\n");
        close(fd);
        return B_ERROR;
    }
    uint64 size = 0;

    if (hasPartitionInfo) {
        size = partitionInfo.size;
    } else if (hasDeviceGeometry) {
        size = uint64(deviceGeometry.bytes_per_sector) * deviceGeometry.sectors_per_track * deviceGeometry.cylinder_count * deviceGeometry.head_count;
    } else if (hasBiosGeometry) {
        size = uint64(biosGeometry.bytes_per_sector) * biosGeometry.sectors_per_track * biosGeometry.cylinder_count * biosGeometry.head_count;
    } else {
        // maybe it's just a file
        struct stat stat;
        if (fstat(fd, &stat) < 0) {
            fprintf(stderr, "Error: couldn't get device partition or geometry information, nor size\n");
            close(fd);
            return B_ERROR;
        }
        size = stat.st_size;
    }

    // TODO still valid on Haiku ?
    /*if (isRawDevice && size > FLOPPY_MAX_SIZE) {
    	fprintf(stderr,"Error: device too large for floppy, or raw devices not supported\n");
    	close(fd);
    	return B_ERROR;
    }*/

    printf("size = %Ld bytes (%Ld sectors), %Ld KB, %Ld MB, %Ld GB\n",
           size,
           size / 512,
           size / 1024,
           size / (1024 * 1024),
           size / (1024 * 1024 * 1024));

    if (fatbits == 0) {
        //auto determine fat type
        if (isRawDevice && size <= FLOPPY_MAX_SIZE && (size / FAT12_CLUSTER_MAX_SIZE) < FAT12_MAX_CLUSTER_COUNT) {
            fatbits = 12;
        } else if ((size / CLUSTER_MAX_SIZE) < FAT16_MAX_CLUSTER_COUNT) {
            fatbits = 16;
        } else if ((size / CLUSTER_MAX_SIZE) < FAT32_MAX_CLUSTER_COUNT) {
            fatbits = 32;
        }
    }

    if (fatbits == 0) {
        fprintf(stderr,"Error: device too large for 32 bit fat\n");
        close(fd);
        return B_ERROR;
    }

    int sectorPerCluster;

    sectorPerCluster = 0;
    if (fatbits == 12) {
        sectorPerCluster = 0;
        if (size <= 4182016LL)
            sectorPerCluster = 2;	// XXX don't know the correct value
        if (size <= 2091008LL)
            sectorPerCluster = 1;	// XXX don't know the correct value
    } else if (fatbits == 16) {
        // special BAD_CLUSTER value is 0xFFF7,
        // but this should work anyway, since space required by
        // two FATs will make maximum cluster count smaller.
        // at least, this is what I think *should* happen
        sectorPerCluster = 0;				//larger than 2 GB must fail
        if (size <= (2048 * 1024 * 1024LL))	// up to 2GB, use 32k clusters
            sectorPerCluster = 64;
        if (size <= (1024 * 1024 * 1024LL))	// up to 1GB, use 16k clusters
            sectorPerCluster = 32;
        if (size <= (512 * 1024 * 1024LL))	// up to 512MB, use 8k clusters
            sectorPerCluster = 16;
        if (size <= (256 * 1024 * 1024LL))	// up to 256MB, use 4k clusters
            sectorPerCluster = 8;
        if (size <= (128 * 1024 * 1024LL))	// up to 128MB, use 2k clusters
            sectorPerCluster = 4;
        if (size <= (16 * 1024 * 1024LL))	// up to 16MB, use 2k clusters
            sectorPerCluster = 2;
        if (size <= 4182016LL)				// smaller than fat32 must fail
            sectorPerCluster = 0;
    }
    if (fatbits == 32) {
        sectorPerCluster = 64;				// default is 32k clusters
        if (size <= (32 * 1024 * 1024 * 1024LL))	// up to 32GB, use 16k clusters
            sectorPerCluster = 32;
        if (size <= (16 * 1024 * 1024 * 1024LL))	// up to 16GB, use 8k clusters
            sectorPerCluster = 16;
        if (size <= (8 * 1024 * 1024 * 1024LL))		// up to 8GB, use 4k clusters
            sectorPerCluster = 8;
        if (size <= (532480 * 512LL))				// up to 260 MB, use 0.5k clusters
            sectorPerCluster = 1;
        if (size <= (66600 * 512LL))		// smaller than 32.5 MB must fail
            sectorPerCluster = 0;
    }

    if (sectorPerCluster == 0) {
        fprintf(stderr,"Error: failed to determine sector per cluster value, partition too large for %d bit fat\n",fatbits);
        close(fd);
        return B_ERROR;
    }

    int reservedSectorCount = 0; // avoid compiler warning
    int rootEntryCount = 0; // avoid compiler warning
    int numFATs;
    int sectorSize;
    uint8 biosDriveId;

    // get bios drive-id, or use 0x80
    if (B_OK != ioctl(fd, B_GET_BIOS_DRIVE_ID, &biosDriveId, sizeof(biosDriveId))) {
        biosDriveId = 0x80;
    } else {
        printf("bios drive id: 0x%02x\n", (int)biosDriveId);
    }

    // default parameters for the bootsector
    numFATs = 2;
    sectorSize = 512;
    if (fatbits == 12 || fatbits == 16)
        reservedSectorCount = 1;
    if (fatbits == 32)
        reservedSectorCount = 32;
    if (fatbits == 12)
        rootEntryCount = 128; // XXX don't know the correct value
    if (fatbits == 16)
        rootEntryCount = 512;
    if (fatbits == 32)
        rootEntryCount = 0;

    // Determine FATSize
    // calculation done as MS recommends
    uint64 dskSize = size / sectorSize;
    uint32 rootDirSectors = ((rootEntryCount * 32) + (sectorSize - 1)) / sectorSize;
    uint64 tmpVal1 = dskSize - (reservedSectorCount + rootDirSectors);
    uint64 tmpVal2 = (256 * sectorPerCluster) + numFATs;
    if (fatbits == 32)
        tmpVal2 = tmpVal2 / 2;
    uint32 FATSize = (tmpVal1 + (tmpVal2 - 1)) / tmpVal2;
    // FATSize should now contain the size of *one* FAT, measured in sectors
    // RootDirSectors should now contain the size of the fat12/16 root directory, measured in sectors

    printf("fatbits = %d, clustersize = %d\n", fatbits, sectorPerCluster * 512);
    printf("FAT size is %ld sectors\n", FATSize);
    printf("disk label: %s\n", label);

    char bootsector[512];
    memset(bootsector,0x00,512);
    memcpy(bootsector + BOOTJMP_START_OFFSET, bootjmp, sizeof(bootjmp));
    memcpy(bootsector + BOOTCODE_START_OFFSET, bootcode, sizeof(bootcode));

    if (fatbits == 32) {
        bootsector32 *bs = (bootsector32 *)bootsector;
        uint16 temp16;
        uint32 temp32;
        memcpy(bs->BS_OEMName,"Haiku   ",8);
        bs->BPB_BytsPerSec = B_HOST_TO_LENDIAN_INT16(sectorSize);
        bs->BPB_SecPerClus = sectorPerCluster;
        bs->BPB_RsvdSecCnt = B_HOST_TO_LENDIAN_INT16(reservedSectorCount);
        bs->BPB_NumFATs = numFATs;
        bs->BPB_RootEntCnt = B_HOST_TO_LENDIAN_INT16(rootEntryCount);
        bs->BPB_TotSec16 = B_HOST_TO_LENDIAN_INT16(0);
        bs->BPB_Media = 0xF8;
        bs->BPB_FATSz16 = B_HOST_TO_LENDIAN_INT16(0);
        temp16 = hasBiosGeometry ? biosGeometry.sectors_per_track : 63;
        bs->BPB_SecPerTrk = B_HOST_TO_LENDIAN_INT16(temp16);
        temp16 = hasBiosGeometry ? biosGeometry.head_count : 255;
        bs->BPB_NumHeads = B_HOST_TO_LENDIAN_INT16(temp16);
        temp32 = hasPartitionInfo ? (partitionInfo.size / 512) : 0;
        bs->BPB_HiddSec = B_HOST_TO_LENDIAN_INT32(temp32);
        temp32 = size / 512;
        bs->BPB_TotSec32 = B_HOST_TO_LENDIAN_INT32(temp32);
        bs->BPB_FATSz32 = B_HOST_TO_LENDIAN_INT32(FATSize);
        bs->BPB_ExtFlags = B_HOST_TO_LENDIAN_INT16(0);
        bs->BPB_FSVer = B_HOST_TO_LENDIAN_INT16(0);
        bs->BPB_RootClus = B_HOST_TO_LENDIAN_INT32(FAT32_ROOT_CLUSTER);
        bs->BPB_FSInfo = B_HOST_TO_LENDIAN_INT16(FSINFO_SECTOR_NUM);
        bs->BPB_BkBootSec = B_HOST_TO_LENDIAN_INT16(BACKUP_SECTOR_NUM);
        memset(bs->BPB_Reserved,0,12);
        bs->BS_DrvNum = biosDriveId;
        bs->BS_Reserved1 = 0x00;
        bs->BS_BootSig = 0x29;
        *(uint32*)bs->BS_VolID = (uint32)system_time();
        memcpy(bs->BS_VolLab,"NO NAME    ",11);
        memcpy(bs->BS_FilSysType,"FAT32   ",8);
        bs->signature = B_HOST_TO_LENDIAN_INT16(0xAA55);
    } else {
        bootsector1216 *bs = (bootsector1216 *)bootsector;
        uint16 temp16;
        uint32 temp32;
        uint32 sectorcount = size / 512;
        memcpy(bs->BS_OEMName, "Haiku   ", 8);
        bs->BPB_BytsPerSec = B_HOST_TO_LENDIAN_INT16(sectorSize);
        bs->BPB_SecPerClus = sectorPerCluster;
        bs->BPB_RsvdSecCnt = B_HOST_TO_LENDIAN_INT16(reservedSectorCount);
        bs->BPB_NumFATs = numFATs;
        bs->BPB_RootEntCnt = B_HOST_TO_LENDIAN_INT16(rootEntryCount);
        temp16 = (sectorcount <= 65535) ? sectorcount : 0;
        bs->BPB_TotSec16 = B_HOST_TO_LENDIAN_INT16(temp16);
        bs->BPB_Media = 0xF8;
        bs->BPB_FATSz16 = B_HOST_TO_LENDIAN_INT16(FATSize);
        temp16 = hasBiosGeometry ? biosGeometry.sectors_per_track : 63;
        bs->BPB_SecPerTrk = B_HOST_TO_LENDIAN_INT16(temp16);
        temp16 = hasBiosGeometry ? biosGeometry.head_count : 255;
        bs->BPB_NumHeads = B_HOST_TO_LENDIAN_INT16(temp16);
        temp32 = hasPartitionInfo ? (partitionInfo.size / 512) : 0;
        bs->BPB_HiddSec = B_HOST_TO_LENDIAN_INT32(temp32);
        temp32 = (sectorcount <= 65535) ? 0 : sectorcount;
        bs->BPB_TotSec32 = B_HOST_TO_LENDIAN_INT32(temp32);
        bs->BS_DrvNum = biosDriveId;
        bs->BS_Reserved1 = 0x00;
        bs->BS_BootSig = 0x29;
        *(uint32*)bs->BS_VolID = (uint32)system_time();
        memcpy(bs->BS_VolLab,"NO NAME    ",11);
        memcpy(bs->BS_FilSysType,(fatbits == 12) ? "FAT12   " : "FAT16   ",8);
        bs->signature = B_HOST_TO_LENDIAN_INT16(0xAA55);
    }

    if (!noprompt) {
        printf("\n");
        printf("Initializing will erase all existing data on the drive.\n");
        printf("Do you wish to proceed? ");
        char answer[1000];
        char *p;
        memset(answer, 0, 1000);
        fflush(stdout);
        p = fgets(answer, 1000, stdin);
        if (p && (p=strchr(p, '\n')))
            *p = '\0'; /* remove newline */
        if ((p == NULL) || (strlen(answer) < 1) || (0 != strncasecmp(answer, "yes", strlen(answer)))) {
            printf("drive NOT initialized\n");
            close(fd);
            return B_OK;
        }
    }
    if (testmode) {
        close(fd);
        return B_OK;
    }

    // Disk layout:
    // 0) reserved sectors, this includes the bootsector, fsinfosector and bootsector backup
    // 1) FAT
    // 2) root directory (not on fat32)
    // 3) file & directory data

    ssize_t written;

    // initialize everything with zero first
    // avoid doing 512 byte writes here, they are slow
    printf("Writing FAT\n");
    char * zerobuffer = (char *)malloc(65536);
    memset(zerobuffer,0,65536);
    int64 bytes_to_write = 512LL * (reservedSectorCount + (numFATs * FATSize) + rootDirSectors);
    int64 pos = 0;
    while (bytes_to_write > 0) {
        ssize_t writesize = min_c(bytes_to_write, 65536);
        written = write_pos(fd, pos, zerobuffer, writesize);
        if (written != writesize) {
            fprintf(stderr,"Error: write error near sector %Ld\n",pos / 512);
            close(fd);
            return B_ERROR;
        }
        bytes_to_write -= writesize;
        pos += writesize;
    }
    free(zerobuffer);

    //write boot sector
    printf("Writing boot block\n");
    written = write_pos(fd, BOOT_SECTOR_NUM * 512, bootsector, 512);
    if (written != 512) {
        fprintf(stderr,"Error: write error at sector %d\n", BOOT_SECTOR_NUM);
        close(fd);
        return B_ERROR;
    }

    if (fatbits == 32) {
        written = write_pos(fd, BACKUP_SECTOR_NUM * 512, bootsector, 512);
        if (written != 512) {
            fprintf(stderr,"Error: write error at sector %d\n", BACKUP_SECTOR_NUM);
            close(fd);
            return B_ERROR;
        }
    }

    //write first fat sector
    printf("Writing first FAT sector\n");
    uint8 sec[512];
    memset(sec,0,512);
    if (fatbits == 12) {
        //FAT[0] contains media byte in lower 8 bits, all other bits set to 1
        //FAT[1] contains EOF marker
        sec[0] = 0xF8;
        sec[1] = 0xFF;
        sec[2] = 0xFF;
    } else if (fatbits == 16) {
        //FAT[0] contains media byte in lower 8 bits, all other bits set to 1
        sec[0] = 0xF8;
        sec[1] = 0xFF;
        //FAT[1] contains EOF marker
        sec[2] = 0xFF;
        sec[3] = 0xFF;
    } else if (fatbits == 32) {
        //FAT[0] contains media byte in lower 8 bits, all other bits set to 1
        sec[0] = 0xF8;
        sec[1] = 0xFF;
        sec[2] = 0xFF;
        sec[3] = 0xFF;
        //FAT[1] contains EOF marker
        sec[4] = 0xFF;
        sec[5] = 0xFF;
        sec[6] = 0xFF;
        sec[7] = 0x0F;
        //FAT[2] contains EOF marker, used to terminate root directory
        sec[8] = 0xFF;
        sec[9] = 0xFF;
        sec[10] = 0xFF;
        sec[11] = 0x0F;
    }
    written = write_pos(fd, reservedSectorCount * 512, sec, 512);
    if (written != 512) {
        fprintf(stderr,"Error: write error at sector %d\n", reservedSectorCount);
        close(fd);
        return B_ERROR;
    }
    if (numFATs > 1) {
        written = write_pos(fd, (reservedSectorCount + FATSize) * 512,sec,512);
        if (written != 512) {
            fprintf(stderr,"Error: write error at sector %ld\n", reservedSectorCount + FATSize);
            close(fd);
            return B_ERROR;
        }
    }

    //write fsinfo sector
    if (fatbits == 32) {
        printf("Writing boot info\n");
        //calculate total sector count first
        uint64 free_count = size / 512;
        //now account for already by metadata used sectors
        free_count -= reservedSectorCount + (numFATs * FATSize) + rootDirSectors;
        //convert from sector to clustercount
        free_count /= sectorPerCluster;
        //and account for 1 already used cluster of root directory
        free_count -= 1;
        fsinfosector32 fsinfosector;
        memset(&fsinfosector,0x00,512);
        fsinfosector.FSI_LeadSig 	= B_HOST_TO_LENDIAN_INT32(0x41615252);
        fsinfosector.FSI_StrucSig 	= B_HOST_TO_LENDIAN_INT32(0x61417272);
        fsinfosector.FSI_Free_Count = B_HOST_TO_LENDIAN_INT32((uint32)free_count);
        fsinfosector.FSI_Nxt_Free 	= B_HOST_TO_LENDIAN_INT32(3);
        fsinfosector.FSI_TrailSig 	= B_HOST_TO_LENDIAN_INT32(0xAA550000);
        written = write_pos(fd, FSINFO_SECTOR_NUM * 512, &fsinfosector, 512);
        if (written != 512) {
            fprintf(stderr,"Error: write error at sector %d\n", FSINFO_SECTOR_NUM);
            close(fd);
            return B_ERROR;
        }
    }

    //write volume label into root directory
    printf("Writing root directory\n");
    if (fatbits == 12 || fatbits == 16) {
        uint8 data[512];
        memset(data, 0, 512);
        CreateVolumeLabel(data, label);
        uint32 rootDirSector = reservedSectorCount + (numFATs * FATSize);
        written = write_pos(fd, rootDirSector * 512, data, 512);
        if (written != 512) {
            fprintf(stderr,"Error: write error at sector %ld\n", rootDirSector);
            close(fd);
            return B_ERROR;
        }
    } else if (fatbits == 32) {
        int size = 512 * sectorPerCluster;
        uint8 *cluster = (uint8*)malloc(size);
        memset(cluster, 0, size);
        CreateVolumeLabel(cluster, label);
        uint32 rootDirSector = reservedSectorCount + (numFATs * FATSize) + rootDirSectors;
        written = write_pos(fd, rootDirSector * 512, cluster, size);
        free(cluster);
        if (written != size) {
            fprintf(stderr,"Error: write error at sector %ld\n", rootDirSector);
            close(fd);
            return B_ERROR;
        }
    }

    ioctl(fd, B_FLUSH_DRIVE_CACHE);
    close(fd);

    return B_OK;
}
Beispiel #7
0
void
MemoryView::_GetNextHexBlock(char* buffer, int32 bufferSize,
	const char* address)
{
	switch(fHexMode) {
		case HexMode8BitInt:
		{
			snprintf(buffer, bufferSize, "%02" B_PRIx8,
				*((const uint8*)address));
			break;
		}
		case HexMode16BitInt:
		{
			uint16 data = *((const uint16*)address);
			switch(fCurrentEndianMode)
			{
				case EndianModeBigEndian:
				{
					data = B_HOST_TO_BENDIAN_INT16(data);
				}
				break;

				case EndianModeLittleEndian:
				{
					data = B_HOST_TO_LENDIAN_INT16(data);
				}
				break;
			}
			snprintf(buffer, bufferSize, "%04" B_PRIx16,
				data);
			break;
		}
		case HexMode32BitInt:
		{
			uint32 data = *((const uint32*)address);
			switch(fCurrentEndianMode)
			{
				case EndianModeBigEndian:
				{
					data = B_HOST_TO_BENDIAN_INT32(data);
				}
				break;

				case EndianModeLittleEndian:
				{
					data = B_HOST_TO_LENDIAN_INT32(data);
				}
				break;
			}
			snprintf(buffer, bufferSize, "%08" B_PRIx32,
				data);
			break;
		}
		case HexMode64BitInt:
		{
			uint64 data = *((const uint64*)address);
			switch(fCurrentEndianMode)
			{
				case EndianModeBigEndian:
				{
					data = B_HOST_TO_BENDIAN_INT64(data);
				}
				break;

				case EndianModeLittleEndian:
				{
					data = B_HOST_TO_LENDIAN_INT64(data);
				}
				break;
			}
			snprintf(buffer, bufferSize, "%0*" B_PRIx64,
				16, data);
			break;
		}
	}
}
Beispiel #8
0
status_t
pll_set(uint8 pllID, uint32 pixelClock, uint8 crtcID)
{
	uint32 connectorIndex = gDisplay[crtcID]->connectorIndex;
	pll_info *pll = &gConnector[connectorIndex]->encoder.pll;

	pll->pixelClock = pixelClock;
	pll->id = pllID;

	pll_setup_flags(pll, crtcID);
		// set up any special flags
	pll_adjust(pll, crtcID);
		// get any needed clock adjustments, set reference/post dividers
	pll_compute(pll);
		// compute dividers

	int index = GetIndexIntoMasterTable(COMMAND, SetPixelClock);
	union set_pixel_clock args;
	memset(&args, 0, sizeof(args));

	uint8 tableMajor;
	uint8 tableMinor;

	atom_parse_cmd_header(gAtomContext, index, &tableMajor, &tableMinor);

	uint32 bitsPerChannel = 8;
		// TODO: Digital Depth, EDID 1.4+ on digital displays
		// isn't in Haiku edid common code?

	switch (tableMinor) {
		case 1:
			args.v1.usPixelClock
				= B_HOST_TO_LENDIAN_INT16(pll->pixelClock / 10);
			args.v1.usRefDiv = B_HOST_TO_LENDIAN_INT16(pll->referenceDiv);
			args.v1.usFbDiv = B_HOST_TO_LENDIAN_INT16(pll->feedbackDiv);
			args.v1.ucFracFbDiv = pll->feedbackDivFrac;
			args.v1.ucPostDiv = pll->postDiv;
			args.v1.ucPpll = pll->id;
			args.v1.ucCRTC = crtcID;
			args.v1.ucRefDivSrc = 1;
			break;
		case 2:
			args.v2.usPixelClock
				= B_HOST_TO_LENDIAN_INT16(pll->pixelClock / 10);
			args.v2.usRefDiv = B_HOST_TO_LENDIAN_INT16(pll->referenceDiv);
			args.v2.usFbDiv = B_HOST_TO_LENDIAN_INT16(pll->feedbackDiv);
			args.v2.ucFracFbDiv = pll->feedbackDivFrac;
			args.v2.ucPostDiv = pll->postDiv;
			args.v2.ucPpll = pll->id;
			args.v2.ucCRTC = crtcID;
			args.v2.ucRefDivSrc = 1;
			break;
		case 3:
			args.v3.usPixelClock
				= B_HOST_TO_LENDIAN_INT16(pll->pixelClock / 10);
			args.v3.usRefDiv = B_HOST_TO_LENDIAN_INT16(pll->referenceDiv);
			args.v3.usFbDiv = B_HOST_TO_LENDIAN_INT16(pll->feedbackDiv);
			args.v3.ucFracFbDiv = pll->feedbackDivFrac;
			args.v3.ucPostDiv = pll->postDiv;
			args.v3.ucPpll = pll->id;
			args.v3.ucMiscInfo = (pll->id << 2);
			// if (ss_enabled && (ss->type & ATOM_EXTERNAL_SS_MASK))
			// 	args.v3.ucMiscInfo |= PIXEL_CLOCK_MISC_REF_DIV_SRC;
			args.v3.ucTransmitterId
				= gConnector[connectorIndex]->encoder.objectID;
			args.v3.ucEncoderMode = display_get_encoder_mode(connectorIndex);
			break;
		case 5:
			args.v5.ucCRTC = crtcID;
			args.v5.usPixelClock
				= B_HOST_TO_LENDIAN_INT16(pll->pixelClock / 10);
			args.v5.ucRefDiv = pll->referenceDiv;
			args.v5.usFbDiv = B_HOST_TO_LENDIAN_INT16(pll->feedbackDiv);
			args.v5.ulFbDivDecFrac
				= B_HOST_TO_LENDIAN_INT32(pll->feedbackDivFrac * 100000);
			args.v5.ucPostDiv = pll->postDiv;
			args.v5.ucMiscInfo = 0; /* HDMI depth, etc. */
			// if (ss_enabled && (ss->type & ATOM_EXTERNAL_SS_MASK))
			//	args.v5.ucMiscInfo |= PIXEL_CLOCK_V5_MISC_REF_DIV_SRC;
			switch (bitsPerChannel) {
				case 8:
				default:
					args.v5.ucMiscInfo |= PIXEL_CLOCK_V5_MISC_HDMI_24BPP;
					break;
				case 10:
					args.v5.ucMiscInfo |= PIXEL_CLOCK_V5_MISC_HDMI_30BPP;
					break;
			}
			args.v5.ucTransmitterID
				= gConnector[connectorIndex]->encoder.objectID;
			args.v5.ucEncoderMode
				= display_get_encoder_mode(connectorIndex);
			args.v5.ucPpll = pllID;
			break;
		case 6:
			args.v6.ulDispEngClkFreq
				= B_HOST_TO_LENDIAN_INT32(crtcID << 24 | pll->pixelClock / 10);
			args.v6.ucRefDiv = pll->referenceDiv;
			args.v6.usFbDiv = B_HOST_TO_LENDIAN_INT16(pll->feedbackDiv);
			args.v6.ulFbDivDecFrac
				= B_HOST_TO_LENDIAN_INT32(pll->feedbackDivFrac * 100000);
			args.v6.ucPostDiv = pll->postDiv;
			args.v6.ucMiscInfo = 0; /* HDMI depth, etc. */
			// if (ss_enabled && (ss->type & ATOM_EXTERNAL_SS_MASK))
			//	args.v6.ucMiscInfo |= PIXEL_CLOCK_V6_MISC_REF_DIV_SRC;
			switch (bitsPerChannel) {
				case 8:
				default:
					args.v6.ucMiscInfo |= PIXEL_CLOCK_V6_MISC_HDMI_24BPP;
					break;
				case 10:
					args.v6.ucMiscInfo |= PIXEL_CLOCK_V6_MISC_HDMI_30BPP;
					break;
				case 12:
					args.v6.ucMiscInfo |= PIXEL_CLOCK_V6_MISC_HDMI_36BPP;
					break;
				case 16:
					args.v6.ucMiscInfo |= PIXEL_CLOCK_V6_MISC_HDMI_48BPP;
					break;
			}
			args.v6.ucTransmitterID
				= gConnector[connectorIndex]->encoder.objectID;
			args.v6.ucEncoderMode = display_get_encoder_mode(connectorIndex);
			args.v6.ucPpll = pllID;
			break;
		default:
			TRACE("%s: ERROR: table version %" B_PRIu8 ".%" B_PRIu8 " TODO\n",
				__func__, tableMajor, tableMinor);
			return B_ERROR;
	}

	TRACE("%s: set adjusted pixel clock %" B_PRIu32 " (was %" B_PRIu32 ")\n",
		__func__, pll->pixelClock, pixelClock);

	return atom_execute_table(gAtomContext, index, (uint32*)&args);
}
Beispiel #9
0
status_t
pll_adjust(pll_info *pll, uint8 crtcID)
{
	// TODO: PLL flags
	radeon_shared_info &info = *gInfo->shared_info;

	uint32 pixelClock = pll->pixelClock;
		// original as pixel_clock will be adjusted

	uint32 connectorIndex = gDisplay[crtcID]->connectorIndex;
	uint32 encoderID = gConnector[connectorIndex]->encoder.objectID;
	uint32 encoderMode = display_get_encoder_mode(connectorIndex);

	if (info.device_chipset >= (RADEON_R600 | 0x20)) {
		union adjust_pixel_clock args;

		uint8 tableMajor;
		uint8 tableMinor;

		int index = GetIndexIntoMasterTable(COMMAND, AdjustDisplayPll);

		if (atom_parse_cmd_header(gAtomContext, index, &tableMajor, &tableMinor)
			!= B_OK) {
			return B_ERROR;
		}

		memset(&args, 0, sizeof(args));
		switch (tableMajor) {
			case 1:
				switch (tableMinor) {
					case 1:
					case 2:
						args.v1.usPixelClock
							= B_HOST_TO_LENDIAN_INT16(pixelClock / 10);
						args.v1.ucTransmitterID = encoderID;
						args.v1.ucEncodeMode = encoderMode;
						// TODO: SS and SS % > 0
						if (0) {
							args.v1.ucConfig
								|= ADJUST_DISPLAY_CONFIG_SS_ENABLE;
						}

						atom_execute_table(gAtomContext, index, (uint32*)&args);
						// get returned adjusted clock
						pll->pixelClock
							= B_LENDIAN_TO_HOST_INT16(args.v1.usPixelClock);
						pll->pixelClock *= 10;
						break;
					case 3:
						args.v3.sInput.usPixelClock
							= B_HOST_TO_LENDIAN_INT16(pixelClock / 10);
						args.v3.sInput.ucTransmitterID = encoderID;
						args.v3.sInput.ucEncodeMode = encoderMode;
						args.v3.sInput.ucDispPllConfig = 0;
						// TODO: SS and SS % > 0
						if (0) {
							args.v3.sInput.ucDispPllConfig
								|= DISPPLL_CONFIG_SS_ENABLE;
						}
						// TODO: if ATOM_DEVICE_DFP_SUPPORT
						// TODO: display port DP

						// TODO: is DP?
						args.v3.sInput.ucExtTransmitterID = 0;

						atom_execute_table(gAtomContext, index, (uint32*)&args);
						// get returned adjusted clock
						pll->pixelClock
							= B_LENDIAN_TO_HOST_INT32(
								args.v3.sOutput.ulDispPllFreq);
						pll->pixelClock *= 10;
							// convert to kHz for storage

						if (args.v3.sOutput.ucRefDiv) {
							pll->flags |= PLL_USE_FRAC_FB_DIV;
							pll->flags |= PLL_USE_REF_DIV;
							pll->referenceDiv = args.v3.sOutput.ucRefDiv;
						}
						if (args.v3.sOutput.ucPostDiv) {
							pll->flags |= PLL_USE_FRAC_FB_DIV;
							pll->flags |= PLL_USE_POST_DIV;
							pll->postDiv = args.v3.sOutput.ucPostDiv;
						}
						break;
					default:
						TRACE("%s: ERROR: table version %" B_PRIu8 ".%" B_PRIu8
							" unknown\n", __func__, tableMajor, tableMinor);
						return B_ERROR;
				}
				break;
			default:
				TRACE("%s: ERROR: table version %" B_PRIu8 ".%" B_PRIu8
					" unknown\n", __func__, tableMajor, tableMinor);
				return B_ERROR;
		}
	}

	TRACE("%s: was: %" B_PRIu32 ", now: %" B_PRIu32 "\n", __func__,
		pixelClock, pll->pixelClock);

	return B_OK;
}
Beispiel #10
0
status_t
pll_external_set(uint32 clock)
{
	TRACE("%s: set external pll clock to %" B_PRIu32 "\n", __func__, clock);

	if (clock == 0)
		ERROR("%s: Warning: default display clock is 0?\n", __func__);

	// also known as PLL display engineering
	uint8 tableMajor;
	uint8 tableMinor;

	int index = GetIndexIntoMasterTable(COMMAND, SetPixelClock);
	atom_parse_cmd_header(gAtomContext, index, &tableMajor, &tableMinor);

	TRACE("%s: table %" B_PRIu8 ".%" B_PRIu8 "\n", __func__,
		tableMajor, tableMinor);

	union setPixelClock {
		SET_PIXEL_CLOCK_PS_ALLOCATION base;
		PIXEL_CLOCK_PARAMETERS v1;
		PIXEL_CLOCK_PARAMETERS_V2 v2;
		PIXEL_CLOCK_PARAMETERS_V3 v3;
		PIXEL_CLOCK_PARAMETERS_V5 v5;
		PIXEL_CLOCK_PARAMETERS_V6 v6;
	};
	union setPixelClock args;
	memset(&args, 0, sizeof(args));

	radeon_shared_info &info = *gInfo->shared_info;
	uint32 dceVersion = (info.dceMajor * 100) + info.dceMinor;
	switch (tableMajor) {
		case 1:
			switch(tableMinor) {
				case 5:
					// If the default DC PLL clock is specified,
					// SetPixelClock provides the dividers.
					args.v5.ucCRTC = ATOM_CRTC_INVALID;
					args.v5.usPixelClock = B_HOST_TO_LENDIAN_INT16(clock / 10);
					args.v5.ucPpll = ATOM_DCPLL;
					break;
				case 6:
					// If the default DC PLL clock is specified,
					// SetPixelClock provides the dividers.
					args.v6.ulDispEngClkFreq
						= B_HOST_TO_LENDIAN_INT32(clock / 10);
					if (dceVersion == 601)
						args.v6.ucPpll = ATOM_EXT_PLL1;
					else if (dceVersion >= 600)
						args.v6.ucPpll = ATOM_PPLL0;
					else
						args.v6.ucPpll = ATOM_DCPLL;
					break;
				default:
					ERROR("%s: Unknown table version %" B_PRIu8
						".%" B_PRIu8 "\n", __func__, tableMajor, tableMinor);
			}
			break;
		default:
			ERROR("%s: Unknown table version %" B_PRIu8
						".%" B_PRIu8 "\n", __func__, tableMajor, tableMinor);
	}
	return B_OK;
}
Beispiel #11
0
status_t
pll_set(display_mode* mode, uint8 crtcID)
{
	uint32 connectorIndex = gDisplay[crtcID]->connectorIndex;
	pll_info* pll = &gConnector[connectorIndex]->encoder.pll;
	uint32 dp_clock = gConnector[connectorIndex]->dpInfo.linkRate;
	bool ssEnabled = false;

	pll->pixelClock = mode->timing.pixel_clock;

	radeon_shared_info &info = *gInfo->shared_info;

	// Probe for PLL spread spectrum info;
	pll->ssPercentage = 0;
	pll->ssType = 0;
	pll->ssStep = 0;
	pll->ssDelay = 0;
	pll->ssRange = 0;
	pll->ssReferenceDiv = 0;

	switch (display_get_encoder_mode(connectorIndex)) {
		case ATOM_ENCODER_MODE_DP_MST:
		case ATOM_ENCODER_MODE_DP:
			if (info.dceMajor >= 4)
				pll_asic_ss_probe(pll, ASIC_INTERNAL_SS_ON_DP);
			else {
				if (dp_clock == 162000) {
					ssEnabled = pll_ppll_ss_probe(pll, ATOM_DP_SS_ID2);
					if (!ssEnabled)
						// id2 failed, try id1
						ssEnabled = pll_ppll_ss_probe(pll, ATOM_DP_SS_ID1);
				} else
					ssEnabled = pll_ppll_ss_probe(pll, ATOM_DP_SS_ID1);
			}
			break;
		case ATOM_ENCODER_MODE_LVDS:
			if (info.dceMajor >= 4)
				ssEnabled = pll_asic_ss_probe(pll, gInfo->lvdsSpreadSpectrumID);
			else
				ssEnabled = pll_ppll_ss_probe(pll, gInfo->lvdsSpreadSpectrumID);
			break;
		case ATOM_ENCODER_MODE_DVI:
			if (info.dceMajor >= 4)
				ssEnabled = pll_asic_ss_probe(pll, ASIC_INTERNAL_SS_ON_TMDS);
			break;
		case ATOM_ENCODER_MODE_HDMI:
			if (info.dceMajor >= 4)
				ssEnabled = pll_asic_ss_probe(pll, ASIC_INTERNAL_SS_ON_HDMI);
			break;
	}

	pll_setup_flags(pll, crtcID);
		// set up any special flags
	pll_adjust(pll, mode, crtcID);
		// get any needed clock adjustments, set reference/post dividers
	pll_compute(pll);
		// compute dividers

	display_crtc_ss(pll, ATOM_DISABLE);
		// disable ss

	uint8 tableMajor;
	uint8 tableMinor;

	int index = GetIndexIntoMasterTable(COMMAND, SetPixelClock);
	atom_parse_cmd_header(gAtomContext, index, &tableMajor, &tableMinor);

	TRACE("%s: table %" B_PRIu8 ".%" B_PRIu8 "\n", __func__,
		tableMajor, tableMinor);

	uint32 bitsPerColor = 8;
		// TODO: Digital Depth, EDID 1.4+ on digital displays
		// isn't in Haiku edid common code?

	// Prepare arguments for AtomBIOS call
	union setPixelClock {
		SET_PIXEL_CLOCK_PS_ALLOCATION base;
		PIXEL_CLOCK_PARAMETERS v1;
		PIXEL_CLOCK_PARAMETERS_V2 v2;
		PIXEL_CLOCK_PARAMETERS_V3 v3;
		PIXEL_CLOCK_PARAMETERS_V5 v5;
		PIXEL_CLOCK_PARAMETERS_V6 v6;
	};
	union setPixelClock args;
	memset(&args, 0, sizeof(args));

	switch (tableMinor) {
		case 1:
			args.v1.usPixelClock
				= B_HOST_TO_LENDIAN_INT16(pll->pixelClock / 10);
			args.v1.usRefDiv = B_HOST_TO_LENDIAN_INT16(pll->referenceDiv);
			args.v1.usFbDiv = B_HOST_TO_LENDIAN_INT16(pll->feedbackDiv);
			args.v1.ucFracFbDiv = pll->feedbackDivFrac;
			args.v1.ucPostDiv = pll->postDiv;
			args.v1.ucPpll = pll->id;
			args.v1.ucCRTC = crtcID;
			args.v1.ucRefDivSrc = 1;
			break;
		case 2:
			args.v2.usPixelClock
				= B_HOST_TO_LENDIAN_INT16(pll->pixelClock / 10);
			args.v2.usRefDiv = B_HOST_TO_LENDIAN_INT16(pll->referenceDiv);
			args.v2.usFbDiv = B_HOST_TO_LENDIAN_INT16(pll->feedbackDiv);
			args.v2.ucFracFbDiv = pll->feedbackDivFrac;
			args.v2.ucPostDiv = pll->postDiv;
			args.v2.ucPpll = pll->id;
			args.v2.ucCRTC = crtcID;
			args.v2.ucRefDivSrc = 1;
			break;
		case 3:
			args.v3.usPixelClock
				= B_HOST_TO_LENDIAN_INT16(pll->pixelClock / 10);
			args.v3.usRefDiv = B_HOST_TO_LENDIAN_INT16(pll->referenceDiv);
			args.v3.usFbDiv = B_HOST_TO_LENDIAN_INT16(pll->feedbackDiv);
			args.v3.ucFracFbDiv = pll->feedbackDivFrac;
			args.v3.ucPostDiv = pll->postDiv;
			args.v3.ucPpll = pll->id;
			args.v3.ucMiscInfo = (pll->id << 2);
			if (pll->ssPercentage > 0
				&& (pll->ssType & ATOM_EXTERNAL_SS_MASK) != 0) {
				args.v3.ucMiscInfo |= PIXEL_CLOCK_MISC_REF_DIV_SRC;
			}
			args.v3.ucTransmitterId
				= gConnector[connectorIndex]->encoder.objectID;
			args.v3.ucEncoderMode = display_get_encoder_mode(connectorIndex);
			break;
		case 5:
			args.v5.ucCRTC = crtcID;
			args.v5.usPixelClock
				= B_HOST_TO_LENDIAN_INT16(pll->pixelClock / 10);
			args.v5.ucRefDiv = pll->referenceDiv;
			args.v5.usFbDiv = B_HOST_TO_LENDIAN_INT16(pll->feedbackDiv);
			args.v5.ulFbDivDecFrac
				= B_HOST_TO_LENDIAN_INT32(pll->feedbackDivFrac * 100000);
			args.v5.ucPostDiv = pll->postDiv;
			args.v5.ucMiscInfo = 0; /* HDMI depth, etc. */
			if (pll->ssPercentage > 0
				&& (pll->ssType & ATOM_EXTERNAL_SS_MASK) != 0) {
				args.v5.ucMiscInfo |= PIXEL_CLOCK_V5_MISC_REF_DIV_SRC;
			}
			switch (bitsPerColor) {
				case 8:
				default:
					args.v5.ucMiscInfo |= PIXEL_CLOCK_V5_MISC_HDMI_24BPP;
					break;
				case 10:
					args.v5.ucMiscInfo |= PIXEL_CLOCK_V5_MISC_HDMI_30BPP;
					break;
			}
			args.v5.ucTransmitterID
				= gConnector[connectorIndex]->encoder.objectID;
			args.v5.ucEncoderMode
				= display_get_encoder_mode(connectorIndex);
			args.v5.ucPpll = pll->id;
			break;
		case 6:
			args.v6.ulDispEngClkFreq
				= B_HOST_TO_LENDIAN_INT32(crtcID << 24 | pll->pixelClock / 10);
			args.v6.ucRefDiv = pll->referenceDiv;
			args.v6.usFbDiv = B_HOST_TO_LENDIAN_INT16(pll->feedbackDiv);
			args.v6.ulFbDivDecFrac
				= B_HOST_TO_LENDIAN_INT32(pll->feedbackDivFrac * 100000);
			args.v6.ucPostDiv = pll->postDiv;
			args.v6.ucMiscInfo = 0; /* HDMI depth, etc. */
			if (pll->ssPercentage > 0
				&& (pll->ssType & ATOM_EXTERNAL_SS_MASK) != 0) {
				args.v6.ucMiscInfo |= PIXEL_CLOCK_V6_MISC_REF_DIV_SRC;
			}
			switch (bitsPerColor) {
				case 8:
				default:
					args.v6.ucMiscInfo |= PIXEL_CLOCK_V6_MISC_HDMI_24BPP;
					break;
				case 10:
					args.v6.ucMiscInfo |= PIXEL_CLOCK_V6_MISC_HDMI_30BPP;
					break;
				case 12:
					args.v6.ucMiscInfo |= PIXEL_CLOCK_V6_MISC_HDMI_36BPP;
					break;
				case 16:
					args.v6.ucMiscInfo |= PIXEL_CLOCK_V6_MISC_HDMI_48BPP;
					break;
			}
			args.v6.ucTransmitterID
				= gConnector[connectorIndex]->encoder.objectID;
			args.v6.ucEncoderMode = display_get_encoder_mode(connectorIndex);
			args.v6.ucPpll = pll->id;
			break;
		default:
			TRACE("%s: ERROR: table version %" B_PRIu8 ".%" B_PRIu8 " TODO\n",
				__func__, tableMajor, tableMinor);
			return B_ERROR;
	}

	TRACE("%s: set adjusted pixel clock %" B_PRIu32 " (was %" B_PRIu32 ")\n",
		__func__, pll->pixelClock, mode->timing.pixel_clock);

	status_t result = atom_execute_table(gAtomContext, index, (uint32*)&args);

	if (ssEnabled)
		display_crtc_ss(pll, ATOM_ENABLE);

	return result;
}
Beispiel #12
0
status_t
pll_adjust(pll_info* pll, display_mode* mode, uint8 crtcID)
{
	radeon_shared_info &info = *gInfo->shared_info;

	uint32 pixelClock = pll->pixelClock;
		// original as pixel_clock will be adjusted

	uint32 connectorIndex = gDisplay[crtcID]->connectorIndex;
	connector_info* connector = gConnector[connectorIndex];

	uint32 encoderID = connector->encoder.objectID;
	uint32 encoderMode = display_get_encoder_mode(connectorIndex);
	uint32 connectorFlags = connector->flags;

	uint32 externalEncoderID = 0;
	pll->adjustedClock = pll->pixelClock;
	if (connector->encoderExternal.isDPBridge)
		externalEncoderID = connector->encoderExternal.objectID;

	if (info.dceMajor >= 3) {

		uint8 tableMajor;
		uint8 tableMinor;

		int index = GetIndexIntoMasterTable(COMMAND, AdjustDisplayPll);
		if (atom_parse_cmd_header(gAtomContext, index, &tableMajor, &tableMinor)
			!= B_OK) {
			ERROR("%s: Couldn't find AtomBIOS PLL adjustment\n", __func__);
			return B_ERROR;
		}

		TRACE("%s: table %" B_PRIu8 ".%" B_PRIu8 "\n", __func__,
			tableMajor, tableMinor);

		// Prepare arguments for AtomBIOS call
		union adjustPixelClock {
			ADJUST_DISPLAY_PLL_PS_ALLOCATION v1;
			ADJUST_DISPLAY_PLL_PS_ALLOCATION_V3 v3;
		};
		union adjustPixelClock args;
		memset(&args, 0, sizeof(args));

		switch (tableMajor) {
			case 1:
				switch (tableMinor) {
					case 1:
					case 2:
						args.v1.usPixelClock
							= B_HOST_TO_LENDIAN_INT16(pixelClock / 10);
						args.v1.ucTransmitterID = encoderID;
						args.v1.ucEncodeMode = encoderMode;
						if (pll->ssPercentage > 0) {
							args.v1.ucConfig
								|= ADJUST_DISPLAY_CONFIG_SS_ENABLE;
						}

						atom_execute_table(gAtomContext, index, (uint32*)&args);
						// get returned adjusted clock
						pll->adjustedClock
							= B_LENDIAN_TO_HOST_INT16(args.v1.usPixelClock);
						pll->adjustedClock *= 10;
						break;
					case 3:
						args.v3.sInput.usPixelClock
							= B_HOST_TO_LENDIAN_INT16(pixelClock / 10);
						args.v3.sInput.ucTransmitterID = encoderID;
						args.v3.sInput.ucEncodeMode = encoderMode;
						args.v3.sInput.ucDispPllConfig = 0;
						if (pll->ssPercentage > 0) {
							args.v3.sInput.ucDispPllConfig
								|= DISPPLL_CONFIG_SS_ENABLE;
						}

						// Handle DP adjustments
						if (encoderMode == ATOM_ENCODER_MODE_DP
							|| encoderMode == ATOM_ENCODER_MODE_DP_MST) {
							TRACE("%s: encoderMode is DP\n", __func__);
							args.v3.sInput.ucDispPllConfig
								|= DISPPLL_CONFIG_COHERENT_MODE;
							/* 162000 or 270000 */
							uint32 dpLinkSpeed
								= dp_get_link_rate(connectorIndex, mode);
							/* 16200 or 27000 */
							args.v3.sInput.usPixelClock
								= B_HOST_TO_LENDIAN_INT16(dpLinkSpeed / 10);
						} else if ((connectorFlags & ATOM_DEVICE_DFP_SUPPORT)
							!= 0) {
							#if 0
							if (encoderMode == ATOM_ENCODER_MODE_HDMI) {
								/* deep color support */
								args.v3.sInput.usPixelClock =
									cpu_to_le16((mode->clock * bpc / 8) / 10);
							}
							#endif
							if (pixelClock > 165000) {
								args.v3.sInput.ucDispPllConfig
									|= DISPPLL_CONFIG_DUAL_LINK;
							}
							if (1) {	// dig coherent mode?
								args.v3.sInput.ucDispPllConfig
									|= DISPPLL_CONFIG_COHERENT_MODE;
							}
						}

						args.v3.sInput.ucExtTransmitterID = externalEncoderID;

						atom_execute_table(gAtomContext, index, (uint32*)&args);

						// get returned adjusted clock
						pll->adjustedClock = B_LENDIAN_TO_HOST_INT32(
								args.v3.sOutput.ulDispPllFreq);
						pll->adjustedClock *= 10;
							// convert to kHz for storage

						if (args.v3.sOutput.ucRefDiv) {
							pll->flags |= PLL_USE_FRAC_FB_DIV;
							pll->flags |= PLL_USE_REF_DIV;
							pll->referenceDiv = args.v3.sOutput.ucRefDiv;
						}
						if (args.v3.sOutput.ucPostDiv) {
							pll->flags |= PLL_USE_FRAC_FB_DIV;
							pll->flags |= PLL_USE_POST_DIV;
							pll->postDiv = args.v3.sOutput.ucPostDiv;
						}
						break;
					default:
						TRACE("%s: ERROR: table version %" B_PRIu8 ".%" B_PRIu8
							" unknown\n", __func__, tableMajor, tableMinor);
						return B_ERROR;
				}
				break;
			default:
				TRACE("%s: ERROR: table version %" B_PRIu8 ".%" B_PRIu8
					" unknown\n", __func__, tableMajor, tableMinor);
				return B_ERROR;
		}
	}

	TRACE("%s: was: %" B_PRIu32 ", now: %" B_PRIu32 "\n", __func__,
		pixelClock, pll->adjustedClock);

	return B_OK;
}