📄 usbd_scsi.c
字号:
/* * A EEEE SSSS OOO PPPP * A A E S O O P P * AAAAA EEEE SSSS O O PPPP * A A E S O O P * A A EEEE SSSS OOO P * * An Entertainment Solution On a Platform (AESOP) is a completely Open Source * based graphical user environment and suite of applications for PDAs and other * devices running Linux. It is included in various embedded Linux distributions * such as OpenZaurus - http://www.aesop-embedded.org * * * 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 of the License, 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. * * * Title : usbd_scsi.c * Author : * Created date : 2005. 06. 26. 23:13:50 KST * Description : * * $Revision: 1.2 $ * $Log: usbd_scsi.c,v $ * Revision 1.2 2005/07/05 14:16:41 jeenspa * usbdmass fixup, nand, mkyaffs * * Revision 1.1.1.1 2005/06/27 17:04:30 linuxpark * Initial import. * * * */ #ident "@(*) $Header: /cvsroot/aesop-embedded/u-boot-aesop/board/aesop2440/usbd_scsi.c,v 1.2 2005/07/05 14:16:41 jeenspa Exp $"/* * Copyright (c) 2005 * Junyoung Song, kernelproject.org <jun0song@kornet.net> * * See file CREDITS for list of people who contributed to this * project. * * 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 of * the License, 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, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, * MA 02111-1307 USA */#if 0#define DEBUGJY 3#endif#include <common.h>#ifdef CONFIG_AESOP_USBDMASS#include <s3c2440.h>#include "usbd_common.h"#include "usbd_24x0.h"#include "usbd_mass.h"#include "usbd_media.h"#include "usbd_scsi.h"const unsigned char scsi_error[SCSI_ERROR_MAX][4] = { {0x70, 0x00, 0x00, 0x00}, /* SCSI_ERROR_NoError */ {0x70, 0x02, 0x04, 0x00}, /* SCSI_ERROR_NotReady : Logical Unit Not Ready-Cause not reportable */ {0x70, 0x02, 0x04, 0x01}, /* SCSI_ERROR_BecomingReady : Not Ready-Logical Unit is in Process of Becoming Ready */ {0x70, 0x02, 0x04, 0x04}, /* SCSI_ERROR_FormatProgress : Not Ready-Logical Unit Not Ready, Format in Progress */ {0x70, 0x02, 0x3a, 0x00}, /* SCSI_ERROR_MediumNotPresent : Not Ready-Medium Not Present */ {0xf0, 0x03, 0x33, 0x00}, /* SCSI_ERROR_WriteFault : Medium Error-Peripheral Device Write Fault */ {0xf0, 0x03, 0x11, 0x00}, /* SCSI_ERROR_ReadError : Medium Error-Unrecovered read error */ {0x70, 0x03, 0x30, 0x00}, /* SCSI_ERROR_IncompatibleMedium : Medium Error-Incompatible Medium Installed */ {0x70, 0x03, 0x30, 0x01}, /* SCSI_ERROR_UnknownFormat : Cannot read Medium-Unknown Format */ {0x70, 0x03, 0x30, 0x02}, /* SCSI_ERROR_IncompatileFormat : Medium Error-Cannot read Medium, Incompatible Format */ {0x70, 0x03, 0x31, 0x01}, /* SCSI_ERROR_FormatFail : Medium Error-Format Command Failed */ {0x71, 0x03, 0x31, 0x01}, /* SCSI_ERROR_FormatFailLast : Medium Error-Format Command Failed */ {0x70, 0x04, 0x40, 0x80}, /* SCSI_ERROR_HardwareError : Hardware Error-Diagnostic Failure on Component NN(80h-FFh) */ {0x70, 0x05, 0x20, 0x00}, /* SCSI_ERROR_InvalidCommand : Illegal Request-Invalid Command Operation Code */ {0xf0, 0x05, 0x21, 0x00}, /* SCSI_ERROR_AddressOutOfRange : Illegal Request-Logical Block Address Out of Range */ {0x70, 0x05, 0x24, 0x00}, /* SCSI_ERROR_InvalidFieldCdb : Illegal Request-Invalid Field in CDB */ {0x70, 0x05, 0x26, 0x00}, /* SCSI_ERROR_InvalidFieldParameter : Illegal Request-Invalid Field in Parameter List */ {0x70, 0x05, 0x39, 0x00}, /* SCSI_ERROR_SavingParameterNotSupported : Illegal Request-Saving Parameter not Supported */ {0x70, 0x05, 0x53, 0x02}, /* SCSI_ERROR_RemovalPrevented : Illegal Request-Medium Removal Prevented */ {0x70, 0x06, 0x28, 0x00}, /* SCSI_ERROR_MediumChanged : Unit Attention-Not Ready to Ready Change, Medium may have Changed */ {0x70, 0x06, 0x29, 0x00}, /* SCSI_ERROR_Reset : Unit Attention-Power on, Reset, or Bus Device reset Occurred */ {0x70, 0x07, 0x27, 0x00} /* SCSI_ERROR_WriteProtect : Data Protect-Write Protected */};/* ------------------------------------------------------------------------- */void usbd_scsi_init(usbd_mass_instance *ma){ ma->scsi_rw_option = 0x80; ma->scsi_rw_rdretry = 4; ma->scsi_rw_wrretry = 4; return;}char usbd_scsi_command(usbd_mass_instance *ma){ debugvs(1, "SCSI Command process :: Command %02x\n", ma->cbw.CBWCB[0]); debughd(3, ma->cbw.CBWCB, 15); switch (ma->cbw.CBWCB[0]) { case SCSI_ComTestUnitReady: return usbd_scsi_com_testunitready(ma); case SCSI_ComRezeroUnit: return usbd_scsi_command_noerror_end(ma); case SCSI_ComRequestSense: return usbd_scsi_com_requestsense(ma); case SCSI_ComFormatUnit: return usbd_scsi_command_noerror_end(ma); case SCSI_ComRead6: return usbd_scsi_com_read(ma); case SCSI_ComRead10: return usbd_scsi_com_read(ma); case SCSI_ComWrite6: return usbd_scsi_com_write(ma); case SCSI_ComWrite10: return usbd_scsi_com_write(ma); case SCSI_ComSeek6: return usbd_scsi_command_noerror_end(ma); case SCSI_ComSeek10: return usbd_scsi_command_noerror_end(ma); case SCSI_ComInquiry: return usbd_scsi_com_inquiry(ma); /*---------------- case SCSI_ComModeSelect6: return usbd_scsi_com_(ma); case SCSI_ComModeSelect10: return usbd_scsi_com_(ma); case SCSI_ComReserveUnit: return usbd_scsi_com_(ma); case SCSI_ComReleaseUnit: return usbd_scsi_com_(ma);-----------------*/ case SCSI_ComModeSense6: return usbd_scsi_com_modesense(ma); case SCSI_ComModeSense10: return usbd_scsi_com_modesense(ma); /*---------------- case SCSI_ComStartStopUnit: return usbd_scsi_com_(ma);-----------------*/ case SCSI_ComPreAllMedRemoval: return usbd_scsi_command_noerror_end(ma); case SCSI_ComSendDiagnostic: return usbd_scsi_com_senddiagnostic(ma); case SCSI_ComReadFormatCapacities: return usbd_scsi_com_readformatcapacities(ma); case SCSI_ComReadCapacity: return usbd_scsi_com_readcapacity(ma); /*---------------- case SCSI_ComWriteVerify: return usbd_scsi_com_(ma); case SCSI_ComVerify: return usbd_scsi_com_(ma);-----------------*/ case SCSI_ComSyncCache: return usbd_scsi_command_noerror_end(ma); default: return usbd_scsi_com_unknown(ma); }}char usbd_scsi_com_(usbd_mass_instance *ma){ debugvs(1, "%s : %s - SCSI Command Handler Not Implemented %02x\n", __FILE__, __FUNCTION__, ma->cbw.CBWCB[0]); usbd_scsi_set_error(ma, SCSI_ERROR_InvalidCommand, 0); ma->state = SEND_CSW; return CSW_STATUS_CommandFailed;}char usbd_scsi_com_unknown(usbd_mass_instance *ma){ debugvs(1, "%s : %s - SCSI Unknown Command %02x\n", __FILE__, __FUNCTION__, ma->cbw.CBWCB[0]); usbd_scsi_set_error(ma, SCSI_ERROR_InvalidCommand, 0); ma->state = SEND_CSW; return CSW_STATUS_CommandFailed;}char usbd_scsi_com_testunitready(usbd_mass_instance *ma){ char ret; debugvs(1, "%s : %s - SCSI TestUnitReady\n", __FILE__, __FUNCTION__);/* usbd_media_probe(ma); switch (ma->media.status) { case ABSENT: debugvs(1, "%s : %s - SCSI TestUnitReady :: Medium NOT Present\n", __FILE__, __FUNCTION__); usbd_scsi_set_error(ma, SCSI_ERROR_MediumNotPresent, 0); ma->state = SEND_CSW; return CSW_STATUS_CommandFailed; case CHANGED: debugvs(1, "%s : %s - SCSI TestUnitReady :: Medium may have changed\n", __FILE__, __FUNCTION__); usbd_scsi_set_error(ma, SCSI_ERROR_MediumChanged, 0); ma->media.status = PRESENT; ma->state = SEND_CSW; return CSW_STATUS_CommandFailed; case PRESENT: debugvs(1, "%s : %s - SCSI TestUnitReady :: Ready\n", __FILE__, __FUNCTION__); break; default: } return usbd_scsi_command_noerror_end(ma);*/ ret = usbd_scsi_check_media(ma); ma->state = SEND_CSW; return ret;}char usbd_scsi_com_senddiagnostic(usbd_mass_instance *ma){ debugvs(1, "%s : %s - SCSI SendDiagnosticResults\n", __FILE__, __FUNCTION__); if ((ma->cbw.CBWCB[1] & 0x14) != 0x04) { usbd_scsi_set_error(ma, SCSI_ERROR_InvalidFieldCdb, 0); ma->state = SEND_CSW; return CSW_STATUS_CommandFailed; } return usbd_scsi_command_noerror_end(ma);}char usbd_scsi_com_requestsense(usbd_mass_instance *ma){ unsigned char len; debugvs(1, "%s : %s - SCSI RequestSense :: ErrorCode %02x\n", __FILE__, __FUNCTION__, scsi_error[ma->scsi_error][0]); debugvs(1, "%s : %s - SCSI RequestSense :: SenseKey %02x\n", __FILE__, __FUNCTION__, scsi_error[ma->scsi_error][1]); debugvs(1, "%s : %s - SCSI RequestSense :: SenseData %02x\n", __FILE__, __FUNCTION__, scsi_error[ma->scsi_error][2]); debugvs(1, "%s : %s - SCSI RequestSense :: SenseExt %02x\n", __FILE__, __FUNCTION__, scsi_error[ma->scsi_error][3]); debugvs(1, "%s : %s - SCSI RequestSense :: ErrorInfo %04lx\n", __FILE__, __FUNCTION__, ma->scsi_error_info); usbd_scsi_clear_buff(ma); ma->buff[0] = scsi_error[ma->scsi_error][0]; ma->buff[2] = scsi_error[ma->scsi_error][1]; usbd_scsi_put_bigendian(&ma->buff[3], ma->scsi_error_info, 4); ma->buff[7] = 0x0c; /* additional length */ ma->buff[12] = scsi_error[ma->scsi_error][2]; ma->buff[13] = scsi_error[ma->scsi_error][3]; len = ma->cbw.CBWCB[4]; if (len > 0x1a) len = 0x1a; ma->buff_length = len; return usbd_scsi_command_end_send(ma);}char usbd_scsi_com_modesense(usbd_mass_instance *ma){ unsigned char desc_len; unsigned short alloc_len; debugvs(1, "%s : %s - SCSI ModeSense\n", __FILE__, __FUNCTION__); if ((ma->cbw.CBWCB[2] & 0xc0) == 0xc0) { usbd_scsi_set_error(ma, SCSI_ERROR_SavingParameterNotSupported, 0); ma->state = SEND_CSW; return CSW_STATUS_CommandFailed; } usbd_scsi_clear_buff(ma); desc_len = 0; if (!(ma->cbw.CBWCB[1] & 0x08)) desc_len = 8; ma->buff_ptr = 0; if (ma->cbw.CBWCB[0] == SCSI_ComModeSense6) { alloc_len = ma->cbw.CBWCB[4]; ma->buff_ptr += 3; ma->buff[ma->buff_ptr++] = desc_len; } else { alloc_len = (ma->cbw.CBWCB[7] << 8) + ma->cbw.CBWCB[8]; ma->buff_ptr += 6; ma->buff[ma->buff_ptr++] = desc_len; ma->buff_ptr++; } if (desc_len) { usbd_scsi_put_bigendian(&ma->buff[ma->buff_ptr], ma->media.total_sector, 4); ma->buff_ptr += 4; usbd_scsi_put_bigendian(&ma->buff[ma->buff_ptr], 0x200, 4); ma->buff_ptr += 4; } switch (ma->cbw.CBWCB[2] & 0x3f) { case 1: usbd_scsi_com_modesense_rwerror(ma); break; case 5: usbd_scsi_com_modesense_flexible(ma); break; case 0x3f: usbd_scsi_com_modesense_rwerror(ma); usbd_scsi_com_modesense_flexible(ma); break; default: usbd_scsi_set_error(ma, SCSI_ERROR_InvalidFieldCdb, 0); return CSW_STATUS_CommandFailed; } ma->buff_length = ma->buff_ptr; ma->buff[0] = (unsigned char)ma->buff_length; ma->buff_ptr = 0; if (ma->buff_length > alloc_len) ma->buff_length = alloc_len; debughd(3, ma->buff, ma->buff_length); return usbd_scsi_command_end_send(ma);}void usbd_scsi_com_modesense_rwerror(usbd_mass_instance *ma){ switch (ma->cbw.CBWCB[2] & 0xc0) { case 0x00: /* current */ ma->buff[ma->buff_ptr++] = 0x01; /* page 1 */ ma->buff[ma->buff_ptr++] = 0x0a; /* length */ ma->buff[ma->buff_ptr++] = ma->scsi_rw_option; /* RW Option */ ma->buff[ma->buff_ptr++] = ma->scsi_rw_rdretry; /* Read Retry */ ma->buff_ptr += 4; ma->buff[ma->buff_ptr++] = ma->scsi_rw_wrretry; /* Write Retry */ ma->buff_ptr += 3; break; case 0x80: /* default */ ma->buff[ma->buff_ptr++] = 0x01; /* page 1 */ ma->buff[ma->buff_ptr++] = 0x0a; /* length */ ma->buff[ma->buff_ptr++] = 0x80; /* AWRE = 1 */ ma->buff[ma->buff_ptr++] = 0x04; /* Read Retry */ ma->buff_ptr += 4; ma->buff[ma->buff_ptr++] = 0x04; /* Write Retry */ ma->buff_ptr += 3; break; default: /* changeable */ ma->buff[ma->buff_ptr++] = 0x01; /* page 1 */ ma->buff[ma->buff_ptr++] = 0x0a; /* length */ ma->buff[ma->buff_ptr++] = 0x05; /* PER, DCR changeable */ ma->buff[ma->buff_ptr++] = 0xff; /* read retry = 0 - 0xff */ ma->buff_ptr += 4; ma->buff[ma->buff_ptr++] = 0xff; /* write retry = 0 - 0xff */ ma->buff_ptr += 3; break; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -