diff options
Diffstat (limited to 'drivers/staging/keucr/smscsi.c')
| -rw-r--r-- | drivers/staging/keucr/smscsi.c | 194 |
1 files changed, 194 insertions, 0 deletions
diff --git a/drivers/staging/keucr/smscsi.c b/drivers/staging/keucr/smscsi.c new file mode 100644 index 00000000000..20858f6777c --- /dev/null +++ b/drivers/staging/keucr/smscsi.c @@ -0,0 +1,194 @@ +#include <linux/sched.h> +#include <linux/errno.h> +#include <linux/slab.h> + +#include <scsi/scsi.h> +#include <scsi/scsi_eh.h> +#include <scsi/scsi_device.h> + +#include "usb.h" +#include "scsiglue.h" +#include "transport.h" +#include "smil.h" + +static int SM_SCSI_Test_Unit_Ready(struct us_data *us, struct scsi_cmnd *srb); +static int SM_SCSI_Inquiry(struct us_data *us, struct scsi_cmnd *srb); +static int SM_SCSI_Mode_Sense(struct us_data *us, struct scsi_cmnd *srb); +static int SM_SCSI_Read_Capacity(struct us_data *us, struct scsi_cmnd *srb); +static int SM_SCSI_Read(struct us_data *us, struct scsi_cmnd *srb); +static int SM_SCSI_Write(struct us_data *us, struct scsi_cmnd *srb); + +/* ----- SM_SCSIIrp() -------------------------------------------------- */ +int SM_SCSIIrp(struct us_data *us, struct scsi_cmnd *srb) +{ + int result; + + us->SrbStatus = SS_SUCCESS; + switch (srb->cmnd[0]) { + case TEST_UNIT_READY: + result = SM_SCSI_Test_Unit_Ready(us, srb); + break; /* 0x00 */ + case INQUIRY: + result = SM_SCSI_Inquiry(us, srb); + break; /* 0x12 */ + case MODE_SENSE: + result = SM_SCSI_Mode_Sense(us, srb); + break; /* 0x1A */ + case READ_CAPACITY: + result = SM_SCSI_Read_Capacity(us, srb); + break; /* 0x25 */ + case READ_10: + result = SM_SCSI_Read(us, srb); + break; /* 0x28 */ + case WRITE_10: + result = SM_SCSI_Write(us, srb); + break; /* 0x2A */ + + default: + us->SrbStatus = SS_ILLEGAL_REQUEST; + result = USB_STOR_TRANSPORT_FAILED; + break; + } + return result; +} + +/* ----- SM_SCSI_Test_Unit_Ready() ------------------------------------- */ +static int SM_SCSI_Test_Unit_Ready(struct us_data *us, struct scsi_cmnd *srb) +{ + if (us->SM_Status.Insert && us->SM_Status.Ready) + return USB_STOR_TRANSPORT_GOOD; + else { + ENE_SMInit(us); + return USB_STOR_TRANSPORT_GOOD; + } + + return USB_STOR_TRANSPORT_GOOD; +} + +/* ----- SM_SCSI_Inquiry() --------------------------------------------- */ +static int SM_SCSI_Inquiry(struct us_data *us, struct scsi_cmnd *srb) +{ + u8 data_ptr[36] = {0x00, 0x80, 0x02, 0x00, 0x1F, 0x00, 0x00, 0x00, + 0x55, 0x53, 0x42, 0x32, 0x2E, 0x30, 0x20, + 0x20, 0x43, 0x61, 0x72, 0x64, 0x52, 0x65, + 0x61, 0x64, 0x65, 0x72, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x30, 0x31, 0x30, 0x30}; + + usb_stor_set_xfer_buf(us, data_ptr, 36, srb, TO_XFER_BUF); + return USB_STOR_TRANSPORT_GOOD; +} + + +/* ----- SM_SCSI_Mode_Sense() ------------------------------------------ */ +static int SM_SCSI_Mode_Sense(struct us_data *us, struct scsi_cmnd *srb) +{ + u8 mediaNoWP[12] = {0x0b, 0x00, 0x00, 0x08, 0x00, 0x00, + 0x71, 0xc0, 0x00, 0x00, 0x02, 0x00}; + u8 mediaWP[12] = {0x0b, 0x00, 0x80, 0x08, 0x00, 0x00, + 0x71, 0xc0, 0x00, 0x00, 0x02, 0x00}; + + if (us->SM_Status.WtP) + usb_stor_set_xfer_buf(us, mediaWP, 12, srb, TO_XFER_BUF); + else + usb_stor_set_xfer_buf(us, mediaNoWP, 12, srb, TO_XFER_BUF); + + + return USB_STOR_TRANSPORT_GOOD; +} + +/* ----- SM_SCSI_Read_Capacity() --------------------------------------- */ +static int SM_SCSI_Read_Capacity(struct us_data *us, struct scsi_cmnd *srb) +{ + unsigned int offset = 0; + struct scatterlist *sg = NULL; + u32 bl_num; + u16 bl_len; + u8 buf[8]; + + dev_dbg(&us->pusb_dev->dev, "SM_SCSI_Read_Capacity\n"); + + bl_len = 0x200; + bl_num = Ssfdc.MaxLogBlocks * Ssfdc.MaxSectors * Ssfdc.MaxZones - 1; + + us->bl_num = bl_num; + dev_dbg(&us->pusb_dev->dev, "bl_len = %x\n", bl_len); + dev_dbg(&us->pusb_dev->dev, "bl_num = %x\n", bl_num); + + buf[0] = (bl_num >> 24) & 0xff; + buf[1] = (bl_num >> 16) & 0xff; + buf[2] = (bl_num >> 8) & 0xff; + buf[3] = (bl_num >> 0) & 0xff; + buf[4] = (bl_len >> 24) & 0xff; + buf[5] = (bl_len >> 16) & 0xff; + buf[6] = (bl_len >> 8) & 0xff; + buf[7] = (bl_len >> 0) & 0xff; + + usb_stor_access_xfer_buf(us, buf, 8, srb, &sg, &offset, TO_XFER_BUF); + + return USB_STOR_TRANSPORT_GOOD; +} + +/* ----- SM_SCSI_Read() -------------------------------------------------- */ +static int SM_SCSI_Read(struct us_data *us, struct scsi_cmnd *srb) +{ + int result = 0; + u8 *Cdb = srb->cmnd; + u32 bn = ((Cdb[2] << 24) & 0xff000000) | + ((Cdb[3] << 16) & 0x00ff0000) | + ((Cdb[4] << 8) & 0x0000ff00) | + ((Cdb[5] << 0) & 0x000000ff); + u16 blen = ((Cdb[7] << 8) & 0xff00) | ((Cdb[8] << 0) & 0x00ff); + u32 blenByte = blen * 0x200; + void *buf; + + + if (bn > us->bl_num) + return USB_STOR_TRANSPORT_ERROR; + + buf = kmalloc(blenByte, GFP_KERNEL); + if (buf == NULL) + return USB_STOR_TRANSPORT_ERROR; + result = Media_D_ReadSector(us, bn, blen, buf); + usb_stor_set_xfer_buf(us, buf, blenByte, srb, TO_XFER_BUF); + kfree(buf); + + if (!result) + return USB_STOR_TRANSPORT_GOOD; + else + return USB_STOR_TRANSPORT_ERROR; + + return USB_STOR_TRANSPORT_GOOD; +} + +/* ----- SM_SCSI_Write() -------------------------------------------------- */ +static int SM_SCSI_Write(struct us_data *us, struct scsi_cmnd *srb) +{ + int result = 0; + u8 *Cdb = srb->cmnd; + u32 bn = ((Cdb[2] << 24) & 0xff000000) | + ((Cdb[3] << 16) & 0x00ff0000) | + ((Cdb[4] << 8) & 0x0000ff00) | + ((Cdb[5] << 0) & 0x000000ff); + u16 blen = ((Cdb[7] << 8) & 0xff00) | ((Cdb[8] << 0) & 0x00ff); + u32 blenByte = blen * 0x200; + void *buf; + + + if (bn > us->bl_num) + return USB_STOR_TRANSPORT_ERROR; + + buf = kmalloc(blenByte, GFP_KERNEL); + if (buf == NULL) + return USB_STOR_TRANSPORT_ERROR; + usb_stor_set_xfer_buf(us, buf, blenByte, srb, FROM_XFER_BUF); + result = Media_D_CopySector(us, bn, blen, buf); + kfree(buf); + + if (!result) + return USB_STOR_TRANSPORT_GOOD; + else + return USB_STOR_TRANSPORT_ERROR; + + return USB_STOR_TRANSPORT_GOOD; +} + |
