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; }
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; }
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; }
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; }
/********************************************************************************* * 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; }
/****************************************************************************** * 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]); }
/****************************************************************************** * 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; }
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; }
int scsi_read_sector(uint_32 lba, uint_8 *buffer) { int r = 0; r = scsi_read(lba,1,buffer); return r; }
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(); } } }