예제 #1
0
파일: sd.c 프로젝트: bradla/OpenBSD-Hammer2
int
sdopen(struct open_file *f, const char *ctrlname, int ctrl, int unit, int lun,
    int part)
{
	struct scsi_private *priv;
	struct vdm_label *vdl;
	int rc;
	char buf[DEV_BSIZE];
	char *msg;
	size_t z;

	f->f_devdata = priv = scsi_initialize(ctrlname, ctrl, unit, lun, part);
	if (priv == NULL)
		return ENXIO;

	/* send TUR */
	rc = scsi_tur(priv);
	if (rc != 0)
		return EIO;

	/* read disklabel. We expect a VDM label since this is the only way
	 * we can boot from disk.  */
	rc = scsi_read(priv, VDM_LABEL_SECTOR, sizeof buf, buf, &z);
	if (rc != 0 || z != sizeof buf)
		return EIO;

	vdl = (struct vdm_label *)(buf + VDM_LABEL_OFFSET);
	if (vdl->signature != VDM_LABEL_SIGNATURE)
		vdl = (struct vdm_label *)(buf + VDM_LABEL_OFFSET_ALT);
	if (vdl->signature != VDM_LABEL_SIGNATURE)
		return EINVAL;
	
	/* XXX ought to search for an OpenBSD vdmpart too. Too lazy for now */
	rc = scsi_read(priv, LABELSECTOR, sizeof buf, buf, &z);
	if (rc != 0 || z != sizeof buf)
		return EIO;

	msg = getdisklabel(buf, &priv->label);
	if (msg != NULL) {
		printf("%s\n", msg);
		return EINVAL;
	}

	return 0;
}
예제 #2
0
파일: sd.c 프로젝트: bradla/OpenBSD-Hammer2
int
sdstrategy(void *devdata, int rw, daddr32_t blk, size_t size, void *buf,
    size_t *rsize)
{
	struct scsi_private *priv = devdata;

	if (rw != F_READ)
		return EROFS;

	blk += priv->label.d_partitions[priv->part].p_offset;

	return scsi_read(priv, blk, size, buf, rsize) != 0 ? EIO : 0;
}
예제 #3
0
파일: scsi.c 프로젝트: aarzho/mkernel
static inline bool scsi_cmd_read16(SCSI* scsi)
{
	bool res = false;
	if (scsi->cmd.cmd_type == SCSI_CMD_16)
		res = scsi_read(scsi, scsi->cmd.additional_data, scsi->cmd.len);
	else
		scsi_error(scsi, SENSE_KEY_ILLEGAL_REQUEST, ASQ_CDB_DECRYPTION_ERROR);

#if (SCSI_DEBUG_FLOW)
	printf("SCSI read16 0x%08X, %x sector(s)\n\r", scsi->cmd.address, scsi->cmd.len);
#endif
	return res;
}
예제 #4
0
파일: pslr.c 프로젝트: nazgul77/libgphoto2
static int ipslr_download(ipslr_handle_t *p, uint32_t addr, uint32_t length, uint8_t *buf)
{
    uint8_t downloadCmd[8] = { 0xf0, 0x24, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00 };
    uint32_t block;
    int n;
    int retry;
    uint32_t length_start = length;

    retry = 0;
    while (length > 0) {
        if (length > BLKSZ)
            block = BLKSZ;
        else
            block = length;

        /*DPRINT("Get 0x%x bytes from 0x%x\n", block, addr); */
        CHECK(ipslr_write_args(p, 2, addr, block));
        CHECK(command(p, 0x06, 0x00, 0x08));
        get_status(p);

        n = scsi_read(p, downloadCmd, sizeof(downloadCmd), buf, block);
	get_status(p);

        if (n < 0) {
            if (retry < BLOCK_RETRY) {
                retry++;
                continue;
            }
            return PSLR_READ_ERROR;
        }
        buf += n;
        length -= n;
        addr += n;
        retry = 0;
        if (progress_callback) {
            progress_callback(length_start-length, length_start);
        }
    }
    return PSLR_OK;
}
예제 #5
0
/*********************************************************************************
 * scsi command intepreter
 */
int do_scsi (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
	switch (argc) {
	case 0:
	case 1:
		return CMD_RET_USAGE;

	case 2:
			if (strncmp(argv[1],"res",3) == 0) {
				printf("\nReset SCSI\n");
				scsi_bus_reset();
				scsi_scan(1);
				return 0;
			}
			if (strncmp(argv[1],"inf",3) == 0) {
				int i;
				for (i=0; i<CONFIG_SYS_SCSI_MAX_DEVICE; ++i) {
					if(scsi_dev_desc[i].type==DEV_TYPE_UNKNOWN)
						continue; /* list only known devices */
					printf ("SCSI dev. %d:  ", i);
					dev_print(&scsi_dev_desc[i]);
				}
				return 0;
			}
			if (strncmp(argv[1],"dev",3) == 0) {
				if ((scsi_curr_dev < 0) || (scsi_curr_dev >= CONFIG_SYS_SCSI_MAX_DEVICE)) {
					printf("\nno SCSI devices available\n");
					return 1;
				}
				printf ("\n    Device %d: ", scsi_curr_dev);
				dev_print(&scsi_dev_desc[scsi_curr_dev]);
				return 0;
			}
			if (strncmp(argv[1],"scan",4) == 0) {
				scsi_scan(1);
				return 0;
			}
			if (strncmp(argv[1],"part",4) == 0) {
				int dev, ok;
				for (ok=0, dev=0; dev<CONFIG_SYS_SCSI_MAX_DEVICE; ++dev) {
					if (scsi_dev_desc[dev].type!=DEV_TYPE_UNKNOWN) {
						ok++;
						if (dev)
							printf("\n");
						debug ("print_part of %x\n",dev);
							print_part(&scsi_dev_desc[dev]);
					}
				}
				if (!ok)
					printf("\nno SCSI devices available\n");
				return 1;
			}
			return CMD_RET_USAGE;
	case 3:
			if (strncmp(argv[1],"dev",3) == 0) {
				int dev = (int)simple_strtoul(argv[2], NULL, 10);
				printf ("\nSCSI device %d: ", dev);
				if (dev >= CONFIG_SYS_SCSI_MAX_DEVICE) {
					printf("unknown device\n");
					return 1;
				}
				printf ("\n    Device %d: ", dev);
				dev_print(&scsi_dev_desc[dev]);
				if(scsi_dev_desc[dev].type == DEV_TYPE_UNKNOWN) {
					return 1;
				}
				scsi_curr_dev = dev;
				printf("... is now current device\n");
				return 0;
			}
			if (strncmp(argv[1],"part",4) == 0) {
				int dev = (int)simple_strtoul(argv[2], NULL, 10);
				if(scsi_dev_desc[dev].type != DEV_TYPE_UNKNOWN) {
					print_part(&scsi_dev_desc[dev]);
				}
				else {
					printf ("\nSCSI device %d not available\n", dev);
				}
				return 1;
			}
			return CMD_RET_USAGE;
    default:
			/* at least 4 args */
			if (strcmp(argv[1],"read") == 0) {
				ulong addr = simple_strtoul(argv[2], NULL, 16);
				ulong blk  = simple_strtoul(argv[3], NULL, 16);
				ulong cnt  = simple_strtoul(argv[4], NULL, 16);
				ulong n;
				printf ("\nSCSI read: device %d block # %ld, count %ld ... ",
						scsi_curr_dev, blk, cnt);
				n = scsi_read(scsi_curr_dev, blk, cnt, (ulong *)addr);
				printf ("%ld blocks read: %s\n",n,(n==cnt) ? "OK" : "ERROR");
				return 0;
			} else if (strcmp(argv[1], "write") == 0) {
				ulong addr = simple_strtoul(argv[2], NULL, 16);
				ulong blk = simple_strtoul(argv[3], NULL, 16);
				ulong cnt = simple_strtoul(argv[4], NULL, 16);
				ulong n;
				printf("\nSCSI write: device %d block # %ld, "
				       "count %ld ... ",
				       scsi_curr_dev, blk, cnt);
				n = scsi_write(scsi_curr_dev, blk, cnt,
					       (ulong *)addr);
				printf("%ld blocks written: %s\n", n,
				       (n == cnt) ? "OK" : "ERROR");
				return 0;
			}
	} /* switch */
	return CMD_RET_USAGE;
}
예제 #6
0
/******************************************************************************
 * scsi boot command intepreter. Derived from diskboot
 */
int do_scsiboot (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
	char *boot_device = NULL;
	char *ep;
	int dev, part = 0;
	ulong addr, cnt;
	disk_partition_t info;
	image_header_t *hdr;
#if defined(CONFIG_FIT)
	const void *fit_hdr = NULL;
#endif

	switch (argc) {
	case 1:
		addr = CONFIG_SYS_LOAD_ADDR;
		boot_device = getenv ("bootdevice");
		break;
	case 2:
		addr = simple_strtoul(argv[1], NULL, 16);
		boot_device = getenv ("bootdevice");
		break;
	case 3:
		addr = simple_strtoul(argv[1], NULL, 16);
		boot_device = argv[2];
		break;
	default:
		return CMD_RET_USAGE;
	}

	if (!boot_device) {
		puts ("\n** No boot device **\n");
		return 1;
	}

	dev = simple_strtoul(boot_device, &ep, 16);
	printf("booting from dev %d\n",dev);
	if (scsi_dev_desc[dev].type == DEV_TYPE_UNKNOWN) {
		printf ("\n** Device %d not available\n", dev);
		return 1;
	}

	if (*ep) {
		if (*ep != ':') {
			puts ("\n** Invalid boot device, use `dev[:part]' **\n");
			return 1;
		}
		part = simple_strtoul(++ep, NULL, 16);
	}
	if (get_partition_info (&scsi_dev_desc[dev], part, &info)) {
		printf("error reading partinfo\n");
		return 1;
	}
	if ((strncmp((char *)(info.type), BOOT_PART_TYPE, sizeof(info.type)) != 0) &&
	    (strncmp((char *)(info.type), BOOT_PART_COMP, sizeof(info.type)) != 0)) {
		printf ("\n** Invalid partition type \"%.32s\""
			" (expect \"" BOOT_PART_TYPE "\")\n",
			info.type);
		return 1;
	}

	printf ("\nLoading from SCSI device %d, partition %d: "
		"Name: %.32s  Type: %.32s\n",
		dev, part, info.name, info.type);

	debug ("First Block: %ld,  # of blocks: %ld, Block Size: %ld\n",
		info.start, info.size, info.blksz);

	if (scsi_read (dev, info.start, 1, (ulong *)addr) != 1) {
		printf ("** Read error on %d:%d\n", dev, part);
		return 1;
	}

	switch (genimg_get_format ((void *)addr)) {
	case IMAGE_FORMAT_LEGACY:
		hdr = (image_header_t *)addr;

		if (!image_check_hcrc (hdr)) {
			puts ("\n** Bad Header Checksum **\n");
			return 1;
		}

		image_print_contents (hdr);
		cnt = image_get_image_size (hdr);
		break;
#if defined(CONFIG_FIT)
	case IMAGE_FORMAT_FIT:
		fit_hdr = (const void *)addr;
		puts ("Fit image detected...\n");

		cnt = fit_get_size (fit_hdr);
		break;
#endif
	default:
		puts ("** Unknown image type\n");
		return 1;
	}

	cnt += info.blksz - 1;
	cnt /= info.blksz;
	cnt -= 1;

	if (scsi_read (dev, info.start+1, cnt,
		      (ulong *)(addr+info.blksz)) != cnt) {
		printf ("** Read error on %d:%d\n", dev, part);
		return 1;
	}

#if defined(CONFIG_FIT)
	/* This cannot be done earlier, we need complete FIT image in RAM first */
	if (genimg_get_format ((void *)addr) == IMAGE_FORMAT_FIT) {
		if (!fit_check_format (fit_hdr)) {
			puts ("** Bad FIT image format\n");
			return 1;
		}
		fit_print_contents (fit_hdr);
	}
#endif

	/* Loading ok, update default load address */
	load_addr = addr;

	flush_cache (addr, (cnt+1)*info.blksz);

	return bootm_maybe_autostart(cmdtp, argv[0]);
}
예제 #7
0
/******************************************************************************
 * scsi boot command intepreter. Derived from diskboot
 */
int do_scsiboot (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
{
	char *boot_device = NULL;
	char *ep;
	int dev, part = 0;
	ulong addr, cnt, checksum;
	disk_partition_t info;
	image_header_t *hdr;
	int rcode = 0;

	switch (argc) {
	case 1:
		addr = CFG_LOAD_ADDR;
		boot_device = getenv ("bootdevice");
		break;
	case 2:
		addr = simple_strtoul(argv[1], NULL, 16);
		boot_device = getenv ("bootdevice");
		break;
	case 3:
		addr = simple_strtoul(argv[1], NULL, 16);
		boot_device = argv[2];
		break;
	default:
		printf ("Usage:\n%s\n", cmdtp->usage);
		return 1;
	}

	if (!boot_device) {
		puts ("\n** No boot device **\n");
		return 1;
	}

	dev = simple_strtoul(boot_device, &ep, 16);
	printf("booting from dev %d\n",dev);
	if (scsi_dev_desc[dev].type == DEV_TYPE_UNKNOWN) {
		printf ("\n** Device %d not available\n", dev);
		return 1;
	}

	if (*ep) {
		if (*ep != ':') {
			puts ("\n** Invalid boot device, use `dev[:part]' **\n");
			return 1;
		}
		part = simple_strtoul(++ep, NULL, 16);
	}
	if (get_partition_info (&scsi_dev_desc[dev], part, &info)) {
		printf("error reading partinfo\n");
		return 1;
	}
	if ((strncmp((char *)(info.type), BOOT_PART_TYPE, sizeof(info.type)) != 0) &&
	    (strncmp((char *)(info.type), BOOT_PART_COMP, sizeof(info.type)) != 0)) {
		printf ("\n** Invalid partition type \"%.32s\""
			" (expect \"" BOOT_PART_TYPE "\")\n",
			info.type);
		return 1;
	}

	printf ("\nLoading from SCSI device %d, partition %d: "
		"Name: %.32s  Type: %.32s\n",
		dev, part, info.name, info.type);

	debug ("First Block: %ld,  # of blocks: %ld, Block Size: %ld\n",
		info.start, info.size, info.blksz);

	if (scsi_read (dev, info.start, 1, (ulong *)addr) != 1) {
		printf ("** Read error on %d:%d\n", dev, part);
		return 1;
	}

	hdr = (image_header_t *)addr;

	if (ntohl(hdr->ih_magic) == IH_MAGIC) {
		printf("\n** Bad Magic Number **\n");
		return 1;
	}

	checksum = ntohl(hdr->ih_hcrc);
	hdr->ih_hcrc = 0;

	if (crc32 (0, (uchar *)hdr, sizeof(image_header_t)) != checksum) {
		puts ("\n** Bad Header Checksum **\n");
		return 1;
	}
	hdr->ih_hcrc = htonl(checksum);	/* restore checksum for later use */

	print_image_hdr (hdr);
	cnt = (ntohl(hdr->ih_size) + sizeof(image_header_t));
	cnt += info.blksz - 1;
	cnt /= info.blksz;
	cnt -= 1;

	if (scsi_read (dev, info.start+1, cnt,
		      (ulong *)(addr+info.blksz)) != cnt) {
		printf ("** Read error on %d:%d\n", dev, part);
		return 1;
	}
	/* Loading ok, update default load address */
	load_addr = addr;

	flush_cache (addr, (cnt+1)*info.blksz);

	/* Check if we should attempt an auto-start */
	if (((ep = getenv("autostart")) != NULL) && (strcmp(ep,"yes") == 0)) {
		char *local_args[2];
		extern int do_bootm (cmd_tbl_t *, int, int, char *[]);
		local_args[0] = argv[0];
		local_args[1] = NULL;
		printf ("Automatic boot of image at addr 0x%08lX ...\n", addr);
		rcode = do_bootm (cmdtp, 0, 1, local_args);
	}
	 return rcode;
}
예제 #8
0
파일: huntdev.c 프로젝트: jamjr/Helios-NG
void DevOperate(DiscDCB *dcb, DiscReq *req)
{
	BYTE	  capacity_data[CAPACITY_LENGTH];
	WORD	  command_status,second_status;
	WORD	  block_addr, block_len;
	WORD	  done = 0;
	WORD	  size;
	BYTE	  *buf = req->Buf;
	INT	  res;
	BYTE sense_data[SENSE_LENGTH];

	FormatReq *freq;

	Wait(&dcb->Lock);

	/* Select the appropriate command */
	switch( req->DevReq.Request & FG_Mask)
	{
		case FG_Read:
#ifdef DEBUG
		IOdebug("read pos = %d size = %d",req->Pos / dcb->SectorSize,req->Size / dcb->SectorSize);
#endif
			size = req->Size;
			while( done < size )
			{
				WORD tfr = size - done;
				WORD position = (req->Pos / dcb->SectorSize) + (done/dcb->SectorSize);
				command_status = 8;/* make loop happen once*/
				if ( tfr > MAX_TFR )
				{
					tfr = MAX_TFR;
				}
				while (command_status == 8)
				  {
				  res = scsi_read(dcb->Link,dcb->Table,dcb->DeviceId,0,position,tfr,dcb->SectorSize,buf,&command_status);
				  }

				if ( ( res < 0 ) || ( command_status ne 0 ))
					{
					 command_status = 8;
					 while (command_status == 8)
					   {
					   res = scsi_read(dcb->Link,dcb->Table,dcb->DeviceId,0,position,tfr,dcb->SectorSize,buf,&command_status);
					   }
				}

				done += tfr;
				buf  += tfr;
			}

			req->DevReq.Result = command_status;
			if ( req->DevReq.Result eq 0 )
				req->Actual = req->Size;
			else
				req->Actual = 0;
			break;

		case FG_Write:
#ifdef DEBUG
			IOdebug("write pos = %d size = %d",req->Pos / dcb->SectorSize,req->Size / dcb->SectorSize);
#endif
			size = req->Size;
			while( done < size )
			{
				WORD tfr = size - done;
				WORD position = (req->Pos / dcb->SectorSize) + (done/dcb->SectorSize);
				command_status = 8; /* make loop happen once*/
				if ( tfr > MAX_TFR )
				{
					tfr = MAX_TFR;
				}
				while (command_status == 8)
				{
				  res = scsi_write(dcb->Link,dcb->Table,dcb->DeviceId,0,position,tfr,dcb->SectorSize,buf,&command_status);
				}
				if ( ( res < 0 ) || ( command_status ne 0 ))
				{
					command_status = 8;
					while (command_status == 8)
					{
					 res = scsi_write(dcb->Link,dcb->Table,dcb->DeviceId,0,position,tfr,dcb->SectorSize,buf,&command_status);
					}
				}
				done += tfr;
				buf  += tfr;
			}


			req->DevReq.Result = command_status;
			if ( req->DevReq.Result eq 0 )
				req->Actual = req->Size;
			else
				req->Actual = 0;
			break;

		case FG_GetSize:
#ifdef DEBUG
			IOdebug("read capacity request");
#endif
			command_status = 8;
			while (command_status == 8)
			{
			scsi_read_capacity(
				dcb->Link,
				dcb->Table,
				dcb->DeviceId,
				0,		/* lun		   */
				8,		/* capacity length */
				capacity_data,
				&command_status);
			}

			if ( command_status eq 0 )
			{
				block_addr = capacity_data[0] * 0x1000000 +
					     capacity_data[1] * 0x10000   +
					     capacity_data[2] * 0x100	  +
					     capacity_data[3];
				block_len  = capacity_data[4] * 0x1000000 +
					     capacity_data[5] * 0x10000   +
					     capacity_data[6] * 0x100	  +
					     capacity_data[7];
				req->DevReq.Result = block_addr * block_len;
			}
			break;
		case FG_Format:
			IOdebug("\rFormatting disk please wait ....");
			freq = (FormatReq *)req;


			command_status = 8;/* so the loop happens once*/
			while (command_status == 8)
			{
			scsi_mode_select(
				dcb->Link,
				dcb->Table,
				dcb->DeviceId,
				0,
				0,			/* format whole disk */
				dcb->SectorSize,
				&command_status);
			}
			command_status = 8;/* so the loop happens once*/
			while (command_status == 8)
			{
			scsi_format(
				dcb->Link,
				dcb->Table,
				dcb->DeviceId,
				0,
				freq->Interleave,
				&command_status);
			}
/* If the disk supports the busy status we need to wait until busy goes away
	before giving the message that we are verifying */

			command_status = 8;
			while (command_status == 8)
			{
			  scsi_test_unit_ready(
				dcb->Link,
				dcb->Table,
				dcb->DeviceId,
				0,
				&command_status);
			}
/* some disks will queue one command so we need to wait twice to cope with this
	*/
			command_status = 8;
			while (command_status != 0)
			{
			  IOdebug("status = %d",command_status);
			  scsi_test_unit_ready(
				dcb->Link,
				dcb->Table,
				dcb->DeviceId,
				0,
				&command_status);

			scsi_request_sense(
				dcb->Link,
				dcb->Table,
				dcb->DeviceId,
				0,
				SENSE_LENGTH,
				sense_data,
				&command_status);
			IOdebug("sense =%x",sense_data[2]);
			}


			{
			WORD	total_blocks;
			WORD	i,j;
			WORD	ten_cent,done = 0;
			BYTE	*data;

			IOdebug("\rVerifying disk please wait ....");
			data = Malloc(dcb->SectorSize);
			command_status = 8; /* do at least once*/
			while (command_status == 8 )
			{
				res = scsi_write(dcb->Link,dcb->Table,dcb->DeviceId,0,1,dcb->SectorSize,dcb->SectorSize,data,&command_status);
			}
			total_blocks = (dcb->SectorsPerTrack * dcb->TracksPerCyl * dcb->Cylinders);
/*			IOdebug("\rdisk size is %d blocks",total_blocks);*/
			ten_cent =  total_blocks  / 10;
			for ( i = 1; i < total_blocks; i++)
			{
			 command_status = 8; /* you know by now*/
			 while (command_status == 8)
			 {
				 res = scsi_write_quick(dcb->Link,dcb->Table,dcb->DeviceId,0,i,&command_status);
			}
			second_status = 8;
			while (second_status == 8)
			{
			 res = scsi_read_quick(dcb->Link,dcb->Table,dcb->DeviceId,0,i,&second_status);
			}
					 if (( i % ten_cent )  eq 0)
				{
					done += 10;
					IOdebug("\rVerified %d percent of disk\v",done);
				}
				if ((command_status ne 0) || (second_status ne 0))
				{
					command_status = 8;
					while (command_status == 8 )
					{
					scsi_write_quick(dcb->Link,dcb->Table,dcb->DeviceId,0,i,&command_status);
					}
					second_status = 8;
					while (second_status == 8)
					{
					scsi_read_quick(dcb->Link,dcb->Table,dcb->DeviceId,0,i,&second_status);
					}
					if (( command_status  ne 0 ) || (second_status ne 0))
					{
						IOdebug("Verifier found bad block at %d",i);
						for( j = 0; j  < 10; j++)
						{
							command_status = 8;
							while (command_status == 8)
							{
							scsi_reassign_block(dcb->Link,dcb->Table,dcb->DeviceId,0,i,&command_status);
							}
							command_status = 8;
							while (command_status == 8)
							{
							scsi_write_quick(dcb->Link,dcb->Table,dcb->DeviceId,0,i,&command_status);
							}
							second_status = 8;
							while (second_status == 8)
							{
							scsi_read_quick(dcb->Link,dcb->Table,dcb->DeviceId,0,i,&second_status);
							}
							if ((command_status eq 0) && (second_status eq 0))break;
						}
						if  (( command_status eq 0 ) && (second_status eq 0))
							IOdebug("Block %d reassigned OK",i);
						else
							IOdebug("Failed to reassign block %d",i);
					}
				}
			}

			}
			IOdebug("Verification complete                         ");
			req->DevReq.Result = 0;
			break;
		default:
			break;
		}
		/* Unlock the driver */
		Signal(&dcb->Lock);
		/* Client action */
		(*req->DevReq.Action)(req);
		return;
}
예제 #9
0
파일: SCSI.c 프로젝트: forbelief/KL25EM
int scsi_read_sector(uint_32 lba, uint_8 *buffer)
{
	int r = 0;
    r = scsi_read(lba,1,buffer);
    return r;
}
예제 #10
0
void scsi_proc(void)
{
    if (USBD_ep_buffer_full(BOMS_EP_DATA_OUT)) {
        if (sizeof(BOMSCmd) == USBD_transfer(BOMS_EP_DATA_OUT, (uint8_t *)&BOMSCmd, sizeof(BOMSCmd))) {
            if (BOMSCmd.dCBWSignature == BOMS_USBC) {
                if (BOMSCmd.CBWCB.unit_ready.op_code == BOMS_SCSI_TEST_UNIT_READY) // SCSI Test Unit Ready
                {
                    scsi_test_unit_ready(&BOMSCmd);
                } 
                else if (BOMSCmd.CBWCB.request_sense.op_code == BOMS_SCSI_READ) // SCSI Read
                {
                    scsi_read(&BOMSCmd);
                }
                else if (BOMSCmd.CBWCB.request_sense.op_code == BOMS_SCSI_WRITE) // SCSI Write
                {
                    scsi_write(&BOMSCmd);
                }
                else if (BOMSCmd.CBWCB.inquiry.op_code == BOMS_SCSI_INQUIRY) // SCSI Inquiry
                {
                    scsi_inquiry(&BOMSCmd);
                }
                else if (BOMSCmd.CBWCB.request_sense.op_code == BOMS_SCSI_REQUEST_SENSE) // SCSI Request Sense
                {
                    scsi_request_sense(&BOMSCmd);
                }
                else if (BOMSCmd.CBWCB.read_capacity.op_code == BOMS_SCSI_READ_CAPACITY) // SCSI Read Capacity (10)
                {
                    scsi_read_capacity(&BOMSCmd);
                }
                else if (BOMSCmd.CBWCB.read_capacity.op_code == BOMS_SCSI_READ_FORMAT_CAPACITY) // SCSI Read Format Capacity (10)
                {
                    scsi_read_format_capacity(&BOMSCmd);
                }
                else if (BOMSCmd.CBWCB.mode_sense.op_code == BOMS_SCSI_MODE_SENSE) // SCSI Mode Sense
                {
                    scsi_mode_sense(&BOMSCmd);
                }
                else if (BOMSCmd.CBWCB.request_sense.op_code == BOMS_SCSI_READ_CAPACITY_16) // SCSI Read Capacity (16)
                {
                    scsi_read_capacity(&BOMSCmd);
                }
                else if (BOMSCmd.CBWCB.request_sense.op_code == BOMS_SCSI_PREVENT_ALLOW_REMOVAL) // SCSI Prevent Allow Removal
                {
                    scsi_prevent_allow_removal(&BOMSCmd);
                }
                else
                {
                    // Send IN a zero length packet.
                    if (BOMSCmd.dCBWDataTransferLength)
                    {
                        USBD_stall_endpoint(BOMS_EP_DATA_IN);
                    }
                    boms_send_status(BOMS_STATUS_COMMAND_FAILED, &BOMSCmd);
                    scsi_sense_illegal_request_command();
                }
            }
            else
            {
                // Was not a USBC signature.
                boms_send_status(BOMS_STATUS_PHASE_ERROR, &BOMSCmd);
                scsi_sense_illegal_request_cdb();
            }
        }else{
            // Wrong command size.
            boms_send_status(BOMS_STATUS_COMMAND_FAILED, &BOMSCmd);
            scsi_sense_illegal_request_parm();
        }
    }
}