static int enumerate(struct usb_host_device_t *device_p) { struct usb_descriptor_interface_t *int_desc_p; std_printf(FSTR("Enumerating a MASS_STORAGE device.\r\n")); int_desc_p = usb_desc_get_interface(device_p->descriptors.buf, device_p->descriptors.size, 1, 0); if (int_desc_p == NULL) { return (-1); } if (usb_host_device_set_configuration(device_p, 1) != 0) { return (-1); } get_max_lun(device_p); scsi_get_inquiry(device_p); if (scsi_test_unit_ready(device_p) != 0) { std_printf(FSTR("device is not ready\r\n")); } return (0); }
void tur_test() { struct io_req io; register int i; char *a, *b; struct timeval start, stop; bzero(&io, sizeof(io)); io.io_unit = test_read_bdev; io.io_data = (char*)&io;/*unused but kernel space*/ start = time; for (i = 0; i < test_read_nreads; i++) { io.io_op = IO_INTERNAL; rz_check(io.io_unit, &a, &b); scsi_test_unit_ready(b,&io); } stop = time; i = stop.tv_usec - start.tv_usec; if (i < 0) { stop.tv_sec -= 1; i += 1000000; } printf("%d test-unit-ready took %3d sec %d us\n", test_read_nreads, stop.tv_sec - start.tv_sec, i); }
int sr_drive_status(struct cdrom_device_info *cdi, int slot) { struct scsi_cd *cd = cdi->handle; struct scsi_sense_hdr sshdr; struct media_event_desc med; if (CDSL_CURRENT != slot) { /* we have no changer support */ return -EINVAL; } if (!scsi_test_unit_ready(cd->device, SR_TIMEOUT, MAX_RETRIES, &sshdr)) return CDS_DISC_OK; /* SK/ASC/ASCQ of 2/4/1 means "unit is becoming ready" */ if (scsi_sense_valid(&sshdr) && sshdr.sense_key == NOT_READY && sshdr.asc == 0x04 && sshdr.ascq == 0x01) return CDS_DRIVE_NOT_READY; if (!cdrom_get_media_event(cdi, &med)) { if (med.media_present) return CDS_DISC_OK; else if (med.door_open) return CDS_TRAY_OPEN; else return CDS_NO_DISC; } /* * SK/ASC/ASCQ of 2/4/2 means "initialization required" * Using CD_TRAY_OPEN results in an START_STOP_UNIT to close * the tray, which resolves the initialization requirement. */ if (scsi_sense_valid(&sshdr) && sshdr.sense_key == NOT_READY && sshdr.asc == 0x04 && sshdr.ascq == 0x02) return CDS_TRAY_OPEN; /* * 0x04 is format in progress .. but there must be a disc present! */ if (sshdr.sense_key == NOT_READY && sshdr.asc == 0x04) return CDS_DISC_OK; /* * If not using Mt Fuji extended media tray reports, * just return TRAY_OPEN since ATAPI doesn't provide * any other way to detect this... */ if (scsi_sense_valid(&sshdr) && /* 0x3a is medium not present */ sshdr.asc == 0x3a) return CDS_NO_DISC; else return CDS_TRAY_OPEN; return CDS_DRIVE_NOT_READY; }
static rtems_status_code rtems_bsd_scsi_test_unit_ready(union ccb *ccb) { scsi_test_unit_ready( &ccb->csio, BSD_SCSI_RETRIES, rtems_bsd_ccb_callback, BSD_SCSI_TAG, SSD_FULL_SIZE, BSD_SCSI_TIMEOUT ); return rtems_bsd_ccb_action(ccb); }
static int tape_attach(struct scst_device *dev) { int res, rc; int retries; struct scsi_mode_data data; const int buffer_size = 512; uint8_t *buffer = NULL; TRACE_ENTRY(); if (dev->scsi_dev == NULL || dev->scsi_dev->type != dev->type) { PRINT_ERROR("%s", "SCSI device not define or illegal type"); res = -ENODEV; goto out; } dev->block_size = TAPE_DEF_BLOCK_SIZE; dev->block_shift = -1; /* not used */ buffer = kmalloc(buffer_size, GFP_KERNEL); if (!buffer) { PRINT_ERROR("Buffer memory allocation (size %d) failure", buffer_size); res = -ENOMEM; goto out; } retries = SCST_DEV_RETRIES_ON_UA; do { TRACE_DBG("%s", "Doing TEST_UNIT_READY"); rc = scsi_test_unit_ready(dev->scsi_dev, SCST_GENERIC_TAPE_SMALL_TIMEOUT, TAPE_RETRIES #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 25) ); #else , NULL); #endif TRACE_DBG("TEST_UNIT_READY done: %x", rc); } while ((--retries > 0) && rc);
static int raid_attach(struct scst_device *dev) { int res, rc; int retries; TRACE_ENTRY(); if (dev->scsi_dev == NULL || dev->scsi_dev->type != dev->type) { PRINT_ERROR("%s", "SCSI device not define or illegal type"); res = -ENODEV; goto out; } /* * If the device is offline, don't try to read capacity or any * of the other stuff */ if (dev->scsi_dev->sdev_state == SDEV_OFFLINE) { TRACE_DBG("%s", "Device is offline"); res = -ENODEV; goto out; } retries = SCST_DEV_UA_RETRIES; do { TRACE_DBG("%s", "Doing TEST_UNIT_READY"); rc = scsi_test_unit_ready(dev->scsi_dev, SCST_GENERIC_RAID_TIMEOUT, RAID_RETRIES #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 25) ); #else , NULL); #endif TRACE_DBG("TEST_UNIT_READY done: %x", rc); } while ((--retries > 0) && rc);
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(); } } }
/** * scsi_ioctl - Dispatch ioctl to scsi device * @sdev: scsi device receiving ioctl * @cmd: which ioctl is it * @arg: data associated with ioctl * * Description: The scsi_ioctl() function differs from most ioctls in that it * does not take a major/minor number as the dev field. Rather, it takes * a pointer to a &struct scsi_device. */ int scsi_ioctl(struct scsi_device *sdev, int cmd, void __user *arg) { char scsi_cmd[MAX_COMMAND_SIZE]; /* No idea how this happens.... */ if (!sdev) return -ENXIO; /* * If we are in the middle of error recovery, don't let anyone * else try and use this device. Also, if error recovery fails, it * may try and take the device offline, in which case all further * access to the device is prohibited. */ if (!scsi_block_when_processing_errors(sdev)) return -ENODEV; /* Check for deprecated ioctls ... all the ioctls which don't * follow the new unique numbering scheme are deprecated */ switch (cmd) { case SCSI_IOCTL_SEND_COMMAND: case SCSI_IOCTL_TEST_UNIT_READY: case SCSI_IOCTL_BENCHMARK_COMMAND: case SCSI_IOCTL_SYNC: case SCSI_IOCTL_START_UNIT: case SCSI_IOCTL_STOP_UNIT: printk(KERN_WARNING "program %s is using a deprecated SCSI " "ioctl, please convert it to SG_IO\n", current->comm); break; default: break; } switch (cmd) { case SCSI_IOCTL_GET_IDLUN: if (!access_ok(VERIFY_WRITE, arg, sizeof(struct scsi_idlun))) return -EFAULT; __put_user((sdev->id & 0xff) + ((sdev->lun & 0xff) << 8) + ((sdev->channel & 0xff) << 16) + ((sdev->host->host_no & 0xff) << 24), &((struct scsi_idlun __user *)arg)->dev_id); __put_user(sdev->host->unique_id, &((struct scsi_idlun __user *)arg)->host_unique_id); return 0; case SCSI_IOCTL_GET_BUS_NUMBER: return put_user(sdev->host->host_no, (int __user *)arg); case SCSI_IOCTL_PROBE_HOST: return ioctl_probe(sdev->host, arg); case SCSI_IOCTL_SEND_COMMAND: if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO)) return -EACCES; return sg_scsi_ioctl(sdev->request_queue, NULL, 0, arg); case SCSI_IOCTL_DOORLOCK: return scsi_set_medium_removal(sdev, SCSI_REMOVAL_PREVENT); case SCSI_IOCTL_DOORUNLOCK: return scsi_set_medium_removal(sdev, SCSI_REMOVAL_ALLOW); case SCSI_IOCTL_TEST_UNIT_READY: return scsi_test_unit_ready(sdev, IOCTL_NORMAL_TIMEOUT, NORMAL_RETRIES, NULL); case SCSI_IOCTL_START_UNIT: scsi_cmd[0] = START_STOP; scsi_cmd[1] = 0; scsi_cmd[2] = scsi_cmd[3] = scsi_cmd[5] = 0; scsi_cmd[4] = 1; return ioctl_internal_command(sdev, scsi_cmd, START_STOP_TIMEOUT, NORMAL_RETRIES); case SCSI_IOCTL_STOP_UNIT: scsi_cmd[0] = START_STOP; scsi_cmd[1] = 0; scsi_cmd[2] = scsi_cmd[3] = scsi_cmd[5] = 0; scsi_cmd[4] = 0; return ioctl_internal_command(sdev, scsi_cmd, START_STOP_TIMEOUT, NORMAL_RETRIES); case SCSI_IOCTL_GET_PCI: return scsi_ioctl_get_pci(sdev, arg); default: if (sdev->host->hostt->ioctl) return sdev->host->hostt->ioctl(sdev, cmd, arg); } return -EINVAL; }
/* * Open the device. Make sure the partition info is as up-to-date as can be. */ int cdopen(dev_t dev, int flag, int fmt, struct proc *p) { struct scsi_link *sc_link; struct cd_softc *cd; int error = 0, part, rawopen, unit; unit = DISKUNIT(dev); part = DISKPART(dev); rawopen = (part == RAW_PART) && (fmt == S_IFCHR); cd = cdlookup(unit); if (cd == NULL) return (ENXIO); sc_link = cd->sc_link; SC_DEBUG(sc_link, SDEV_DB1, ("cdopen: dev=0x%x (unit %d (of %d), partition %d)\n", dev, unit, cd_cd.cd_ndevs, part)); if ((error = cdlock(cd)) != 0) { device_unref(&cd->sc_dev); return (error); } if (cd->sc_dk.dk_openmask != 0) { /* * If any partition is open, but the disk has been invalidated, * disallow further opens. */ if ((sc_link->flags & SDEV_MEDIA_LOADED) == 0) { if (rawopen) goto out; error = EIO; goto bad; } } else { /* * Check that it is still responding and ok. Drive can be in * progress of loading media so use increased retries number * and don't ignore NOT_READY. */ /* Use cd_interpret_sense() now. */ sc_link->flags |= SDEV_OPEN; error = scsi_test_unit_ready(sc_link, TEST_READY_RETRIES, (rawopen ? SCSI_SILENT : 0) | SCSI_IGNORE_ILLEGAL_REQUEST | SCSI_IGNORE_MEDIA_CHANGE); /* Start the cd spinning if necessary. */ if (error == EIO) error = scsi_start(sc_link, SSS_START, SCSI_IGNORE_ILLEGAL_REQUEST | SCSI_IGNORE_MEDIA_CHANGE | SCSI_SILENT); if (error) { if (rawopen) { error = 0; goto out; } else goto bad; } /* Lock the cd in. */ error = scsi_prevent(sc_link, PR_PREVENT, SCSI_IGNORE_ILLEGAL_REQUEST | SCSI_IGNORE_MEDIA_CHANGE | SCSI_SILENT); if (error) goto bad; /* Load the physical device parameters. */ sc_link->flags |= SDEV_MEDIA_LOADED; if (cd_get_parms(cd, (rawopen ? SCSI_SILENT : 0) | SCSI_IGNORE_ILLEGAL_REQUEST | SCSI_IGNORE_MEDIA_CHANGE)) { sc_link->flags &= ~SDEV_MEDIA_LOADED; error = ENXIO; goto bad; } SC_DEBUG(sc_link, SDEV_DB3, ("Params loaded\n")); /* Fabricate a disk label. */ cdgetdisklabel(dev, cd, cd->sc_dk.dk_label, 0); SC_DEBUG(sc_link, SDEV_DB3, ("Disklabel fabricated\n")); } /* Check that the partition exists. */ if (part != RAW_PART && (part >= cd->sc_dk.dk_label->d_npartitions || cd->sc_dk.dk_label->d_partitions[part].p_fstype == FS_UNUSED)) { error = ENXIO; goto bad; } out: /* Insure only one open at a time. */ switch (fmt) { case S_IFCHR: cd->sc_dk.dk_copenmask |= (1 << part); break; case S_IFBLK: cd->sc_dk.dk_bopenmask |= (1 << part); break; } cd->sc_dk.dk_openmask = cd->sc_dk.dk_copenmask | cd->sc_dk.dk_bopenmask; sc_link->flags |= SDEV_OPEN; SC_DEBUG(sc_link, SDEV_DB3, ("open complete\n")); /* It's OK to fall through because dk_openmask is now non-zero. */ bad: if (cd->sc_dk.dk_openmask == 0) { scsi_prevent(sc_link, PR_ALLOW, SCSI_IGNORE_ILLEGAL_REQUEST | SCSI_IGNORE_MEDIA_CHANGE | SCSI_SILENT); sc_link->flags &= ~(SDEV_OPEN | SDEV_MEDIA_LOADED); } cdunlock(cd); device_unref(&cd->sc_dev); return (error); }
int scsi_ioctl(struct scsi_device *sdev, int cmd, void __user *arg) { char scsi_cmd[MAX_COMMAND_SIZE]; if (!sdev) return -ENXIO; if (!scsi_block_when_processing_errors(sdev)) return -ENODEV; switch (cmd) { case SCSI_IOCTL_SEND_COMMAND: case SCSI_IOCTL_TEST_UNIT_READY: case SCSI_IOCTL_BENCHMARK_COMMAND: case SCSI_IOCTL_SYNC: case SCSI_IOCTL_START_UNIT: case SCSI_IOCTL_STOP_UNIT: printk(KERN_WARNING "program %s is using a deprecated SCSI " "ioctl, please convert it to SG_IO\n", current->comm); break; default: break; } switch (cmd) { case SCSI_IOCTL_GET_IDLUN: if (!access_ok(VERIFY_WRITE, arg, sizeof(struct scsi_idlun))) return -EFAULT; __put_user((sdev->id & 0xff) + ((sdev->lun & 0xff) << 8) + ((sdev->channel & 0xff) << 16) + ((sdev->host->host_no & 0xff) << 24), &((struct scsi_idlun __user *)arg)->dev_id); __put_user(sdev->host->unique_id, &((struct scsi_idlun __user *)arg)->host_unique_id); return 0; case SCSI_IOCTL_GET_BUS_NUMBER: return put_user(sdev->host->host_no, (int __user *)arg); case SCSI_IOCTL_PROBE_HOST: return ioctl_probe(sdev->host, arg); case SCSI_IOCTL_SEND_COMMAND: if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO)) return -EACCES; return sg_scsi_ioctl(sdev->request_queue, NULL, 0, arg); case SCSI_IOCTL_DOORLOCK: return scsi_set_medium_removal(sdev, SCSI_REMOVAL_PREVENT); case SCSI_IOCTL_DOORUNLOCK: return scsi_set_medium_removal(sdev, SCSI_REMOVAL_ALLOW); case SCSI_IOCTL_TEST_UNIT_READY: return scsi_test_unit_ready(sdev, IOCTL_NORMAL_TIMEOUT, NORMAL_RETRIES, NULL); case SCSI_IOCTL_START_UNIT: scsi_cmd[0] = START_STOP; scsi_cmd[1] = 0; scsi_cmd[2] = scsi_cmd[3] = scsi_cmd[5] = 0; scsi_cmd[4] = 1; return ioctl_internal_command(sdev, scsi_cmd, START_STOP_TIMEOUT, NORMAL_RETRIES); case SCSI_IOCTL_STOP_UNIT: scsi_cmd[0] = START_STOP; scsi_cmd[1] = 0; scsi_cmd[2] = scsi_cmd[3] = scsi_cmd[5] = 0; scsi_cmd[4] = 0; return ioctl_internal_command(sdev, scsi_cmd, START_STOP_TIMEOUT, NORMAL_RETRIES); case SCSI_IOCTL_GET_PCI: return scsi_ioctl_get_pci(sdev, arg); default: if (sdev->host->hostt->ioctl) return sdev->host->hostt->ioctl(sdev, cmd, arg); } return -EINVAL; }
/* * Open the device. Make sure the partition info is as up-to-date as can be. */ int sdopen(dev_t dev, int flag, int fmt, struct proc *p) { struct scsi_link *sc_link; struct sd_softc *sc; int error = 0, part, rawopen, unit; unit = DISKUNIT(dev); part = DISKPART(dev); rawopen = (part == RAW_PART) && (fmt == S_IFCHR); sc = sdlookup(unit); if (sc == NULL) return (ENXIO); sc_link = sc->sc_link; if (sc->flags & SDF_DYING) { device_unref(&sc->sc_dev); return (ENXIO); } if (ISSET(flag, FWRITE) && ISSET(sc_link->flags, SDEV_READONLY)) { device_unref(&sc->sc_dev); return (EACCES); } SC_DEBUG(sc_link, SDEV_DB1, ("sdopen: dev=0x%x (unit %d (of %d), partition %d)\n", dev, unit, sd_cd.cd_ndevs, part)); if ((error = disk_lock(&sc->sc_dk)) != 0) { device_unref(&sc->sc_dev); return (error); } if (sc->sc_dk.dk_openmask != 0) { /* * If any partition is open, but the disk has been invalidated, * disallow further opens of non-raw partition. */ if ((sc_link->flags & SDEV_MEDIA_LOADED) == 0) { if (rawopen) goto out; error = EIO; goto bad; } } else { /* Spin up non-UMASS devices ready or not. */ if ((sc->sc_link->flags & SDEV_UMASS) == 0) scsi_start(sc_link, SSS_START, (rawopen ? SCSI_SILENT : 0) | SCSI_IGNORE_ILLEGAL_REQUEST | SCSI_IGNORE_MEDIA_CHANGE); /* Use sd_interpret_sense() for sense errors. * * But only after spinning the disk up! Just in case a broken * device returns "Initialization command required." and causes * a loop of scsi_start() calls. */ sc_link->flags |= SDEV_OPEN; /* * Try to prevent the unloading of a removable device while * it's open. But allow the open to proceed if the device can't * be locked in. */ if ((sc_link->flags & SDEV_REMOVABLE) != 0) { scsi_prevent(sc_link, PR_PREVENT, SCSI_SILENT | SCSI_IGNORE_ILLEGAL_REQUEST | SCSI_IGNORE_MEDIA_CHANGE); } /* Check that it is still responding and ok. */ error = scsi_test_unit_ready(sc_link, TEST_READY_RETRIES, SCSI_SILENT | SCSI_IGNORE_ILLEGAL_REQUEST | SCSI_IGNORE_MEDIA_CHANGE); if (error) { if (rawopen) { error = 0; goto out; } else goto bad; } /* Load the physical device parameters. */ sc_link->flags |= SDEV_MEDIA_LOADED; if (sd_get_parms(sc, &sc->params, (rawopen ? SCSI_SILENT : 0)) == SDGP_RESULT_OFFLINE) { sc_link->flags &= ~SDEV_MEDIA_LOADED; error = ENXIO; goto bad; } SC_DEBUG(sc_link, SDEV_DB3, ("Params loaded\n")); /* Load the partition info if not already loaded. */ if (sdgetdisklabel(dev, sc, sc->sc_dk.dk_label, 0) == EIO) { error = EIO; goto bad; } SC_DEBUG(sc_link, SDEV_DB3, ("Disklabel loaded\n")); } out: if ((error = disk_openpart(&sc->sc_dk, part, fmt, 1)) != 0) goto bad; SC_DEBUG(sc_link, SDEV_DB3, ("open complete\n")); /* It's OK to fall through because dk_openmask is now non-zero. */ bad: if (sc->sc_dk.dk_openmask == 0) { if ((sc->sc_link->flags & SDEV_REMOVABLE) != 0) scsi_prevent(sc_link, PR_ALLOW, SCSI_SILENT | SCSI_IGNORE_ILLEGAL_REQUEST | SCSI_IGNORE_MEDIA_CHANGE); sc_link->flags &= ~(SDEV_OPEN | SDEV_MEDIA_LOADED); } disk_unlock(&sc->sc_dk); device_unref(&sc->sc_dev); return (error); }
/* * The routine called by the low level scsi routine when it discovers * a device suitable for this driver. */ void sdattach(struct device *parent, struct device *self, void *aux) { struct sd_softc *sc = (struct sd_softc *)self; struct scsi_attach_args *sa = aux; struct disk_parms *dp = &sc->params; struct scsi_link *sc_link = sa->sa_sc_link; int sd_autoconf = scsi_autoconf | SCSI_SILENT | SCSI_IGNORE_ILLEGAL_REQUEST | SCSI_IGNORE_MEDIA_CHANGE; struct dk_cache dkc; int error, result; SC_DEBUG(sc_link, SDEV_DB2, ("sdattach:\n")); /* * Store information needed to contact our base driver */ sc->sc_link = sc_link; sc_link->interpret_sense = sd_interpret_sense; sc_link->device_softc = sc; if ((sc_link->flags & SDEV_ATAPI) && (sc_link->flags & SDEV_REMOVABLE)) sc_link->quirks |= SDEV_NOSYNCCACHE; if (!(sc_link->inqdata.flags & SID_RelAdr)) sc_link->quirks |= SDEV_ONLYBIG; /* * Note if this device is ancient. This is used in sdminphys(). */ if (!(sc_link->flags & SDEV_ATAPI) && SCSISPC(sa->sa_inqbuf->version) == 0) sc->flags |= SDF_ANCIENT; /* * Use the subdriver to request information regarding * the drive. We cannot use interrupts yet, so the * request must specify this. */ printf("\n"); scsi_xsh_set(&sc->sc_xsh, sc_link, sdstart); timeout_set(&sc->sc_timeout, (void (*)(void *))scsi_xsh_add, &sc->sc_xsh); /* Spin up non-UMASS devices ready or not. */ if ((sc->sc_link->flags & SDEV_UMASS) == 0) scsi_start(sc_link, SSS_START, sd_autoconf); /* * Some devices (e.g. Blackberry Pearl) won't admit they have * media loaded unless its been locked in. */ if ((sc_link->flags & SDEV_REMOVABLE) != 0) scsi_prevent(sc_link, PR_PREVENT, sd_autoconf); /* Check that it is still responding and ok. */ error = scsi_test_unit_ready(sc->sc_link, TEST_READY_RETRIES * 3, sd_autoconf); if (error) result = SDGP_RESULT_OFFLINE; else result = sd_get_parms(sc, &sc->params, sd_autoconf); if ((sc_link->flags & SDEV_REMOVABLE) != 0) scsi_prevent(sc_link, PR_ALLOW, sd_autoconf); switch (result) { case SDGP_RESULT_OK: printf("%s: %lluMB, %lu bytes/sector, %llu sectors", sc->sc_dev.dv_xname, dp->disksize / (1048576 / dp->secsize), dp->secsize, dp->disksize); printf("\n"); break; case SDGP_RESULT_OFFLINE: break; #ifdef DIAGNOSTIC default: panic("sdattach: unknown result (%#x) from get_parms", result); break; #endif } /* * Initialize disk structures. */ sc->sc_dk.dk_name = sc->sc_dev.dv_xname; bufq_init(&sc->sc_bufq, BUFQ_FIFO); /* * Enable write cache by default. */ memset(&dkc, 0, sizeof(dkc)); if (sd_ioctl_cache(sc, DIOCGCACHE, &dkc) == 0 && dkc.wrcache == 0) { dkc.wrcache = 1; sd_ioctl_cache(sc, DIOCSCACHE, &dkc); } /* * Establish a shutdown hook so that we can ensure that * our data has actually made it onto the platter at * shutdown time. Note that this relies on the fact * that the shutdown hook code puts us at the head of * the list (thus guaranteeing that our hook runs before * our ancestors'). */ if ((sc->sc_sdhook = shutdownhook_establish(sd_shutdown, sc)) == NULL) printf("%s: WARNING: unable to establish shutdown hook\n", sc->sc_dev.dv_xname); /* Attach disk. */ disk_attach(&sc->sc_dev, &sc->sc_dk); }
int scsi_get_info(struct scsi_info *info, unsigned int lun, struct scsi_transport *tr, void *priv) { int rc; u32 *cap; unsigned char __cacheline_aligned buf[64]; struct scsi_request srb; if (!info || !tr || !tr->transport) { return VMM_EINVALID; } memset(info, 0, sizeof(*info)); INIT_SCSI_REQUEST(&srb, lun, &buf, sizeof(buf)); rc = scsi_inquiry(&srb, tr, priv); if (rc) { return rc; } info->lun = lun; info->perph_qualifier = (buf[0] & 0xE0) >> 5; info->perph_type = buf[0] & 0x1F; info->removable = (buf[1] & 0x80) ? TRUE : FALSE; memcpy(&info->vendor[0], (const void *)&buf[8], 8); memcpy(&info->product[0], (const void *)&buf[16], 16); memcpy(&info->revision[0], (const void *)&buf[32], 4); info->vendor[8] = 0; info->product[16] = 0; info->revision[4] = 0; INIT_SCSI_REQUEST(&srb, lun, NULL, 0); rc = scsi_test_unit_ready(&srb, tr, priv); if (rc) { return rc; } INIT_SCSI_REQUEST(&srb, lun, buf, sizeof(buf)); rc = scsi_read_capacity(&srb, tr, priv); if (rc) { return rc; } cap = (u32 *)buf; cap[0] = vmm_cpu_to_be32(cap[0]); cap[1] = vmm_cpu_to_be32(cap[1]); info->capacity = cap[0] + 1; info->blksz = cap[1]; info->readonly = TRUE; switch (info->perph_type) { case 0x00: case 0x0C: case 0x0E: case 0x0F: info->readonly = FALSE; break; default: break; }; if (tr->info_fixup) { tr->info_fixup(info, tr, priv); } return VMM_OK; }
/* * Download firmware stored in buf to cam_dev. If simulation mode * is enabled, only show what packet sizes would be sent to the * device but do not sent any actual packets */ static int fw_download_img(struct cam_device *cam_dev, const struct fw_vendor *vp, char *buf, int img_size, int sim_mode, int verbose, int retry_count, int timeout) { struct scsi_write_buffer cdb; union ccb *ccb; int pkt_count = 0; u_int32_t pkt_size = 0; char *pkt_ptr = buf; u_int32_t offset; int last_pkt = 0; if ((ccb = cam_getccb(cam_dev)) == NULL) { warnx("Could not allocate CCB"); return (1); } scsi_test_unit_ready(&ccb->csio, 0, NULL, MSG_SIMPLE_Q_TAG, SSD_FULL_SIZE, 5000); /* Disable freezing the device queue. */ ccb->ccb_h.flags |= CAM_DEV_QFRZDIS; if (cam_send_ccb(cam_dev, ccb) < 0) { warnx("Error sending test unit ready"); if (verbose) cam_error_print(cam_dev, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr); cam_freeccb(ccb); return(1); } if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { warnx("Device is not ready"); if (verbose) cam_error_print(cam_dev, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr); cam_freeccb(ccb); return (1); } pkt_size = vp->max_pkt_size; if (verbose || sim_mode) { fprintf(stdout, "--------------------------------------------------\n"); fprintf(stdout, "PktNo. PktSize BytesRemaining LastPkt\n"); fprintf(stdout, "--------------------------------------------------\n"); } /* Download single fw packets. */ do { if (img_size <= vp->max_pkt_size) { last_pkt = 1; pkt_size = img_size; } if (verbose || sim_mode) fprintf(stdout, "%3u %5u (0x%05X) %7u (0x%06X) " "%d\n", pkt_count, pkt_size, pkt_size, img_size - pkt_size, img_size - pkt_size, last_pkt); bzero(&cdb, sizeof(cdb)); cdb.opcode = WRITE_BUFFER; cdb.control = 0; /* Parameter list length. */ scsi_ulto3b(pkt_size, &cdb.length[0]); offset = vp->inc_cdb_offset ? (pkt_ptr - buf) : 0; scsi_ulto3b(offset, &cdb.offset[0]); cdb.byte2 = last_pkt ? vp->cdb_byte2_last : vp->cdb_byte2; cdb.buffer_id = vp->inc_cdb_buffer_id ? pkt_count : 0; /* Zero out payload of ccb union after ccb header. */ bzero((u_char *)ccb + sizeof(struct ccb_hdr), sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr)); /* Copy previously constructed cdb into ccb_scsiio struct. */ bcopy(&cdb, &ccb->csio.cdb_io.cdb_bytes[0], sizeof(struct scsi_write_buffer)); /* Fill rest of ccb_scsiio struct. */ if (!sim_mode) { cam_fill_csio(&ccb->csio, /* ccb_scsiio */ retry_count, /* retries */ NULL, /* cbfcnp */ CAM_DIR_OUT | CAM_DEV_QFRZDIS, /* flags */ CAM_TAG_ACTION_NONE, /* tag_action */ (u_char *)pkt_ptr, /* data_ptr */ pkt_size, /* dxfer_len */ SSD_FULL_SIZE, /* sense_len */ sizeof(struct scsi_write_buffer), /* cdb_len */ timeout ? timeout : CMD_TIMEOUT); /* timeout */ /* Execute the command. */ if (cam_send_ccb(cam_dev, ccb) < 0) { warnx("Error writing image to device"); if (verbose) cam_error_print(cam_dev, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr); goto bailout; } } /* Prepare next round. */ pkt_count++; pkt_ptr += pkt_size; img_size -= pkt_size; } while(!last_pkt); if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { if (verbose) cam_error_print(cam_dev, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr); goto bailout; } cam_freeccb(ccb); return (0); bailout: cam_freeccb(ccb); return (1); }
int chopen(dev_t dev, int flags, int fmt, struct proc *p) { struct ch_softc *sc; int oldcounts[4]; int i, unit, error = 0; unit = CHUNIT(dev); if ((unit >= ch_cd.cd_ndevs) || ((sc = ch_cd.cd_devs[unit]) == NULL)) return (ENXIO); /* * Only allow one open at a time. */ if (sc->sc_link->flags & SDEV_OPEN) return (EBUSY); sc->sc_link->flags |= SDEV_OPEN; /* * Absorb any unit attention errors. We must notice * "Not ready" errors as a changer will report "In the * process of getting ready" any time it must rescan * itself to determine the state of the changer. */ error = scsi_test_unit_ready(sc->sc_link, TEST_READY_RETRIES, SCSI_IGNORE_ILLEGAL_REQUEST | SCSI_IGNORE_MEDIA_CHANGE); if (error) goto bad; /* * Get information about the device. Save old information * so we can decide whether to be verbose about new parameters. */ for (i = 0; i < 4; i++) { oldcounts[i] = sc->sc_counts[i]; } error = ch_get_params(sc, scsi_autoconf); if (error) goto bad; for (i = 0; i < 4; i++) { if (oldcounts[i] != sc->sc_counts[i]) { break; } } if (i < 4) { #ifdef CHANGER_DEBUG #define PLURAL(c) (c) == 1 ? "" : "s" printf("%s: %d slot%s, %d drive%s, %d picker%s, %d portal%s\n", sc->sc_dev.dv_xname, sc->sc_counts[CHET_ST], PLURAL(sc->sc_counts[CHET_ST]), sc->sc_counts[CHET_DT], PLURAL(sc->sc_counts[CHET_DT]), sc->sc_counts[CHET_MT], PLURAL(sc->sc_counts[CHET_MT]), sc->sc_counts[CHET_IE], PLURAL(sc->sc_counts[CHET_IE])); #undef PLURAL printf("%s: move mask: 0x%x 0x%x 0x%x 0x%x\n", sc->sc_dev.dv_xname, sc->sc_movemask[CHET_MT], sc->sc_movemask[CHET_ST], sc->sc_movemask[CHET_IE], sc->sc_movemask[CHET_DT]); printf("%s: exchange mask: 0x%x 0x%x 0x%x 0x%x\n", sc->sc_dev.dv_xname, sc->sc_exchangemask[CHET_MT], sc->sc_exchangemask[CHET_ST], sc->sc_exchangemask[CHET_IE], sc->sc_exchangemask[CHET_DT]); #endif /* CHANGER_DEBUG */ } /* Default the current picker. */ sc->sc_picker = sc->sc_firsts[CHET_MT]; return (0); bad: sc->sc_link->flags &= ~SDEV_OPEN; return (error); }
int scsi_parse(uint8_t *block, uint8_t in_len) { /* set new operation */ if (state == USB_MS_SCSI_STATE_IDLE) { state = USB_MS_SCSI_STATE_PARSE; op = block[0]; } /* skip operation if sending reply */ if (state != USB_MS_SCSI_STATE_REPLY) { switch (op) { case SCSI_INQUIRY: scsi_inquiry(block, in_len); break; case SCSI_MODE_SENSE6: scsi_mode_sense6(block, in_len); break; case SCSI_READ10: scsi_read10(block, in_len); break; case SCSI_READ_CAPACITY10: scsi_read_capacity10(block, in_len); break; case SCSI_READ_FORMAT_CAPACITIES: scsi_read_format_capacities(block, in_len); break; case SCSI_REPORT_LUNS: scsi_report_luns(block, in_len); break; case SCSI_REQUEST_SENSE: scsi_request_sense(block, in_len); break; case SCSI_START_STOP_UNIT: scsi_start_stop_unit(block, in_len); break; case SCSI_SYNCHRONIZE_CACHE10: scsi_synchronize_cache10(block, in_len); break; case SCSI_TEST_UNIT_READY: scsi_test_unit_ready(block, in_len); break; case SCSI_WRITE10: scsi_write10(block, in_len); break; default: state = USB_MS_SCSI_STATE_REPLY; scsi_sense_code(SCSI_SENSE_ILLEGAL_REQUEST, SCSI_SENSE_CODE_INVALID_COMMAND_OPERATION_CODE); break; } } /* error during data rx/tx */ if (((state == USB_MS_SCSI_STATE_DATA_OUT) || (state == USB_MS_SCSI_STATE_DATA_IN)) && scsi_sense_data.key) { btable_ep[USB_EP_MS_TX].tx_count = 0; state = USB_MS_SCSI_STATE_REPLY; return SCSI_STATUS_CONTINUE; } /* done sending data */ if (state == USB_MS_SCSI_STATE_REPLY) { state = USB_MS_SCSI_STATE_IDLE; return scsi_sense_data.key; } /* still sending/receiving data and no error has occurred */ return SCSI_STATUS_CONTINUE; }
/* * Download firmware stored in buf to cam_dev. If simulation mode * is enabled, only show what packet sizes would be sent to the * device but do not sent any actual packets */ static int fw_download_img(struct cam_device *cam_dev, const struct fw_vendor *vp, char *buf, int img_size, int sim_mode, int printerrors, int retry_count, int timeout, const char *imgname, const char *type) { struct scsi_write_buffer cdb; progress_t progress; int size; union ccb *ccb; int pkt_count = 0; int max_pkt_size; u_int32_t pkt_size = 0; char *pkt_ptr = buf; u_int32_t offset; int last_pkt = 0; int16_t *ptr; if ((ccb = cam_getccb(cam_dev)) == NULL) { warnx("Could not allocate CCB"); return (1); } if (strcmp(type, "scsi") == 0) { scsi_test_unit_ready(&ccb->csio, 0, NULL, MSG_SIMPLE_Q_TAG, SSD_FULL_SIZE, 5000); } else if (strcmp(type, "ata") == 0) { /* cam_getccb cleans up the header, caller has to zero the payload */ bzero(&(&ccb->ccb_h)[1], sizeof(struct ccb_ataio) - sizeof(struct ccb_hdr)); ptr = (uint16_t *)malloc(sizeof(struct ata_params)); if (ptr == NULL) { cam_freeccb(ccb); warnx("can't malloc memory for identify\n"); return(1); } bzero(ptr, sizeof(struct ata_params)); cam_fill_ataio(&ccb->ataio, 1, NULL, /*flags*/CAM_DIR_IN, MSG_SIMPLE_Q_TAG, /*data_ptr*/(uint8_t *)ptr, /*dxfer_len*/sizeof(struct ata_params), timeout ? timeout : 30 * 1000); ata_28bit_cmd(&ccb->ataio, ATA_ATA_IDENTIFY, 0, 0, 0); } else { warnx("weird disk type '%s'", type); return 1; } /* Disable freezing the device queue. */ ccb->ccb_h.flags |= CAM_DEV_QFRZDIS; if (cam_send_ccb(cam_dev, ccb) < 0) { warnx("Error sending identify/test unit ready"); if (printerrors) cam_error_print(cam_dev, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr); cam_freeccb(ccb); return(1); } if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { warnx("Device is not ready"); if (printerrors) cam_error_print(cam_dev, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr); cam_freeccb(ccb); return (1); } max_pkt_size = vp->max_pkt_size; if (vp->max_pkt_size == 0 && strcmp(type, "ata") == 0) { max_pkt_size = UNKNOWN_MAX_PKT_SIZE; } pkt_size = vp->max_pkt_size; progress_init(&progress, imgname, size = img_size); /* Download single fw packets. */ do { if (img_size <= max_pkt_size) { last_pkt = 1; pkt_size = img_size; } progress_update(&progress, size - img_size); progress_draw(&progress); bzero(&cdb, sizeof(cdb)); if (strcmp(type, "scsi") == 0) { cdb.opcode = WRITE_BUFFER; cdb.control = 0; /* Parameter list length. */ scsi_ulto3b(pkt_size, &cdb.length[0]); offset = vp->inc_cdb_offset ? (pkt_ptr - buf) : 0; scsi_ulto3b(offset, &cdb.offset[0]); cdb.byte2 = last_pkt ? vp->cdb_byte2_last : vp->cdb_byte2; cdb.buffer_id = vp->inc_cdb_buffer_id ? pkt_count : 0; /* Zero out payload of ccb union after ccb header. */ bzero((u_char *)ccb + sizeof(struct ccb_hdr), sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr)); /* Copy previously constructed cdb into ccb_scsiio struct. */ bcopy(&cdb, &ccb->csio.cdb_io.cdb_bytes[0], sizeof(struct scsi_write_buffer)); /* Fill rest of ccb_scsiio struct. */ if (!sim_mode) { cam_fill_csio(&ccb->csio, /* ccb_scsiio */ retry_count, /* retries */ NULL, /* cbfcnp */ CAM_DIR_OUT | CAM_DEV_QFRZDIS, /* flags */ CAM_TAG_ACTION_NONE, /* tag_action */ (u_char *)pkt_ptr, /* data_ptr */ pkt_size, /* dxfer_len */ SSD_FULL_SIZE, /* sense_len */ sizeof(struct scsi_write_buffer), /* cdb_len */ timeout ? timeout : CMD_TIMEOUT); /* timeout */ } } else if (strcmp(type, "ata") == 0) { bzero(&(&ccb->ccb_h)[1], sizeof(struct ccb_ataio) - sizeof(struct ccb_hdr)); if (!sim_mode) { uint32_t off; cam_fill_ataio(&ccb->ataio, (last_pkt) ? 256 : retry_count, NULL, /*flags*/CAM_DIR_OUT | CAM_DEV_QFRZDIS, CAM_TAG_ACTION_NONE, /*data_ptr*/(uint8_t *)pkt_ptr, /*dxfer_len*/pkt_size, timeout ? timeout : 30 * 1000); off = (uint32_t)(pkt_ptr - buf); ata_28bit_cmd(&ccb->ataio, ATA_DOWNLOAD_MICROCODE, USE_OFFSETS_FEATURE, ATA_MAKE_LBA(off, pkt_size), ATA_MAKE_SECTORS(pkt_size)); } } if (!sim_mode) { /* Execute the command. */ if (cam_send_ccb(cam_dev, ccb) < 0 || (ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { warnx("Error writing image to device"); if (printerrors) cam_error_print(cam_dev, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr); goto bailout; } } /* Prepare next round. */ pkt_count++; pkt_ptr += pkt_size; img_size -= pkt_size; } while(!last_pkt); progress_complete(&progress, size - img_size); cam_freeccb(ccb); return (0); bailout: progress_complete(&progress, size - img_size); cam_freeccb(ccb); return (1); }
DiscDCB *DevOpen(Device *dev, DiscDevInfo * info) { DiscDCB *dcb; DriveInfo *dvi; WORD command_status; BYTE sense_data[SENSE_LENGTH]; /* Create a DiscDCB for File System Server */ if ((dcb = Malloc(sizeof(DiscDCB))) == NULL) { IOdebug("File System driver failed to allocate work space"); return(NULL); } dvi = (DriveInfo *)RTOA(info->Drives); /* Initialise controlling link to the HE1000 */ if(( dcb->Table = HE1000_init( info->Controller, dvi->DriveId , info->Mode)) < 0) { IOdebug("File System driver failed to initialise HE1000"); return(NULL); } /* Initialise DiscDCB with drive information */ dcb->DeviceId = dvi->DriveId; dcb->SectorSize = dvi->SectorSize; dcb->DCB.Device = dev; dcb->DCB.Operate = DevOperate; dcb->DCB.Close = DevClose; dcb->Link = info->Controller; dcb->BlockSize = info->Addressing; dcb->SectorsPerTrack = dvi->SectorsPerTrack; dcb->TracksPerCyl = dvi->TracksPerCyl; dcb->Cylinders = dvi->Cylinders; dcb->Mode = info->Mode; scsi_start_stop( dcb->Link, dcb->Table, dcb->DeviceId, 0, 1, /* place head on track 0 */ &command_status); /* Test disc for ready */ do { scsi_test_unit_ready( dcb->Link, dcb->Table, dcb->DeviceId, 0, &command_status); if( command_status eq CHECK_SENSE ) { scsi_request_sense( dcb->Link, dcb->Table, dcb->DeviceId, 0, SENSE_LENGTH, sense_data, &command_status); } } while ( command_status ne 0 ); /* Initialise the access locking semaphore */ InitSemaphore(&dcb->Lock, 1); /* return DiscDCB */ return(dcb); }
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; }