Пример #1
0
void
AHCIPort::ScsiReadCapacity(scsi_ccb *request)
{
    TRACE("AHCIPort::ScsiReadCapacity port %d\n", fIndex);

    const scsi_cmd_read_capacity *cmd = (const scsi_cmd_read_capacity *)request->cdb;
    scsi_res_read_capacity scsiData;

    if (cmd->pmi || cmd->lba || request->data_length < sizeof(scsiData)) {
        TRACE("invalid request\n");
        request->subsys_status = SCSI_REQ_ABORTED;
        gSCSI->finished(request, 1);
        return;
    }

    TRACE("SectorSize %" B_PRIu32 ", SectorCount 0x%" B_PRIx64 "\n",
          fSectorSize, fSectorCount);

    scsiData.block_size = B_HOST_TO_BENDIAN_INT32(fSectorSize);

    if (fSectorCount <= 0xffffffff)
        scsiData.lba = B_HOST_TO_BENDIAN_INT32(fSectorCount - 1);
    else
        scsiData.lba = 0xffffffff;

    if (sg_memcpy(request->sg_list, request->sg_count, &scsiData,
                  sizeof(scsiData)) < B_OK) {
        request->subsys_status = SCSI_DATA_RUN_ERR;
    } else {
        request->subsys_status = SCSI_REQ_CMP;
        request->data_resid = request->data_length - sizeof(scsiData);
    }
    gSCSI->finished(request, 1);
}
Пример #2
0
void
AHCIPort::ScsiReadCapacity(scsi_ccb *request)
{
	TRACE("AHCIPort::ScsiReadCapacity port %d\n", fIndex);

	scsi_cmd_read_capacity *cmd = (scsi_cmd_read_capacity *)request->cdb;
	scsi_res_read_capacity scsiData;

	if (cmd->pmi || cmd->lba || request->data_length < sizeof(scsiData)) {
		TRACE("invalid request\n");
		return;
	}

	TRACE("SectorSize %lu, SectorCount 0x%llx\n", fSectorSize, fSectorCount);

	if (fSectorCount > 0xffffffff)
		panic("ahci: SCSI emulation doesn't support harddisks larger than 2TB");

	scsiData.block_size = B_HOST_TO_BENDIAN_INT32(fSectorSize);
	scsiData.lba = B_HOST_TO_BENDIAN_INT32(fSectorCount - 1);

	if (sg_memcpy(request->sg_list, request->sg_count, &scsiData, sizeof(scsiData)) < B_OK) {
		request->subsys_status = SCSI_DATA_RUN_ERR;
	} else {
		request->subsys_status = SCSI_REQ_CMP;
		request->data_resid = request->data_length - sizeof(scsiData);
	}
	gSCSI->finished(request, 1);
}
Пример #3
0
void
AHCIPort::ScsiReadCapacity16(scsi_ccb* request)
{
	TRACE("AHCIPort::ScsiReadCapacity16 port %d\n", fIndex);

	scsi_res_read_capacity_long scsiData;

	TRACE("SectorSize %" B_PRIu32 ", SectorCount 0x%" B_PRIx64 "\n",
		fSectorSize, fSectorCount);

	scsiData.block_size = B_HOST_TO_BENDIAN_INT32(fSectorSize);
	scsiData.lba = B_HOST_TO_BENDIAN_INT64(fSectorCount - 1);

	if (sg_memcpy(request->sg_list, request->sg_count, &scsiData,
			sizeof(scsiData)) < B_OK) {
		request->subsys_status = SCSI_DATA_RUN_ERR;
	} else {
		request->subsys_status = SCSI_REQ_CMP;
		request->data_resid = request->data_length - sizeof(scsiData);
	}
	gSCSI->finished(request, 1);
}
Пример #4
0
void
AHCIPort::ScsiInquiry(scsi_ccb *request)
{
    TRACE("AHCIPort::ScsiInquiry port %d\n", fIndex);

    const scsi_cmd_inquiry *cmd = (const scsi_cmd_inquiry *)request->cdb;
    scsi_res_inquiry scsiData;
    ata_device_infoblock ataData;

    ASSERT(sizeof(ataData) == 512);

    if (cmd->evpd || cmd->page_code || request->data_length < sizeof(scsiData)) {
        TRACE("invalid request\n");
        request->subsys_status = SCSI_REQ_ABORTED;
        gSCSI->finished(request, 1);
        return;
    }

    sata_request sreq;
    sreq.set_data(&ataData, sizeof(ataData));
    sreq.set_ata_cmd(fIsATAPI ? 0xa1 : 0xec); // Identify (Packet) Device
    ExecuteSataRequest(&sreq);
    sreq.wait_for_completion();

    if (sreq.completion_status() & ATA_ERR) {
        TRACE("identify device failed\n");
        request->subsys_status = SCSI_REQ_CMP_ERR;
        gSCSI->finished(request, 1);
        return;
    }

    /*
    	uint8 *data = (uint8*) &ataData;
    	for (int i = 0; i < 512; i += 8) {
    		TRACE("  %02x %02x %02x %02x %02x %02x %02x %02x\n", data[i], data[i+1],
    			data[i+2], data[i+3], data[i+4], data[i+5], data[i+6], data[i+7]);
    	}
    */

    scsiData.device_type = fIsATAPI
                           ? ataData.word_0.atapi.command_packet_set : scsi_dev_direct_access;
    scsiData.device_qualifier = scsi_periph_qual_connected;
    scsiData.device_type_modifier = 0;
    scsiData.removable_medium = ataData.word_0.ata.removable_media_device;
    scsiData.ansi_version = 2;
    scsiData.ecma_version = 0;
    scsiData.iso_version = 0;
    scsiData.response_data_format = 2;
    scsiData.term_iop = false;
    scsiData.additional_length = sizeof(scsi_res_inquiry) - 4;
    scsiData.soft_reset = false;
    scsiData.cmd_queue = false;
    scsiData.linked = false;
    scsiData.sync = false;
    scsiData.write_bus16 = true;
    scsiData.write_bus32 = false;
    scsiData.relative_address = false;

    if (!fIsATAPI) {
        fSectorCount = ataData.SectorCount(fUse48BitCommands, true);
        fSectorSize = ataData.SectorSize();
        fTrim = ataData.data_set_management_support;
        TRACE("lba %d, lba48 %d, fUse48BitCommands %d, sectors %" B_PRIu32
              ", sectors48 %" B_PRIu64 ", size %" B_PRIu64 "\n",
              ataData.dma_supported != 0, ataData.lba48_supported != 0,
              fUse48BitCommands, ataData.lba_sector_count,
              ataData.lba48_sector_count, fSectorCount * fSectorSize);
    }

#if 0
    if (fSectorCount < 0x0fffffff) {
        TRACE("disabling 48 bit commands\n");
        fUse48BitCommands = 0;
    }
#endif

    char modelNumber[sizeof(ataData.model_number) + 1];
    char serialNumber[sizeof(ataData.serial_number) + 1];
    char firmwareRev[sizeof(ataData.firmware_revision) + 1];

    strlcpy(modelNumber, ataData.model_number, sizeof(modelNumber));
    strlcpy(serialNumber, ataData.serial_number, sizeof(serialNumber));
    strlcpy(firmwareRev, ataData.firmware_revision, sizeof(firmwareRev));

    swap_words(modelNumber, sizeof(modelNumber) - 1);
    swap_words(serialNumber, sizeof(serialNumber) - 1);
    swap_words(firmwareRev, sizeof(firmwareRev) - 1);

    TRACE("model number: %s\n", modelNumber);
    TRACE("serial number: %s\n", serialNumber);
    TRACE("firmware rev.: %s\n", firmwareRev);
    TRACE("trim support: %s\n", fTrim ? "yes" : "no");

    // There's not enough space to fit all of the data in. ATA has 40 bytes for
    // the model number, 20 for the serial number and another 8 for the
    // firmware revision. SCSI has room for 8 for vendor ident, 16 for product
    // ident and another 4 for product revision. We just try and fit in as much
    // as possible of the model number into the vendor and product ident fields
    // and put a little of the serial number into the product revision field.
    memcpy(scsiData.vendor_ident, modelNumber, sizeof(scsiData.vendor_ident));
    memcpy(scsiData.product_ident, modelNumber + 8,
           sizeof(scsiData.product_ident));
    memcpy(scsiData.product_rev, serialNumber, sizeof(scsiData.product_rev));

    if (sg_memcpy(request->sg_list, request->sg_count, &scsiData,
                  sizeof(scsiData)) < B_OK) {
        request->subsys_status = SCSI_DATA_RUN_ERR;
    } else {
        request->subsys_status = SCSI_REQ_CMP;
        request->data_resid = request->data_length - sizeof(scsiData);
    }
    gSCSI->finished(request, 1);
}
Пример #5
0
void
AHCIPort::ScsiInquiry(scsi_ccb *request)
{
	TRACE("AHCIPort::ScsiInquiry port %d\n", fIndex);

	scsi_cmd_inquiry *cmd = (scsi_cmd_inquiry *)request->cdb;
	scsi_res_inquiry scsiData;
	ata_res_identify_device	ataData;

	ASSERT(sizeof(ataData) == 512);

	if (cmd->evpd || cmd->page_code || request->data_length < sizeof(scsiData)) {
		TRACE("invalid request\n");
		request->subsys_status = SCSI_REQ_ABORTED;
		gSCSI->finished(request, 1);
		return;
	}

	sata_request sreq;
	sreq.set_data(&ataData, sizeof(ataData));
	sreq.set_ata_cmd(fIsATAPI ? 0xa1 : 0xec); // Identify (Packet) Device
	ExecuteSataRequest(&sreq);
	sreq.wait_for_completition();

	if (sreq.completition_status() & ATA_ERR) {
		TRACE("identify device failed\n");
		request->subsys_status = SCSI_REQ_CMP_ERR;
		gSCSI->finished(request, 1);
		return;
	}

/*
	uint8 *data = (uint8*) &ataData;
	for (int i = 0; i < 512; i += 8) {
		TRACE("  %02x %02x %02x %02x %02x %02x %02x %02x\n", data[i], data[i+1],
			data[i+2], data[i+3], data[i+4], data[i+5], data[i+6], data[i+7]);
	}
*/

	scsiData.device_type = fIsATAPI ? scsi_dev_CDROM : scsi_dev_direct_access;
	scsiData.device_qualifier = scsi_periph_qual_connected;
	scsiData.device_type_modifier = 0;
	scsiData.removable_medium = fIsATAPI;
	scsiData.ansi_version = 2;
	scsiData.ecma_version = 0;
	scsiData.iso_version = 0;
	scsiData.response_data_format = 2;
	scsiData.term_iop = false;
	scsiData.additional_length = sizeof(scsiData) - 4;
	scsiData.soft_reset = false;
	scsiData.cmd_queue = false;
	scsiData.linked = false;
	scsiData.sync = false;
	scsiData.write_bus16 = true;
	scsiData.write_bus32 = false;
	scsiData.relative_address = false;
	memcpy(scsiData.vendor_ident, ataData.model_number,
		sizeof(scsiData.vendor_ident));
	memcpy(scsiData.product_ident, ataData.model_number + 8,
		sizeof(scsiData.product_ident));
	memcpy(scsiData.product_rev, ataData.serial_number,
		sizeof(scsiData.product_rev));

	if (!fIsATAPI) {
		bool lba			= (ataData.words[49] & (1 << 9)) != 0;
		bool lba48			= (ataData.words[83] & (1 << 10)) != 0;
		uint32 sectors		= *(uint32*)&ataData.words[60];
		uint64 sectors48	= *(uint64*)&ataData.words[100];
		fUse48BitCommands   = lba && lba48;
		fSectorSize			= 512;
		fSectorCount		= !(lba || sectors) ? 0 : lba48 ? sectors48 : sectors;
		TRACE("lba %d, lba48 %d, fUse48BitCommands %d, sectors %lu, "
			"sectors48 %llu, size %llu\n",
			lba, lba48, fUse48BitCommands, sectors, sectors48,
			fSectorCount * fSectorSize);
	}

#if 0
	if (fSectorCount < 0x0fffffff) {
		TRACE("disabling 48 bit commands\n");
		fUse48BitCommands = 0;
	}
#endif

	char modelNumber[sizeof(ataData.model_number) + 1];
	char serialNumber[sizeof(ataData.serial_number) + 1];
	char firmwareRev[sizeof(ataData.firmware_revision) + 1];

	strlcpy(modelNumber, ataData.model_number, sizeof(modelNumber));
	strlcpy(serialNumber, ataData.serial_number, sizeof(serialNumber));
	strlcpy(firmwareRev, ataData.firmware_revision, sizeof(firmwareRev));

	swap_words(modelNumber, sizeof(modelNumber) - 1);
	swap_words(serialNumber, sizeof(serialNumber) - 1);
	swap_words(firmwareRev, sizeof(firmwareRev) - 1);

	TRACE("model number: %s\n", modelNumber);
	TRACE("serial number: %s\n", serialNumber);
  	TRACE("firmware rev.: %s\n", firmwareRev);

	if (sg_memcpy(request->sg_list, request->sg_count, &scsiData,
		sizeof(scsiData)) < B_OK) {
		request->subsys_status = SCSI_DATA_RUN_ERR;
	} else {
		request->subsys_status = SCSI_REQ_CMP;
		request->data_resid = request->data_length - sizeof(scsiData);
	}
	gSCSI->finished(request, 1);
}
Пример #6
0
template<class T> SGNDArray<T> SGNDArray<T>::clone() const
{
	SGNDArray<T> array_clone(get_dimensions());
	sg_memcpy(array_clone.array, array, sizeof(T)*len_array);
	return array_clone;
}