/* * 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; }
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; }