/* ( -- 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 ); }
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; } }
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; }
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); }
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); }
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; }
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; }
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; }
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; }
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; } }
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); }
/* * 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; }
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); }
/* 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); } }
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; }
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; }
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); }
/* 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; }
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); } }
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; }