コード例 #1
0
ファイル: ds_scsi.c プロジェクト: xiaomailong/fms
/*
 * Given a list of supported mode pages, determine if the given page is present.
 */
static boolean_t
mode_page_present(uchar_t *pgdata, uint_t pgdatalen, uchar_t pagecode)
{
	uint_t i = 0;
	struct mode_page *pg;
	boolean_t found = B_FALSE;

	/*
	 * The mode page list contains all mode pages supported by the device,
	 * one after the other.
	 */
	while (i < pgdatalen) {
		pg = (struct mode_page *)&pgdata[i];

		if (pg->code == pagecode) {
			found = B_TRUE;
			break;
		}

		i += MODESENSE_PAGE_LEN(pg);
	}

	return (found);
}
コード例 #2
0
ファイル: drive.c プロジェクト: apprisi/illumos-gate
static int
uscsi_mode_sense(int fd, int page_code, int page_control, caddr_t page_data,
	int page_size, struct  scsi_ms_header *header)
{
	caddr_t			mode_sense_buf;
	struct mode_header	*hdr;
	struct mode_page	*pg;
	int			nbytes;
	struct uscsi_cmd	ucmd;
	union scsi_cdb		cdb;
	int			status;
	int			maximum;
	char			rqbuf[255];

	/*
	 * Allocate a buffer for the mode sense headers
	 * and mode sense data itself.
	 */
	nbytes = sizeof (struct block_descriptor) +
				sizeof (struct mode_header) + page_size;
	nbytes = page_size;
	if ((mode_sense_buf = malloc((uint_t)nbytes)) == NULL) {
	    return (-1);
	}

	/*
	 * Build and execute the uscsi ioctl
	 */
	(void) memset(mode_sense_buf, 0, nbytes);
	(void) memset((char *)&ucmd, 0, sizeof (ucmd));
	(void) memset((char *)&cdb, 0, sizeof (union scsi_cdb));

	cdb.scc_cmd = SCMD_MODE_SENSE;
	FORMG0COUNT(&cdb, (uchar_t)nbytes);
	cdb.cdb_opaque[2] = page_control | page_code;
	ucmd.uscsi_cdb = (caddr_t)&cdb;
	ucmd.uscsi_cdblen = CDB_GROUP0;
	ucmd.uscsi_bufaddr = mode_sense_buf;
	ucmd.uscsi_buflen = nbytes;

	ucmd.uscsi_flags |= USCSI_SILENT;
	ucmd.uscsi_flags |= USCSI_READ;
	ucmd.uscsi_timeout = 30;
	ucmd.uscsi_flags |= USCSI_RQENABLE;
	if (ucmd.uscsi_rqbuf == NULL)  {
	    ucmd.uscsi_rqbuf = rqbuf;
	    ucmd.uscsi_rqlen = sizeof (rqbuf);
	    ucmd.uscsi_rqresid = sizeof (rqbuf);
	}
	ucmd.uscsi_rqstatus = IMPOSSIBLE_SCSI_STATUS;

	status = ioctl(fd, USCSICMD, &ucmd);

	if (status || ucmd.uscsi_status != 0) {
	    free(mode_sense_buf);
	    return (-1);
	}

	/*
	 * Verify that the returned data looks reasonabled,
	 * find the actual page data, and copy it into the
	 * user's buffer.  Copy the mode_header and block_descriptor
	 * into the header structure, which can then be used to
	 * return the same data to the drive when issuing a mode select.
	 */
	hdr = (struct mode_header *)mode_sense_buf;
	(void) memset((caddr_t)header, 0, sizeof (struct scsi_ms_header));
	if (hdr->bdesc_length != sizeof (struct block_descriptor) &&
	    hdr->bdesc_length != 0) {
	    free(mode_sense_buf);
	    return (-1);
	}
	(void) memcpy((caddr_t)header, mode_sense_buf,
	    (int) (sizeof (struct mode_header) + hdr->bdesc_length));
	pg = (struct mode_page *)((ulong_t)mode_sense_buf +
	    sizeof (struct mode_header) + hdr->bdesc_length);
	if (pg->code != page_code) {
	    free(mode_sense_buf);
	    return (-1);
	}

	/*
	 * Accept up to "page_size" bytes of mode sense data.
	 * This allows us to accept both CCS and SCSI-2
	 * structures, as long as we request the greater
	 * of the two.
	 */
	maximum = page_size - sizeof (struct mode_page) - hdr->bdesc_length;
	if (((int)pg->length) > maximum) {
	    free(mode_sense_buf);
	    return (-1);
	}

	(void) memcpy(page_data, (caddr_t)pg, MODESENSE_PAGE_LEN(pg));

	free(mode_sense_buf);
	return (0);
}