예제 #1
0
/*
 * Initializes a host.
 */
static int sd_init(struct sd_host *host)
{
	int retval;

	spin_lock_init(&host->lock);

	host->refcnt = 0;
	set_bit(__SD_MEDIA_CHANGED, &host->flags);

	host->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34;
	sd_set_clock(host, SD_SPI_CLK);
	sd_calc_timeouts(host);

	retval = sd_init_blk_dev(host);
	if (!retval) {
		retval = sd_revalidate_disk(host->disk);
		if (retval < 0 || !mmc_card_present(&host->card)) {
			retval = -ENODEV;
			goto err_blk_dev;
		}

		retval = sd_init_io_thread(host);
		if (retval)
			goto err_blk_dev;

		add_disk(host->disk);
	}

	return retval;

err_blk_dev:
	sd_exit_blk_dev(host);
	return retval;
}
예제 #2
0
파일: sd.c 프로젝트: Voskrese/mipsonqemu
static ssize_t sd_store_cache_type(struct class_device *cdev, const char *buf,
				   size_t count)
{
	int i, ct = -1, rcd, wce, sp;
	struct scsi_disk *sdkp = to_scsi_disk(cdev);
	struct scsi_device *sdp = sdkp->device;
	char buffer[64];
	char *buffer_data;
	struct scsi_mode_data data;
	struct scsi_sense_hdr sshdr;
	int len;

	if (sdp->type != TYPE_DISK)
		/* no cache control on RBC devices; theoretically they
		 * can do it, but there's probably so many exceptions
		 * it's not worth the risk */
		return -EINVAL;

	for (i = 0; i < ARRAY_SIZE(sd_cache_types); i++) {
		const int len = strlen(sd_cache_types[i]);
		if (strncmp(sd_cache_types[i], buf, len) == 0 &&
		    buf[len] == '\n') {
			ct = i;
			break;
		}
	}
	if (ct < 0)
		return -EINVAL;
	rcd = ct & 0x01 ? 1 : 0;
	wce = ct & 0x02 ? 1 : 0;
	if (scsi_mode_sense(sdp, 0x08, 8, buffer, sizeof(buffer), SD_TIMEOUT,
			    SD_MAX_RETRIES, &data, NULL))
		return -EINVAL;
	len = min_t(size_t, sizeof(buffer), data.length - data.header_length -
		  data.block_descriptor_length);
	buffer_data = buffer + data.header_length +
		data.block_descriptor_length;
	buffer_data[2] &= ~0x05;
	buffer_data[2] |= wce << 2 | rcd;
	sp = buffer_data[0] & 0x80 ? 1 : 0;

	if (scsi_mode_select(sdp, 1, sp, 8, buffer_data, len, SD_TIMEOUT,
			     SD_MAX_RETRIES, &data, &sshdr)) {
		if (scsi_sense_valid(&sshdr))
			scsi_print_sense_hdr(sdkp->disk->disk_name, &sshdr);
		return -EINVAL;
	}
	sd_revalidate_disk(sdkp->disk);
	return count;
}