Esempio n. 1
0
static rtems_status_code
rtems_bsd_scsi_inquiry(union ccb *ccb, struct scsi_inquiry_data *inq_data)
{
	memset(inq_data, 0, sizeof(*inq_data));

	scsi_inquiry(
		&ccb->csio,
		BSD_SCSI_RETRIES,
		rtems_bsd_ccb_callback,
		BSD_SCSI_TAG,
		(u_int8_t *) inq_data,
		sizeof(*inq_data) - 1,
		FALSE,
		0,
		SSD_MIN_SIZE,
		BSD_SCSI_TIMEOUT
	);

	return rtems_bsd_ccb_action(ccb);
}
Esempio n. 2
0
int scsi_get_info(struct scsi_info *info, unsigned int lun,
		  struct scsi_transport *tr, void *priv)
{
	int rc;
	u32 *cap;
	unsigned char __cacheline_aligned buf[64];
	struct scsi_request srb;

	if (!info || !tr || !tr->transport) {
		return VMM_EINVALID;
	}

	memset(info, 0, sizeof(*info));

	INIT_SCSI_REQUEST(&srb, lun, &buf, sizeof(buf));
	rc = scsi_inquiry(&srb, tr, priv);
	if (rc) {
		return rc;
	}

	info->lun = lun;
	info->perph_qualifier = (buf[0] & 0xE0) >> 5;
	info->perph_type = buf[0] & 0x1F;
	info->removable = (buf[1] & 0x80) ? TRUE : FALSE;

	memcpy(&info->vendor[0], (const void *)&buf[8], 8);
	memcpy(&info->product[0], (const void *)&buf[16], 16);
	memcpy(&info->revision[0], (const void *)&buf[32], 4);
	info->vendor[8] = 0;
	info->product[16] = 0;
	info->revision[4] = 0;

	INIT_SCSI_REQUEST(&srb, lun, NULL, 0);
	rc = scsi_test_unit_ready(&srb, tr, priv);
	if (rc) {
		return rc;
	}

	INIT_SCSI_REQUEST(&srb, lun, buf, sizeof(buf));
	rc = scsi_read_capacity(&srb, tr, priv);
	if (rc) {
		return rc;
	}
	cap = (u32 *)buf;
	cap[0] = vmm_cpu_to_be32(cap[0]);
	cap[1] = vmm_cpu_to_be32(cap[1]);

	info->capacity = cap[0] + 1;
	info->blksz = cap[1];

	info->readonly = TRUE;
	switch (info->perph_type) {
	case 0x00:
	case 0x0C:
	case 0x0E:
	case 0x0F:
		info->readonly = FALSE;
		break;
	default:
		break;
	};

	if (tr->info_fixup) {
		tr->info_fixup(info, tr, priv);
	}

	return VMM_OK;
}
Esempio n. 3
0
bool usbhmsdLUNConnect(USBHMassStorageLUNDriver *lunp) {
	osalDbgCheck(lunp != NULL);
	osalDbgCheck(lunp->msdp != NULL);
	msd_result_t res;

	chSemWait(&lunp->sem);
	osalDbgAssert((lunp->state == BLK_READY) || (lunp->state == BLK_ACTIVE), "invalid state");
	if (lunp->state == BLK_READY) {
		chSemSignal(&lunp->sem);
		return HAL_SUCCESS;
	}
	lunp->state = BLK_CONNECTING;

    {
		USBH_DEFINE_BUFFER(scsi_inquiry_response_t inq);
		uinfo("INQUIRY...");
		res = scsi_inquiry(lunp, &inq);
		if (res == MSD_RESULT_DISCONNECTED) {
			goto failed;
		} else if (res == MSD_RESULT_TRANSPORT_ERROR) {
			//retry?
			goto failed;
		} else if (res == MSD_RESULT_FAILED) {
			//retry?
			goto failed;
		}

		uinfof("\tPDT=%02x", inq.peripheral & 0x1f);
		if (inq.peripheral != 0) {
			uerr("\tUnsupported PDT");
			goto failed;
		}
	}

	// Test if unit ready
    uint8_t i;
	for (i = 0; i < 10; i++) {
		uinfo("TEST UNIT READY...");
		res = scsi_testunitready(lunp);
		if (res == MSD_RESULT_DISCONNECTED) {
			goto failed;
		} else if (res == MSD_RESULT_TRANSPORT_ERROR) {
			//retry?
			goto failed;
		} else if (res == MSD_RESULT_FAILED) {
			uinfo("\tTEST UNIT READY: Command Failed, retry");
			osalThreadSleepMilliseconds(200);
			continue;
		}
		uinfo("\tReady.");
		break;
	}
	if (i == 10) goto failed;

	{
		USBH_DEFINE_BUFFER(scsi_readcapacity10_response_t cap);
		// Read capacity
		uinfo("READ CAPACITY(10)...");
		res = scsi_readcapacity10(lunp, &cap);
		if (res == MSD_RESULT_DISCONNECTED) {
			goto failed;
		} else if (res == MSD_RESULT_TRANSPORT_ERROR) {
			//retry?
			goto failed;
		} else if (res == MSD_RESULT_FAILED) {
			//retry?
			goto failed;
		}

		lunp->info.blk_size = __REV(cap.block_size);
		lunp->info.blk_num = __REV(cap.last_block_addr) + 1;
	}

	uinfof("\tBlock size=%dbytes, blocks=%u (~%u MB)", lunp->info.blk_size, lunp->info.blk_num,
		(uint32_t)(((uint64_t)lunp->info.blk_size * lunp->info.blk_num) / (1024UL * 1024UL)));

	uinfo("MSD Connected.");
	lunp->state = BLK_READY;
	chSemSignal(&lunp->sem);
	return HAL_SUCCESS;

  /* Connection failed, state reset to BLK_ACTIVE.*/
failed:
	uinfo("MSD Connect failed.");
	lunp->state = BLK_ACTIVE;
	chSemSignal(&lunp->sem);
	return HAL_FAILED;
}
Esempio n. 4
0
int scsi_parse(uint8_t *block, uint8_t in_len)
{
	/* set new operation */
	if (state == USB_MS_SCSI_STATE_IDLE) {
		state = USB_MS_SCSI_STATE_PARSE;

		op = block[0];
	}

	/* skip operation if sending reply */
	if (state != USB_MS_SCSI_STATE_REPLY) {
		switch (op) {
		case SCSI_INQUIRY:
			scsi_inquiry(block, in_len);
		break;
		case SCSI_MODE_SENSE6:
			scsi_mode_sense6(block, in_len);
		break;
		case SCSI_READ10:
			scsi_read10(block, in_len);
		break;
		case SCSI_READ_CAPACITY10:
			scsi_read_capacity10(block, in_len);
		break;
		case SCSI_READ_FORMAT_CAPACITIES:
			scsi_read_format_capacities(block, in_len);
		break;
		case SCSI_REPORT_LUNS:
			scsi_report_luns(block, in_len);
		break;
		case SCSI_REQUEST_SENSE:
			scsi_request_sense(block, in_len);
		break;
		case SCSI_START_STOP_UNIT:
			scsi_start_stop_unit(block, in_len);
		break;
		case SCSI_SYNCHRONIZE_CACHE10:
			scsi_synchronize_cache10(block, in_len);
		break;
		case SCSI_TEST_UNIT_READY:
			scsi_test_unit_ready(block, in_len);
		break;
		case SCSI_WRITE10:
			scsi_write10(block, in_len);
		break;
		default:
			state = USB_MS_SCSI_STATE_REPLY;
			scsi_sense_code(SCSI_SENSE_ILLEGAL_REQUEST,
				SCSI_SENSE_CODE_INVALID_COMMAND_OPERATION_CODE);
		break;
		}
	}

	/* error during data rx/tx */
	if (((state == USB_MS_SCSI_STATE_DATA_OUT) ||
			(state == USB_MS_SCSI_STATE_DATA_IN)) &&
			scsi_sense_data.key) {
		btable_ep[USB_EP_MS_TX].tx_count = 0;
		state = USB_MS_SCSI_STATE_REPLY;
		return SCSI_STATUS_CONTINUE;
	}

	/* done sending data */
	if (state == USB_MS_SCSI_STATE_REPLY) {
		state = USB_MS_SCSI_STATE_IDLE;
		return scsi_sense_data.key;
	}

	/* still sending/receiving data and no error has occurred */
	return SCSI_STATUS_CONTINUE;
}
void scsi_proc(void)
{
    if (USBD_ep_buffer_full(BOMS_EP_DATA_OUT)) {
        if (sizeof(BOMSCmd) == USBD_transfer(BOMS_EP_DATA_OUT, (uint8_t *)&BOMSCmd, sizeof(BOMSCmd))) {
            if (BOMSCmd.dCBWSignature == BOMS_USBC) {
                if (BOMSCmd.CBWCB.unit_ready.op_code == BOMS_SCSI_TEST_UNIT_READY) // SCSI Test Unit Ready
                {
                    scsi_test_unit_ready(&BOMSCmd);
                } 
                else if (BOMSCmd.CBWCB.request_sense.op_code == BOMS_SCSI_READ) // SCSI Read
                {
                    scsi_read(&BOMSCmd);
                }
                else if (BOMSCmd.CBWCB.request_sense.op_code == BOMS_SCSI_WRITE) // SCSI Write
                {
                    scsi_write(&BOMSCmd);
                }
                else if (BOMSCmd.CBWCB.inquiry.op_code == BOMS_SCSI_INQUIRY) // SCSI Inquiry
                {
                    scsi_inquiry(&BOMSCmd);
                }
                else if (BOMSCmd.CBWCB.request_sense.op_code == BOMS_SCSI_REQUEST_SENSE) // SCSI Request Sense
                {
                    scsi_request_sense(&BOMSCmd);
                }
                else if (BOMSCmd.CBWCB.read_capacity.op_code == BOMS_SCSI_READ_CAPACITY) // SCSI Read Capacity (10)
                {
                    scsi_read_capacity(&BOMSCmd);
                }
                else if (BOMSCmd.CBWCB.read_capacity.op_code == BOMS_SCSI_READ_FORMAT_CAPACITY) // SCSI Read Format Capacity (10)
                {
                    scsi_read_format_capacity(&BOMSCmd);
                }
                else if (BOMSCmd.CBWCB.mode_sense.op_code == BOMS_SCSI_MODE_SENSE) // SCSI Mode Sense
                {
                    scsi_mode_sense(&BOMSCmd);
                }
                else if (BOMSCmd.CBWCB.request_sense.op_code == BOMS_SCSI_READ_CAPACITY_16) // SCSI Read Capacity (16)
                {
                    scsi_read_capacity(&BOMSCmd);
                }
                else if (BOMSCmd.CBWCB.request_sense.op_code == BOMS_SCSI_PREVENT_ALLOW_REMOVAL) // SCSI Prevent Allow Removal
                {
                    scsi_prevent_allow_removal(&BOMSCmd);
                }
                else
                {
                    // Send IN a zero length packet.
                    if (BOMSCmd.dCBWDataTransferLength)
                    {
                        USBD_stall_endpoint(BOMS_EP_DATA_IN);
                    }
                    boms_send_status(BOMS_STATUS_COMMAND_FAILED, &BOMSCmd);
                    scsi_sense_illegal_request_command();
                }
            }
            else
            {
                // Was not a USBC signature.
                boms_send_status(BOMS_STATUS_PHASE_ERROR, &BOMSCmd);
                scsi_sense_illegal_request_cdb();
            }
        }else{
            // Wrong command size.
            boms_send_status(BOMS_STATUS_COMMAND_FAILED, &BOMSCmd);
            scsi_sense_illegal_request_parm();
        }
    }
}