예제 #1
0
/* ( -- success? ) */
static void
scsi_open( instance_data_t *sd )
{
    static int once = 0;
    phandle_t ph;

    fword("my-unit");
    sd->target = POP();

    if( !once ) {
        once++;
        OSI_SCSIControl( SCSI_CTRL_INIT, 0 );
    }

    /* obtiain device information */
    if( inquiry(sd) )
        RET(0);

    selfword("open-deblocker");

    /* interpose disk-label */
    ph = find_dev("/packages/disk-label");
    fword("my-args");
    PUSH_ph( ph );
    fword("interpose");

    PUSH( -1 );
}
예제 #2
0
void
test_inquiry_supported_vpd(void)
{
	int ret, i;
	struct scsi_inquiry_supported_pages *sup_inq;

	logging(LOG_VERBOSE, LOG_BLANK_LINE);
	logging(LOG_VERBOSE, "Test INQUIRY supported VPD pages");

	logging(LOG_VERBOSE, "Verify we can read the SUPPORTED VPD page");
	ret = inquiry(sd, &task,
		      1, SCSI_INQUIRY_PAGECODE_SUPPORTED_VPD_PAGES, 255,
		      EXPECT_STATUS_GOOD);
	CU_ASSERT_EQUAL(ret, 0);

	logging(LOG_VERBOSE, "Verify we got at least 4 bytes of data");
	CU_ASSERT(task->datain.size >= 4);

	logging(LOG_VERBOSE, "Verify we can unmarshall the DATA-IN buffer");
	sup_inq = scsi_datain_unmarshall(task);
	CU_ASSERT_NOT_EQUAL(sup_inq, NULL);
	if (sup_inq == NULL) {
		logging(LOG_NORMAL, "[FAILED] Failed to unmarshall DATA-IN "
			"buffer");
		return;
	}

	logging(LOG_VERBOSE, "Verify we read all the supported pages");
	for (i = 0; i < sup_inq->num_pages; i++) {
		logging(LOG_VERBOSE, "Verify we can read page 0x%02x",
			sup_inq->pages[i]);

		ret = inquiry(sd, NULL, 1, sup_inq->pages[i], 255,
			      EXPECT_STATUS_GOOD);
		CU_ASSERT_EQUAL(ret, 0);
	}

	if (task != NULL) {
		scsi_free_scsi_task(task);
		task = NULL;
	}
}
예제 #3
0
static int open_scsi_device2 (struct dev_info_spti *di, int unitnum)
{
	HANDLE h;
	TCHAR *dev;

	if (di->bus >= 0) {
		dev = xmalloc (TCHAR, 100);
		_stprintf (dev, L"\\\\.\\Scsi%d:", di->bus);
	} else {
		dev = my_strdup (di->drvpath);
	}
	if (!di->scsibuf)
		di->scsibuf = (uae_u8*)VirtualAlloc (NULL, DEVICE_SCSI_BUFSIZE, MEM_COMMIT, PAGE_READWRITE);
	h = CreateFile(dev,GENERIC_READ|GENERIC_WRITE,FILE_SHARE_READ|FILE_SHARE_WRITE,NULL,OPEN_EXISTING,0,NULL);
	di->handle = h;
	if (h == INVALID_HANDLE_VALUE) {
		write_log (L"SPTI: failed to open unit %d err=%d ('%s')\n", unitnum, GetLastError (), dev);
	} else {
		uae_u8 inqdata[INQUIRY_SIZE + 1] = { 0 };
		checkcapabilities (di);
		if (!inquiry (di, unitnum, inqdata)) {
			write_log (L"SPTI: inquiry failed unit %d ('%s':%d:%d:%d:%d)\n", unitnum, dev,
				di->bus, di->path, di->target, di->lun);
			close_scsi_device2 (di);
			xfree (dev);
			return 0;
		}
		inqdata[INQUIRY_SIZE] = 0;
		di->name = my_strdup_ansi ((char*)inqdata + 8);
		if (di->type == INQ_ROMD) {
			di->mediainserted = mediacheck (di, unitnum);
			write_log (L"SPTI: unit %d (%c:\\) opened [%s], %s, '%s'\n",
				unitnum, di->drvletter ? di->drvletter : '*',
				di->isatapi ? L"ATAPI" : L"SCSI",
				di->mediainserted ? L"media inserted" : L"drive empty",
				di->name);
		} else {
			write_log (L"SPTI: unit %d, type %d, '%s'\n",
				unitnum, di->type, di->name);
		}
		di->inquirydata = xmalloc (uae_u8, INQUIRY_SIZE);
		memcpy (di->inquirydata, inqdata, INQUIRY_SIZE);
		xfree (dev);
		di->open = true;
		update_device_info (unitnum);
		if (di->type == INQ_ROMD)
			blkdev_cd_change (unitnum, di->drvletter ? di->drvlettername : di->name);
		return 1;
	}
	xfree (dev);
	return 0;
}
예제 #4
0
파일: readiso.c 프로젝트: tjko/readiso
void scan_bus()
{
  char vendor[9],model[17],rev[5];
  char d[1024];
  int bus,dev,type;
  
  int firstbus,lastbus;
  int firstdev,lastdev;

  firstbus=0;
  firstdev=0;
  lastbus=0;
  lastdev=0;

#ifdef LINUX
  lastdev=16;
#endif
#ifdef IRIX
  firstdev=1;
  lastdev=15;
  lastbus=1;
#endif

  printf("Device                   Manufacturer  Model              Revision\n"
	 "-----------------------  ------------- ------------------ --------\n"
	 );

  for (bus=firstbus;bus<=lastbus;bus++) {

    for (dev=firstdev;dev<=lastdev;dev++) {
#ifdef LINUX
      snprintf(d,1024,"/dev/sg%c",'a'+dev);
#else
      snprintf(d,1024,"/dev/scsi/sc%dd%dl0",bus,dev);
#endif
      /* fprintf(stderr,"try: '%s'\n",d); */

      if (scsi_open(d)==0) {
	if ((type=inquiry(vendor,model,rev))>=0) {
	  type=type&0x1f;
	  printf("%-23s  %-13s %-18s %-8s %s\n",d,vendor,model,rev,
		 (type==0x5?"[CD-ROM]":""));
	}
	scsi_close();
      }

    }

  }
    
    
}
void
test_inquiry_mandatory_vpd_sbc(void)
{
        int ret;

        logging(LOG_VERBOSE, LOG_BLANK_LINE);
        logging(LOG_VERBOSE, "Test INQUIRY support for mandatory SBC VPD");

        CHECK_FOR_SBC;


        logging(LOG_VERBOSE, "SUPPORTED_VPD_PAGES is mandatory for SBC devices. Verify we can read it.");
        ret = inquiry(sd, NULL,
                      1, SCSI_INQUIRY_PAGECODE_SUPPORTED_VPD_PAGES, 255,
                      EXPECT_STATUS_GOOD);
        CU_ASSERT_EQUAL(ret, 0);

        logging(LOG_VERBOSE, "DEVICE_IDENTIFICATION is mandatory for SBC devices. Verify we can read it.");
        ret = inquiry(sd, NULL,
                      1, SCSI_INQUIRY_PAGECODE_DEVICE_IDENTIFICATION, 255,
                      EXPECT_STATUS_GOOD);
        CU_ASSERT_EQUAL(ret, 0);
}
예제 #6
0
void
test_mandatory_sbc(void)
{
	int ret;
	//unsigned char buf[4096];
	//struct unmap_list list[1];

	logging(LOG_VERBOSE, LOG_BLANK_LINE);
	logging(LOG_VERBOSE, "Test support for all mandatory opcodes on SBC devices");

	CHECK_FOR_SBC;

	logging(LOG_VERBOSE, "Test INQUIRY.");
	ret = inquiry(sd, NULL, 0, 0, 255,
		      EXPECT_STATUS_GOOD);
	CU_ASSERT_EQUAL(ret, 0);

	logging(LOG_VERBOSE, "Test READCAPACITY10.");
	ret = readcapacity10(sd, NULL, 0, 0,
			     EXPECT_STATUS_GOOD);
	CU_ASSERT_EQUAL(ret, 0);

	if (sbc3_support) {
		logging(LOG_VERBOSE, "Test READCAPACITY16. The device claims SBC-3 support.");
		ret = readcapacity16(sd, NULL, 15,
				     EXPECT_STATUS_GOOD);
		CU_ASSERT_EQUAL(ret, 0);
	}

	logging(LOG_VERBOSE, "Test READ10.");
	ret = read10(sd, NULL, 0, block_size, block_size,
		     0, 0, 0, 0, 0, NULL,
		     EXPECT_STATUS_GOOD);
	CU_ASSERT_EQUAL(ret, 0);

	if (sbc3_support) {
		logging(LOG_VERBOSE, "Test READ16. the device claims SBC-3 support.");
		ret = read16(sd, 0, block_size, block_size,
			     0, 0, 0, 0, 0, NULL,
			     EXPECT_STATUS_GOOD);
		CU_ASSERT_EQUAL(ret, 0);
	}

	logging(LOG_VERBOSE, "Test TESTUNITREADY.");
	ret = testunitready(sd,
			    EXPECT_STATUS_GOOD);
	CU_ASSERT_EQUAL(ret, 0);
}
예제 #7
0
int Worker::exec()
{
    for (;;) {
        switch (status) {
        case BRIDGE_CONNECT:
            bridge_connect();
            status = WAIT;
            break;
        case INQUIRY_REQ:
            if (inquiry() == 0)
                status = CONNECT;
            else
                status = WAIT;
            break;
        case CONNECT:
            if (connection() == 0)
                status = DATA_LOOP;
            else
                status = WAIT;
            break;
        case DATA_LOOP:
            dataLoop();
            break;
        case KILL:
            kill();
            status = QUIT;
            break;
        case WAIT:
            sync->acquire();
            break;
        case QUIT:
            return 0;
            break;
        default: break;
        }
    }
    return 0;
}
예제 #8
0
static int
mpath_check_matching_ids_serial_vpd(int num_sds,
				    struct scsi_device **sds)
{
	int i;
	int num_sds_with_valid_id = 0;
	struct scsi_task *inq_task = NULL;
	char *usn_saved = NULL;

	for (i = 0; i < num_sds; i++) {
		int full_size;
		struct scsi_inquiry_unit_serial_number *inq_serial;

		/*
		 * inquiry to confirm that all multipath devices carry an
		 * identical unit serial number.
		 */
		inq_task = NULL;
		inquiry(sds[i], &inq_task, 1,
			SCSI_INQUIRY_PAGECODE_UNIT_SERIAL_NUMBER, 64,
			EXPECT_STATUS_GOOD);
		if (inq_task && inq_task->status != SCSI_STATUS_GOOD) {
			printf("Inquiry command failed : %s\n",
			       sds[i]->error_str);
			goto err_cleanup;
		}
		full_size = scsi_datain_getfullsize(inq_task);
		if (full_size > inq_task->datain.size) {
			scsi_free_scsi_task(inq_task);

			/* we need more data */
			inq_task = NULL;
			inquiry(sds[i], &inq_task, 1,
				SCSI_INQUIRY_PAGECODE_UNIT_SERIAL_NUMBER,
				full_size,
				EXPECT_STATUS_GOOD);
			if (inq_task == NULL) {
				printf("Inquiry command failed : %s\n",
				       sds[i]->error_str);
				goto err_cleanup;
			}
		}

		inq_serial = scsi_datain_unmarshall(inq_task);
		if (inq_serial == NULL) {
			printf("failed to unmarshall inquiry datain blob\n");
			goto err_cleanup;
		}

		if (inq_serial->qualifier
			       != SCSI_INQUIRY_PERIPHERAL_QUALIFIER_CONNECTED) {
			printf("error: multipath device not connected\n");
			goto err_cleanup;
		}

		if (inq_serial->device_type
			 != SCSI_INQUIRY_PERIPHERAL_DEVICE_TYPE_DIRECT_ACCESS) {
			printf("error: multipath devices must be SBC\n");
			goto err_cleanup;
		}

		if (inq_serial->usn == NULL) {
			printf("error: empty usn for multipath device\n");
			goto err_cleanup;
		}

		if (usn_saved == NULL) {
			usn_saved = strdup(inq_serial->usn);
			if (usn_saved == NULL) {
				goto err_cleanup;
			}
			num_sds_with_valid_id++;
		} else if (strcmp(usn_saved, inq_serial->usn) == 0) {
			num_sds_with_valid_id++;
		} else {
			printf("multipath unit serial mismatch: %s != %s\n",
			       usn_saved, inq_serial->usn);
		}

		scsi_free_scsi_task(inq_task);
		inq_task = NULL;
	}

	if (num_sds_with_valid_id != num_sds) {
		printf("failed to find matching serial number for all paths\n");
		goto err_cleanup;
	}

	printf("found matching serial number for all (%d) paths: %s\n",
	       num_sds, usn_saved);
	free(usn_saved);

	return 0;

err_cleanup:
	free(usn_saved);
	scsi_free_scsi_task(inq_task);
	return -1;
}
예제 #9
0
static int
mpath_check_matching_ids_devid_vpd(int num_sds,
				   struct scsi_device **sds)
{
	int i;
	int num_sds_with_valid_id = 0;
	struct scsi_task *inq_task = NULL;
	struct scsi_inquiry_device_designator *des_saved = NULL;

	for (i = 0; i < num_sds; i++) {
		int ret;
		int full_size;
		struct scsi_inquiry_device_identification *inq_id_data;
		struct scsi_inquiry_device_designator *des;

		/*
		 * dev ID inquiry to confirm that all multipath devices carry
		 * an identical logical unit identifier.
		 */
		inquiry(sds[i], &inq_task, 1,
			SCSI_INQUIRY_PAGECODE_DEVICE_IDENTIFICATION,
			64,
			EXPECT_STATUS_GOOD);
		if (inq_task && inq_task->status != SCSI_STATUS_GOOD) {
			printf("Inquiry command failed : %s\n",
			       sds[i]->error_str);
			goto err_cleanup;
		}
		full_size = scsi_datain_getfullsize(inq_task);
		if (full_size > inq_task->datain.size) {
			/* we need more data */
			scsi_free_scsi_task(inq_task);
			inq_task = NULL;
			inquiry(sds[i], &inq_task, 1,
				SCSI_INQUIRY_PAGECODE_DEVICE_IDENTIFICATION,
				full_size,
				EXPECT_STATUS_GOOD);
			if (inq_task == NULL) {
				printf("Inquiry command failed : %s\n",
				       sds[i]->error_str);
				goto err_cleanup;
			}
		}

		inq_id_data = scsi_datain_unmarshall(inq_task);
		if (inq_id_data == NULL) {
			printf("failed to unmarshall inquiry ID datain blob\n");
			goto err_cleanup;
		}

		if (inq_id_data->qualifier
			       != SCSI_INQUIRY_PERIPHERAL_QUALIFIER_CONNECTED) {
			printf("error: multipath device not connected\n");
			goto err_cleanup;
		}

		if (inq_id_data->device_type
			 != SCSI_INQUIRY_PERIPHERAL_DEVICE_TYPE_DIRECT_ACCESS) {
			printf("error: multipath devices must be SBC\n");
			goto err_cleanup;
		}

		/* walk the list of IDs, and find a suitable LU candidate */
		for (des = inq_id_data->designators;
		     des != NULL;
		     des = des->next) {
			if (des->association != SCSI_ASSOCIATION_LOGICAL_UNIT) {
				printf("skipping non-LU designator: %d\n",
				       des->association);
				continue;
			}

			if ((des->designator_type != SCSI_DESIGNATOR_TYPE_EUI_64)
			 && (des->designator_type != SCSI_DESIGNATOR_TYPE_NAA)
			 && (des->designator_type != SCSI_DESIGNATOR_TYPE_MD5_LOGICAL_UNIT_IDENTIFIER)
			 && (des->designator_type != SCSI_DESIGNATOR_TYPE_SCSI_NAME_STRING)) {
				printf("skipping unsupported des type: %d\n",
				       des->designator_type);
				continue;
			}

			if (des->designator_length <= 0) {
				printf("skipping designator with bad len: %d\n",
				       des->designator_length);
				continue;
			}

			if (des_saved == NULL) {
				ret = mpath_des_copy(des, &des_saved);
				if (ret < 0) {
					goto err_cleanup;
				}
				/*
				 * we now have a reference to look for in all
				 * subsequent paths.
				 */
				num_sds_with_valid_id++;
				break;
			} else if (mpath_des_cmp(des, des_saved) == 0) {
				/* found match for previous path designator */
				num_sds_with_valid_id++;
				break;
			}
			/* no match yet, keep checking other designators */
		}

		scsi_free_scsi_task(inq_task);
		inq_task = NULL;
	}
	mpath_des_free(des_saved);

	if (num_sds_with_valid_id != num_sds) {
		printf("failed to find matching LU device ID for all paths\n");
		return -1;
	}

	printf("found matching LU device identifier for all (%d) paths\n",
	       num_sds);
	return 0;

err_cleanup:
	mpath_des_free(des_saved);
	scsi_free_scsi_task(inq_task);
	return -1;
}
예제 #10
0
int main()
{
    Datagram dg;
    Serial_t serialConfig;

    t=0;

    serialConfig.baud_rate = 9600;
    serialConfig.bits = 8;
    serialConfig.parity = 0;
    serialConfig.stop_bits = 1;
    serialConfig.device = "ttyUSB0";

    serial.setConfig(serialConfig);
    if (serial.connect() == -1) {
        qDebug() << "Serial connection error!";
        exit(1);
    }
    qDebug() << "Serial connected!";

    qDebug() << "Ping...";
    ping();
    qDebug() << "DONE";

    bool remain = true;
    while (remain) {
        qDebug() << "Inquiry or ok?";
        receiveDatagram(&serial, &dg);
        switch (dg.type) {
        case REQUEST:
            switch (dg.id) {
            case INQUIRY:
                qDebug() << "Inquiry Request...";
                inquiry();
                qDebug() << "DONE";
                break;
            default:
                qDebug() << "Unknown";
                break;
            }
            break;
        case RESPONSE:
            switch (dg.id) {
            case OK:
                qDebug() << "OK";
                remain = false;
                break;
            default:
                qDebug() << "Unknown";
                break;
            }
            break;
        default:
            qDebug() << "Unknown";
            break;
        }
    }

    receiveDatagram(&serial, &dg);
    if (dg.type != REQUEST || dg.id != CONNECT_TO) {
        qDebug() << "Expected connection!";
        qDebug() << "QUIT";
        exit(1);
    }

    qDebug() << "Connecting to: " << *dg.data;
    sendDatagram(&serial, RESPONSE, SUCCESS);
    qDebug() << "DONE";

    loop();
    return 0;
}
예제 #11
0
void
test_inquiry_standard(void)
{
        int ret, i;
        struct scsi_inquiry_standard *std_inq;

        logging(LOG_VERBOSE, LOG_BLANK_LINE);
        logging(LOG_VERBOSE, "Test of the standard INQUIRY page");

        logging(LOG_VERBOSE, "Verify we can read standard INQUIRY page");
        /* 260 bytes is the maximum possible size of the standard vpd */
        ret = inquiry(sd, &task, 0, 0, 260,
                      EXPECT_STATUS_GOOD);
        CU_ASSERT_EQUAL(ret, 0);

        logging(LOG_VERBOSE, "Verify we got at least 36 bytes of data");
        CU_ASSERT(task->datain.size >= 36);

        logging(LOG_VERBOSE, "Verify we can unmarshall the DATA-IN buffer");
        std_inq = scsi_datain_unmarshall(task);
        CU_ASSERT_NOT_EQUAL(std_inq, NULL);
        if (std_inq == NULL) {
                logging(LOG_NORMAL, "[FAILED] Failed to unmarshall DATA-IN "
                        "buffer");
                return;
        }

        logging(LOG_VERBOSE, "Verify peripheral-qualifier is 0");
        CU_ASSERT_EQUAL(std_inq->qualifier, 0);

        logging(LOG_VERBOSE, "Verify version field is either 0x4, 0x5 or 0x6");
        switch (std_inq->version) {
        case 0x0:
                logging(LOG_NORMAL, "[WARNING] Standard INQUIRY data claims "
                        "conformance to no standard. Version==0. "
                        "Bad sport.");

                break;
        case 0x4:
        case 0x5:
        case 0x6:
                break;
        default:
                logging(LOG_NORMAL, "[FAILED] Invalid version in standard "
                        "INQUIRY data. Version %d found but only versions "
                        "0x4,0x4,0x6 are valid.", std_inq->version);
                CU_FAIL("Invalid version in INQUIRY data");
        }

        logging(LOG_VERBOSE, "Verify response-data-format is 2 "
                "(SPC-2 or later)");
        if (std_inq->response_data_format != 2) {
                logging(LOG_NORMAL, "[FAILED] Response data format is "
                        "invalid. Must be 2 but device returned %d",
                        std_inq->response_data_format);
        }
        CU_ASSERT_EQUAL(std_inq->response_data_format, 2);

        logging(LOG_VERBOSE, "Verify additional-length is correct");
        if (std_inq->additional_length > task->datain.size - 5) {
                logging(LOG_NORMAL, "[FAILED] Bad additional length "
                        "returned. Should be %d but device returned %d.",
                        task->datain.size - 5,
                        std_inq->additional_length);
                logging(LOG_NORMAL, "[FAILED] Additional length points "
                        "beyond end of data");
                CU_FAIL("Additional length points beyond end of data");
        }
        if (std_inq->additional_length < task->datain.size - 5) {
                logging(LOG_NORMAL, "[WARNING] Bad additional length "
                        "returned. Should be %d but device returned %d. ",
                        task->datain.size - 5,
                        std_inq->additional_length);
                logging(LOG_VERBOSE, "Verify that all padding data is 0");
                for (i = std_inq->additional_length + 6; i < task->datain.size; i++) {
                        if (!task->datain.data[i])
                                continue;
                        logging(LOG_NORMAL, "[FAILED] Padding data is not zero."
                                           " Are we leaking data?");
                        CU_FAIL("Padding data is not zero. Leaking data?");
                }
        }

        logging(LOG_VERBOSE, "Verify VENDOR_IDENTIFICATION is in ASCII");
        for (i = 8; i < 16; i++) {
                /* SPC-4 4.4.1 only characters 0x00 and 0x20-0x7E allowed */
                if (task->datain.data[i] == 0) {
                        continue;
                }
                if (task->datain.data[i] >= 0x20 && task->datain.data[i] <= 0x7e) {
                        continue;
                }

                logging(LOG_NORMAL, "[FAILED] VENDOR_IDENTIFICATION contains "
                        "non-ASCII characters");
                CU_FAIL("Invalid characters in VENDOR_IDENTIFICATION");
                break;
        }

        logging(LOG_VERBOSE, "Verify PRODUCT_IDENTIFICATION is in ASCII");
        for (i = 16; i < 32; i++) {
                /* SPC-4 4.4.1 only characters 0x00 and 0x20-0x7E allowed */
                if (task->datain.data[i] == 0) {
                        continue;
                }
                if (task->datain.data[i] >= 0x20 && task->datain.data[i] <= 0x7e) {
                        continue;
                }

                logging(LOG_NORMAL, "[FAILED] PRODUCT_IDENTIFICATION contains "
                        "non-ASCII characters");
                CU_FAIL("Invalid characters in PRODUCT_IDENTIFICATION");
                break;
        }

        logging(LOG_VERBOSE, "Verify PRODUCT_REVISION_LEVEL is in ASCII");
        for (i = 32; i < 36; i++) {
                /* SPC-4 4.4.1 only characters 0x00 and 0x20-0x7E allowed */
                if (task->datain.data[i] == 0) {
                        continue;
                }
                if (task->datain.data[i] >= 0x20 && task->datain.data[i] <= 0x7e) {
                        continue;
                }

                logging(LOG_NORMAL, "[FAILED] PRODUCT_REVISON_LEVEL contains "
                        "non-ASCII characters");
                CU_FAIL("Invalid characters in PRODUCT_REVISON_LEVEL");
                break;
        }

        logging(LOG_VERBOSE, "Verify AERC is clear in SPC-3 and later");
        if (task->datain.data[3] & 0x80 && std_inq->version >= 5) {
                logging(LOG_NORMAL, "[FAILED] AERC is set but this device "
                        "reports SPC-3 or later.");
                CU_FAIL("AERC is set but SPC-3+ is claimed");
        }

        logging(LOG_VERBOSE, "Verify TRMTSK is clear in SPC-2 and later");
        if (task->datain.data[3] & 0x40 && std_inq->version >= 4) {
                logging(LOG_NORMAL, "[FAILED] TRMTSK is set but this device "
                        "reports SPC-2 or later.");
                CU_FAIL("TRMTSK is set but SPC-2+ is claimed");
        }

        if (task != NULL) {
                scsi_free_scsi_task(task);
                task = NULL;
        }
}
예제 #12
0
파일: ibm.c 프로젝트: DspaceSPI/SPIScan
static SANE_Status
attach (const char *devnam, Ibm_Device ** devp)
{
  SANE_Status status;
  Ibm_Device *dev;

  int fd;
  struct inquiry_data ibuf;
  struct measurements_units_page mup;
  struct ibm_window_data wbuf;
  size_t buf_size;
  char *str;
  DBG (11, ">> attach\n");

  for (dev = first_dev; dev; dev = dev->next)
    {
      if (strcmp (dev->sane.name, devnam) == 0)
        {
          if (devp)
            *devp = dev;
          return (SANE_STATUS_GOOD);
        }
    }

  DBG (3, "attach: opening %s\n", devnam);
  status = sanei_scsi_open (devnam, &fd, NULL, NULL);
  if (status != SANE_STATUS_GOOD)
    {
      DBG (1, "attach: open failed: %s\n", sane_strstatus (status));
      return (status);
    }

  DBG (3, "attach: sending INQUIRY\n");
  memset (&ibuf, 0, sizeof (ibuf));
  buf_size = sizeof(ibuf);
/* next line by mf */
  ibuf.byte2 = 2;
  status = inquiry (fd, &ibuf, &buf_size);
  if (status != SANE_STATUS_GOOD)
    {
      DBG (1, "attach: inquiry failed: %s\n", sane_strstatus (status));
      sanei_scsi_close (fd);
      return (status);
    }

  if (ibuf.devtype != 6)
    {
      DBG (1, "attach: device \"%s\" is not a scanner\n", devnam);
      sanei_scsi_close (fd);
      return (SANE_STATUS_INVAL);
    }

  if (!(
	(strncmp ((char *)ibuf.vendor, "IBM", 3) ==0
         && strncmp ((char *)ibuf.product, "2456", 4) == 0)
        || (strncmp ((char *)ibuf.vendor, "RICOH", 5) == 0 
	    && strncmp ((char *)ibuf.product, "IS420", 5) == 0) 
        || (strncmp ((char *)ibuf.vendor, "RICOH", 5) == 0 
	    && strncmp ((char *)ibuf.product, "IS410", 5) == 0) 
        || (strncmp ((char *)ibuf.vendor, "RICOH", 5) == 0 
	    && strncmp ((char *)ibuf.product, "IS430", 5) == 0) 
	))
    {
      DBG (1, "attach: device \"%s\" doesn't look like a scanner I know\n",
	   devnam);
      sanei_scsi_close (fd);
      return (SANE_STATUS_INVAL);
    }

  DBG (3, "attach: sending TEST_UNIT_READY\n");
  status = test_unit_ready (fd);
  if (status != SANE_STATUS_GOOD)
    {
      DBG (1, "attach: test unit ready failed (%s)\n",
           sane_strstatus (status));
      sanei_scsi_close (fd);
      return (status);
    }
  /*
   * Causes a problem with RICOH IS420
   * Ignore this function ... seems to work ok
   * Suggested to George Murphy [email protected] by henning
   */
  if (strncmp((char *)ibuf.vendor, "RICOH", 5) != 0
      && strncmp((char *)ibuf.product, "IS420", 5) != 0)
    {
      DBG (3, "attach: sending OBJECT POSITION\n");
      status = object_position (fd, OBJECT_POSITION_UNLOAD);
      if (status != SANE_STATUS_GOOD)
    	{
	  DBG (1, "attach: OBJECT POSTITION failed\n");
	  sanei_scsi_close (fd);
	  return (SANE_STATUS_INVAL);
    	}
    }

  memset (&mup, 0, sizeof (mup));
  mup.page_code = MEASUREMENTS_PAGE;
  mup.parameter_length = 0x06;
  mup.bmu = INCHES;
  mup.mud[0] = (DEFAULT_MUD >> 8) & 0xff;
  mup.mud[1] = (DEFAULT_MUD & 0xff);

#if 0
  DBG (3, "attach: sending MODE SELECT\n");
  status = mode_select (fd, (struct mode_pages *) &mup);
  if (status != SANE_STATUS_GOOD)
    {
      DBG (1, "attach: MODE_SELECT failed\n");
      sanei_scsi_close (fd);
      return (SANE_STATUS_INVAL);
    } 
#endif

#if 0
  DBG (3, "attach: sending MODE SENSE\n");
  memset (&mup, 0, sizeof (mup));
  status = mode_sense (fd, (struct mode_pages *) &mup, PC_CURRENT | MEASUREMENTS_PAGE);
  if (status != SANE_STATUS_GOOD)
    {
      DBG (1, "attach: MODE_SENSE failed\n");
      sanei_scsi_close (fd);
      return (SANE_STATUS_INVAL);
    }
#endif

  DBG (3, "attach: sending GET WINDOW\n");
  memset (&wbuf, 0, sizeof (wbuf));
  status = get_window (fd, &wbuf);
  if (status != SANE_STATUS_GOOD)
    {
      DBG (1, "attach: GET_WINDOW failed %d\n", status);
      sanei_scsi_close (fd);
      DBG (11, "<< attach\n");
      return (SANE_STATUS_INVAL);
    }

  sanei_scsi_close (fd);

  dev = malloc (sizeof (*dev));
  if (!dev)
    return (SANE_STATUS_NO_MEM);
  memset (dev, 0, sizeof (*dev));

  dev->sane.name = strdup (devnam);
  dev->sane.vendor = "IBM";
  str = malloc (16 + 1);
  memset (str, 0, sizeof (str));
  strncpy (str, (char *)ibuf.product, sizeof(ibuf.product));
  strncpy (str + sizeof(ibuf.revision), (char *)ibuf.revision, sizeof(ibuf.revision));
  str[sizeof(ibuf.product) + sizeof(ibuf.revision)] = '\0';
  dev->sane.model = str;
  dev->sane.type = "flatbed scanner";

  DBG (5, "dev->sane.name = %s\n", dev->sane.name);
  DBG (5, "dev->sane.vendor = %s\n", dev->sane.vendor);
  DBG (5, "dev->sane.model = %s\n", dev->sane.model);
  DBG (5, "dev->sane.type = %s\n", dev->sane.type);

  dev->info.xres_default = _2btol(wbuf.x_res);
  dev->info.yres_default = _2btol(wbuf.y_res);
  dev->info.image_mode_default = wbuf.image_comp;

  /* if you throw the MRIF bit the brighness control reverses too */
  /* so I reverse the reversal in software for symmetry's sake */
  /* I should make this into an option */

  if (wbuf.image_comp == IBM_GRAYSCALE || wbuf.image_comp == IBM_DITHERED_MONOCHROME)
    {
      dev->info.brightness_default = 256 - wbuf.brightness;
/*
      if (is50)
	dev->info.contrast_default = wbuf.contrast;
      else
*/
      dev->info.contrast_default = 256 - wbuf.contrast;
    }
  else /* wbuf.image_comp == IBM_BINARY_MONOCHROME */
    {
      dev->info.brightness_default = wbuf.brightness;
      dev->info.contrast_default = wbuf.contrast;
    }
  
/* da rivedere
  dev->info.adf_default = wbuf.adf_state;
*/
  dev->info.adf_default = ADF_UNUSED;
  dev->info.adf_default = IBM_PAPER_USER_DEFINED;
  
#if 1
  dev->info.bmu = mup.bmu;
  dev->info.mud = _2btol(mup.mud);
  if (dev->info.mud == 0) {
    /* The Ricoh says it uses points as default Basic Measurement Unit */
    /* but gives a Measurement Unit Divisor of zero */
    /* So, we set it to the default (SCSI-standard) of 1200 */
    /* with BMU in inches, i.e. 1200 points equal 1 inch */
    dev->info.bmu = INCHES;
    dev->info.mud = DEFAULT_MUD;
  }
#else
    dev->info.bmu = INCHES;
    dev->info.mud = DEFAULT_MUD;
#endif

  DBG (5, "xres_default=%d\n", dev->info.xres_default);
  DBG (5, "xres_range.max=%d\n", dev->info.xres_range.max);
  DBG (5, "xres_range.min=%d\n", dev->info.xres_range.min);

  DBG (5, "yres_default=%d\n", dev->info.yres_default);
  DBG (5, "yres_range.max=%d\n", dev->info.yres_range.max);
  DBG (5, "yres_range.min=%d\n", dev->info.yres_range.min);

  DBG (5, "x_range.max=%d\n", dev->info.x_range.max);
  DBG (5, "y_range.max=%d\n", dev->info.y_range.max);

  DBG (5, "image_mode=%d\n", dev->info.image_mode_default);

  DBG (5, "brightness=%d\n", dev->info.brightness_default);
  DBG (5, "contrast=%d\n", dev->info.contrast_default);
  
  DBG (5, "adf_state=%d\n", dev->info.adf_default);

  DBG (5, "bmu=%d\n", dev->info.bmu);
  DBG (5, "mud=%d\n", dev->info.mud);

  ++num_devices;
  dev->next = first_dev;
  first_dev = dev;

  if (devp)
    *devp = dev;

  DBG (11, "<< attach\n");
  return (SANE_STATUS_GOOD);
}
예제 #13
0
/*
 * Scan SCSI busses to detect any devices
 * that we want to supply to the Amgia.
 *
 * Based on code from cdrecord
 */
static int scanscsi (SCSI *scgp)
{
    int bus;
    int tgt;
    int lun = 0;
    int initiator;
    int have_tgt;
    int n;

    scgp->silent++;
    for (bus = 0; bus < 16; bus++) {
	scg_settarget (scgp, bus, 0, 0);

	if (!scg_havebus (scgp, bus))
	    continue;

	initiator = scg_initiator_id (scgp);
	write_log ("scsibus%d:\n", bus);

	for (tgt = 0; tgt < 16; tgt++) {
	    n = bus * 100 + tgt;

	    scg_settarget (scgp, bus, tgt, lun);
	    have_tgt = unit_ready (scgp) || scgp->scmd->error != SCG_FATAL;

	    if (!have_tgt && tgt > 7) {
		if (scgp->scmd->ux_errno == EINVAL)
		    break;
		continue;
	    }

	    write_log ("  %d,%d,%d  %d ", bus, tgt, lun, n);

	    if (tgt == initiator) {
		write_log ("HOST ADAPTOR\n");
		continue;
	    }
	    if (!have_tgt) {
		/* Hack: fd -> -2 means no access */
		write_log ( "%c\n", scgp->fd == -2 ? '?':'*');
		continue;
	    }

	    if ((scgp->scmd->error < SCG_FATAL)
		|| (scgp->scmd->scb.chk && scgp->scmd->sense_count > 0)) {
		struct scsi_inquiry *inq = scgp->inq;

		inquiry (scgp, inq, sizeof (*inq));
		print_product (inq);

		/* Just CD/DVD drives for now */
		if (inq->type == INQ_ROMD)
		    add_drive (scgp);
	    }

	    write_log ("\n");
	}
    }
    scgp->silent--;
    return 0;
}
예제 #14
0
void
test_sanitize_reset(void)
{ 
        int ret;
        struct scsi_command_descriptor *cd;
        struct scsi_task *sanitize_task;
        struct scsi_task *rl_task;
        struct iscsi_data data;

        logging(LOG_VERBOSE, LOG_BLANK_LINE);
        logging(LOG_VERBOSE, "Test SANITIZE with Task/Lun/Target/Session reset");

        CHECK_FOR_SANITIZE;
        CHECK_FOR_DATALOSS;

        if (sd->iscsi_ctx == NULL) {
                const char *err = "[SKIPPED] This SANITIZE test is only "
                        "supported for iSCSI backends";
                logging(LOG_NORMAL, "%s", err);
                CU_PASS(err);
                return;
        }

        logging(LOG_VERBOSE, "Check that SANITIZE OVERWRITE will continue "
                "even after Task/Lun/Target/* reset.");
        cd = get_command_descriptor(SCSI_OPCODE_SANITIZE,
                                    SCSI_SANITIZE_OVERWRITE);
        if (cd == NULL) {
                logging(LOG_NORMAL, "[SKIPPED] SANITIZE OVERWRITE is not "
                        "implemented according to REPORT_SUPPORTED_OPCODES.");
                CU_PASS("SANITIZE is not implemented.");
                return;
        }

        logging(LOG_VERBOSE, "Send an asyncronous SANITIZE to the target.");
        data.size = block_size + 4;
        data.data = alloca(data.size);
        memset(&data.data[4], 0, block_size);

        data.data[0] = 0x01;
        data.data[1] = 0x00;
        data.data[2] = block_size >> 8;
        data.data[3] = block_size & 0xff;
        sanitize_task = iscsi_sanitize_task(sd->iscsi_ctx, sd->iscsi_lun,
                                            0, 0, SCSI_SANITIZE_OVERWRITE,
                                            data.size, &data,
                                            sanitize_cb, NULL);
        CU_ASSERT_NOT_EQUAL(sanitize_task, NULL);
        /* just send something so that we know the sanitize command is sent
         * to the target
         */
        rl_task = iscsi_reportluns_sync(sd->iscsi_ctx, 0, 64);
        if (rl_task) {
                scsi_free_scsi_task(rl_task);
        }


        logging(LOG_VERBOSE, "Sleep for three seconds incase the target is "
                "slow to start the SANITIZE");
        sleep(3);

        logging(LOG_VERBOSE, "Verify that the SANITIZE has started and that "
                "TESTUNITREADY fails with SANITIZE_IN_PROGRESS");
        TESTUNITREADY(sd,
                      EXPECT_SANITIZE);

        logging(LOG_VERBOSE, "Verify that STARTSTOPUNIT fails with "
                "SANITIZE_IN_PROGRESS");
        STARTSTOPUNIT(sd, 1, 0, 1, 0, 1, 0,
                      EXPECT_SANITIZE);

        logging(LOG_VERBOSE, "Verify that READ16 fails with "
                "SANITIZE_IN_PROGRESS");
        READ16(sd, NULL, 0, block_size,
               block_size, 0, 0, 0, 0, 0, NULL,
               EXPECT_SANITIZE);

        logging(LOG_VERBOSE, "Verify that INQUIRY is still allowed while "
                "SANITIZE is in progress");
        ret = inquiry(sd, NULL, 0, 0, 255,
                      EXPECT_STATUS_GOOD);
        CU_ASSERT_EQUAL(ret, 0);


        logging(LOG_VERBOSE, "Send an ABORT TASK");
        ret = iscsi_task_mgmt_abort_task_sync(sd->iscsi_ctx, sanitize_task);
        if (ret != 0) {
                logging(LOG_NORMAL, "ABORT TASK failed. %s",
                        iscsi_get_error(sd->iscsi_ctx));
        }

        logging(LOG_VERBOSE, "Send an ABORT TASK SET");
        ret = iscsi_task_mgmt_abort_task_set_sync(sd->iscsi_ctx, sd->iscsi_lun);
        if (ret != 0) {
                logging(LOG_NORMAL, "ABORT TASK SET failed. %s",
                        iscsi_get_error(sd->iscsi_ctx));
        }

        logging(LOG_VERBOSE, "Send a LUN Reset");
        ret = iscsi_task_mgmt_lun_reset_sync(sd->iscsi_ctx, sd->iscsi_lun);
        if (ret != 0) {
                logging(LOG_NORMAL, "LUN reset failed. %s", iscsi_get_error(sd->iscsi_ctx));
        }

        logging(LOG_VERBOSE, "Send a Warm Reset");
        ret = iscsi_task_mgmt_target_warm_reset_sync(sd->iscsi_ctx);
        if (ret != 0) {
                logging(LOG_NORMAL, "Warm reset failed. %s", iscsi_get_error(sd->iscsi_ctx));
        }

        logging(LOG_VERBOSE, "Send a Cold Reset");
        ret = iscsi_task_mgmt_target_cold_reset_sync(sd->iscsi_ctx);
        if (ret != 0) {
                logging(LOG_NORMAL, "Cold reset failed. %s", iscsi_get_error(sd->iscsi_ctx));
        }

        logging(LOG_VERBOSE, "Disconnect from the target.");
        iscsi_destroy_context(sd->iscsi_ctx);

        logging(LOG_VERBOSE, "Sleep for one seconds incase the target is "
                "slow to reset");
        sleep(1);

        logging(LOG_VERBOSE, "Reconnect to target");
        sd->iscsi_ctx = iscsi_context_login(initiatorname1, sd->iscsi_url, &sd->iscsi_lun);
        if (sd->iscsi_ctx == NULL) {
                logging(LOG_VERBOSE, "Failed to login to target");
                return;
        }

        logging(LOG_VERBOSE, "Verify that the SANITIZE is still going.");
        TESTUNITREADY(sd,
                      EXPECT_SANITIZE);

        logging(LOG_VERBOSE, "Wait until the SANITIZE operation has finished");
        while (testunitready_clear_ua(sd)) {
                sleep(60);
        }
}
void
test_extendedcopy_validate_tgt_descr(void)
{
        int tgt_desc_len = 0, seg_desc_len = 0, offset = XCOPY_DESC_OFFSET;
        int ret;
        struct scsi_inquiry_standard *std_inq;
        struct iscsi_data data;
        unsigned char *xcopybuf;

        logging(LOG_VERBOSE, LOG_BLANK_LINE);
        logging(LOG_VERBOSE, "Test EXTENDED COPY target descriptor fields");

        CHECK_FOR_DATALOSS;

        ret = inquiry(sd, &task, 0, 0, 260,
                      EXPECT_STATUS_GOOD);
        CU_ASSERT_EQUAL(ret, 0);
        std_inq = scsi_datain_unmarshall(task);
        CU_ASSERT_NOT_EQUAL(std_inq, NULL);

        data.size = XCOPY_DESC_OFFSET +
                get_desc_len(IDENT_DESCR_TGT_DESCR) +
                get_desc_len(BLK_TO_BLK_SEG_DESCR);
        data.data = alloca(data.size);
        xcopybuf = data.data;
        memset(xcopybuf, 0, data.size);

        logging(LOG_VERBOSE, "Unsupported LU_ID TYPE");
        /* Unsupported LU ID TYPE */
        offset += populate_tgt_desc(xcopybuf+offset, IDENT_DESCR_TGT_DESCR,
                        LU_ID_TYPE_RSVD, 0, 0, 0, 0, sd);
        tgt_desc_len = offset - XCOPY_DESC_OFFSET;
        offset += populate_seg_desc_b2b(xcopybuf+offset, 0, 0, 0, 0,
                        2048, 0, num_blocks - 2048);
        seg_desc_len = offset - XCOPY_DESC_OFFSET - tgt_desc_len;
        populate_param_header(xcopybuf, 1, 0, 0, 0,
                        tgt_desc_len, seg_desc_len, 0);

        if (std_inq->version >= 6) {
                /* SPC-4 - LU ID should be ignored "*/
                EXTENDEDCOPY(sd, &data, EXPECT_STATUS_GOOD);
        } else {
                /* SPC-3 - LU ID is reserved */
                EXTENDEDCOPY(sd, &data, EXPECT_INVALID_FIELD_IN_CDB);
        }

        if (std_inq->version >= 6) {
                /* NUL bit is obsolete in SPC-4 */
                CU_PASS("[SKIPPED] Target is SPC-4+. Skipping NUL bit test");
                return;
        }
        logging(LOG_VERBOSE, "Test NUL bit in target descriptor");
        /* NUL bit */
        memset(xcopybuf, 0, data.size);
        offset = XCOPY_DESC_OFFSET;
        offset += populate_tgt_desc(xcopybuf+offset, IDENT_DESCR_TGT_DESCR,
                        LU_ID_TYPE_LUN, 1, 0, 0, 0, sd);
        tgt_desc_len = offset - XCOPY_DESC_OFFSET;
        offset += populate_seg_desc_b2b(xcopybuf+offset, 0, 0, 0, 0,
                        2048, 0, num_blocks - 2048);
        seg_desc_len = offset - XCOPY_DESC_OFFSET - tgt_desc_len;
        populate_param_header(xcopybuf, 1, 0, 0, 0,
                        tgt_desc_len, seg_desc_len, 0);

        EXTENDEDCOPY(sd, &data, EXPECT_COPY_ABORTED);
}
예제 #16
0
/* A worker thread receives a number and a 4-letter name via targ */
void * tmain(void * targ)
{
   /* Local variables are not shared with other threads */
   int no, i;
   char name[5];
   pthread_t tid;
   int isBooked[t];//Tells how many times train i has been booked by this thread.
   memset(isBooked, 0, sizeof(isBooked));
   int trainsBooked[t];//Tells which all trains have been booked by this thread
   int numTrainsBooked = 0;//Count of the number of trains booked by this thread
   
   /* Retrieve my number and name from the parameter passed */
   no = ((tinfo *)targ) -> tno;
   strcpy(name,((tinfo *)targ) -> tname);

   /* Retrieve my thread id */
   tid = pthread_self();

   while (1) {
      /* Check for termination condition */

      pthread_mutex_lock(&donemutex);

      /* if the master thread is done */
      if(mdone)
      {
         pthread_mutex_unlock(&donemutex);
         pthread_barrier_wait(&barrier);         
         pthread_exit(NULL);
      }
      /* The master thread is still sleeping, so I continue to work */
      pthread_mutex_unlock(&donemutex);


      //Check if number of active queries is less than MAX
      pthread_mutex_lock(&querymutex);
      if(numActiveQueries == MAX)
      {
         printf("\nThread %d : Blocked since active queries = MAX\n", no);
         pthread_cond_wait(&querycond, &querymutex);
      }      
      numActiveQueries++;
      pthread_mutex_unlock(&querymutex);        

      int a123;
      //Start query
      int queryType = 1 + rand()%3;
      if(queryType == INQUIRE)
      {
         inquiry(no);
      }
      else if(queryType == BOOK)
      {
         booking(no, isBooked, trainsBooked, &numTrainsBooked);
      }
      else
      {
         cancellation(no, isBooked, trainsBooked, &numTrainsBooked);
      }

      pthread_mutex_lock(&querymutex);
      numActiveQueries--;
      if(numActiveQueries == (MAX-1))//wake up a waiting query
         pthread_cond_signal(&querycond);
      pthread_mutex_unlock(&querymutex);
      
      sleep(SLEEPTIME);
   }
}
예제 #17
0
파일: readiso.c 프로젝트: tjko/readiso
int main(int argc, char **argv) 
{
  iso_primary_descriptor_type  ipd;
  char *dev = default_dev;
  char vendor[9],model[17],rev[5];
  unsigned char reply[1024];
  char tmpstr[255];
  int replylen=sizeof(reply);
  int trackno = 0;
  int info_only = 0;
  unsigned char *buffer;
  int buffersize = READBLOCKS*BLOCKSIZE;
  int start,stop,imagesize=0,tracksize=0;
  int counter = 0;
  long readsize = 0;
  long imagesize_bytes = 0;
  int drive_block_size, init_bsize;
  int force_mode = 0;
  int scanbus_mode = 0;
  int dump_start, dump_count;
  MD5_CTX *MD5; 
  char digest[16],digest_text[33];
  int md5_mode = 0;
  int opt_index = 0;
  int audio_track = 0;
  int readblocksize = BLOCKSIZE;
  int file_format = AF_FILE_AIFFC;
#ifdef IRIX
  CDPARSER *cdp = CDcreateparser();
  CDFRAME  cdframe;
#endif
  int dev_type;
  int i,c,o;
  int len;
  int start_time,cur_time,kbps;

  if (rcsid); 

  MD5 = malloc(sizeof(MD5_CTX));
  buffer=(unsigned char*)malloc(READBLOCKS*AUDIOBLOCKSIZE);
  if (!buffer || !MD5) die("No memory");

  if (argc<2) die("parameter(s) missing\n"
	          "Try '%s --help' for more information.\n",PRGNAME);

 
  /* parse command line parameters */
  while(1) {
    if ((c=getopt_long(argc,argv,"SMmvhid:",long_options,&opt_index))
	== -1) break;
    switch (c) {
    case 'a':
      file_format=AF_FILE_AIFF;
      break;
    case 'A':
      file_format=AF_FILE_AIFFC;
      break;
    case 'v':
      verbose_mode=1;
      break;
    case 'h':
      p_usage();
      break;
    case 'd':
      dev=strdup(optarg);
      break;
    case 't':
      if (sscanf(optarg,"%d",&trackno)!=1) trackno=0;
      break;
    case 'i':
      info_only=1; 
      break;
    case 'c':
      if (sscanf(optarg,"%d,%d",&dump_start,&dump_count)!=2)
	die("invalid parameters");
      dump_mode=1;
      break;
#ifdef IRIX
    case 'C':
      if (sscanf(optarg,"%d,%d",&dump_start,&dump_count)!=2)
	die("invalid parameters");
      dump_mode=2;
      break;
#endif
    case 'f':
      if (sscanf(optarg,"%d",&force_mode)!=1) die("invalid parameters");
      if (force_mode<1 || force_mode >2) {
	die("invalid parameters");
      }
      break;
    case 'm':
      md5_mode=1;
      break;
    case 'M':
      md5_mode=2;
      break;
    case 's':
      audio_mode=1;
      break;
    case 'S':
      scanbus_mode=1;
      break;
    case 'V':
      printf(PRGNAME " "  VERSION "  " HOST_TYPE
	     "\nCopyright (c) Timo Kokkonen, 1997-1998.\n\n"); 
      exit(0);
      break;

    case '?':
      break;

    default:
      die("error parsing parameters");

    }
  }


  if (!info_only) {
    if (md5_mode==2) outfile=fopen("/dev/null","w");
    else outfile=fopen(argv[optind],"w");
    if (!outfile) {
      if (argv[optind]) die("cannot open output file '%s'",argv[optind]);
      info_only=1;
    }
  }

  printf("readiso(9660) " VERSION "\n");

  /* open the scsi device */
  if (scsi_open(dev)) die("error opening scsi device '%s'",dev); 

  if (scanbus_mode) {
    printf("\n");
    scan_bus();
    exit(0);
  }
  
  memset(reply,0,sizeof(reply));
  if ((dev_type=inquiry(vendor,model,rev))<0) 
    die("error accessing scsi device");

  if (verbose_mode) {
    printf("device:   %s\n",dev);
    printf("Vendor:   %s\nModel:    %s\nRevision: %s\n",vendor,model,rev);
  }

  if ( (dev_type&0x1f) != 0x5 ) {
    die("Device doesn't seem to be a CD-ROM!");
  }

#ifdef IRIX
  if (strcmp(vendor,"TOSHIBA")) {
    warn("NOTE! Audio track reading probably not supported on this device.\n");
  }
#endif

  test_ready();
  if (test_ready()!=0) {
    sleep(2);
    if (test_ready()!=0)  die("device not ready");
  }

  fprintf(stderr,"Initializing...\n");
  if (audio_mode) {
#ifdef IRIX
    audioport=ALopenport("readiso","w",0);
    if (!audioport) {
      warn("Cannot initialize audio.");
      audio_mode=0;
    }
#else
    audio_mode=0;
#endif
  }


#ifdef IRIX
  /* Make sure we get sane underflow exception handling */
  sigfpe_[_UNDERFL].repls = _ZERO;
  handle_sigfpes(_ON, _EN_UNDERFL, NULL, _ABORT_ON_ERROR, NULL);
#endif

  /* set_removable(1); */

#if 0
  replylen=255;
  if (mode_sense10(reply,&replylen)==0) {
    printf("replylen=%d blocks=%d blocklen=%d\n",replylen,
	   V3(&reply[8+1]),V3(&reply[8+5]));
    PRINT_BUF(reply,replylen);
  }
  replylen=255; /* sizeof(reply); */
  if (mode_sense(reply,&replylen)==0) {
    printf("replylen=%d blocks=%d blocklen=%d\n",replylen,
	   V3(&reply[4+1]),V3(&reply[4+5]));
    PRINT_BUF(reply,replylen);
  }
#endif

  if (dump_mode==2) init_bsize=AUDIOBLOCKSIZE;
  else init_bsize=BLOCKSIZE;

  start_stop(0);

  if ( (drive_block_size=get_block_size()) < 0 ) {
    warn("cannot get current block size");
    drive_block_size=init_bsize;
  }

  if (drive_block_size != init_bsize) {
    mode_select(init_bsize,(dump_mode==2?0x82:0x00));
    drive_block_size=get_block_size();
    if (drive_block_size!=init_bsize) warn("cannot set drive block size.");
  }

  start_stop(1);

  if (dump_mode && !info_only) {
#ifdef IRIX
    CDFRAME buf;
    if (dump_mode==2) {
      if (cdp) {
	CDaddcallback(cdp, cd_audio, (CDCALLBACKFUNC)playaudio, 0);
      } else die("No audioparser");
    }
#endif
    fprintf(stderr,"Dumping %d sector(s) starting from LBA=%d\n",
	    dump_count,dump_start);
    for (i=dump_start;i<dump_start+dump_count;i++) {
      len=buffersize;
      read_10(i,1,buffer,&len);
      if (len<init_bsize) break;

#ifdef IRIX
      if (dump_mode==2) {
	memcpy(&buf,buffer,CDDA_BLOCKSIZE);
	CDparseframe(cdp,&buf);
      }
#endif
	
      fwrite(buffer,len,1,outfile); 
      fprintf(stderr,".");
    }
    fprintf(stderr,"\ndone.\n");
    
    goto quit;
  }


  fprintf(stderr,"Reading disc TOC...");
  replylen=sizeof(reply);
  read_toc(reply,&replylen,verbose_mode);
  printf("\n");

  if (trackno==0) { /* try to find first data track */
    for (i=0;i<(reply[3]-reply[2]+1);i++) {
      o=4+i*8;
      if (reply[o+1]&DATA_TRACK) { trackno=i+1; break; }
    }
    if (trackno==0) die("No data track(s) found.");
  }

  fprintf(stderr,"Reading track %d...\n",trackno); 

  if ( (trackno < reply[2]) || (trackno > reply[3]) )
    die("Invalid track specified.");
    
  if ( ((reply[(trackno-1)*8+4+1]&DATA_TRACK)==0) ) {
    fprintf(stderr,"Not a data track.\n");
    mode_select(AUDIOBLOCKSIZE,0x82);
    if (mode_sense(reply,&replylen)!=0) die("cannot get sense data");
    drive_block_size=V3(&reply[9]);
    fprintf(stderr,"Selecting CD-DA mode, output file format: %s\n",
	    file_format==AF_FILE_AIFFC?"AIFFC":"AIFF");
    audio_track=1;
  } else {
    audio_track=0;
  }


  start=V4(&reply[(trackno-1)*8+4+4]);
  stop=V4(&reply[(trackno)*8+4+4]);
  tracksize=abs(stop-start);
  /* if (verbose_mode) printf("Start LBA=%d\nStop  LBA=%d\n",start,stop); */

  len=buffersize;
  read_10(start-0,1,buffer,&len);
  /* PRINT_BUF(buffer,32); */

  
  if (!audio_track) {
    /* read the iso9660 primary descriptor */
    fprintf(stderr,"Reading ISO9660 primary descriptor...\n");
    len=buffersize;
    read_10(start+16,1,buffer,&len);
    if (len<sizeof(ipd)) die("cannot read iso9660 primary descriptor.");
    memcpy(&ipd,buffer,sizeof(ipd));
    
    imagesize=ISONUM(ipd.volume_space_size);
    
    /* we should really check here if we really got a valid primary 
       descriptor or not... */
    if ( (imagesize>(stop-start)) || (imagesize<1) ) {
      fprintf(stderr,"\aInvalid ISO primary descriptor!!!\n");
      if (!info_only) fprintf(stderr,"Copying entire track to image file.\n");
      force_mode=2;
    }
    
    if (force_mode==1) {} /* use size from ISO primary descriptor */
    else if (force_mode==2) imagesize=tracksize; /* use size from TOC */
    else {
      if (  ( (tracksize-imagesize) > MAX_DIFF_ALLOWED ) || 
	    ( imagesize > tracksize )  )   {
	fprintf(stderr,"ISO primary descriptor has suspicious volume size"
		" (%d blocks)\n",imagesize);
	imagesize=tracksize;
	fprintf(stderr,
		"Using track size from TOC record (%d blocks) instead.\n", 
		imagesize);
	fprintf(stderr,
		"(option -f can be used to override this behaviour.)\n");
      }
    }

    imagesize_bytes=imagesize*BLOCKSIZE;
    

    if (verbose_mode||info_only) {
      printf("ISO9660 image info:\n");
      printf("Type:              %02xh\n",ipd.type[0]);  
      ISOGETSTR(tmpstr,ipd.id,5);
      printf("ID:                %s\n",tmpstr);
      printf("Version:           %u\n",ipd.version[0]);
      ISOGETSTR(tmpstr,ipd.system_id,32);
      printf("System id:         %s\n",tmpstr);
      ISOGETSTR(tmpstr,ipd.volume_id,32);
      printf("Volume id:         %s\n",tmpstr);
      ISOGETSTR(tmpstr,ipd.volume_set_id,128);
      if (strlen(tmpstr)>0) printf("Volume set id:     %s\n",tmpstr);
      ISOGETSTR(tmpstr,ipd.publisher_id,128);
      if (strlen(tmpstr)>0) printf("Publisher id:      %s\n",tmpstr);
      ISOGETSTR(tmpstr,ipd.preparer_id,128);
      if (strlen(tmpstr)>0) printf("Preparer id:       %s\n",tmpstr);
      ISOGETSTR(tmpstr,ipd.application_id,128);
      if (strlen(tmpstr)>0) printf("Application id:    %s\n",tmpstr);
      ISOGETDATE(tmpstr,ipd.creation_date);
      printf("Creation date:     %s\n",tmpstr);
      ISOGETDATE(tmpstr,ipd.modification_date);
      if (!NULLISODATE(ipd.modification_date)) 
	printf("Modification date: %s\n",tmpstr);
      ISOGETDATE(tmpstr,ipd.expiration_date);
      if (!NULLISODATE(ipd.expiration_date))
	printf("Expiration date:   %s\n",tmpstr);
      ISOGETDATE(tmpstr,ipd.effective_date);
      if (!NULLISODATE(ipd.effective_date))
	printf("Effective date:    %s\n",tmpstr);
      
      printf("Image size:        %02d:%02d:%02d, %d blocks (%ld bytes)\n",
	      LBA_MIN(ISONUM(ipd.volume_space_size)),
	      LBA_SEC(ISONUM(ipd.volume_space_size)),
	      LBA_FRM(ISONUM(ipd.volume_space_size)),
	      ISONUM(ipd.volume_space_size),
	      (long)ISONUM(ipd.volume_space_size)*BLOCKSIZE
	     );
      printf("Track size:        %02d:%02d:%02d, %d blocks (%ld bytes)\n",
	      LBA_MIN(tracksize),
	      LBA_SEC(tracksize),
	      LBA_FRM(tracksize),
	      tracksize,
	      (long)tracksize*BLOCKSIZE
	     );
    }
  } else { 
#ifdef IRIX
    /* if reading audio track */
    imagesize=tracksize;
    imagesize_bytes=imagesize*CDDA_DATASIZE;
    buffersize = READBLOCKS*AUDIOBLOCKSIZE;
    readblocksize = AUDIOBLOCKSIZE;

    if (cdp) {
      CDaddcallback(cdp, cd_audio, (CDCALLBACKFUNC)playaudio, 0);
    } else die("No audioparser");
    
    fclose(outfile);
    aiffsetup=AFnewfilesetup();
    AFinitrate(aiffsetup,AF_DEFAULT_TRACK,44100.0); /* 44.1 kHz */
    AFinitfilefmt(aiffsetup,file_format);           /* set file format */
    AFinitchannels(aiffsetup,AF_DEFAULT_TRACK,2);   /* stereo */
    AFinitsampfmt(aiffsetup,AF_DEFAULT_TRACK,
		  AF_SAMPFMT_TWOSCOMP,16);          /* 16bit */
    aiffoutfile=AFopenfile(argv[optind],"w",aiffsetup);
    if (!aiffoutfile) die("Cannot open target file (%s).",argv[optind]);
#endif
  }

  /* read the image */

  if (md5_mode) MD5Init(MD5);

  if (!info_only) {
    start_time=(int)time(NULL);
    fprintf(stderr,"Reading %s (%ldMb)...\n",
	    audio_track?"audio track":"ISO9660 image",
	    imagesize_bytes/(1024*1024));

    do {
      len=buffersize;
      if(readsize/readblocksize+READBLOCKS>imagesize) {
	read_10(start+counter,imagesize-readsize/readblocksize,buffer,&len);
      }
      else
	read_10(start+counter,READBLOCKS,buffer,&len);
      if ((counter%(1024*1024/readblocksize))<READBLOCKS) {
	cur_time=(int)time(NULL);
	if ((cur_time-start_time)>0) {
	  kbps=(readsize/1024)/(cur_time-start_time);
	} else {
	  kbps=0;
	}
	
	fprintf(stderr,"%3dM of %dM read. (%d kb/s)         \r",
		counter/512,imagesize/512,kbps);
      }
      counter+=READBLOCKS;
      readsize+=len;
      if (!audio_track) {
	fwrite(buffer,len,1,outfile);
      } else {
#ifdef IRIX
	/* audio track */
	for(i=0;i<(len/CDDA_BLOCKSIZE);i++) {
	  CDparseframe(cdp,(CDFRAME*)&buffer[i*CDDA_BLOCKSIZE]);
	}
#endif
      }
      if (md5_mode) MD5Update(MD5,buffer,(readsize>imagesize_bytes?
				       len-(readsize-imagesize_bytes):len) );
    } while (len==readblocksize*READBLOCKS&&readsize<imagesize*readblocksize);
    
    fprintf(stderr,"\n");
    if (!audio_track) {
      if (readsize > imagesize_bytes) 
	ftruncate(fileno(outfile),imagesize_bytes);
      if (readsize < imagesize_bytes) 
	fprintf(stderr,"Image not complete!\n");
      else fprintf(stderr,"Image complete.\n");
      fclose(outfile);
    } else {
#ifdef IRIX
      AFclosefile(aiffoutfile);
#endif
    }
  }

  if (md5_mode && !info_only) {
    MD5Final((unsigned char*)digest,MD5);
    md2str((unsigned char*)digest,digest_text);
    fprintf(stderr,"MD5 (%s) = %s\n",(md5_mode==2?"'image'":argv[optind]),
	    digest_text);
  }

 quit:
  start_stop(0);
  /* set_removable(1); */

  /* close the scsi device */
  scsi_close();

  return 0;
}
예제 #18
0
int
main(int argc, char *argv[])
{
	char *testname_re = NULL;
	CU_BasicRunMode mode = CU_BRM_VERBOSE;
	CU_ErrorAction error_action = CUEA_IGNORE;
	int res;
	struct scsi_readcapacity10 *rc10;
	struct scsi_task *inq_task = NULL;
	struct scsi_task *inq_lbp_task = NULL;
	struct scsi_task *inq_bdc_task = NULL;
	struct scsi_task *inq_bl_task = NULL;
	struct scsi_task *rc16_task = NULL;
	struct scsi_task *rsop_task = NULL;
	int full_size;
	int xml_mode = 0;
	static struct option long_opts[] = {
		{ "help", no_argument, 0, '?' },
		{ "list", no_argument, 0, 'l' },
		{ "initiator-name", required_argument, 0, 'i' },
		{ "initiator-name-2", required_argument, 0, 'I' },
		{ "test", required_argument, 0, 't' },
		{ "dataloss", no_argument, 0, 'd' },
		{ "allow-sanitize", no_argument, 0, 'S' },
		{ "ignore", no_argument, 0, 'g' },
		{ "fail", no_argument, 0, 'f' },
		{ "abort", no_argument, 0, 'A' },
		{ "silent", no_argument, 0, 's' },
		{ "normal", no_argument, 0, 'n' },
		{ "verbose", no_argument, 0, 'v' },
		{ "xml", no_argument, 0, 'x' },
		{ "Verbose-scsi", no_argument, 0, 'V' },
		{ NULL, 0, 0, 0 }
	};
	int i, c;
	int opt_idx = 0;

	while ((c = getopt_long(argc, argv, "?hli:I:t:sdgfAsSnvxV", long_opts,
		    &opt_idx)) > 0) {
		switch (c) {
		case 'h':
		case '?':
			print_usage();
			return 0;
		case 'l':
			list_all_tests();
			return 0;
		case 'i':
			initiatorname1 = strdup(optarg);
			break;
		case 'I':
			initiatorname2 = strdup(optarg);
			break;
		case 't':
			testname_re = strdup(optarg);
			break;
		case 'd':
			data_loss++;
			break;
		case 'g':
			error_action = CUEA_IGNORE; /* default */
			break;
		case 'f':
			error_action = CUEA_FAIL;
			break;
		case 'A':
			error_action = CUEA_ABORT;
			break;
		case 's':
			mode = CU_BRM_SILENT;
			break;
		case 'S':
			allow_sanitize = 1;
			break;
		case 'n':
			mode = CU_BRM_NORMAL;
			break;
		case 'v':
			mode = CU_BRM_VERBOSE;	/* default */
			break;
		case 'x':
		        xml_mode = 1;
			break;
		case 'V':
			loglevel = LOG_VERBOSE;
			break;
		default:
			fprintf(stderr,
			    "error: unknown option return: %c (option %s)\n",
			    c, argv[optind]);
			return 1;
		}
	}

	/* parse all trailing arguments as device paths */
	mp_num_sds = 0;
	while (optind < argc) {
		if (mp_num_sds >= MPATH_MAX_DEVS) {
			fprintf(stderr, "Too many multipath device URLs\n");
			print_usage();
			free(testname_re);
			return 10;
		}

		mp_sds[mp_num_sds] = malloc(sizeof(struct scsi_device));
		memset(mp_sds[mp_num_sds], '\0', sizeof(struct scsi_device));
		mp_sds[mp_num_sds]->sgio_fd = -1;

		if (!strncmp(argv[optind], "iscsi://", 8)) {
			mp_sds[mp_num_sds]->iscsi_url = strdup(argv[optind++]);
#ifdef HAVE_SG_IO
		} else {
			mp_sds[mp_num_sds]->sgio_dev = strdup(argv[optind++]);
#endif
		}
		mp_num_sds++;
	}

	/* So that we can override iscsi_queue_pdu in tests
	 * and replace or mutate the blob that we are about to write to the
	 * wire.
	 * This allows such tests to do their mutates and then call out
	 * to the real queueing function once they have modified the data.
	 */
	real_iscsi_queue_pdu = dlsym(RTLD_NEXT, "iscsi_queue_pdu");

	if ((mp_num_sds == 0) || (mp_sds[0]->iscsi_url == NULL
					&& mp_sds[0]->sgio_dev == NULL)) {
#ifdef HAVE_SG_IO
		fprintf(stderr, "You must specify either an iSCSI URL or a device file\n");
#else
		fprintf(stderr, "You must specify an iSCSI URL\n");
#endif
		print_usage();
		if (testname_re)
			free(testname_re);
		return 10;
	}

	/* sd remains an alias for the first device */
	sd = mp_sds[0];

	for (i = 0; i < mp_num_sds; i++) {
		res = connect_scsi_device(mp_sds[i], initiatorname1);
		if (res < 0) {
			fprintf(stderr,
				"Failed to connect to SCSI device %d\n", i);
			goto err_sds_free;
		}
	}

	if (mp_num_sds > 1) {
		/* check that all multipath sds identify as the same LU */
		res = mpath_check_matching_ids(mp_num_sds, mp_sds);
		if (res < 0) {
			fprintf(stderr, "multipath devices don't match\n");
			goto err_sds_free;
		}
	}

	/*
	 * find the size of the LUN
	 * All devices support readcapacity10 but only some support
	 * readcapacity16
	 */
	task = NULL;
	readcapacity10(sd, &task, 0, 0, EXPECT_STATUS_GOOD);
	if (task == NULL) {
		printf("Failed to send READCAPACITY10 command: %s\n", sd->error_str);
		goto err_sds_free;
	}
	if (task->status != SCSI_STATUS_GOOD) {
		printf("READCAPACITY10 command: failed with sense. %s\n", sd->error_str);
		scsi_free_scsi_task(task);
		goto err_sds_free;
	}
	rc10 = scsi_datain_unmarshall(task);
	if (rc10 == NULL) {
		printf("failed to unmarshall READCAPACITY10 data.\n");
		scsi_free_scsi_task(task);
		goto err_sds_free;
	}
	block_size = rc10->block_size;
	num_blocks = rc10->lba + 1;
	scsi_free_scsi_task(task);

	rc16_task = NULL;
	readcapacity16(sd, &rc16_task, 96, EXPECT_STATUS_GOOD);
	if (rc16_task == NULL) {
		printf("Failed to send READCAPACITY16 command: %s\n", sd->error_str);
		goto err_sds_free;
	}
	if (rc16_task->status == SCSI_STATUS_GOOD) {
		rc16 = scsi_datain_unmarshall(rc16_task);
		if (rc16 == NULL) {
			printf("failed to unmarshall READCAPACITY16 data. %s\n", sd->error_str);
			scsi_free_scsi_task(rc16_task);
			goto err_sds_free;
		}
		block_size = rc16->block_length;
		num_blocks = rc16->returned_lba + 1;
		lbppb = 1 << rc16->lbppbe;
	}

	inq_task = NULL;
	inquiry(sd, &inq_task, 0, 0, 64, EXPECT_STATUS_GOOD);
	if (inq_task == NULL || inq_task->status != SCSI_STATUS_GOOD) {
		printf("Inquiry command failed : %s\n", sd->error_str);
		goto err_sds_free;
	}
	full_size = scsi_datain_getfullsize(inq_task);
	if (full_size > inq_task->datain.size) {
		scsi_free_scsi_task(inq_task);

		/* we need more data for the full list */
		inq_task = NULL;
		inquiry(sd, &inq_task, 0, 0, full_size, EXPECT_STATUS_GOOD);
		if (inq_task == NULL) {
			printf("Inquiry command failed : %s\n", sd->error_str);
			goto err_sds_free;
		}
	}
	inq = scsi_datain_unmarshall(inq_task);
	if (inq == NULL) {
		printf("failed to unmarshall inquiry datain blob\n");
		scsi_free_scsi_task(inq_task);
		goto err_sds_free;
	}

	sbc3_support = 0;
	for (i = 0; i < 8; i++) {
		if (inq->version_descriptor[i] == 0x04C0) {
			sbc3_support = 1;
		}
	}

	/* try reading block limits vpd */
	inq_bl_task = NULL;
	inquiry(sd, &inq_bl_task, 1, SCSI_INQUIRY_PAGECODE_BLOCK_LIMITS, 64, EXPECT_STATUS_GOOD);
	if (inq_bl_task && inq_bl_task->status != SCSI_STATUS_GOOD) {
		scsi_free_scsi_task(inq_bl_task);
		inq_bl_task = NULL;
	}
	if (inq_bl_task) {
		full_size = scsi_datain_getfullsize(inq_bl_task);
		if (full_size > inq_bl_task->datain.size) {
			scsi_free_scsi_task(inq_bl_task);

			inq_bl_task = NULL;
			inquiry(sd, &inq_bl_task, 1, SCSI_INQUIRY_PAGECODE_BLOCK_LIMITS, full_size,
				EXPECT_STATUS_GOOD);
			if (inq_bl_task == NULL) {
				printf("Inquiry command failed : %s\n", sd->error_str);
				goto err_sds_free;
			}
		}

		inq_bl = scsi_datain_unmarshall(inq_bl_task);
		if (inq_bl == NULL) {
			printf("failed to unmarshall inquiry datain blob\n");
			goto err_sds_free;
		}
	}

	/* try reading block device characteristics vpd */
	inquiry(sd, &inq_bdc_task, 1, SCSI_INQUIRY_PAGECODE_BLOCK_DEVICE_CHARACTERISTICS, 255,
		EXPECT_STATUS_GOOD);
	if (inq_bdc_task == NULL || inq_bdc_task->status != SCSI_STATUS_GOOD) {
		printf("Failed to read Block Device Characteristics page\n");
	} else {
		inq_bdc = scsi_datain_unmarshall(inq_bdc_task);
		if (inq_bdc == NULL) {
			printf("failed to unmarshall inquiry datain blob\n");
			goto err_sds_free;
		}
	}

	/* if thin provisioned we also need to read the VPD page for it */
	if (rc16 && rc16->lbpme != 0){
		inq_lbp_task = NULL;
		inquiry(sd, &inq_lbp_task, 1, SCSI_INQUIRY_PAGECODE_LOGICAL_BLOCK_PROVISIONING, 64,
			EXPECT_STATUS_GOOD);
		if (inq_lbp_task == NULL || inq_lbp_task->status != SCSI_STATUS_GOOD) {
			printf("Inquiry command failed : %s\n", sd->error_str);
			goto err_sds_free;
		}
		full_size = scsi_datain_getfullsize(inq_lbp_task);
		if (full_size > inq_lbp_task->datain.size) {
			scsi_free_scsi_task(inq_lbp_task);

			/* we need more data for the full list */
			inq_lbp_task = NULL;
			inquiry(sd, &inq_lbp_task, 1, SCSI_INQUIRY_PAGECODE_LOGICAL_BLOCK_PROVISIONING,
				full_size, EXPECT_STATUS_GOOD);
			if (inq_lbp_task == NULL) {
				printf("Inquiry command failed : %s\n", sd->error_str);
				goto err_sds_free;
			}
		}

		inq_lbp = scsi_datain_unmarshall(inq_lbp_task);
		if (inq_lbp == NULL) {
			printf("failed to unmarshall inquiry datain blob\n");
			goto err_sds_free;
		}
	}

	rsop_task = NULL;
	report_supported_opcodes(sd, &rsop_task, 1, SCSI_REPORT_SUPPORTING_OPS_ALL, 0, 0, 65535,
				 EXPECT_STATUS_GOOD);
	if (rsop_task == NULL) {
		printf("Failed to send REPORT_SUPPORTED_OPCODES command: %s\n", sd->error_str);
		goto err_sds_free;
	}
	if (rsop_task->status == SCSI_STATUS_GOOD) {
		rsop = scsi_datain_unmarshall(rsop_task);
		if (rsop == NULL) {
			printf("failed to unmarshall REPORT_SUPPORTED_OPCODES data.\n");
			scsi_free_scsi_task(rsop_task);
			rsop_task = NULL;
		}
	}

	/* check if the device is write protected or not */
	task = NULL;
	modesense6(sd, &task, 0, SCSI_MODESENSE_PC_CURRENT, SCSI_MODEPAGE_RETURN_ALL_PAGES, 0, 255,
		   EXPECT_STATUS_GOOD);
	if (task == NULL) {
		printf("Failed to send MODE_SENSE6 command: %s\n", sd->error_str);
		goto err_sds_free;
	}
	if (task->status == SCSI_STATUS_GOOD) {
		struct scsi_mode_sense *ms;

		ms = scsi_datain_unmarshall(task);
		if (ms == NULL) {
			printf("failed to unmarshall mode sense datain blob\n");
			scsi_free_scsi_task(task);
			goto err_sds_free;
		}
		readonly = !!(ms->device_specific_parameter & 0x80);
	}
	scsi_free_scsi_task(task);

	if (maxsectbytes) {
		maximum_transfer_length = maxsectbytes / block_size;
		printf("Bus transfer size is limited to %d bytes. Clamping "
		       "max transfers accordingly.\n", maxsectbytes);
	}

	if (CU_initialize_registry() != 0) {
		fprintf(stderr, "error: unable to initialize test registry\n");
		goto err_sds_free;
	}
	if (CU_is_test_running()) {
		fprintf(stderr, "error: test suite(s) already running!?\n");
		exit(1);
	}

	parse_and_add_tests(testname_re);
	if (testname_re)
		free(testname_re);

	CU_basic_set_mode(mode);
	CU_set_error_action(error_action);
	printf("\n");

	/*
	 * this actually runs the tests ...
	 */

	if (xml_mode) {
	  CU_list_tests_to_file();
	  CU_automated_run_tests();
	} else {
	  res = CU_basic_run_tests();
	  printf("Tests completed with return value: %d\n", res);
	}

	CU_cleanup_registry();

	if (inq_task != NULL) {
		scsi_free_scsi_task(inq_task);
	}
	if (inq_bl_task != NULL) {
		scsi_free_scsi_task(inq_bl_task);
	}
	if (inq_lbp_task != NULL) {
		scsi_free_scsi_task(inq_lbp_task);
	}
	if (inq_bdc_task != NULL) {
		scsi_free_scsi_task(inq_bdc_task);
	}
	if (rc16_task != NULL) {
		scsi_free_scsi_task(rc16_task);
	}
	if (rsop_task != NULL) {
		scsi_free_scsi_task(rsop_task);
	}
	for (i = 0; i < mp_num_sds; i++) {
		free_scsi_device(mp_sds[i]);
	}

	return 0;

err_sds_free:
	for (i = 0; i < mp_num_sds; i++) {
		free_scsi_device(mp_sds[i]);
	}
	return -1;
}
예제 #19
0
void
test_writeatomic16_vpd(void)
{
	int ret;
	struct scsi_inquiry_block_limits *bl;
	struct scsi_task *bl_task = NULL;
	int gran;
	unsigned char *buf;

	logging(LOG_VERBOSE, LOG_BLANK_LINE);
	logging(LOG_VERBOSE, "Test WRITEATOMIC16 VPD data");

	CHECK_FOR_SBC;
	CHECK_FOR_DATALOSS;


	logging(LOG_VERBOSE, "Block device. Verify that we can read Block "
		"Limits VPD");
	ret = inquiry(sd, &bl_task,
		      1, SCSI_INQUIRY_PAGECODE_BLOCK_LIMITS, 255,
		      EXPECT_STATUS_GOOD);
	CU_ASSERT_EQUAL(ret, 0);
	if (ret != 0) {
		logging(LOG_NORMAL, "[FAILURE] failed to read Block Limits VDP");
		CU_FAIL("[FAILURE] failed to read Block Limits VDP");
		goto finished;
	}
	bl = scsi_datain_unmarshall(bl_task);
	if (bl == NULL) {
		logging(LOG_NORMAL, "[FAILURE] failed to unmarshall Block Limits VDP");
		CU_FAIL("[FAILURE] failed to unmarshall Block Limits VDP");
		goto finished;
	}


	logging(LOG_VERBOSE, "Check if WRITEATOMIC16 is supported");
	gran = inq_bl->atomic_gran ? inq_bl->atomic_gran : 1;
	buf = alloca(block_size * gran);
	memset(buf, 0x00, block_size * gran);
	ret = writeatomic16(sd, 0, block_size * gran,
			    block_size, 0, 0, 0, 0, buf,
			    EXPECT_STATUS_GOOD);
	if (ret == -2) {
		logging(LOG_VERBOSE, "WRITEATOMIC16 is NOT supported by the target.");

		logging(LOG_VERBOSE, "Verify that MAXIMUM_ATOMIC_TRANSFER_LENGTH is zero");
		if (bl->max_atomic_xfer_len) {
			logging(LOG_VERBOSE, "MAXIMUM_ATOMIC_TRANSFER_LENGTH is non-zero but target does not support ATOMICWRITE16");
			CU_FAIL("MAXIMUM_ATOMIC_TRANSFER_LENGTH is non-zero but target does not support ATOMICWRITE16");
		}

		logging(LOG_VERBOSE, "Verify that ATOMIC_ALIGNMENT is zero");
		if (bl->atomic_align) {
			logging(LOG_VERBOSE, "ATOMIC_ALIGNMENT is non-zero but target does not support ATOMICWRITE16");
			CU_FAIL("ATOMIC_ALIGNMENT is non-zero but target does not support ATOMICWRITE16");
		}

		logging(LOG_VERBOSE, "Verify that ATOMIC_GRANULARITY is zero");
		if (bl->atomic_gran) {
			logging(LOG_VERBOSE, "ATOMIC_GRANULARITY is non-zero but target does not support ATOMICWRITE16");
			CU_FAIL("ATOMIC_GRANULARITY is non-zero but target does not support ATOMICWRITE16");
		}
		goto finished;
	}

	logging(LOG_VERBOSE, "WRITEATOMIC16 IS supported by the target.");
	logging(LOG_VERBOSE, "Verify that MAXIMUM_ATOMIC_TRANSFER_LENGTH is non-zero");
	if (!bl->max_atomic_xfer_len) {
		logging(LOG_VERBOSE, "[WARNING] MAXIMUM_ATOMIC_TRANSFER_LENGTH is zero but target supports ATOMICWRITE16");
		CU_FAIL("[WARNING] MAXIMUM_ATOMIC_TRANSFER_LENGTH is zero but target supports ATOMICWRITE16");
	}

	logging(LOG_VERBOSE, "Verify that MAXIMUM_ATOMIC_TRANSFER_LENGTH is less than or equal to MAXIMUM_TRANSFER_LENGTH");
	if (bl->max_atomic_xfer_len > bl->max_xfer_len) {
		logging(LOG_VERBOSE, "[FAILED] MAXIMUM_ATOMIC_TRANSFER_LENGTH is greater than MAXIMUM_TRANSFER_LENGTH");
		CU_FAIL("[FAILED] MAXIMUM_ATOMIC_TRANSFER_LENGTH is greater than MAXIMUM_TRANSFER_LENGTH");
	}

	logging(LOG_VERBOSE, "Check handling on misaligned writes");
	if (bl->atomic_align < 2) {
		logging(LOG_VERBOSE, "[SKIPPED] No alignment restrictions on this LUN");
	} else {
		logging(LOG_VERBOSE, "Atomic Write at LBA 1 should fail due to misalignment");
		ret = writeatomic16(sd, 1, block_size * gran,
				    block_size, 0, 0, 0, 0, buf,
				    EXPECT_INVALID_FIELD_IN_CDB);
		if (ret) {
			logging(LOG_VERBOSE, "[FAILED] Misaligned write did NOT fail with INVALID_FIELD_IN_CDB");
		CU_FAIL("[FAILED] Misaligned write did NOT fail with INVALID_FIELD_IN_CDB");
		}
	}

	logging(LOG_VERBOSE, "Check handling on invalid granularity");
	if (bl->atomic_gran < 2) {
		logging(LOG_VERBOSE, "[SKIPPED] No granularity restrictions on this LUN");
	} else {
		logging(LOG_VERBOSE, "Atomic Write of 1 block should fail due to invalid granularity");
		ret = writeatomic16(sd, 0, block_size,
				    block_size, 0, 0, 0, 0, buf,
				    EXPECT_INVALID_FIELD_IN_CDB);
		if (ret) {
			logging(LOG_VERBOSE, "[FAILED] Misgranularity write did NOT fail with INVALID_FIELD_IN_CDB");
		CU_FAIL("[FAILED] Misgranularity write did NOT fail with INVALID_FIELD_IN_CDB");
		}
	}


finished:
	scsi_free_scsi_task(bl_task);
}
예제 #20
0
파일: kvs40xx.c 프로젝트: DspaceSPI/SPIScan
/* Open device, return the device handle */
SANE_Status
sane_open (SANE_String_Const devname, SANE_Handle * handle)
{
  unsigned i, j, id = 0;
  struct scanner *s;
  SANE_Int h, bus;
  SANE_Status st = SANE_STATUS_GOOD;
  if (!devlist)
    {
      st = sane_get_devices (NULL, 0);
      if (st)
	return st;
    }
  for (i = 0; devlist[i]; i++)
    {
      if (!strcmp (devlist[i]->name, devname))
	break;
    }
  if (!devlist[i])
    return SANE_STATUS_INVAL;
  for (j = 0; j < sizeof (known_devices) / sizeof (known_devices[0]); j++)
    {
      if (!strcmp (devlist[i]->model, known_devices[j].scanner.model))
	{
	  id = known_devices[j].id;
	  break;
	}
    }

  st = sanei_usb_open (devname, &h);

  if (st == SANE_STATUS_ACCESS_DENIED)
    return st;
  if (st)
    {
      st = sanei_scsi_open (devname, &h, kvs40xx_sense_handler, NULL);
      if (st)
	{
	  return st;
	}
      bus = SCSI;
    }
  else
    {
      bus = USB;
      st = sanei_usb_claim_interface (h, 0);
      if (st)
	{
	  sanei_usb_close (h);
	  return st;
	}
    }

  s = malloc (sizeof (struct scanner));
  if (!s)
    return SANE_STATUS_NO_MEM;
  memset (s, 0, sizeof (struct scanner));
  s->buffer = malloc (MAX_READ_DATA_SIZE + BULK_HEADER_SIZE);
  if (!s->buffer)
    return SANE_STATUS_NO_MEM;

  s->file = h;
  s->bus = bus;
  s->id = id;
  strcpy (s->name, devname);
  *handle = s;
  for (i = 0; i < 3; i++)
    {
      st = kvs40xx_test_unit_ready (s);
      if (st)
	{
	  if (s->bus == SCSI)
	    {
	      sanei_scsi_close (s->file);
	      st = sanei_scsi_open (devname, &h, kvs40xx_sense_handler, NULL);
	      if (st)
		return st;
	    }
	  else
	    {
	      sanei_usb_release_interface (s->file, 0);
	      sanei_usb_close (s->file);
	      st = sanei_usb_open (devname, &h);
	      if (st)
		return st;
	      st = sanei_usb_claim_interface (h, 0);
	      if (st)
		{
		  sanei_usb_close (h);
		  return st;
		}
	    }
	  s->file = h;
	}
      else
	break;
    }
  if (i == 3)
    return SANE_STATUS_DEVICE_BUSY;

  if (id == KV_S4085C || id == KV_S4065C)
    {
      char str[16];
      st = inquiry (s, str);
      if (st)
	goto err;
      if (id == KV_S4085C)
	s->id = !strcmp (str, "KV-S4085CL") ? KV_S4085CL : KV_S4085CW;
      else
	s->id = !strcmp (str, "KV-S4065CL") ? KV_S4065CL : KV_S4065CW;
    }
  kvs40xx_init_options (s);
  st = kvs40xx_set_timeout (s, s->val[FEED_TIMEOUT].w);
  if (st)
    goto err;

  return SANE_STATUS_GOOD;
err:
  sane_close (s);
  return st;
}
예제 #21
0
void
test_inquiry_block_limits(void)
{
	int ret;
	struct scsi_inquiry_block_limits *bl;
	struct scsi_task *bl_task = NULL;
	struct scsi_inquiry_logical_block_provisioning *lbp = NULL;
	struct scsi_task *lbp_task = NULL;

	logging(LOG_VERBOSE, LOG_BLANK_LINE);
	logging(LOG_VERBOSE, "Test of the INQUIRY Block Limits");

	CHECK_FOR_SBC;

	logging(LOG_VERBOSE, "Block device. Verify that we can read Block Limits VPD");
	ret = inquiry(iscsic, tgt_lun,
		      1, SCSI_INQUIRY_PAGECODE_BLOCK_LIMITS,
		      64, &bl_task);
	CU_ASSERT_EQUAL(ret, 0);
	if (ret != 0) {
		logging(LOG_NORMAL, "[FAILURE] failed to send inquiry.");
		goto finished;
	}

	bl = scsi_datain_unmarshall(bl_task);
	if (bl == NULL) {
		logging(LOG_NORMAL, "[FAILURE] failed to unmarshall inquiry "
			"datain blob.");
		CU_FAIL("[FAILURE] failed to unmarshall inquiry "
			"datain blob.");
		goto finished;
	}

	logging(LOG_VERBOSE, "Verify that the PageLength matches up with the size of the DATA-IN buffer.");
	CU_ASSERT_EQUAL(bl_task->datain.size, bl_task->datain.data[3] + 4);
	if (bl_task->datain.size != bl_task->datain.data[3] + 4) {
		logging(LOG_NORMAL, "[FAILURE] Invalid PageLength returned. "
			"Was %d but expected %d",
			bl_task->datain.data[3], bl_task->datain.size - 4);
	} else {
		logging(LOG_VERBOSE, "[SUCCESS] PageLength matches DataIn buffer size");
	}

	logging(LOG_VERBOSE, "Verify that the PageLength matches SCSI-level.");
	/* if it is not SBC3 then we assume it must be SBC2 */
	if (sbc3_support) {
		logging(LOG_VERBOSE, "Device claims SBC-3. Verify that "				"PageLength == 0x3C");
	} else {
		logging(LOG_VERBOSE, "Device is not SBC-3. Verify that "
			"PageLength == 0x0C (but allow 0x3C too. Some SBC-2 "
			"devices support some SBC-3 features.");
	}
	switch (bl_task->datain.data[3]) {
	case 0x3c:
		/* accept 0x3c (==SBC-3) for all levels */
		if (!sbc3_support) {
			logging(LOG_NORMAL, "[WARNING] SBC-3 pagelength (0x3C) "
				"returned but SBC-3 support was not claimed "
				"in the standard inquiry page.");
		}
		break;
	case 0x0c:
		/* only accept 0x0c for levels < SBC-3 */
		if (!sbc3_support) {
			break;
		}
		/* fallthrough */
	default:
		CU_FAIL("[FAILED] Invalid pagelength returned");
		logging(LOG_NORMAL, "[FAILURE] Invalid PageLength returned.");
	}


	if (bl_task->datain.data[3] != 0x3c) {
		goto finished;
	}


	/*
	 * MAXIMUM UNMAP LBA COUNT
	 * MAXIMUM UNMAP BLOCK DESCRIPTOR COUNT
	 */
	logging(LOG_VERBOSE, "Try reading the logical block provisioning VPD");
	ret = inquiry(iscsic, tgt_lun,
		      1, SCSI_INQUIRY_PAGECODE_LOGICAL_BLOCK_PROVISIONING,
		      64, &lbp_task);
	if (ret == 0) {
		lbp = scsi_datain_unmarshall(lbp_task);
		if (lbp == NULL) {
			logging(LOG_NORMAL, "[FAILURE] failed to unmarshall "
			"inquiry datain blob.");
		}
	}

	if (lbp && lbp->lbpu) {
		/* We support UNMAP so MAXIMUM UNMAP LBA COUNT and
		 * MAXIMUM UNMAP BLOCK DESCRIPTOR COUNT.
		 * They must be > 0.
		 * It can be 0xffffffff which means no limit, but if there is
		 * an explicit limit set, then we check that it looks sane.
		 * Sane here means < 1M.
		 */
		logging(LOG_VERBOSE, "Device claims UNMAP support via LBPU");
		logging(LOG_VERBOSE, "Verify that MAXIMUM UNMAP LBA COUNT is "
			"not 0");
		CU_ASSERT_NOT_EQUAL(bl->max_unmap, 0);

		logging(LOG_VERBOSE, "Verify that MAXIMUM UNMAP LBA COUNT is "
			"at least 2^LBPPBE");
		CU_ASSERT_EQUAL(bl->max_unmap >= (1U << rc16->lbppbe), 1);

		if (bl->max_unmap != 0xffffffff) {
			logging(LOG_VERBOSE, "Verify that MAXIMUM UNMAP LBA "
				"COUNT is not insanely big");
			CU_ASSERT_TRUE(bl->max_unmap <= 1024*1024);
		}

		logging(LOG_VERBOSE, "Verify that MAXIMUM UNMAP BLOCK "
			"DESCRIPTOR COUNT is not 0");
		CU_ASSERT_NOT_EQUAL(bl->max_unmap_bdc, 0);
		if (bl->max_unmap_bdc != 0xffffffff) {
			logging(LOG_VERBOSE, "Verify that MAXIMUM UNMAP "
				"BLOCK DESCRIPTOR COUNT is not insanely big");
			CU_ASSERT_TRUE(bl->max_unmap_bdc <= 1024*1024);
		}
	} else {
		logging(LOG_VERBOSE, "Device does not claim UNMAP support via "
			"LBPU");
		logging(LOG_VERBOSE, "Verify that MAXIMUM UNMAP LBA COUNT is "
			"0");
		CU_ASSERT_EQUAL(bl->max_unmap, 0);

		logging(LOG_VERBOSE, "Verify that MAXIMUM UNMAP BLOCK "
			"DESCRIPTOR COUNT is 0");
		CU_ASSERT_EQUAL(bl->max_unmap_bdc, 0);
	}



finished:
	if (bl_task != NULL) {
		scsi_free_scsi_task(bl_task);
	}
	if (lbp_task != NULL) {
		scsi_free_scsi_task(lbp_task);
	}
}
예제 #22
0
파일: esp.c 프로젝트: xHypervisor/WinQEMU
int
ob_esp_init(unsigned int slot, uint64_t base, unsigned long espoffset,
            unsigned long dmaoffset)
{
    int id, diskcount = 0, cdcount = 0, *counter_ptr;
    char nodebuff[256], aliasbuff[256];
    esp_private_t *esp;
    unsigned int i;

    DPRINTF("Initializing SCSI...");

    esp = malloc(sizeof(esp_private_t));
    if (!esp) {
        DPRINTF("Can't allocate ESP private structure\n");
        return -1;
    }

    global_esp = esp;

    if (espdma_init(slot, base, dmaoffset, &esp->espdma) != 0) {
        return -1;
    }
    /* Get the IO region */
    esp->ll = (void *)ofmem_map_io(base + (uint64_t)espoffset,
                             sizeof(struct esp_regs));
    if (esp->ll == NULL) {
        DPRINTF("Can't map ESP registers\n");
        return -1;
    }

    esp->buffer = (void *)dvma_alloc(BUFSIZE, &esp->buffer_dvma);
    if (!esp->buffer || !esp->buffer_dvma) {
        DPRINTF("Can't get a DVMA buffer\n");
        return -1;
    }

    // Chip reset
    esp->ll->regs[ESP_CMD] = ESP_CMD_RC;

    DPRINTF("ESP at 0x%lx, buffer va 0x%lx dva 0x%lx\n", (unsigned long)esp,
            (unsigned long)esp->buffer, (unsigned long)esp->buffer_dvma);
    DPRINTF("done\n");
    DPRINTF("Initializing SCSI devices...");

    for (id = 0; id < 8; id++) {
        esp->sd[id].id = id;
        if (!inquiry(esp, &esp->sd[id])) {
            DPRINTF("Unit %d not present\n", id);
            continue;
        }
        /* Clear Unit Attention condition from reset */
        for (i = 0; i < 5; i++) {
            if (test_unit_ready(esp, &esp->sd[id])) {
                break;
            }
        }
        if (i == 5) {
            DPRINTF("Unit %d present but won't become ready\n", id);
            continue;
        }
        DPRINTF("Unit %d present\n", id);
        read_capacity(esp, &esp->sd[id]);

#ifdef CONFIG_DEBUG_ESP
        dump_drive(&esp->sd[id]);
#endif
    }

    REGISTER_NAMED_NODE(ob_esp, "/iommu/sbus/espdma/esp");
    device_end();
    /* set reg */
    push_str("/iommu/sbus/espdma/esp");
    fword("find-device");
    PUSH(slot);
    fword("encode-int");
    PUSH(espoffset);
    fword("encode-int");
    fword("encode+");
    PUSH(0x00000010);
    fword("encode-int");
    fword("encode+");
    push_str("reg");
    fword("property");

    PUSH(0x02625a00);
    fword("encode-int");
    push_str("clock-frequency");
    fword("property");

    for (id = 0; id < 8; id++) {
        if (!esp->sd[id].present)
            continue;
        push_str("/iommu/sbus/espdma/esp");
        fword("find-device");
        fword("new-device");
        push_str("sd");
        fword("device-name");
        push_str("block");
        fword("device-type");
        fword("is-deblocker");
        PUSH(id);
        fword("encode-int");
        PUSH(0);
        fword("encode-int");
        fword("encode+");
        push_str("reg");
        fword("property");
        fword("finish-device");
        snprintf(nodebuff, sizeof(nodebuff), "/iommu/sbus/espdma/esp/sd@%d,0",
                 id);
        REGISTER_NODE_METHODS(ob_sd, nodebuff);
        if (esp->sd[id].media == TYPE_ROM) {
            counter_ptr = &cdcount;
        } else {
            counter_ptr = &diskcount;
        }
        if (*counter_ptr == 0) {
            add_alias(nodebuff, esp->sd[id].media_str[0]);
            add_alias(nodebuff, esp->sd[id].media_str[1]);
        }
        snprintf(aliasbuff, sizeof(aliasbuff), "%s%d",
                 esp->sd[id].media_str[0], *counter_ptr);
        add_alias(nodebuff, aliasbuff);
        snprintf(aliasbuff, sizeof(aliasbuff), "%s%d",
                 esp->sd[id].media_str[1], *counter_ptr);
        add_alias(nodebuff, aliasbuff);
        snprintf(aliasbuff, sizeof(aliasbuff), "sd(0,%d,0)", id);
        add_alias(nodebuff, aliasbuff);
        snprintf(aliasbuff, sizeof(aliasbuff), "sd(0,%d,0)@0,0", id);
        add_alias(nodebuff, aliasbuff);
        (*counter_ptr)++;
    }
    DPRINTF("done\n");

    return 0;
}