2N/A/*
2N/A * CDDL HEADER START
2N/A *
2N/A * The contents of this file are subject to the terms of the
2N/A * Common Development and Distribution License, Version 1.0 only
2N/A * (the "License"). You may not use this file except in compliance
2N/A * with the License.
2N/A *
2N/A * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
2N/A * or http://www.opensolaris.org/os/licensing.
2N/A * See the License for the specific language governing permissions
2N/A * and limitations under the License.
2N/A *
2N/A * When distributing Covered Code, include this CDDL HEADER in each
2N/A * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
2N/A * If applicable, add the following below this CDDL HEADER, with the
2N/A * fields enclosed by brackets "[]" replaced with your own identifying
2N/A * information: Portions Copyright [yyyy] [name of copyright owner]
2N/A *
2N/A * CDDL HEADER END
2N/A */
2N/A/*
2N/A * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
2N/A * Use is subject to license terms.
2N/A */
2N/A
2N/A#pragma ident "%Z%%M% %I% %E% SMI"
2N/A
2N/A/*
2N/A * s_generic.c :
2N/A * This file contains generic SCSI related functions for scsi plug-in
2N/A * for libsm.so.
2N/A */
2N/A
2N/A
2N/A#include <sys/types.h>
2N/A#include <sys/stat.h>
2N/A#include <sys/ioctl.h>
2N/A#include <unistd.h>
2N/A#include <sys/shm.h>
2N/A#include <sys/mman.h>
2N/A#include <sys/smedia.h>
2N/A#include "../../../library/inc/rmedia.h"
2N/A#include <smserver.h>
2N/A#include <dirent.h>
2N/A#include <fcntl.h>
2N/A#include <sys/scsi/scsi.h>
2N/A#include <strings.h>
2N/A#include "../../../library/common/l_defines.h"
2N/A
2N/A
2N/Astatic int32_t remap_shared_buf(rmedia_handle_t *, size_t, char *);
2N/A
2N/A#define W_E_MASK 0x80
2N/A#define BUF_SIZE_MULTIPLE 0x2000
2N/A
2N/Aint32_t
2N/A_m_get_media_info(rmedia_handle_t *handle, void *ip)
2N/A{
2N/A smmedium_prop_t *medinfo = ip;
2N/A int32_t ret_val;
2N/A smedia_reqget_medium_property_t reqget_medium_property;
2N/A smedia_retget_medium_property_t *retget_medium_property;
2N/A smedia_reterror_t *reterror;
2N/A door_arg_t door_args;
2N/A char rbuf[sizeof (smedia_services_t) + sizeof (door_desc_t)];
2N/A
2N/A DPRINTF("get_media_info called.\n");
2N/A /* Check for valid handle */
2N/A if (handle == NULL) {
2N/A DPRINTF("Null Handle\n");
2N/A errno = EINVAL;
2N/A return (-1);
2N/A }
2N/A if (handle->sm_signature != (int32_t)LIBSMEDIA_SIGNATURE) {
2N/A DPRINTF("Invalid signature in handle.\n");
2N/A DPRINTF2(
2N/A "Signature expected=0x%x, found=0x%x\n",
2N/A LIBSMEDIA_SIGNATURE, handle->sm_signature);
2N/A DPRINTF1("fd=%d\n", handle->sm_fd);
2N/A errno = EINVAL;
2N/A return (-1);
2N/A }
2N/A (void) memset((void *) medinfo, 0, sizeof (smmedium_prop_t));
2N/A
2N/A reqget_medium_property.cnum = SMEDIA_CNUM_GET_MEDIUM_PROPERTY;
2N/A door_args.data_ptr = (char *)&reqget_medium_property;
2N/A door_args.data_size = sizeof (smedia_services_t);
2N/A door_args.desc_ptr = NULL;
2N/A door_args.desc_num = 0;
2N/A door_args.rbuf = rbuf;
2N/A door_args.rsize = sizeof (rbuf);
2N/A
2N/A ret_val = door_call(handle->sm_door, &door_args);
2N/A if (ret_val < 0) {
2N/A perror("door_call");
2N/A return (-1);
2N/A }
2N/A retget_medium_property =
2N/A (smedia_retget_medium_property_t *)((void *)door_args.data_ptr);
2N/A reterror = (smedia_reterror_t *)((void *)door_args.data_ptr);
2N/A if (reterror->cnum == SMEDIA_CNUM_ERROR) {
2N/A DPRINTF1(
2N/A "Error in get_medium_property. errnum = 0x%x \n", reterror->errnum);
2N/A errno = reterror->errnum;
2N/A return (-1);
2N/A }
2N/A
2N/A *medinfo = retget_medium_property->smprop;
2N/A
2N/A return (0);
2N/A}
2N/A
2N/Aint32_t
2N/A_m_get_device_info(rmedia_handle_t *handle, void *ip)
2N/A{
2N/A struct smdevice_info *dev_info = ip;
2N/A int32_t ret_val;
2N/A smedia_reqget_device_info_t reqget_device_info;
2N/A smedia_retget_device_info_t *retget_device_info;
2N/A smedia_reterror_t *reterror;
2N/A door_arg_t door_args;
2N/A char rbuf[sizeof (smedia_services_t) + sizeof (door_desc_t)];
2N/A char *vendor_name, *product_name, *fw_version;
2N/A
2N/A /* Check for valid handle */
2N/A if (handle == NULL) {
2N/A DPRINTF("Null Handle\n");
2N/A errno = EINVAL;
2N/A return (-1);
2N/A }
2N/A if (handle->sm_signature != LIBSMEDIA_SIGNATURE) {
2N/A DPRINTF("Invalid signature in handle.\n");
2N/A errno = EINVAL;
2N/A return (-1);
2N/A }
2N/A
2N/A vendor_name = (char *)malloc(9);
2N/A if (vendor_name == NULL) {
2N/A if (!errno)
2N/A errno = ENOMEM;
2N/A return (-1);
2N/A }
2N/A product_name = (char *)malloc(17);
2N/A if (product_name == NULL) {
2N/A free(vendor_name);
2N/A if (!errno)
2N/A errno = ENOMEM;
2N/A return (-1);
2N/A }
2N/A
2N/A fw_version = (char *)malloc(18);
2N/A if (fw_version == NULL) {
2N/A free(vendor_name);
2N/A free(product_name);
2N/A if (!errno)
2N/A errno = ENOMEM;
2N/A return (-1);
2N/A }
2N/A reqget_device_info.cnum = SMEDIA_CNUM_GET_DEVICE_INFO;
2N/A door_args.data_ptr = (char *)&reqget_device_info;
2N/A door_args.data_size = sizeof (smedia_services_t);
2N/A door_args.desc_ptr = NULL;
2N/A door_args.desc_num = 0;
2N/A door_args.rbuf = rbuf;
2N/A door_args.rsize = sizeof (rbuf);
2N/A
2N/A ret_val = door_call(handle->sm_door, &door_args);
2N/A if (ret_val < 0) {
2N/A perror("door_call");
2N/A free(vendor_name);
2N/A free(product_name);
2N/A free(fw_version);
2N/A return (-1);
2N/A }
2N/A retget_device_info = (smedia_retget_device_info_t *)
2N/A ((void *)door_args.data_ptr);
2N/A reterror = (smedia_reterror_t *)((void *)door_args.data_ptr);
2N/A if (reterror->cnum == SMEDIA_CNUM_ERROR) {
2N/A DPRINTF1(
2N/A "Error in get_device_info. errnum = 0x%x \n", reterror->errnum);
2N/A errno = reterror->errnum;
2N/A free(vendor_name);
2N/A free(product_name);
2N/A free(fw_version);
2N/A return (-1);
2N/A }
2N/A
2N/A dev_info->sm_vendor_name = vendor_name;
2N/A dev_info->sm_product_name = product_name;
2N/A dev_info->sm_firmware_version = fw_version;
2N/A
2N/A
2N/A (void) strlcpy(dev_info->sm_vendor_name,
2N/A retget_device_info->sm_vendor_name, 8);
2N/A dev_info->sm_vendor_name[8] = 0;
2N/A (void) strlcpy(dev_info->sm_product_name,
2N/A retget_device_info->sm_product_name, 16);
2N/A dev_info->sm_product_name[16] = 0;
2N/A (void) strlcpy(dev_info->sm_firmware_version,
2N/A retget_device_info->sm_firmware_version, 17);
2N/A dev_info->sm_firmware_version[17] = 0;
2N/A
2N/A dev_info->sm_interface_type = retget_device_info->sm_interface_type;
2N/A
2N/A#ifdef DEBUG
2N/A DPRINTF1("Vendor name = %s\n", dev_info->sm_vendor_name);
2N/A DPRINTF1("product name = %s\n", dev_info->sm_product_name);
2N/A DPRINTF1("Firmware revision = %s\n", dev_info->sm_firmware_version);
2N/A#endif /* DEBUG */
2N/A
2N/A return (0);
2N/A}
2N/A
2N/Aint32_t
2N/A_m_free_device_info(rmedia_handle_t *handle, void *ip)
2N/A{
2N/A struct smdevice_info *dev_info = ip;
2N/A
2N/A /* Check for valid handle */
2N/A if (handle == NULL) {
2N/A DPRINTF("Null Handle\n");
2N/A errno = EINVAL;
2N/A return (-1);
2N/A }
2N/A if (handle->sm_signature != LIBSMEDIA_SIGNATURE) {
2N/A DPRINTF("Invalid signature in handle.\n");
2N/A errno = EINVAL;
2N/A return (-1);
2N/A }
2N/A
2N/A free(dev_info->sm_vendor_name);
2N/A free(dev_info->sm_product_name);
2N/A free(dev_info->sm_firmware_version);
2N/A return (0);
2N/A}
2N/A
2N/Aint32_t
2N/A_m_raw_write(rmedia_handle_t *handle, void *i_p)
2N/A{
2N/A int32_t ret_val;
2N/A struct raw_params *r_p = (struct raw_params *)i_p;
2N/A smedia_reqraw_write_t reqraw_write;
2N/A smedia_retraw_write_t *retraw_write;
2N/A smedia_reterror_t *reterror;
2N/A door_arg_t door_args;
2N/A char rbuf[sizeof (smedia_services_t) + sizeof (door_desc_t)];
2N/A
2N/A /* Check for valid handle */
2N/A if (handle == NULL) {
2N/A DPRINTF("Null Handle\n");
2N/A errno = EINVAL;
2N/A return (-1);
2N/A }
2N/A if (handle->sm_signature != LIBSMEDIA_SIGNATURE) {
2N/A DPRINTF("Invalid signature in handle.\n");
2N/A errno = EINVAL;
2N/A return (-1);
2N/A }
2N/A (void) mutex_lock(&handle->sm_bufmutex);
2N/A ret_val = remap_shared_buf(handle, r_p->size, r_p->buffer);
2N/A if (ret_val != 0) goto error;
2N/A reqraw_write.cnum = SMEDIA_CNUM_RAW_WRITE;
2N/A reqraw_write.blockno = r_p->offset;
2N/A reqraw_write.nbytes = r_p->size;
2N/A bcopy(r_p->buffer, handle->sm_buf, r_p->size);
2N/A door_args.data_ptr = (char *)&reqraw_write;
2N/A door_args.data_size = sizeof (reqraw_write);
2N/A door_args.desc_ptr = NULL;
2N/A door_args.desc_num = 0;
2N/A door_args.rbuf = rbuf;
2N/A door_args.rsize = sizeof (rbuf);
2N/A
2N/A ret_val = door_call(handle->sm_door, &door_args);
2N/A if (ret_val < 0) {
2N/A perror("door_call");
2N/A goto error;
2N/A }
2N/A retraw_write = (smedia_retraw_write_t *)((void *)door_args.data_ptr);
2N/A reterror = (smedia_reterror_t *)((void *)door_args.data_ptr);
2N/A if (reterror->cnum == SMEDIA_CNUM_ERROR) {
2N/A DPRINTF3(
2N/A "Error in raw write. errnum = 0x%x blk_num = 0x%x(%d)\n",
2N/A reterror->errnum, r_p->offset, r_p->offset);
2N/A errno = reterror->errnum;
2N/A goto error;
2N/A }
2N/A (void) mutex_unlock(&handle->sm_bufmutex);
2N/A return (retraw_write->nbytes);
2N/A
2N/Aerror:
2N/A (void) mutex_unlock(&handle->sm_bufmutex);
2N/A return (-1);
2N/A}
2N/A
2N/Asize_t
2N/A_m_raw_read(rmedia_handle_t *handle, void *i_p)
2N/A{
2N/A struct raw_params *r_p = (struct raw_params *)i_p;
2N/A int32_t ret_val, bytes_read;
2N/A smedia_reqraw_read_t reqraw_read;
2N/A smedia_retraw_read_t *retraw_read;
2N/A smedia_reterror_t *reterror;
2N/A door_arg_t door_args;
2N/A char rbuf[sizeof (smedia_services_t) + sizeof (door_desc_t)];
2N/A
2N/A /* Check for valid handle */
2N/A if (handle == NULL) {
2N/A DPRINTF("Null Handle\n");
2N/A errno = EINVAL;
2N/A return (size_t)(-1);
2N/A }
2N/A if (handle->sm_signature != LIBSMEDIA_SIGNATURE) {
2N/A DPRINTF("Invalid signature in handle.\n");
2N/A return (size_t)(-1);
2N/A }
2N/A /*
2N/A * Check if another thread is doing an IO with same handle.
2N/A * In that case ww block here.
2N/A */
2N/A (void) mutex_lock(&handle->sm_bufmutex);
2N/A ret_val = remap_shared_buf(handle, r_p->size, r_p->buffer);
2N/A if (ret_val != 0) goto error;
2N/A
2N/A reqraw_read.cnum = SMEDIA_CNUM_RAW_READ;
2N/A reqraw_read.blockno = r_p->offset;
2N/A reqraw_read.nbytes = r_p->size;
2N/A door_args.data_ptr = (char *)&reqraw_read;
2N/A door_args.data_size = sizeof (smedia_services_t);
2N/A door_args.desc_ptr = NULL;
2N/A door_args.desc_num = 0;
2N/A door_args.rbuf = rbuf;
2N/A door_args.rsize = sizeof (rbuf);
2N/A
2N/A ret_val = door_call(handle->sm_door, &door_args);
2N/A if (ret_val < 0) {
2N/A perror("door_call");
2N/A goto error;
2N/A }
2N/A retraw_read = (smedia_retraw_read_t *)((void *)door_args.data_ptr);
2N/A reterror = (smedia_reterror_t *)((void *)door_args.data_ptr);
2N/A if (reterror->cnum == SMEDIA_CNUM_ERROR) {
2N/A /*
2N/A * free(rbuf);
2N/A */
2N/A DPRINTF3(
2N/A "Error in raw read. errnum = 0x%x blk_num = 0x%x(%d)\n",
2N/A reterror->errnum, r_p->offset, r_p->offset);
2N/A errno = reterror->errnum;
2N/A goto error;
2N/A }
2N/A (void) memcpy(r_p->buffer, handle->sm_buf, retraw_read->nbytes);
2N/A bytes_read = retraw_read->nbytes;
2N/A (void) mutex_unlock(&handle->sm_bufmutex);
2N/A return (bytes_read);
2N/A
2N/Aerror:
2N/A (void) mutex_unlock(&handle->sm_bufmutex);
2N/A return (size_t)(-1);
2N/A
2N/A}
2N/A
2N/Asize_t
2N/A_m_media_format(rmedia_handle_t *handle, void *ip)
2N/A{
2N/A int32_t ret_val;
2N/A struct format_flags *ffl = (struct format_flags *)ip;
2N/A smedia_reqformat_t reqformat;
2N/A smedia_retformat_t *retformat;
2N/A smedia_reterror_t *reterror;
2N/A door_arg_t door_args;
2N/A char rbuf[sizeof (smedia_services_t) + sizeof (door_desc_t)];
2N/A
2N/A /* Check for valid handle */
2N/A if (handle == NULL) {
2N/A DPRINTF("Null Handle\n");
2N/A errno = EINVAL;
2N/A return (size_t)(-1);
2N/A }
2N/A if (handle->sm_signature != LIBSMEDIA_SIGNATURE) {
2N/A DPRINTF("Invalid signature in handle.\n");
2N/A errno = EINVAL;
2N/A return (size_t)(-1);
2N/A }
2N/A reqformat.cnum = SMEDIA_CNUM_FORMAT;
2N/A reqformat.flavor = ffl->flavor;
2N/A reqformat.mode = ffl->mode;
2N/A door_args.data_ptr = (char *)&reqformat;
2N/A door_args.data_size = sizeof (smedia_services_t);
2N/A door_args.desc_ptr = NULL;
2N/A door_args.desc_num = 0;
2N/A door_args.rbuf = rbuf;
2N/A door_args.rsize = sizeof (rbuf);
2N/A
2N/A ret_val = door_call(handle->sm_door, &door_args);
2N/A if (ret_val < 0) {
2N/A perror("door_call");
2N/A return (size_t)(-1);
2N/A }
2N/A retformat = (smedia_retformat_t *)((void *)door_args.data_ptr);
2N/A#ifdef lint
2N/A retformat = retformat;
2N/A#endif
2N/A reterror = (smedia_reterror_t *)((void *)door_args.data_ptr);
2N/A if (reterror->cnum == SMEDIA_CNUM_ERROR) {
2N/A DPRINTF1("Error in format. errnum = 0x%x \n", reterror->errnum);
2N/A errno = reterror->errnum;
2N/A return (size_t)(-1);
2N/A }
2N/A return (0);
2N/A}
2N/A
2N/Aint32_t
2N/A_m_get_media_status(rmedia_handle_t *handle, void *ip)
2N/A{
2N/A smwp_state_t *wp = ip;
2N/A int32_t ret_val;
2N/A smedia_reqget_protection_status_t reqget_protection_status;
2N/A smedia_retget_protection_status_t *retget_protection_status;
2N/A smedia_reterror_t *reterror;
2N/A door_arg_t door_args;
2N/A char rbuf[sizeof (smedia_services_t) + sizeof (door_desc_t)];
2N/A
2N/A /* Check for valid handle */
2N/A if (handle == NULL) {
2N/A DPRINTF("Null Handle\n");
2N/A errno = EINVAL;
2N/A return (-1);
2N/A }
2N/A if (handle->sm_signature != LIBSMEDIA_SIGNATURE) {
2N/A DPRINTF("Invalid signature in handle.\n");
2N/A errno = EINVAL;
2N/A return (-1);
2N/A }
2N/A reqget_protection_status.cnum = SMEDIA_CNUM_GET_PROTECTION_STATUS;
2N/A door_args.data_ptr = (char *)&reqget_protection_status;
2N/A door_args.data_size = sizeof (smedia_services_t);
2N/A door_args.desc_ptr = NULL;
2N/A door_args.desc_num = 0;
2N/A door_args.rbuf = rbuf;
2N/A door_args.rsize = sizeof (rbuf);
2N/A
2N/A ret_val = door_call(handle->sm_door, &door_args);
2N/A if (ret_val < 0) {
2N/A perror("door_call");
2N/A return (-1);
2N/A }
2N/A retget_protection_status =
2N/A (smedia_retget_protection_status_t *)
2N/A ((void *)door_args.data_ptr);
2N/A reterror = (smedia_reterror_t *)((void *)door_args.data_ptr);
2N/A if (reterror->cnum == SMEDIA_CNUM_ERROR) {
2N/A DPRINTF1(
2N/A "Error in get_protection-status. errnum = 0x%x \n", reterror->errnum);
2N/A errno = reterror->errnum;
2N/A return (-1);
2N/A }
2N/A (void) memcpy((char *)wp, (char *)&retget_protection_status->prot_state,
2N/A sizeof (smwp_state_t));
2N/A return (0);
2N/A}
2N/A
2N/Aint32_t
2N/A_m_set_media_status(rmedia_handle_t *handle, void *ip) {
2N/A
2N/A smwp_state_t *wp = ip;
2N/A int32_t ret_val;
2N/A smedia_reqset_protection_status_t reqset_protection_status;
2N/A smedia_reterror_t *reterror;
2N/A door_arg_t door_args;
2N/A char rbuf[sizeof (smedia_services_t) + sizeof (door_desc_t)];
2N/A
2N/A /* Check for valid handle */
2N/A if (handle == NULL) {
2N/A DPRINTF("Null Handle\n");
2N/A errno = EINVAL;
2N/A return (-1);
2N/A }
2N/A if (handle->sm_signature != LIBSMEDIA_SIGNATURE) {
2N/A DPRINTF("Invalid signature in handle.\n");
2N/A errno = EINVAL;
2N/A return (-1);
2N/A }
2N/A reqset_protection_status.cnum = SMEDIA_CNUM_SET_PROTECTION_STATUS;
2N/A reqset_protection_status.prot_state = *wp;
2N/A door_args.data_ptr = (char *)&reqset_protection_status;
2N/A door_args.data_size = sizeof (smedia_services_t);
2N/A door_args.desc_ptr = NULL;
2N/A door_args.desc_num = 0;
2N/A door_args.rbuf = rbuf;
2N/A door_args.rsize = sizeof (rbuf);
2N/A
2N/A ret_val = door_call(handle->sm_door, &door_args);
2N/A if (ret_val < 0) {
2N/A perror("door_call");
2N/A return (-1);
2N/A }
2N/A reterror = (smedia_reterror_t *)((void *)door_args.data_ptr);
2N/A if (reterror->cnum == SMEDIA_CNUM_ERROR) {
2N/A DPRINTF1(
2N/A "Error in set_protection-status. errnum = 0x%x \n", reterror->errnum);
2N/A errno = reterror->errnum;
2N/A return (-1);
2N/A }
2N/A return (0);
2N/A}
2N/A
2N/Aint32_t
2N/A_m_reassign_block(rmedia_handle_t *handle, void *ip)
2N/A{
2N/A uint32_t block;
2N/A diskaddr_t *blockp = (diskaddr_t *)ip;
2N/A int32_t ret_val;
2N/A smedia_reqreassign_block_t reqreassign_block;
2N/A smedia_reterror_t *reterror;
2N/A door_arg_t door_args;
2N/A char rbuf[sizeof (smedia_services_t) + sizeof (door_desc_t)];
2N/A
2N/A /* Check for valid handle */
2N/A if (handle == NULL) {
2N/A DPRINTF("Null Handle\n");
2N/A errno = EINVAL;
2N/A return (-1);
2N/A }
2N/A if (handle->sm_signature != LIBSMEDIA_SIGNATURE) {
2N/A DPRINTF("Invalid signature in handle.\n");
2N/A errno = EINVAL;
2N/A return (-1);
2N/A }
2N/A block = *blockp;
2N/A DPRINTF1("reassign block %d\n", block);
2N/A reqreassign_block.cnum = SMEDIA_CNUM_REASSIGN_BLOCK;
2N/A reqreassign_block.blockno = block;
2N/A door_args.data_ptr = (char *)&reqreassign_block;
2N/A door_args.data_size = sizeof (smedia_services_t);
2N/A door_args.desc_ptr = NULL;
2N/A door_args.desc_num = 0;
2N/A door_args.rbuf = rbuf;
2N/A door_args.rsize = sizeof (rbuf);
2N/A
2N/A ret_val = door_call(handle->sm_door, &door_args);
2N/A if (ret_val < 0) {
2N/A perror("door_call");
2N/A return (-1);
2N/A }
2N/A reterror = (smedia_reterror_t *)((void *)door_args.data_ptr);
2N/A if (reterror->cnum == SMEDIA_CNUM_ERROR) {
2N/A DPRINTF2(
2N/A "Error in reassign_block. block = 0x%x errnum = 0x%x \n",
2N/A block, reterror->errnum);
2N/A errno = reterror->errnum;
2N/A return (-1);
2N/A }
2N/A return (0);
2N/A}
2N/A
2N/A/* ARGSUSED1 */
2N/Aint32_t
2N/A_m_eject(rmedia_handle_t *handle, void *ip)
2N/A{
2N/A int32_t fd;
2N/A
2N/A /* Check for valid handle */
2N/A if (handle == NULL) {
2N/A DPRINTF("Null Handle\n");
2N/A errno = EINVAL;
2N/A return (-1);
2N/A }
2N/A if (handle->sm_signature != LIBSMEDIA_SIGNATURE) {
2N/A DPRINTF("Invalid signature in handle.\n");
2N/A errno = EINVAL;
2N/A return (-1);
2N/A }
2N/A fd = handle->sm_fd;
2N/A return (ioctl(fd, DKIOCEJECT));
2N/A}
2N/A
2N/Aint32_t
2N/A_m_device_type(ushort_t ctype, ushort_t mtype)
2N/A{
2N/A if ((ctype == DKC_SCSI_CCS) ||
2N/A (ctype == DKC_MD21) ||
2N/A (ctype == DKC_CDROM)) {
2N/A if (mtype == 0)
2N/A return (0);
2N/A }
2N/A return (-1);
2N/A}
2N/A
2N/Aint32_t
2N/A_m_version_no(void)
2N/A{
2N/A return (SM_SCSI_VERSION_1);
2N/A}
2N/A
2N/Aint32_t
2N/A_m_check_format_status(rmedia_handle_t *handle, void *ip)
2N/A{
2N/A int32_t ret_val;
2N/A smedia_reqcheck_format_status_t reqcheck_format_status;
2N/A smedia_retcheck_format_status_t *retcheck_format_status;
2N/A smedia_reterror_t *reterror;
2N/A door_arg_t door_args;
2N/A char rbuf[sizeof (smedia_services_t) + sizeof (door_desc_t)];
2N/A#ifdef lint
2N/A ip = ip;
2N/A#endif
2N/A
2N/A /* Check for valid handle */
2N/A if (handle == NULL) {
2N/A DPRINTF("Null Handle\n");
2N/A errno = EINVAL;
2N/A return (-1);
2N/A }
2N/A if (handle->sm_signature != LIBSMEDIA_SIGNATURE) {
2N/A DPRINTF("Invalid signature in handle.\n");
2N/A errno = EINVAL;
2N/A return (-1);
2N/A }
2N/A reqcheck_format_status.cnum = SMEDIA_CNUM_CHECK_FORMAT_STATUS;
2N/A door_args.data_ptr = (char *)&reqcheck_format_status;
2N/A door_args.data_size = sizeof (smedia_services_t);
2N/A door_args.desc_ptr = NULL;
2N/A door_args.desc_num = 0;
2N/A door_args.rbuf = rbuf;
2N/A door_args.rsize = sizeof (rbuf);
2N/A
2N/A ret_val = door_call(handle->sm_door, &door_args);
2N/A if (ret_val < 0) {
2N/A perror("door_call");
2N/A return (-1);
2N/A }
2N/A retcheck_format_status =
2N/A (smedia_retcheck_format_status_t *)((void *)door_args.data_ptr);
2N/A reterror = (smedia_reterror_t *)((void *)door_args.data_ptr);
2N/A if (reterror->cnum == SMEDIA_CNUM_ERROR) {
2N/A DPRINTF1(
2N/A "Error in check_format_status. errnum = 0x%x \n", reterror->errnum);
2N/A errno = reterror->errnum;
2N/A return (-1);
2N/A }
2N/A return (retcheck_format_status->percent_complete);
2N/A}
2N/A
2N/Aint32_t
2N/A_m_uscsi_cmd(rmedia_handle_t *handle, struct uscsi_cmd *ucmd)
2N/A{
2N/A int32_t ret_val;
2N/A smedia_requscsi_cmd_t requscsi_cmd;
2N/A smedia_retuscsi_cmd_t *retuscsi_cmd;
2N/A smedia_reterror_t *reterror;
2N/A door_arg_t door_args;
2N/A char rbuf[sizeof (smedia_services_t) + sizeof (door_desc_t)];
2N/A
2N/A /* Check for valid handle */
2N/A if (handle == NULL) {
2N/A DPRINTF("Null Handle\n");
2N/A errno = EINVAL;
2N/A return (-1);
2N/A }
2N/A if (handle->sm_signature != LIBSMEDIA_SIGNATURE) {
2N/A DPRINTF("Invalid signature in handle.\n");
2N/A errno = EINVAL;
2N/A return (-1);
2N/A }
2N/A /*
2N/A * We will be validating the user supplied buffer lengths and
2N/A * buffer pointers.
2N/A */
2N/A if (ucmd->uscsi_cdblen > MAX_CDB_LEN) {
2N/A DPRINTF("Invalid cdblen specified.\n");
2N/A errno = EINVAL;
2N/A return (-1);
2N/A }
2N/A if ((ucmd->uscsi_flags & USCSI_RQENABLE) &&
2N/A (ucmd->uscsi_rqlen > MAX_RQ_LEN)) {
2N/A DPRINTF("Invalid rqlen specified.\n");
2N/A errno = EINVAL;
2N/A return (-1);
2N/A }
2N/A if (ucmd->uscsi_cdb == NULL) {
2N/A DPRINTF("cdb buffer is NULL.\n");
2N/A errno = EINVAL;
2N/A return (-1);
2N/A }
2N/A if ((ucmd->uscsi_buflen) && (ucmd->uscsi_bufaddr == NULL)) {
2N/A DPRINTF("bufaddr is NULL.\n");
2N/A errno = EINVAL;
2N/A return (-1);
2N/A }
2N/A if ((ucmd->uscsi_flags & USCSI_RQENABLE) &&
2N/A (ucmd->uscsi_rqbuf == NULL)) {
2N/A DPRINTF("rqbuf is NULL.\n");
2N/A errno = EINVAL;
2N/A return (-1);
2N/A }
2N/A /*
2N/A * Check if another thread is doing an IO with same handle.
2N/A * In that case we block here.
2N/A */
2N/A (void) mutex_lock(&handle->sm_bufmutex);
2N/A ret_val = remap_shared_buf(handle, ucmd->uscsi_buflen,
2N/A ucmd->uscsi_bufaddr);
2N/A if (ret_val != 0) {
2N/A DPRINTF("remap of shared buf failed.\n");
2N/A goto error;
2N/A }
2N/A
2N/A requscsi_cmd.cnum = SMEDIA_CNUM_USCSI_CMD;
2N/A requscsi_cmd.uscsi_flags = ucmd->uscsi_flags;
2N/A requscsi_cmd.uscsi_timeout = ucmd->uscsi_timeout;
2N/A requscsi_cmd.uscsi_buflen = ucmd->uscsi_buflen;
2N/A requscsi_cmd.uscsi_cdblen = ucmd->uscsi_cdblen;
2N/A requscsi_cmd.uscsi_rqlen = ucmd->uscsi_rqlen;
2N/A
2N/A /*
2N/A * The uscsi_buflen has been validated in the call to
2N/A * remap_shared_buf() done earlier.
2N/A */
2N/A /* Check for write */
2N/A if (!(ucmd->uscsi_flags & USCSI_READ)) {
2N/A bcopy(ucmd->uscsi_bufaddr, handle->sm_buf, ucmd->uscsi_buflen);
2N/A }
2N/A
2N/A bcopy(ucmd->uscsi_cdb, requscsi_cmd.uscsi_cdb, ucmd->uscsi_cdblen);
2N/A
2N/A door_args.data_ptr = (char *)&requscsi_cmd;
2N/A door_args.data_size = sizeof (smedia_services_t);
2N/A door_args.desc_ptr = NULL;
2N/A door_args.desc_num = 0;
2N/A door_args.rbuf = rbuf;
2N/A door_args.rsize = sizeof (rbuf);
2N/A
2N/A ret_val = door_call(handle->sm_door, &door_args);
2N/A if (ret_val < 0) {
2N/A perror("door_call");
2N/A goto error;
2N/A }
2N/A retuscsi_cmd = (smedia_retuscsi_cmd_t *)((void *)door_args.data_ptr);
2N/A reterror = (smedia_reterror_t *)((void *)door_args.data_ptr);
2N/A if (reterror->cnum == SMEDIA_CNUM_ERROR) {
2N/A DPRINTF1(
2N/A "Error in uscsi cmd. errnum = 0x%x\n", reterror->errnum);
2N/A errno = reterror->errnum;
2N/A goto error;
2N/A }
2N/A ucmd->uscsi_status = retuscsi_cmd->uscsi_status;
2N/A ucmd->uscsi_resid = retuscsi_cmd->uscsi_resid;
2N/A ucmd->uscsi_rqstatus = retuscsi_cmd->uscsi_rqstatus;
2N/A ucmd->uscsi_rqresid = retuscsi_cmd->uscsi_rqresid;
2N/A if ((ucmd->uscsi_flags & USCSI_RQENABLE) &&
2N/A (ucmd->uscsi_rqbuf != NULL)) {
2N/A bcopy(retuscsi_cmd->uscsi_rqbuf,
2N/A ucmd->uscsi_rqbuf, ucmd->uscsi_rqlen);
2N/A }
2N/A errno = retuscsi_cmd->uscsi_errno;
2N/A if (errno) {
2N/A goto error;
2N/A }
2N/A
2N/A if (ucmd->uscsi_resid > ucmd->uscsi_buflen) {
2N/A /*
2N/A * Invalid resid value. return error.
2N/A */
2N/A errno = EINVAL;
2N/A goto error;
2N/A }
2N/A if (ucmd->uscsi_flags & USCSI_READ) {
2N/A (void) memcpy(ucmd->uscsi_bufaddr,
2N/A handle->sm_buf,
2N/A ucmd->uscsi_buflen - ucmd->uscsi_resid);
2N/A }
2N/A (void) mutex_unlock(&handle->sm_bufmutex);
2N/A#ifdef DEBUG
2N/A if (retuscsi_cmd->uscsi_retval || ucmd->uscsi_status)
2N/A DPRINTF2("Error in uscsi_cmd: retval=0x%x uscsi_status=0x%x\n",
2N/A retuscsi_cmd->uscsi_retval, ucmd->uscsi_status);
2N/A#endif
2N/A return (retuscsi_cmd->uscsi_retval);
2N/Aerror:
2N/A (void) mutex_unlock(&handle->sm_bufmutex);
2N/A return (-1);
2N/A}
2N/A
2N/Aint32_t
2N/Aremap_shared_buf(rmedia_handle_t *handle, size_t buf_size, char *buffer)
2N/A{
2N/A char rbuf[sizeof (smedia_services_t) + sizeof (door_desc_t)];
2N/A char fname[128];
2N/A smedia_reqset_shfd_t reqset_shfd;
2N/A smedia_reterror_t *reterror;
2N/A int ret_val, fd;
2N/A door_arg_t door_args;
2N/A door_desc_t ddesc[2];
2N/A char *fbuf;
2N/A size_t shared_bufsize;
2N/A off_t file_size, ret;
2N/A
2N/A if (handle->sm_bufsize >= buf_size)
2N/A return (0);
2N/A shared_bufsize = ((buf_size + BUF_SIZE_MULTIPLE - 1)/BUF_SIZE_MULTIPLE)
2N/A * BUF_SIZE_MULTIPLE;
2N/A if (handle->sm_buffd != -1) {
2N/A /* extend the file and re-map */
2N/A fd = handle->sm_buffd;
2N/A ret_val = munmap(handle->sm_buf, handle->sm_bufsize);
2N/A if (ret_val != 0) {
2N/A DPRINTF1("remap:munmap failed. errno = 0x%x\n", errno);
2N/A (void) close(fd);
2N/A handle->sm_buf = NULL;
2N/A handle->sm_bufsize = 0;
2N/A handle->sm_buffd = -1;
2N/A return (errno);
2N/A }
2N/A file_size = lseek(fd, 0, SEEK_END);
2N/A if (file_size == -1) {
2N/A DPRINTF1("remap:lseek failed. errno = 0x%x\n", errno);
2N/A return (errno);
2N/A }
2N/A handle->sm_buf = NULL;
2N/A handle->sm_bufsize = 0;
2N/A handle->sm_buffd = -1;
2N/A } else {
2N/A /* create a new file and mapping */
2N/A (void) sprintf(fname, "/tmp/libsmedia_mmaped_file_XXXXXX");
2N/A fd = mkstemp(fname);
2N/A if (fd == -1) {
2N/A DPRINTF1("remap:mktemp failed. errno = 0x%x\n", errno);
2N/A return (errno);
2N/A }
2N/A ret_val = unlink(fname);
2N/A if (ret_val == -1) {
2N/A DPRINTF1("remap:unlink failed. errno = 0x%x\n", errno);
2N/A (void) close(fd);
2N/A return (errno);
2N/A }
2N/A file_size = 0;
2N/A }
2N/A /* Need to start at the beginning of the file when enlarging */
2N/A ret = lseek(fd, 0, SEEK_SET);
2N/A if (ret == -1) {
2N/A DPRINTF1("remap:lseek failed. errno = 0x%x\n", errno);
2N/A return (errno);
2N/A }
2N/A while (file_size < shared_bufsize) {
2N/A ret_val = write(fd, buffer, buf_size);
2N/A if (ret_val != buf_size) {
2N/A DPRINTF1("remap:write failed. errno = 0x%x\n", errno);
2N/A (void) close(fd);
2N/A return (errno);
2N/A }
2N/A file_size += buf_size;
2N/A }
2N/A fbuf = (char *)mmap(0, shared_bufsize, PROT_READ | PROT_WRITE,
2N/A MAP_SHARED, fd, 0);
2N/A if (fbuf == (char *)-1) {
2N/A perror("mmap failed");
2N/A (void) close(fd);
2N/A return (errno);
2N/A }
2N/A
2N/A reqset_shfd.cnum = SMEDIA_CNUM_SET_SHFD;
2N/A reqset_shfd.fdbuf_len = shared_bufsize;
2N/A ddesc[0].d_data.d_desc.d_descriptor = fd;
2N/A ddesc[0].d_attributes = DOOR_DESCRIPTOR;
2N/A door_args.data_ptr = (char *)&reqset_shfd;
2N/A door_args.data_size = sizeof (reqset_shfd);
2N/A door_args.desc_ptr = &ddesc[0];
2N/A door_args.desc_num = 1;
2N/A door_args.rbuf = rbuf;
2N/A door_args.rsize = sizeof (rbuf);
2N/A
2N/A ret_val = door_call(handle->sm_door, &door_args);
2N/A if (ret_val < 0) {
2N/A perror("door_call");
2N/A (void) close(fd);
2N/A return (-1);
2N/A }
2N/A reterror = (smedia_reterror_t *)((void *)door_args.data_ptr);
2N/A if (reterror->cnum == SMEDIA_CNUM_ERROR) {
2N/A DPRINTF1("Error in set shfd. errnum = 0x%x\n",
2N/A reterror->errnum);
2N/A errno = reterror->errnum;
2N/A (void) close(fd);
2N/A return (errno);
2N/A }
2N/A handle->sm_buffd = fd;
2N/A handle->sm_buf = fbuf;
2N/A handle->sm_bufsize = shared_bufsize;
2N/A DPRINTF("Returned successful from remap shared buf routine.\n");
2N/A return (0);
2N/A}