diff options
Diffstat (limited to 'drivers/staging/rts5139/rts51x_scsi.c')
-rw-r--r-- | drivers/staging/rts5139/rts51x_scsi.c | 2135 |
1 files changed, 0 insertions, 2135 deletions
diff --git a/drivers/staging/rts5139/rts51x_scsi.c b/drivers/staging/rts5139/rts51x_scsi.c deleted file mode 100644 index 75282fe..0000000 --- a/drivers/staging/rts5139/rts51x_scsi.c +++ /dev/null @@ -1,2135 +0,0 @@ -/* Driver for Realtek RTS51xx USB card reader - * - * Copyright(c) 2009 Realtek Semiconductor Corp. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2, or (at your option) any - * later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, see <http://www.gnu.org/licenses/>. - * - * Author: - * wwang (wei_wang@realsil.com.cn) - * No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China - * Maintainer: - * Edwin Rong (edwin_rong@realsil.com.cn) - * No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China - */ - -#include <linux/blkdev.h> -#include <linux/kthread.h> -#include <linux/sched.h> -#include <linux/slab.h> -#include <linux/vmalloc.h> -#include <linux/export.h> - -#include <scsi/scsi.h> -#include <scsi/scsi_eh.h> -#include <scsi/scsi_device.h> - -#include "debug.h" -#include "rts51x.h" -#include "rts51x_chip.h" -#include "rts51x_scsi.h" -#include "rts51x_card.h" -#include "rts51x_transport.h" -#include "sd_cprm.h" -#include "ms_mg.h" -#include "trace.h" - -void rts51x_scsi_show_command(struct scsi_cmnd *srb) -{ - char *what = NULL; - int i, unknown_cmd = 0; - - switch (srb->cmnd[0]) { - case TEST_UNIT_READY: - what = (char *)"TEST_UNIT_READY"; - break; - case REZERO_UNIT: - what = (char *)"REZERO_UNIT"; - break; - case REQUEST_SENSE: - what = (char *)"REQUEST_SENSE"; - break; - case FORMAT_UNIT: - what = (char *)"FORMAT_UNIT"; - break; - case READ_BLOCK_LIMITS: - what = (char *)"READ_BLOCK_LIMITS"; - break; - case 0x07: - what = (char *)"REASSIGN_BLOCKS"; - break; - case READ_6: - what = (char *)"READ_6"; - break; - case WRITE_6: - what = (char *)"WRITE_6"; - break; - case SEEK_6: - what = (char *)"SEEK_6"; - break; - case READ_REVERSE: - what = (char *)"READ_REVERSE"; - break; - case WRITE_FILEMARKS: - what = (char *)"WRITE_FILEMARKS"; - break; - case SPACE: - what = (char *)"SPACE"; - break; - case INQUIRY: - what = (char *)"INQUIRY"; - break; - case RECOVER_BUFFERED_DATA: - what = (char *)"RECOVER_BUFFERED_DATA"; - break; - case MODE_SELECT: - what = (char *)"MODE_SELECT"; - break; - case RESERVE: - what = (char *)"RESERVE"; - break; - case RELEASE: - what = (char *)"RELEASE"; - break; - case COPY: - what = (char *)"COPY"; - break; - case ERASE: - what = (char *)"ERASE"; - break; - case MODE_SENSE: - what = (char *)"MODE_SENSE"; - break; - case START_STOP: - what = (char *)"START_STOP"; - break; - case RECEIVE_DIAGNOSTIC: - what = (char *)"RECEIVE_DIAGNOSTIC"; - break; - case SEND_DIAGNOSTIC: - what = (char *)"SEND_DIAGNOSTIC"; - break; - case ALLOW_MEDIUM_REMOVAL: - what = (char *)"ALLOW_MEDIUM_REMOVAL"; - break; - case SET_WINDOW: - what = (char *)"SET_WINDOW"; - break; - case READ_CAPACITY: - what = (char *)"READ_CAPACITY"; - break; - case READ_10: - what = (char *)"READ_10"; - break; - case WRITE_10: - what = (char *)"WRITE_10"; - break; - case SEEK_10: - what = (char *)"SEEK_10"; - break; - case WRITE_VERIFY: - what = (char *)"WRITE_VERIFY"; - break; - case VERIFY: - what = (char *)"VERIFY"; - break; - case SEARCH_HIGH: - what = (char *)"SEARCH_HIGH"; - break; - case SEARCH_EQUAL: - what = (char *)"SEARCH_EQUAL"; - break; - case SEARCH_LOW: - what = (char *)"SEARCH_LOW"; - break; - case SET_LIMITS: - what = (char *)"SET_LIMITS"; - break; - case READ_POSITION: - what = (char *)"READ_POSITION"; - break; - case SYNCHRONIZE_CACHE: - what = (char *)"SYNCHRONIZE_CACHE"; - break; - case LOCK_UNLOCK_CACHE: - what = (char *)"LOCK_UNLOCK_CACHE"; - break; - case READ_DEFECT_DATA: - what = (char *)"READ_DEFECT_DATA"; - break; - case MEDIUM_SCAN: - what = (char *)"MEDIUM_SCAN"; - break; - case COMPARE: - what = (char *)"COMPARE"; - break; - case COPY_VERIFY: - what = (char *)"COPY_VERIFY"; - break; - case WRITE_BUFFER: - what = (char *)"WRITE_BUFFER"; - break; - case READ_BUFFER: - what = (char *)"READ_BUFFER"; - break; - case UPDATE_BLOCK: - what = (char *)"UPDATE_BLOCK"; - break; - case READ_LONG: - what = (char *)"READ_LONG"; - break; - case WRITE_LONG: - what = (char *)"WRITE_LONG"; - break; - case CHANGE_DEFINITION: - what = (char *)"CHANGE_DEFINITION"; - break; - case WRITE_SAME: - what = (char *)"WRITE_SAME"; - break; - case GPCMD_READ_SUBCHANNEL: - what = (char *)"READ SUBCHANNEL"; - break; - case READ_TOC: - what = (char *)"READ_TOC"; - break; - case GPCMD_READ_HEADER: - what = (char *)"READ HEADER"; - break; - case GPCMD_PLAY_AUDIO_10: - what = (char *)"PLAY AUDIO (10)"; - break; - case GPCMD_PLAY_AUDIO_MSF: - what = (char *)"PLAY AUDIO MSF"; - break; - case GPCMD_GET_EVENT_STATUS_NOTIFICATION: - what = (char *)"GET EVENT/STATUS NOTIFICATION"; - break; - case GPCMD_PAUSE_RESUME: - what = (char *)"PAUSE/RESUME"; - break; - case LOG_SELECT: - what = (char *)"LOG_SELECT"; - break; - case LOG_SENSE: - what = (char *)"LOG_SENSE"; - break; - case GPCMD_STOP_PLAY_SCAN: - what = (char *)"STOP PLAY/SCAN"; - break; - case GPCMD_READ_DISC_INFO: - what = (char *)"READ DISC INFORMATION"; - break; - case GPCMD_READ_TRACK_RZONE_INFO: - what = (char *)"READ TRACK INFORMATION"; - break; - case GPCMD_RESERVE_RZONE_TRACK: - what = (char *)"RESERVE TRACK"; - break; - case GPCMD_SEND_OPC: - what = (char *)"SEND OPC"; - break; - case MODE_SELECT_10: - what = (char *)"MODE_SELECT_10"; - break; - case GPCMD_REPAIR_RZONE_TRACK: - what = (char *)"REPAIR TRACK"; - break; - case 0x59: - what = (char *)"READ MASTER CUE"; - break; - case MODE_SENSE_10: - what = (char *)"MODE_SENSE_10"; - break; - case GPCMD_CLOSE_TRACK: - what = (char *)"CLOSE TRACK/SESSION"; - break; - case 0x5C: - what = (char *)"READ BUFFER CAPACITY"; - break; - case 0x5D: - what = (char *)"SEND CUE SHEET"; - break; - case GPCMD_BLANK: - what = (char *)"BLANK"; - break; - case REPORT_LUNS: - what = (char *)"REPORT LUNS"; - break; - case MOVE_MEDIUM: - what = (char *)"MOVE_MEDIUM or PLAY AUDIO (12)"; - break; - case READ_12: - what = (char *)"READ_12"; - break; - case WRITE_12: - what = (char *)"WRITE_12"; - break; - case WRITE_VERIFY_12: - what = (char *)"WRITE_VERIFY_12"; - break; - case SEARCH_HIGH_12: - what = (char *)"SEARCH_HIGH_12"; - break; - case SEARCH_EQUAL_12: - what = (char *)"SEARCH_EQUAL_12"; - break; - case SEARCH_LOW_12: - what = (char *)"SEARCH_LOW_12"; - break; - case SEND_VOLUME_TAG: - what = (char *)"SEND_VOLUME_TAG"; - break; - case READ_ELEMENT_STATUS: - what = (char *)"READ_ELEMENT_STATUS"; - break; - case GPCMD_READ_CD_MSF: - what = (char *)"READ CD MSF"; - break; - case GPCMD_SCAN: - what = (char *)"SCAN"; - break; - case GPCMD_SET_SPEED: - what = (char *)"SET CD SPEED"; - break; - case GPCMD_MECHANISM_STATUS: - what = (char *)"MECHANISM STATUS"; - break; - case GPCMD_READ_CD: - what = (char *)"READ CD"; - break; - case 0xE1: - what = (char *)"WRITE CONTINUE"; - break; - case WRITE_LONG_2: - what = (char *)"WRITE_LONG_2"; - break; - case VENDOR_CMND: - what = (char *)"Realtek's vendor command"; - break; - default: - what = (char *)"(unknown command)"; - unknown_cmd = 1; - break; - } - - if (srb->cmnd[0] != TEST_UNIT_READY) - RTS51X_DEBUGP("Command %s (%d bytes)\n", what, srb->cmd_len); - if (unknown_cmd) { - RTS51X_DEBUGP(""); - for (i = 0; i < srb->cmd_len && i < 16; i++) - RTS51X_DEBUGPN(" %02x", srb->cmnd[i]); - RTS51X_DEBUGPN("\n"); - } -} - -void rts51x_set_sense_type(struct rts51x_chip *chip, unsigned int lun, int sense_type) -{ - switch (sense_type) { - case SENSE_TYPE_MEDIA_CHANGE: - rts51x_set_sense_data(chip, lun, CUR_ERR, 0x06, 0, 0x28, 0, 0, 0); - break; - - case SENSE_TYPE_MEDIA_NOT_PRESENT: - rts51x_set_sense_data(chip, lun, CUR_ERR, 0x02, 0, 0x3A, 0, 0, 0); - break; - - case SENSE_TYPE_MEDIA_LBA_OVER_RANGE: - rts51x_set_sense_data(chip, lun, CUR_ERR, 0x05, 0, 0x21, 0, 0, 0); - break; - - case SENSE_TYPE_MEDIA_LUN_NOT_SUPPORT: - rts51x_set_sense_data(chip, lun, CUR_ERR, 0x05, 0, 0x25, 0, 0, 0); - break; - - case SENSE_TYPE_MEDIA_WRITE_PROTECT: - rts51x_set_sense_data(chip, lun, CUR_ERR, 0x07, 0, 0x27, 0, 0, 0); - break; - - case SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR: - rts51x_set_sense_data(chip, lun, CUR_ERR, 0x03, 0, 0x11, 0, 0, 0); - break; - - case SENSE_TYPE_MEDIA_WRITE_ERR: - rts51x_set_sense_data(chip, lun, CUR_ERR, 0x03, 0, 0x0C, 0x02, 0, 0); - break; - - case SENSE_TYPE_MEDIA_INVALID_CMD_FIELD: - rts51x_set_sense_data(chip, lun, CUR_ERR, ILGAL_REQ, 0, - ASC_INVLD_CDB, ASCQ_INVLD_CDB, CDB_ILLEGAL, 1); - break; - - case SENSE_TYPE_FORMAT_CMD_FAILED: - rts51x_set_sense_data(chip, lun, CUR_ERR, 0x03, 0, 0x31, 0x01, 0, 0); - break; - -#ifdef SUPPORT_MAGIC_GATE - case SENSE_TYPE_MG_KEY_FAIL_NOT_ESTAB: - rts51x_set_sense_data(chip, lun, CUR_ERR, 0x05, 0, 0x6F, 0x02, 0, 0); - break; - - case SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN: - rts51x_set_sense_data(chip, lun, CUR_ERR, 0x05, 0, 0x6F, 0x00, 0, 0); - break; - - case SENSE_TYPE_MG_INCOMPATIBLE_MEDIUM: - rts51x_set_sense_data(chip, lun, CUR_ERR, 0x02, 0, 0x30, 0x00, 0, 0); - break; - - case SENSE_TYPE_MG_WRITE_ERR: - rts51x_set_sense_data(chip, lun, CUR_ERR, 0x03, 0, 0x0C, 0x00, 0, 0); - break; -#endif - - case SENSE_TYPE_NO_SENSE: - default: - rts51x_set_sense_data(chip, lun, CUR_ERR, 0, 0, 0, 0, 0, 0); - break; - } -} - -void rts51x_set_sense_data(struct rts51x_chip *chip, unsigned int lun, u8 err_code, - u8 sense_key, u32 info, u8 asc, u8 ascq, u8 sns_key_info0, - u16 sns_key_info1) -{ - struct sense_data_t *sense = &(chip->sense_buffer[lun]); - - sense->err_code = err_code; - sense->sense_key = sense_key; - sense->info[0] = (u8) (info >> 24); - sense->info[1] = (u8) (info >> 16); - sense->info[2] = (u8) (info >> 8); - sense->info[3] = (u8) info; - - sense->ad_sense_len = sizeof(struct sense_data_t) - 8; - sense->asc = asc; - sense->ascq = ascq; - if (sns_key_info0 != 0) { - sense->sns_key_info[0] = SKSV | sns_key_info0; - sense->sns_key_info[1] = (sns_key_info1 & 0xf0) >> 8; - sense->sns_key_info[2] = sns_key_info1 & 0x0f; - } -} - -static int test_unit_ready(struct scsi_cmnd *srb, struct rts51x_chip *chip) -{ - unsigned int lun = SCSI_LUN(srb); - - rts51x_init_cards(chip); - - if (!check_card_ready(chip, lun)) { - rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT); - return TRANSPORT_FAILED; - } - - if (!check_lun_mc(chip, lun)) { - set_lun_mc(chip, lun); - rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_CHANGE); - return TRANSPORT_FAILED; - } - - return TRANSPORT_GOOD; -} - -static unsigned char formatter_inquiry_str[20] = { - 'M', 'E', 'M', 'O', 'R', 'Y', 'S', 'T', 'I', 'C', 'K', - '-', 'M', 'G', /* Byte[47:49] */ - 0x0B, /* Byte[50]: MG, MS, MSPro, MSXC */ - 0x00, /* Byte[51]: Category Specific Commands */ - 0x00, /* Byte[52]: Access Control and feature */ - 0x20, 0x20, 0x20, /* Byte[53:55] */ -}; - -static int inquiry(struct scsi_cmnd *srb, struct rts51x_chip *chip) -{ - unsigned int lun = SCSI_LUN(srb); - char *inquiry_default = (char *)"Generic-xD/SD/M.S. 1.00 "; - char *inquiry_string; - unsigned char sendbytes; - unsigned char *buf; - u8 card = rts51x_get_lun_card(chip, lun); - int pro_formatter_flag = 0; - unsigned char inquiry_buf[] = { - QULIFIRE | DRCT_ACCESS_DEV, - RMB_DISC | 0x0D, - 0x00, - 0x01, - 0x1f, - 0x02, - 0, - REL_ADR | WBUS_32 | WBUS_16 | SYNC | LINKED | CMD_QUE | SFT_RE, - }; - - inquiry_string = inquiry_default; - - buf = vmalloc(scsi_bufflen(srb)); - if (buf == NULL) - TRACE_RET(chip, TRANSPORT_ERROR); - - if (MS_FORMATTER_ENABLED(chip) && (get_lun2card(chip, lun) & MS_CARD)) { - if (!card || (card == MS_CARD)) - pro_formatter_flag = 1; - } - - if (pro_formatter_flag) { - if (scsi_bufflen(srb) < 56) - sendbytes = (unsigned char)(scsi_bufflen(srb)); - else - sendbytes = 56; - } else { - if (scsi_bufflen(srb) < 36) - sendbytes = (unsigned char)(scsi_bufflen(srb)); - else - sendbytes = 36; - } - - if (sendbytes > 8) { - memcpy(buf, inquiry_buf, 8); - memcpy(buf + 8, inquiry_string, sendbytes - 8); - if (pro_formatter_flag) - buf[4] = 0x33; /* Additional Length */ - } else { - memcpy(buf, inquiry_buf, sendbytes); - } - - if (pro_formatter_flag) { - if (sendbytes > 36) - memcpy(buf + 36, formatter_inquiry_str, sendbytes - 36); - } - - scsi_set_resid(srb, 0); - - rts51x_set_xfer_buf(buf, scsi_bufflen(srb), srb); - vfree(buf); - - return TRANSPORT_GOOD; -} - -static int start_stop_unit(struct scsi_cmnd *srb, struct rts51x_chip *chip) -{ - unsigned int lun = SCSI_LUN(srb); - - scsi_set_resid(srb, scsi_bufflen(srb)); - - if (srb->cmnd[1] == 1) - return TRANSPORT_GOOD; - - switch (srb->cmnd[0x4]) { - case STOP_MEDIUM: - /* Media disabled */ - return TRANSPORT_GOOD; - - case UNLOAD_MEDIUM: - /* Media shall be unload */ - if (check_card_ready(chip, lun)) - rts51x_eject_card(chip, lun); - return TRANSPORT_GOOD; - - case MAKE_MEDIUM_READY: - case LOAD_MEDIUM: - if (check_card_ready(chip, lun)) { - return TRANSPORT_GOOD; - } else { - rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT); - TRACE_RET(chip, TRANSPORT_FAILED); - } - - break; - } - - TRACE_RET(chip, TRANSPORT_ERROR); -} - -static int allow_medium_removal(struct scsi_cmnd *srb, struct rts51x_chip *chip) -{ - int prevent; - - prevent = srb->cmnd[4] & 0x1; - - scsi_set_resid(srb, 0); - - if (prevent) { - rts51x_set_sense_type(chip, SCSI_LUN(srb), - SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); - TRACE_RET(chip, TRANSPORT_FAILED); - } - - return TRANSPORT_GOOD; -} - -static void ms_mode_sense(struct rts51x_chip *chip, u8 cmd, - int lun, u8 *buf, int buf_len) -{ - struct ms_info *ms_card = &(chip->ms_card); - int sys_info_offset; - int data_size = buf_len; - int support_format = 0; - int i = 0; - - if (cmd == MODE_SENSE) { - sys_info_offset = 8; - if (data_size > 0x68) - data_size = 0x68; - buf[i++] = 0x67; /* Mode Data Length */ - } else { - sys_info_offset = 12; - if (data_size > 0x6C) - data_size = 0x6C; - buf[i++] = 0x00; /* Mode Data Length (MSB) */ - buf[i++] = 0x6A; /* Mode Data Length (LSB) */ - } - - /* Medium Type Code */ - if (check_card_ready(chip, lun)) { - if (CHK_MSXC(ms_card)) { - support_format = 1; - buf[i++] = 0x40; - } else if (CHK_MSPRO(ms_card)) { - support_format = 1; - buf[i++] = 0x20; - } else { - buf[i++] = 0x10; - } - - /* WP */ - if (check_card_wp(chip, lun)) - buf[i++] = 0x80; - else - buf[i++] = 0x00; - } else { - buf[i++] = 0x00; /* MediaType */ - buf[i++] = 0x00; /* WP */ - } - - buf[i++] = 0x00; /* Reserved */ - - if (cmd == MODE_SENSE_10) { - buf[i++] = 0x00; /* Reserved */ - buf[i++] = 0x00; /* Block descriptor length(MSB) */ - buf[i++] = 0x00; /* Block descriptor length(LSB) */ - - /* The Following Data is the content of "Page 0x20" */ - if (data_size >= 9) - buf[i++] = 0x20; /* Page Code */ - if (data_size >= 10) - buf[i++] = 0x62; /* Page Length */ - if (data_size >= 11) - buf[i++] = 0x00; /* No Access Control */ - if (data_size >= 12) { - if (support_format) - buf[i++] = 0xC0; /* SF, SGM */ - else - buf[i++] = 0x00; - } - } else { - /* The Following Data is the content of "Page 0x20" */ - if (data_size >= 5) - buf[i++] = 0x20; /* Page Code */ - if (data_size >= 6) - buf[i++] = 0x62; /* Page Length */ - if (data_size >= 7) - buf[i++] = 0x00; /* No Access Control */ - if (data_size >= 8) { - if (support_format) - buf[i++] = 0xC0; /* SF, SGM */ - else - buf[i++] = 0x00; - } - } - - if (data_size > sys_info_offset) { - /* 96 Bytes Attribute Data */ - int len = data_size - sys_info_offset; - len = (len < 96) ? len : 96; - - memcpy(buf + sys_info_offset, ms_card->raw_sys_info, len); - } -} - -static int mode_sense(struct scsi_cmnd *srb, struct rts51x_chip *chip) -{ - unsigned int lun = SCSI_LUN(srb); - unsigned int dataSize; - int status; - int pro_formatter_flag; - unsigned char pageCode, *buf; - u8 card = rts51x_get_lun_card(chip, lun); - - if (!check_card_ready(chip, lun)) { - rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT); - scsi_set_resid(srb, scsi_bufflen(srb)); - TRACE_RET(chip, TRANSPORT_FAILED); - } - - pro_formatter_flag = 0; - dataSize = 8; - /* In Combo mode, device responses ModeSense command as a MS LUN - * when no card is inserted */ - if ((get_lun2card(chip, lun) & MS_CARD)) { - if (!card || (card == MS_CARD)) { - dataSize = 108; - if (chip->option.rts51x_mspro_formatter_enable) - pro_formatter_flag = 1; - } - } - - buf = kmalloc(dataSize, GFP_KERNEL); - if (buf == NULL) - TRACE_RET(chip, TRANSPORT_ERROR); - - pageCode = srb->cmnd[2] & 0x3f; - - if ((pageCode == 0x3F) || (pageCode == 0x1C) || - (pageCode == 0x00) || (pro_formatter_flag && (pageCode == 0x20))) { - if (srb->cmnd[0] == MODE_SENSE) { - if ((pageCode == 0x3F) || (pageCode == 0x20)) { - ms_mode_sense(chip, srb->cmnd[0], lun, buf, - dataSize); - } else { - dataSize = 4; - buf[0] = 0x03; - buf[1] = 0x00; - if (check_card_wp(chip, lun)) - buf[2] = 0x80; - else - buf[3] = 0x00; - } - } else { - if ((pageCode == 0x3F) || (pageCode == 0x20)) { - ms_mode_sense(chip, srb->cmnd[0], lun, buf, - dataSize); - } else { - dataSize = 8; - buf[0] = 0x00; - buf[1] = 0x06; - buf[2] = 0x00; - if (check_card_wp(chip, lun)) - buf[3] = 0x80; - else - buf[3] = 0x00; - buf[4] = 0x00; - buf[5] = 0x00; - buf[6] = 0x00; - buf[7] = 0x00; - } - } - status = TRANSPORT_GOOD; - } else { - rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); - scsi_set_resid(srb, scsi_bufflen(srb)); - status = TRANSPORT_FAILED; - } - - if (status == TRANSPORT_GOOD) { - unsigned int len = min(scsi_bufflen(srb), dataSize); - rts51x_set_xfer_buf(buf, len, srb); - scsi_set_resid(srb, scsi_bufflen(srb) - len); - } - kfree(buf); - - return status; -} - -static int request_sense(struct scsi_cmnd *srb, struct rts51x_chip *chip) -{ - struct sense_data_t *sense; - unsigned int lun = SCSI_LUN(srb); - struct ms_info *ms_card = &(chip->ms_card); - unsigned char *tmp, *buf; - - sense = &(chip->sense_buffer[lun]); - - if ((rts51x_get_lun_card(chip, lun) == MS_CARD) - && PRO_UNDER_FORMATTING(ms_card)) { - rts51x_mspro_format_sense(chip, lun); - } - - buf = vmalloc(scsi_bufflen(srb)); - if (buf == NULL) - TRACE_RET(chip, TRANSPORT_ERROR); - - tmp = (unsigned char *)sense; - memcpy(buf, tmp, scsi_bufflen(srb)); - - rts51x_set_xfer_buf(buf, scsi_bufflen(srb), srb); - vfree(buf); - - scsi_set_resid(srb, 0); - /* Reset Sense Data */ - rts51x_set_sense_type(chip, lun, SENSE_TYPE_NO_SENSE); - return TRANSPORT_GOOD; -} - -static int read_write(struct scsi_cmnd *srb, struct rts51x_chip *chip) -{ - unsigned int lun = SCSI_LUN(srb); - int retval; - u32 start_sec; - u16 sec_cnt; - - if (!check_card_ready(chip, lun) || (chip->capacity[lun] == 0)) { - rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT); - TRACE_RET(chip, TRANSPORT_FAILED); - } - - if (!check_lun_mc(chip, lun)) { - set_lun_mc(chip, lun); - rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_CHANGE); - return TRANSPORT_FAILED; - } - - rts51x_prepare_run(chip); - RTS51X_SET_STAT(chip, STAT_RUN); - - if ((srb->cmnd[0] == READ_10) || (srb->cmnd[0] == WRITE_10)) { - start_sec = - ((u32) srb->cmnd[2] << 24) | - ((u32) srb->cmnd[3] << 16) | - ((u32) srb->cmnd[4] << 8) | - ((u32) srb->cmnd[5]); - sec_cnt = ((u16) (srb->cmnd[7]) << 8) | srb->cmnd[8]; - } else if ((srb->cmnd[0] == READ_6) || (srb->cmnd[0] == WRITE_6)) { - start_sec = ((u32) (srb->cmnd[1] & 0x1F) << 16) | - ((u32) srb->cmnd[2] << 8) | ((u32) srb->cmnd[3]); - sec_cnt = srb->cmnd[4]; - } else if ((srb->cmnd[0] == VENDOR_CMND) && - (srb->cmnd[1] == SCSI_APP_CMD) && - ((srb->cmnd[2] == PP_READ10) || - (srb->cmnd[2] == PP_WRITE10))) { - start_sec = ((u32) srb->cmnd[4] << 24) | - ((u32) srb->cmnd[5] << 16) | - ((u32) srb->cmnd[6] << 8) | - ((u32) srb->cmnd[7]); - sec_cnt = ((u16) (srb->cmnd[9]) << 8) | srb->cmnd[10]; - } else { - rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); - TRACE_RET(chip, TRANSPORT_FAILED); - } - - if ((start_sec > chip->capacity[lun]) || - ((start_sec + sec_cnt) > chip->capacity[lun])) { - rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_LBA_OVER_RANGE); - TRACE_RET(chip, TRANSPORT_FAILED); - } - - if (sec_cnt == 0) { - scsi_set_resid(srb, 0); - return TRANSPORT_GOOD; - } - - if ((srb->sc_data_direction == DMA_TO_DEVICE) - && check_card_wp(chip, lun)) { - RTS51X_DEBUGP("Write protected card!\n"); - rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_WRITE_PROTECT); - TRACE_RET(chip, TRANSPORT_FAILED); - } - - retval = rts51x_card_rw(srb, chip, start_sec, sec_cnt); - if (retval != STATUS_SUCCESS) { - if (srb->sc_data_direction == DMA_FROM_DEVICE) { - rts51x_set_sense_type(chip, lun, - SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR); - } else { - rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_WRITE_ERR); - } - TRACE_RET(chip, TRANSPORT_FAILED); - } - - scsi_set_resid(srb, 0); - - return TRANSPORT_GOOD; -} - -static int read_format_capacity(struct scsi_cmnd *srb, struct rts51x_chip *chip) -{ - unsigned char *buf; - unsigned int lun = SCSI_LUN(srb); - unsigned int buf_len; - u8 card = rts51x_get_lun_card(chip, lun); - int desc_cnt; - int i = 0; - - if (!check_card_ready(chip, lun)) { - if (!chip->option.rts51x_mspro_formatter_enable) { - rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT); - TRACE_RET(chip, TRANSPORT_FAILED); - } - } - - buf_len = (scsi_bufflen(srb) > 12) ? 0x14 : 12; - - buf = kmalloc(buf_len, GFP_KERNEL); - if (buf == NULL) - TRACE_RET(chip, TRANSPORT_ERROR); - - buf[i++] = 0; - buf[i++] = 0; - buf[i++] = 0; - - /* Capacity List Length */ - if ((buf_len > 12) && chip->option.rts51x_mspro_formatter_enable && - (chip->lun2card[lun] & MS_CARD) && (!card || (card == MS_CARD))) { - buf[i++] = 0x10; - desc_cnt = 2; - } else { - buf[i++] = 0x08; - desc_cnt = 1; - } - - while (desc_cnt) { - if (check_card_ready(chip, lun)) { - buf[i++] = (unsigned char)((chip->capacity[lun]) >> 24); - buf[i++] = (unsigned char)((chip->capacity[lun]) >> 16); - buf[i++] = (unsigned char)((chip->capacity[lun]) >> 8); - buf[i++] = (unsigned char)(chip->capacity[lun]); - - if (desc_cnt == 2) - /* Byte[8]: Descriptor Type: Formatted medium */ - buf[i++] = 2; - else - buf[i++] = 0; /* Byte[16] */ - } else { - buf[i++] = 0xFF; - buf[i++] = 0xFF; - buf[i++] = 0xFF; - buf[i++] = 0xFF; - - if (desc_cnt == 2) - /* Byte[8]: Descriptor Type: No medium */ - buf[i++] = 3; - else - buf[i++] = 0; /*Byte[16] */ - } - - buf[i++] = 0x00; - buf[i++] = 0x02; - buf[i++] = 0x00; - - desc_cnt--; - } - - buf_len = min(scsi_bufflen(srb), buf_len); - rts51x_set_xfer_buf(buf, buf_len, srb); - kfree(buf); - - scsi_set_resid(srb, scsi_bufflen(srb) - buf_len); - - return TRANSPORT_GOOD; -} - -static int read_capacity(struct scsi_cmnd *srb, struct rts51x_chip *chip) -{ - unsigned char *buf; - unsigned int lun = SCSI_LUN(srb); - - if (!check_card_ready(chip, lun)) { - rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT); - TRACE_RET(chip, TRANSPORT_FAILED); - } - - if (!check_lun_mc(chip, lun)) { - set_lun_mc(chip, lun); - rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_CHANGE); - return TRANSPORT_FAILED; - } - - buf = kmalloc(8, GFP_KERNEL); - if (buf == NULL) - TRACE_RET(chip, TRANSPORT_ERROR); - - buf[0] = (unsigned char)((chip->capacity[lun] - 1) >> 24); - buf[1] = (unsigned char)((chip->capacity[lun] - 1) >> 16); - buf[2] = (unsigned char)((chip->capacity[lun] - 1) >> 8); - buf[3] = (unsigned char)(chip->capacity[lun] - 1); - - buf[4] = 0x00; - buf[5] = 0x00; - buf[6] = 0x02; - buf[7] = 0x00; - - rts51x_set_xfer_buf(buf, scsi_bufflen(srb), srb); - kfree(buf); - - scsi_set_resid(srb, 0); - - return TRANSPORT_GOOD; -} - -static int get_dev_status(struct scsi_cmnd *srb, struct rts51x_chip *chip) -{ - unsigned int lun = SCSI_LUN(srb); - unsigned int buf_len; - u8 status[32] = { 0 }; - - rts51x_pp_status(chip, lun, status, 32); - - buf_len = min_t(unsigned int, scsi_bufflen(srb), sizeof(status)); - rts51x_set_xfer_buf(status, buf_len, srb); - scsi_set_resid(srb, scsi_bufflen(srb) - buf_len); - - return TRANSPORT_GOOD; -} - -static int read_status(struct scsi_cmnd *srb, struct rts51x_chip *chip) -{ - u8 rts51x_status[16]; - unsigned int buf_len; - unsigned int lun = SCSI_LUN(srb); - - rts51x_read_status(chip, lun, rts51x_status, 16); - - buf_len = min_t(unsigned int, scsi_bufflen(srb), sizeof(rts51x_status)); - rts51x_set_xfer_buf(rts51x_status, buf_len, srb); - scsi_set_resid(srb, scsi_bufflen(srb) - buf_len); - - return TRANSPORT_GOOD; -} - -static int read_mem(struct scsi_cmnd *srb, struct rts51x_chip *chip) -{ - unsigned int lun = SCSI_LUN(srb); - unsigned short addr, len, i; - int retval; - u8 *buf; - - rts51x_prepare_run(chip); - RTS51X_SET_STAT(chip, STAT_RUN); - - addr = ((u16) srb->cmnd[2] << 8) | srb->cmnd[3]; - len = ((u16) srb->cmnd[4] << 8) | srb->cmnd[5]; - - if (addr < 0xe000) { - RTS51X_DEBUGP("filter!addr=0x%x\n", addr); - return TRANSPORT_GOOD; - } - - buf = vmalloc(len); - if (!buf) - TRACE_RET(chip, TRANSPORT_ERROR); - - for (i = 0; i < len; i++) { - retval = rts51x_ep0_read_register(chip, addr + i, buf + i); - if (retval != STATUS_SUCCESS) { - vfree(buf); - rts51x_set_sense_type(chip, lun, - SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR); - TRACE_RET(chip, TRANSPORT_FAILED); - } - } - - len = (unsigned short)min(scsi_bufflen(srb), (unsigned int)len); - rts51x_set_xfer_buf(buf, len, srb); - scsi_set_resid(srb, scsi_bufflen(srb) - len); - - vfree(buf); - - return TRANSPORT_GOOD; -} - -static int write_mem(struct scsi_cmnd *srb, struct rts51x_chip *chip) -{ - unsigned int lun = SCSI_LUN(srb); - unsigned short addr, len, i; - int retval; - u8 *buf; - - rts51x_prepare_run(chip); - RTS51X_SET_STAT(chip, STAT_RUN); - - addr = ((u16) srb->cmnd[2] << 8) | srb->cmnd[3]; - len = ((u16) srb->cmnd[4] << 8) | srb->cmnd[5]; - - if (addr < 0xe000) { - RTS51X_DEBUGP("filter!addr=0x%x\n", addr); - return TRANSPORT_GOOD; - } - - len = (unsigned short)min(scsi_bufflen(srb), (unsigned int)len); - buf = vmalloc(len); - if (!buf) - TRACE_RET(chip, TRANSPORT_ERROR); - - rts51x_get_xfer_buf(buf, len, srb); - - for (i = 0; i < len; i++) { - retval = - rts51x_ep0_write_register(chip, addr + i, 0xFF, buf[i]); - if (retval != STATUS_SUCCESS) { - vfree(buf); - rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_WRITE_ERR); - TRACE_RET(chip, TRANSPORT_FAILED); - } - } - - vfree(buf); - scsi_set_resid(srb, scsi_bufflen(srb) - len); - - return TRANSPORT_GOOD; -} - -static int get_sd_csd(struct scsi_cmnd *srb, struct rts51x_chip *chip) -{ - struct sd_info *sd_card = &(chip->sd_card); - unsigned int lun = SCSI_LUN(srb); - - if (!check_card_ready(chip, lun)) { - rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT); - TRACE_RET(chip, TRANSPORT_FAILED); - } - - if (rts51x_get_lun_card(chip, lun) != SD_CARD) { - rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR); - TRACE_RET(chip, TRANSPORT_FAILED); - } - - scsi_set_resid(srb, 0); - rts51x_set_xfer_buf(sd_card->raw_csd, scsi_bufflen(srb), srb); - - return TRANSPORT_GOOD; -} - -static int read_phy_register(struct scsi_cmnd *srb, struct rts51x_chip *chip) -{ - int retval; - u8 addr, len, i; - u8 *buf; - - rts51x_prepare_run(chip); - RTS51X_SET_STAT(chip, STAT_RUN); - - addr = srb->cmnd[5]; - len = srb->cmnd[7]; - - if (len) { - buf = vmalloc(len); - if (!buf) - TRACE_RET(chip, TRANSPORT_ERROR); - - for (i = 0; i < len; i++) { - retval = - rts51x_read_phy_register(chip, addr + i, buf + i); - if (retval != STATUS_SUCCESS) { - vfree(buf); - rts51x_set_sense_type(chip, SCSI_LUN(srb), - SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR); - TRACE_RET(chip, TRANSPORT_FAILED); - } - } - - len = min(scsi_bufflen(srb), (unsigned int)len); - rts51x_set_xfer_buf(buf, len, srb); - scsi_set_resid(srb, scsi_bufflen(srb) - len); - - vfree(buf); - } - - return TRANSPORT_GOOD; -} - -static int write_phy_register(struct scsi_cmnd *srb, struct rts51x_chip *chip) -{ - int retval; - u8 addr, len, i; - u8 *buf; - - rts51x_prepare_run(chip); - RTS51X_SET_STAT(chip, STAT_RUN); - - addr = srb->cmnd[5]; - len = srb->cmnd[7]; - - if (len) { - len = min(scsi_bufflen(srb), (unsigned int)len); - - buf = vmalloc(len); - if (buf == NULL) - TRACE_RET(chip, TRANSPORT_ERROR); - - rts51x_get_xfer_buf(buf, len, srb); - scsi_set_resid(srb, scsi_bufflen(srb) - len); - - for (i = 0; i < len; i++) { - retval = - rts51x_write_phy_register(chip, addr + i, buf[i]); - if (retval != STATUS_SUCCESS) { - vfree(buf); - rts51x_set_sense_type(chip, SCSI_LUN(srb), - SENSE_TYPE_MEDIA_WRITE_ERR); - TRACE_RET(chip, TRANSPORT_FAILED); - } - } - - vfree(buf); - } - - return TRANSPORT_GOOD; -} - -static int get_card_bus_width(struct scsi_cmnd *srb, struct rts51x_chip *chip) -{ - unsigned int lun = SCSI_LUN(srb); - u8 card, bus_width; - - if (!check_card_ready(chip, lun)) { - rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT); - TRACE_RET(chip, TRANSPORT_FAILED); - } - - card = rts51x_get_lun_card(chip, lun); - if ((card == SD_CARD) || (card == MS_CARD)) { - bus_width = chip->card_bus_width[lun]; - } else { - rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR); - TRACE_RET(chip, TRANSPORT_FAILED); - } - - scsi_set_resid(srb, 0); - rts51x_set_xfer_buf(&bus_width, scsi_bufflen(srb), srb); - - return TRANSPORT_GOOD; -} - -#ifdef _MSG_TRACE -static int trace_msg_cmd(struct scsi_cmnd *srb, struct rts51x_chip *chip) -{ - unsigned char *buf = NULL; - u8 clear; - unsigned int buf_len; - - buf_len = - 4 + - ((2 + MSG_FUNC_LEN + MSG_FILE_LEN + TIME_VAL_LEN) * TRACE_ITEM_CNT); - - if ((scsi_bufflen(srb) < buf_len) || (scsi_sglist(srb) == NULL)) { - rts51x_set_sense_type(chip, SCSI_LUN(srb), - SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR); - TRACE_RET(chip, TRANSPORT_FAILED); - } - - clear = srb->cmnd[2]; - - buf = vmalloc(scsi_bufflen(srb)); - if (buf == NULL) - TRACE_RET(chip, TRANSPORT_ERROR); - - rts51x_trace_msg(chip, buf, clear); - - rts51x_set_xfer_buf(buf, scsi_bufflen(srb), srb); - vfree(buf); - - scsi_set_resid(srb, 0); - return TRANSPORT_GOOD; -} -#endif - -static int rw_mem_cmd_buf(struct scsi_cmnd *srb, struct rts51x_chip *chip) -{ - int retval = STATUS_SUCCESS; - unsigned int lun = SCSI_LUN(srb); - u8 cmd_type, mask, value, idx, mode, len; - u16 addr; - u32 timeout; - - rts51x_prepare_run(chip); - RTS51X_SET_STAT(chip, STAT_RUN); - - switch (srb->cmnd[3]) { - case INIT_BATCHCMD: - rts51x_init_cmd(chip); - break; - - case ADD_BATCHCMD: - cmd_type = srb->cmnd[4]; - if (cmd_type > 2) { - rts51x_set_sense_type(chip, lun, - SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); - TRACE_RET(chip, TRANSPORT_FAILED); - } - addr = (srb->cmnd[5] << 8) | srb->cmnd[6]; - mask = srb->cmnd[7]; - value = srb->cmnd[8]; - rts51x_add_cmd(chip, cmd_type, addr, mask, value); - break; - - case SEND_BATCHCMD: - mode = srb->cmnd[4]; - len = srb->cmnd[5]; - timeout = - ((u32) srb->cmnd[6] << 24) | ((u32) srb-> - cmnd[7] << 16) | ((u32) srb-> - cmnd[8] << - 8) | ((u32) - srb-> - cmnd - [9]); - retval = rts51x_send_cmd(chip, mode, 1000); - if (retval != STATUS_SUCCESS) { - rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_WRITE_ERR); - TRACE_RET(chip, TRANSPORT_FAILED); - } - if (mode & STAGE_R) { - retval = rts51x_get_rsp(chip, len, timeout); - if (retval != STATUS_SUCCESS) { - rts51x_set_sense_type(chip, lun, - SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR); - TRACE_RET(chip, TRANSPORT_FAILED); - } - } - break; - - case GET_BATCHRSP: - idx = srb->cmnd[4]; - value = chip->rsp_buf[idx]; - if (scsi_bufflen(srb) < 1) { - rts51x_set_sense_type(chip, lun, - SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); - TRACE_RET(chip, TRANSPORT_FAILED); - } - rts51x_set_xfer_buf(&value, 1, srb); - scsi_set_resid(srb, 0); - break; - - default: - rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); - TRACE_RET(chip, TRANSPORT_FAILED); - } - - if (retval != STATUS_SUCCESS) { - rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_WRITE_ERR); - TRACE_RET(chip, TRANSPORT_FAILED); - } - - return TRANSPORT_GOOD; -} - -static int suit_cmd(struct scsi_cmnd *srb, struct rts51x_chip *chip) -{ - int result; - - switch (srb->cmnd[3]) { - case INIT_BATCHCMD: - case ADD_BATCHCMD: - case SEND_BATCHCMD: - case GET_BATCHRSP: - result = rw_mem_cmd_buf(srb, chip); - break; - default: - result = TRANSPORT_ERROR; - } - - return result; -} - -static int app_cmd(struct scsi_cmnd *srb, struct rts51x_chip *chip) -{ - int result; - - switch (srb->cmnd[2]) { - case PP_READ10: - case PP_WRITE10: - result = read_write(srb, chip); - break; - - case SUIT_CMD: - result = suit_cmd(srb, chip); - break; - - case READ_PHY: - result = read_phy_register(srb, chip); - break; - - case WRITE_PHY: - result = write_phy_register(srb, chip); - break; - - case GET_DEV_STATUS: - result = get_dev_status(srb, chip); - break; - - default: - rts51x_set_sense_type(chip, SCSI_LUN(srb), - SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); - TRACE_RET(chip, TRANSPORT_FAILED); - } - - return result; -} - -static int vendor_cmnd(struct scsi_cmnd *srb, struct rts51x_chip *chip) -{ - int result = TRANSPORT_GOOD; - - switch (srb->cmnd[1]) { - case READ_STATUS: - result = read_status(srb, chip); - break; - - case READ_MEM: - result = read_mem(srb, chip); - break; - - case WRITE_MEM: - result = write_mem(srb, chip); - break; - - case GET_BUS_WIDTH: - result = get_card_bus_width(srb, chip); - break; - - case GET_SD_CSD: - result = get_sd_csd(srb, chip); - break; - -#ifdef _MSG_TRACE - case TRACE_MSG: - result = trace_msg_cmd(srb, chip); - break; -#endif - - case SCSI_APP_CMD: - result = app_cmd(srb, chip); - break; - - default: - rts51x_set_sense_type(chip, SCSI_LUN(srb), - SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); - TRACE_RET(chip, TRANSPORT_FAILED); - } - - return result; -} - -static int ms_format_cmnd(struct scsi_cmnd *srb, struct rts51x_chip *chip) -{ - struct ms_info *ms_card = &(chip->ms_card); - unsigned int lun = SCSI_LUN(srb); - int retval, quick_format; - - if (rts51x_get_lun_card(chip, lun) != MS_CARD) { - rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_LUN_NOT_SUPPORT); - TRACE_RET(chip, TRANSPORT_FAILED); - } - - if ((srb->cmnd[3] != 0x4D) || (srb->cmnd[4] != 0x47) - || (srb->cmnd[5] != 0x66) || (srb->cmnd[6] != 0x6D) - || (srb->cmnd[7] != 0x74)) { - rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); - TRACE_RET(chip, TRANSPORT_FAILED); - } - - if (srb->cmnd[8] & 0x01) - quick_format = 0; - else - quick_format = 1; - - if (!(chip->card_ready & MS_CARD)) { - rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT); - TRACE_RET(chip, TRANSPORT_FAILED); - } - - if (chip->card_wp & MS_CARD) { - rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_WRITE_PROTECT); - TRACE_RET(chip, TRANSPORT_FAILED); - } - - if (!CHK_MSPRO(ms_card)) { - rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_LUN_NOT_SUPPORT); - TRACE_RET(chip, TRANSPORT_FAILED); - } - - rts51x_prepare_run(chip); - RTS51X_SET_STAT(chip, STAT_RUN); - - retval = rts51x_mspro_format(srb, chip, MS_SHORT_DATA_LEN, quick_format); - if (retval != STATUS_SUCCESS) { - rts51x_set_sense_type(chip, lun, SENSE_TYPE_FORMAT_CMD_FAILED); - TRACE_RET(chip, TRANSPORT_FAILED); - } - - scsi_set_resid(srb, 0); - return TRANSPORT_GOOD; -} - -#ifdef SUPPORT_PCGL_1P18 -static int get_ms_information(struct scsi_cmnd *srb, struct rts51x_chip *chip) -{ - struct ms_info *ms_card = &(chip->ms_card); - unsigned int lun = SCSI_LUN(srb); - u8 dev_info_id, data_len; - u8 *buf; - unsigned int buf_len; - int i; - - if (!check_card_ready(chip, lun)) { - rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT); - TRACE_RET(chip, TRANSPORT_FAILED); - } - if ((rts51x_get_lun_card(chip, lun) != MS_CARD)) { - rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_LUN_NOT_SUPPORT); - TRACE_RET(chip, TRANSPORT_FAILED); - } - - if ((srb->cmnd[2] != 0xB0) || (srb->cmnd[4] != 0x4D) || - (srb->cmnd[5] != 0x53) || (srb->cmnd[6] != 0x49) || - (srb->cmnd[7] != 0x44)) { - rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); - TRACE_RET(chip, TRANSPORT_FAILED); - } - - dev_info_id = srb->cmnd[3]; - if ((CHK_MSXC(ms_card) && (dev_info_id == 0x10)) || - (!CHK_MSXC(ms_card) && (dev_info_id == 0x13)) || - !CHK_MSPRO(ms_card)) { - rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); - TRACE_RET(chip, TRANSPORT_FAILED); - } - - if (dev_info_id == 0x15) - buf_len = data_len = 0x3A; - else - buf_len = data_len = 0x6A; - - buf = kmalloc(buf_len, GFP_KERNEL); - if (!buf) - TRACE_RET(chip, TRANSPORT_ERROR); - - i = 0; - /* GET Memory Stick Media Information Response Header */ - buf[i++] = 0x00; /* Data length MSB */ - buf[i++] = data_len; /* Data length LSB */ - /* Device Information Type Code */ - if (CHK_MSXC(ms_card)) - buf[i++] = 0x03; - else - buf[i++] = 0x02; - /* SGM bit */ - buf[i++] = 0x01; - /* Reserved */ - buf[i++] = 0x00; - buf[i++] = 0x00; - buf[i++] = 0x00; - /* Number of Device Information */ - buf[i++] = 0x01; - - /* Device Information Body - * Device Information ID Number */ - buf[i++] = dev_info_id; - /* Device Information Length */ - if (dev_info_id == 0x15) - data_len = 0x31; - else - data_len = 0x61; - buf[i++] = 0x00; /* Data length MSB */ - buf[i++] = data_len; /* Data length LSB */ - /* Valid Bit */ - buf[i++] = 0x80; - if ((dev_info_id == 0x10) || (dev_info_id == 0x13)) { - /* System Information */ - memcpy(buf + i, ms_card->raw_sys_info, 96); - } else { - /* Model Name */ - memcpy(buf + i, ms_card->raw_model_name, 48); - } - - rts51x_set_xfer_buf(buf, buf_len, srb); - - if (dev_info_id == 0x15) - scsi_set_resid(srb, scsi_bufflen(srb) - 0x3C); - else - scsi_set_resid(srb, scsi_bufflen(srb) - 0x6C); - - kfree(buf); - return STATUS_SUCCESS; -} -#endif - -static int ms_sp_cmnd(struct scsi_cmnd *srb, struct rts51x_chip *chip) -{ - int retval = TRANSPORT_ERROR; - - if (srb->cmnd[2] == MS_FORMAT) - retval = ms_format_cmnd(srb, chip); -#ifdef SUPPORT_PCGL_1P18 - else if (srb->cmnd[2] == GET_MS_INFORMATION) - retval = get_ms_information(srb, chip); -#endif - - return retval; -} - -#ifdef SUPPORT_CPRM -static int sd_extention_cmnd(struct scsi_cmnd *srb, struct rts51x_chip *chip) -{ - unsigned int lun = SCSI_LUN(srb); - int result; - - rts51x_prepare_run(chip); - RTS51X_SET_STAT(chip, STAT_RUN); - - rts51x_sd_cleanup_work(chip); - - if (!check_card_ready(chip, lun)) { - rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT); - TRACE_RET(chip, TRANSPORT_FAILED); - } - if ((rts51x_get_lun_card(chip, lun) != SD_CARD)) { - rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_LUN_NOT_SUPPORT); - TRACE_RET(chip, TRANSPORT_FAILED); - } - - switch (srb->cmnd[0]) { - case SD_PASS_THRU_MODE: - result = rts51x_sd_pass_thru_mode(srb, chip); - break; - - case SD_EXECUTE_NO_DATA: - result = rts51x_sd_execute_no_data(srb, chip); - break; - - case SD_EXECUTE_READ: - result = rts51x_sd_execute_read_data(srb, chip); - break; - - case SD_EXECUTE_WRITE: - result = rts51x_sd_execute_write_data(srb, chip); - break; - - case SD_GET_RSP: - result = rts51x_sd_get_cmd_rsp(srb, chip); - break; - - case SD_HW_RST: - result = rts51x_sd_hw_rst(srb, chip); - break; - - default: - rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); - TRACE_RET(chip, TRANSPORT_FAILED); - } - - return result; -} -#endif - -#ifdef SUPPORT_MAGIC_GATE -static int mg_report_key(struct scsi_cmnd *srb, struct rts51x_chip *chip) -{ - struct ms_info *ms_card = &(chip->ms_card); - unsigned int lun = SCSI_LUN(srb); - int retval; - u8 key_format; - - rts51x_prepare_run(chip); - RTS51X_SET_STAT(chip, STAT_RUN); - - rts51x_ms_cleanup_work(chip); - - if (!check_card_ready(chip, lun)) { - rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT); - TRACE_RET(chip, TRANSPORT_FAILED); - } - if ((rts51x_get_lun_card(chip, lun) != MS_CARD)) { - rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_LUN_NOT_SUPPORT); - TRACE_RET(chip, TRANSPORT_FAILED); - } - - if (srb->cmnd[7] != KC_MG_R_PRO) { - rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); - TRACE_RET(chip, TRANSPORT_FAILED); - } - - if (!CHK_MSPRO(ms_card)) { - rts51x_set_sense_type(chip, lun, SENSE_TYPE_MG_INCOMPATIBLE_MEDIUM); - TRACE_RET(chip, TRANSPORT_FAILED); - } - - key_format = srb->cmnd[10] & 0x3F; - - switch (key_format) { - case KF_GET_LOC_EKB: - if ((scsi_bufflen(srb) == 0x41C) && - (srb->cmnd[8] == 0x04) && (srb->cmnd[9] == 0x1C)) { - retval = rts51x_mg_get_local_EKB(srb, chip); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, TRANSPORT_FAILED); - } else { - rts51x_set_sense_type(chip, lun, - SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); - TRACE_RET(chip, TRANSPORT_FAILED); - } - break; - - case KF_RSP_CHG: - if ((scsi_bufflen(srb) == 0x24) && - (srb->cmnd[8] == 0x00) && (srb->cmnd[9] == 0x24)) { - retval = rts51x_mg_get_rsp_chg(srb, chip); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, TRANSPORT_FAILED); - } else { - rts51x_set_sense_type(chip, lun, - SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); - TRACE_RET(chip, TRANSPORT_FAILED); - } - break; - - case KF_GET_ICV: - ms_card->mg_entry_num = srb->cmnd[5]; - if ((scsi_bufflen(srb) == 0x404) && - (srb->cmnd[8] == 0x04) && - (srb->cmnd[9] == 0x04) && - (srb->cmnd[2] == 0x00) && - (srb->cmnd[3] == 0x00) && - (srb->cmnd[4] == 0x00) && (srb->cmnd[5] < 32)) { - retval = rts51x_mg_get_ICV(srb, chip); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, TRANSPORT_FAILED); - } else { - rts51x_set_sense_type(chip, lun, - SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); - TRACE_RET(chip, TRANSPORT_FAILED); - } - break; - - default: - rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); - TRACE_RET(chip, TRANSPORT_FAILED); - } - - scsi_set_resid(srb, 0); - return TRANSPORT_GOOD; -} - -static int mg_send_key(struct scsi_cmnd *srb, struct rts51x_chip *chip) -{ - struct ms_info *ms_card = &(chip->ms_card); - unsigned int lun = SCSI_LUN(srb); - int retval; - u8 key_format; - - rts51x_prepare_run(chip); - RTS51X_SET_STAT(chip, STAT_RUN); - - rts51x_ms_cleanup_work(chip); - - if (!check_card_ready(chip, lun)) { - rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT); - TRACE_RET(chip, TRANSPORT_FAILED); - } - if (check_card_wp(chip, lun)) { - rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_WRITE_PROTECT); - TRACE_RET(chip, TRANSPORT_FAILED); - } - if ((rts51x_get_lun_card(chip, lun) != MS_CARD)) { - rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_LUN_NOT_SUPPORT); - TRACE_RET(chip, TRANSPORT_FAILED); - } - - if (srb->cmnd[7] != KC_MG_R_PRO) { - rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); - TRACE_RET(chip, TRANSPORT_FAILED); - } - - if (!CHK_MSPRO(ms_card)) { - rts51x_set_sense_type(chip, lun, SENSE_TYPE_MG_INCOMPATIBLE_MEDIUM); - TRACE_RET(chip, TRANSPORT_FAILED); - } - - key_format = srb->cmnd[10] & 0x3F; - - switch (key_format) { - case KF_SET_LEAF_ID: - if ((scsi_bufflen(srb) == 0x0C) && - (srb->cmnd[8] == 0x00) && (srb->cmnd[9] == 0x0C)) { - retval = rts51x_mg_set_leaf_id(srb, chip); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, TRANSPORT_FAILED); - } else { - rts51x_set_sense_type(chip, lun, - SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); - TRACE_RET(chip, TRANSPORT_FAILED); - } - break; - - case KF_CHG_HOST: - if ((scsi_bufflen(srb) == 0x0C) && - (srb->cmnd[8] == 0x00) && (srb->cmnd[9] == 0x0C)) { - retval = rts51x_mg_chg(srb, chip); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, TRANSPORT_FAILED); - } else { - rts51x_set_sense_type(chip, lun, - SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); - TRACE_RET(chip, TRANSPORT_FAILED); - } - break; - - case KF_RSP_HOST: - if ((scsi_bufflen(srb) == 0x0C) && - (srb->cmnd[8] == 0x00) && (srb->cmnd[9] == 0x0C)) { - retval = rts51x_mg_rsp(srb, chip); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, TRANSPORT_FAILED); - } else { - rts51x_set_sense_type(chip, lun, - SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); - TRACE_RET(chip, TRANSPORT_FAILED); - } - break; - - case KF_SET_ICV: - ms_card->mg_entry_num = srb->cmnd[5]; - if ((scsi_bufflen(srb) == 0x404) && - (srb->cmnd[8] == 0x04) && - (srb->cmnd[9] == 0x04) && - (srb->cmnd[2] == 0x00) && - (srb->cmnd[3] == 0x00) && - (srb->cmnd[4] == 0x00) && (srb->cmnd[5] < 32)) { - retval = rts51x_mg_set_ICV(srb, chip); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, TRANSPORT_FAILED); - } else { - rts51x_set_sense_type(chip, lun, - SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); - TRACE_RET(chip, TRANSPORT_FAILED); - } - break; - - default: - rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); - TRACE_RET(chip, TRANSPORT_FAILED); - } - - scsi_set_resid(srb, 0); - return TRANSPORT_GOOD; -} -#endif - -int rts51x_scsi_handler(struct scsi_cmnd *srb, struct rts51x_chip *chip) -{ - struct ms_info *ms_card = &(chip->ms_card); - unsigned int lun = SCSI_LUN(srb); - int result = TRANSPORT_GOOD; - - if ((rts51x_get_lun_card(chip, lun) == MS_CARD) && - (ms_card->format_status == FORMAT_IN_PROGRESS)) { - if ((srb->cmnd[0] != REQUEST_SENSE) - && (srb->cmnd[0] != INQUIRY)) { - /* Logical Unit Not Ready Format in Progress */ - rts51x_set_sense_data(chip, lun, CUR_ERR, 0x02, 0, 0x04, 0x04, - 0, (u16) (ms_card->progress)); - TRACE_RET(chip, TRANSPORT_FAILED); - } - } - - switch (srb->cmnd[0]) { - case READ_10: - case WRITE_10: - case READ_6: - case WRITE_6: - result = read_write(srb, chip); - break; - - case TEST_UNIT_READY: - result = test_unit_ready(srb, chip); - break; - - case INQUIRY: - result = inquiry(srb, chip); - break; - - case READ_CAPACITY: - result = read_capacity(srb, chip); - break; - - case START_STOP: - result = start_stop_unit(srb, chip); - break; - - case ALLOW_MEDIUM_REMOVAL: - result = allow_medium_removal(srb, chip); - break; - - case REQUEST_SENSE: - result = request_sense(srb, chip); - break; - - case MODE_SENSE: - case MODE_SENSE_10: - result = mode_sense(srb, chip); - break; - - case 0x23: - result = read_format_capacity(srb, chip); - break; - - case VENDOR_CMND: - result = vendor_cmnd(srb, chip); - break; - - case MS_SP_CMND: - result = ms_sp_cmnd(srb, chip); - break; - -#ifdef SUPPORT_CPRM - case SD_PASS_THRU_MODE: - case SD_EXECUTE_NO_DATA: - case SD_EXECUTE_READ: - case SD_EXECUTE_WRITE: - case SD_GET_RSP: - case SD_HW_RST: - result = sd_extention_cmnd(srb, chip); - break; -#endif - -#ifdef SUPPORT_MAGIC_GATE - case CMD_MSPRO_MG_RKEY: - result = mg_report_key(srb, chip); - break; - - case CMD_MSPRO_MG_SKEY: - result = mg_send_key(srb, chip); - break; -#endif - - case FORMAT_UNIT: - case MODE_SELECT: - case VERIFY: - result = TRANSPORT_GOOD; - break; - - default: - rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); - result = TRANSPORT_FAILED; - } - - return result; -} - -/*********************************************************************** - * Host functions - ***********************************************************************/ - -int slave_alloc(struct scsi_device *sdev) -{ - /* - * Set the INQUIRY transfer length to 36. We don't use any of - * the extra data and many devices choke if asked for more or - * less than 36 bytes. - */ - sdev->inquiry_len = 36; - return 0; -} - -int slave_configure(struct scsi_device *sdev) -{ - /* Scatter-gather buffers (all but the last) must have a length - * divisible by the bulk maxpacket size. Otherwise a data packet - * would end up being short, causing a premature end to the data - * transfer. Since high-speed bulk pipes have a maxpacket size - * of 512, we'll use that as the scsi device queue's DMA alignment - * mask. Guaranteeing proper alignment of the first buffer will - * have the desired effect because, except at the beginning and - * the end, scatter-gather buffers follow page boundaries. */ - blk_queue_dma_alignment(sdev->request_queue, (512 - 1)); - - /* Set the SCSI level to at least 2. We'll leave it at 3 if that's - * what is originally reported. We need this to avoid confusing - * the SCSI layer with devices that report 0 or 1, but need 10-byte - * commands (ala ATAPI devices behind certain bridges, or devices - * which simply have broken INQUIRY data). - * - * NOTE: This means /dev/sg programs (ala cdrecord) will get the - * actual information. This seems to be the preference for - * programs like that. - * - * NOTE: This also means that /proc/scsi/scsi and sysfs may report - * the actual value or the modified one, depending on where the - * data comes from. - */ - if (sdev->scsi_level < SCSI_2) - sdev->scsi_level = sdev->sdev_target->scsi_level = SCSI_2; - - return 0; -} - -/*********************************************************************** - * /proc/scsi/ functions - ***********************************************************************/ - -/* we use this macro to help us write into the buffer */ -#undef SPRINTF -#define SPRINTF(args...) seq_printf(m, ##args) - -static int write_info(struct Scsi_Host *host, char *buffer, int length) -{ - /* if someone is sending us data, just throw it away */ - return length; -} - -static int show_info(struct seq_file *m, struct Scsi_Host *host) -{ - /* print the controller name */ - SPRINTF(" Host scsi%d: %s\n", host->host_no, RTS51X_NAME); - - /* print product, vendor, and driver version strings */ - SPRINTF(" Vendor: Realtek Corp.\n"); - SPRINTF(" Product: RTS51xx USB Card Reader\n"); - SPRINTF(" Version: %s\n", DRIVER_VERSION); - return 0; -} - -/* queue a command */ -/* This is always called with scsi_lock(host) held */ -static int queuecommand_lck(struct scsi_cmnd *srb, void (*done) (struct scsi_cmnd *)) -{ - struct rts51x_chip *chip = host_to_rts51x(srb->device->host); - - /* check for state-transition errors */ - if (chip->srb != NULL) { - RTS51X_DEBUGP("Error in %s: chip->srb = %p\n", - __func__, chip->srb); - return SCSI_MLQUEUE_HOST_BUSY; - } - - /* fail the command if we are disconnecting */ - if (test_bit(FLIDX_DISCONNECTING, &chip->usb->dflags)) { - RTS51X_DEBUGP("Fail command during disconnect\n"); - srb->result = DID_NO_CONNECT << 16; - done(srb); - return 0; - } - - /* enqueue the command and wake up the control thread */ - srb->scsi_done = done; - chip->srb = srb; - complete(&chip->usb->cmnd_ready); - - return 0; -} - -DEF_SCSI_QCMD(queuecommand) -/*********************************************************************** - * Error handling functions - ***********************************************************************/ -/* Command timeout and abort */ -int command_abort(struct scsi_cmnd *srb) -{ - struct rts51x_chip *chip = host_to_rts51x(srb->device->host); - - RTS51X_DEBUGP("%s called\n", __func__); - - /* us->srb together with the TIMED_OUT, RESETTING, and ABORTING - * bits are protected by the host lock. */ - scsi_lock(rts51x_to_host(chip)); - - /* Is this command still active? */ - if (chip->srb != srb) { - scsi_unlock(rts51x_to_host(chip)); - RTS51X_DEBUGP("-- nothing to abort\n"); - return FAILED; - } - - /* Set the TIMED_OUT bit. Also set the ABORTING bit, but only if - * a device reset isn't already in progress (to avoid interfering - * with the reset). Note that we must retain the host lock while - * calling usb_stor_stop_transport(); otherwise it might interfere - * with an auto-reset that begins as soon as we release the lock. */ - set_bit(FLIDX_TIMED_OUT, &chip->usb->dflags); - if (!test_bit(FLIDX_RESETTING, &chip->usb->dflags)) { - set_bit(FLIDX_ABORTING, &chip->usb->dflags); - /* rts51x_stop_transport(us); */ - } - scsi_unlock(rts51x_to_host(chip)); - - /* Wait for the aborted command to finish */ - wait_for_completion(&chip->usb->notify); - return SUCCESS; -} - -/* This invokes the transport reset mechanism to reset the state of the - * device */ -static int device_reset(struct scsi_cmnd *srb) -{ - int result = 0; - - RTS51X_DEBUGP("%s called\n", __func__); - - return result < 0 ? FAILED : SUCCESS; -} - -/* Simulate a SCSI bus reset by resetting the device's USB port. */ -int bus_reset(struct scsi_cmnd *srb) -{ - int result = 0; - - RTS51X_DEBUGP("%s called\n", __func__); - - return result < 0 ? FAILED : SUCCESS; -} - -static const char *rts5139_info(struct Scsi_Host *host) -{ - return "SCSI emulation for RTS5139 USB card reader"; -} - -struct scsi_host_template rts51x_host_template = { - /* basic userland interface stuff */ - .name = RTS51X_NAME, - .proc_name = RTS51X_NAME, - .show_info = show_info, - .write_info = write_info, - .info = rts5139_info, - - /* command interface -- queued only */ - .queuecommand = queuecommand, - - /* error and abort handlers */ - .eh_abort_handler = command_abort, - .eh_device_reset_handler = device_reset, - .eh_bus_reset_handler = bus_reset, - - /* queue commands only, only one command per LUN */ - .can_queue = 1, - .cmd_per_lun = 1, - - /* unknown initiator id */ - .this_id = -1, - - .slave_alloc = slave_alloc, - .slave_configure = slave_configure, - - /* lots of sg segments can be handled */ - .sg_tablesize = SG_ALL, - - /* limit the total size of a transfer to 120 KB */ - .max_sectors = 240, - - /* merge commands... this seems to help performance, but - * periodically someone should test to see which setting is more - * optimal. - */ - .use_clustering = 1, - - /* emulated HBA */ - .emulated = 1, - - /* we do our own delay after a device or bus reset */ - .skip_settle_delay = 1, - - /* sysfs device attributes */ - /* .sdev_attrs = sysfs_device_attr_list, */ - - /* module management */ - .module = THIS_MODULE -}; - |