ATF_TC_BODY(cam_get_device_negative_test_root, tc) { char parsed_dev_name[DEV_IDLEN + 1]; int parsed_unit; ATF_REQUIRE_MSG(cam_get_device("/", parsed_dev_name, nitems(parsed_dev_name), &parsed_unit) == -1, "cam_get_device succeeded unexpectedly"); }
/* Similar to scsi_pt_open_device() but takes Unix style open flags OR-ed * together. The 'flags' argument is ignored in FreeBSD. * Returns >= 0 if successful, otherwise returns negated errno. */ int scsi_pt_open_flags(const char * device_name, int flags __attribute__ ((unused)), int verbose) { struct freebsd_dev_channel *fdchan; struct cam_device* cam_dev; int k; if (NULL == sg_warnings_strm) sg_warnings_strm = stderr; // Search table for a free entry for (k = 0; k < FREEBSD_MAXDEV; k++) if (! devicetable[k]) break; // If no free entry found, return error. We have max allowed number // of "file descriptors" already allocated. if (k == FREEBSD_MAXDEV) { if (verbose) fprintf(sg_warnings_strm, "too many open file descriptors " "(%d)\n", FREEBSD_MAXDEV); errno = EMFILE; return -1; } fdchan = (struct freebsd_dev_channel *) calloc(1,sizeof(struct freebsd_dev_channel)); if (fdchan == NULL) { // errno already set by call to calloc() return -1; } if (! (fdchan->devname = (char *)calloc(1, DEV_IDLEN+1))) return -1; if (cam_get_device(device_name, fdchan->devname, DEV_IDLEN, &(fdchan->unitnum)) == -1) { if (verbose) fprintf(sg_warnings_strm, "bad device name structure\n"); errno = EINVAL; return -1; } if (! (cam_dev = cam_open_spec_device(fdchan->devname, fdchan->unitnum, O_RDWR, NULL))) { if (verbose) fprintf(sg_warnings_strm, "cam_open_spec_device: %s\n", cam_errbuf); errno = EPERM; /* permissions or no CAM */ return -1; } fdchan->cam_dev = cam_dev; // return pointer to "file descriptor" table entry, properly offset. devicetable[k] = fdchan; return k + FREEBSD_FDOFFSET; }
ATF_TC_BODY(cam_get_device_positive_test, tc) { char expected_dev_name[] = "foo"; char parsed_dev_name[DEV_IDLEN + 1]; int expected_unit, parsed_unit; expected_unit = 1; ATF_REQUIRE_MSG(cam_get_device("/dev/foo1", parsed_dev_name, nitems(parsed_dev_name), &parsed_unit) == 0, "cam_get_device failed"); ATF_REQUIRE_STREQ(parsed_dev_name, expected_dev_name); ATF_REQUIRE(parsed_unit == expected_unit); strcpy(parsed_dev_name, ""); parsed_unit = -1; ATF_REQUIRE_MSG(cam_get_device("foo1", parsed_dev_name, nitems(parsed_dev_name), &parsed_unit) == 0, "cam_get_device failed"); ATF_REQUIRE_STREQ(parsed_dev_name, expected_dev_name); ATF_REQUIRE(parsed_unit == expected_unit); }
/* * Backwards compatible wrapper for the real open routine. This translates * a pathname into a device name and unit number for use with the real open * routine. */ struct cam_device * cam_open_device(const char *path, int flags) { int unit; char dev_name[DEV_IDLEN + 1]; /* * cam_get_device() has already put an error message in cam_errbuf, * so we don't need to. */ if (cam_get_device(path, dev_name, sizeof(dev_name), &unit) == -1) return(NULL); return(cam_lookup_pass(dev_name, unit, flags, path, NULL)); }
/* open ata device */ int ata_open(ATA **ataptr, const char *device) { int rc; assert(ataptr != NULL); *ataptr = malloc(sizeof(ATA)); { ATA *ata = *ataptr; if (ata == NULL) err(EX_SOFTWARE, NULL); ata->devhandle.fd = -1; /* TODO better detection of SCSI/SAT */ ata->access_mode = ACCESS_MODE_ATA; if (strncmp(device, scsi_prefix_da, strlen(scsi_prefix_da)) == 0) ata->access_mode = ACCESS_MODE_SAT; switch (ata->access_mode) { case ACCESS_MODE_ATA: rc = open( device, O_RDONLY ); if (rc > 0) ata->devhandle.fd = rc; break; case ACCESS_MODE_SAT: rc = cam_get_device( device, ata->devhandle.camdevname, DEV_IDLEN, &(ata->devhandle.camunit) ); if (rc != 0) goto fail; ata->devhandle.camdev = cam_open_spec_device( ata->devhandle.camdevname, ata->devhandle.camunit, O_RDONLY, NULL ); if (ata->devhandle.camdev == NULL) { rc = -1; warnx("%s", cam_errbuf); goto fail; } break; } } return rc; fail: free(*ataptr); return rc; }
/* Note that CAM (circa FreeBSD 9) cannot directly communicate with a SAS * expander because it isn't a SCSI device. FreeBSD assumes each SAS * expander is paired with a SES (enclosure) device. This seems to be true * for SAS-2 expanders but not the older SAS-1 expanders. Hence device_name * will be something like /dev/ses0 . */ int smp_initiator_open(const char * device_name, int subvalue, const char * i_params, uint64_t sa, struct smp_target_obj * tobj, int verbose) { struct cam_device* cam_dev; struct tobj_cam_t * tcp; if (i_params) { ; } /* unused, suppress warning */ if ((NULL == tobj) || (NULL == device_name)) return -1; memset(tobj, 0, sizeof(struct smp_target_obj)); strncpy(tobj->device_name, device_name, SMP_MAX_DEVICE_NAME); if (sa) sg_put_unaligned_be64(sa, tobj->sas_addr + 0); tobj->interface_selector = I_CAM; tcp = (struct tobj_cam_t *) calloc(1, sizeof(struct tobj_cam_t)); if (tcp == NULL) { // errno already set by call to calloc() return -1; } if (cam_get_device(device_name, tcp->devname, DEV_IDLEN, &(tcp->unitnum)) == -1) { if (verbose) fprintf(stderr, "bad device name structure\n"); free(tcp); return -1; } if (! (cam_dev = cam_open_spec_device(tcp->devname, tcp->unitnum, O_RDWR, NULL))) { fprintf(stderr, "cam_open_spec_device: %s\n", cam_errbuf); free(tcp); return -1; } tcp->cam_dev = cam_dev; tobj->vp = tcp; tobj->opened = 1; tobj->subvalue = subvalue; /* unused */ return 0; }
/* * Core interface function to lowlevel SCSI interface. */ static inline bool do_scsi_cmd_page(int fd, const char *device_name, void *cdb, unsigned int cdb_len, void *cmd_page, unsigned int cmd_page_len, int direction) { int unitnum, len; union ccb *ccb; char errbuf[128]; char cam_devicename[64]; struct cam_device *cam_dev; SCSI_PAGE_SENSE sense; bool retval = false; /* * See what CAM device to use. */ if (cam_get_device(device_name, cam_devicename, sizeof(cam_devicename), &unitnum) == -1) { berrno be; Emsg2(M_ERROR, 0, _("Failed to find CAM device for %s: ERR=%s\n"), device_name, be.bstrerror()); Dmsg2(010, "Failed to find CAM device for %s: ERR=%s\n", device_name, be.bstrerror()); return false; } cam_dev = cam_open_spec_device(cam_devicename, unitnum, O_RDWR, NULL); if (!cam_dev) { berrno be; Emsg2(M_ERROR, 0, _("Failed to open CAM device for %s: ERR=%s\n"), device_name, be.bstrerror()); Dmsg2(010, "Failed to open CAM device for %s: ERR=%s\n", device_name, be.bstrerror()); return false; } ccb = cam_getccv(cam_dev); if (!ccb) { Emsg1(M_ERROR, 0, _("Failed to allocate new ccb for %s\n"), device_name); Dmsg1(0, "Failed to allocate new ccb for %s\n", device_name); goto bail_out; } /* * Clear out structure, except for header that was filled for us. */ memset(&ccb->ccb_h)[1], 0, sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr)); cam_fill_csio(&ccb->csio, 1, /* retries */ NULL, /* cbfcnp */ direction, /* flags */ MSG_SIMPLE_Q_TAG,, /* tagaction */ cmd_page, /* dataptr */ cmd_page_len, /* datalen */ sizeof(sense), /* senselength */ cdb_len, /* cdblength */ 15000 /* timeout (millisecs) */); memcpy(ccb->csio.cdb_io.cdb_bytes, cdb, SPP_SP_CMD_LEN); if (cam_send_ccb(cam_dev, ccb) < 0) { Emsg2(M_ERROR, 0, _("Failed to send ccb to device %s: %s\n"), device_name, cam_error_string(cam_dev, ccb, errbuf, sizeof(errbuf), CAM_ESF_ALL, CAM_EPF_ALL)); Dmsg2(010, "Failed to send ccb to device %s: %s\n", device_name, cam_error_string(cam_dev, ccb, errbuf, sizeof(errbuf), CAM_ESF_ALL, CAM_EPF_ALL)); cam_freeccb(ccb); goto bail_out; } /* * Retrieve the SCSI sense data. */ if (((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) || ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_SCSI_STATUS_ERROR)) { if ((SAM_STAT_CHECK_CONDITION == ccb->csio.scsi_status) || (SAM_STAT_COMMAND_TERMINATED == ccb->csio.scsi_status)) { len = sizeof(sense) - ccb->csio.sense_resid; if (len) { memcpy(&sense, &(ccb->csio.sense_data), len); } } } retval = true; bail_out: /* * Close the CAM device. */ cam_close_device(cam_dev); return retval; }