scsi.c

来自「网络数据管理协议的开发」· C语言 代码 · 共 430 行

C
430
字号
/*                               -*- Mode: C -*-  * scsi.c *  * Description     : NDMP SCSI request handler functions. *  * Copyright (c) 1996,1997 PDC, Network Appliance. All Rights Reserved. * * $Id: scsi.c,v 1.7 1998/02/09 06:52:38 tim Exp $ */#if !defined(lint) && !defined(SABER)static char rcsId[] __attribute__ ((unused)) = "@(#) $Id: scsi.c,v 1.7 1998/02/09 06:52:38 tim Exp $";#endif#include <unistd.h>#include <stdlib.h>#include <errno.h>#include <string.h>#include <sys/scsi/scsi.h>#include <sys/scsi/impl/uscsi.h>#include "ndmp_common.h"#include "ndmpd.h"voidexecuteCdb(NdmpdSession*				session,		   int							fd,		   ndmp_execute_cdb_request*	request);/* * ndmpdScsiOpen * * This handler opens the specified SCSI device. * * Parameters: *   connection (input) - connection handle. *   body       (input) - request message body. * * Returns: *   void */voidndmpdScsiOpen(NdmpConnection	connection,			  void*				body){	ndmp_scsi_open_request*		request		= (ndmp_scsi_open_request *)body;	ndmp_scsi_open_reply		reply;	NdmpdSession*				session = ndmpGetClientData(connection);		Debug(DBG_CAT_SCSI|DBG_FOC_FLOW,		  "ndmpdScsiOpen: device:%s.\n",		  request->device);	memset((void*)&reply, 0, sizeof(reply));		if (session->tape.fd != -1 ||		session->scsi.fd != -1)	{		Error(LOG_ERR,			  "ndmpdScsiOpen: connection already has a tape or scsi device open.\n");		reply.error = NDMP_DEVICE_OPENED_ERR;		if (ndmpSendReply(connection, NDMP_NO_ERR, (void *)&reply) < 0)			Error(LOG_ERR, "ndmpdScsiOpen: error sending scsi_open reply.\n");		return;	}	if ((session->scsi.fd = open(request->device, O_RDONLY)) < 0)	{		Error(LOG_ERR,			  "ndmpdScsiOpen: error opening SCSI device: %s: %s.\n",			  request->device, strerror(errno));		switch (errno)		{			case EACCES: 				reply.error = NDMP_WRITE_PROTECT_ERR;				break;			case ENOENT: 				reply.error = NDMP_NO_DEVICE_ERR;				break;			case EBUSY:				reply.error = NDMP_DEVICE_BUSY_ERR;				break;			default:				reply.error = NDMP_IO_ERR;				break;		}				if (ndmpSendReply(connection, NDMP_NO_ERR, (void *)&reply) < 0)			Error(LOG_ERR, "ndmpdScsiOpen: error sending scsi_open reply.\n");		return;	}		reply.error = NDMP_NO_ERR;	if (ndmpSendReply(connection, NDMP_NO_ERR, (void *)&reply) < 0)		Error(LOG_ERR, "ndmpdScsiOpen: error sending scsi_open reply.\n");}/* * ndmpdScsiClose * * This handler closes the currently open SCSI device. * * Parameters: *   connection (input) - connection handle. *   body       (input) - request message body. * * Returns: *   void */voidndmpdScsiClose(NdmpConnection	connection,			  void*				body __attribute__ ((unused))){	ndmp_scsi_close_reply		reply;	NdmpdSession*				session = ndmpGetClientData(connection);		Debug(DBG_CAT_SCSI|DBG_FOC_FLOW,		  "ndmpdScsiClose:\n");	memset((void*)&reply, 0, sizeof(reply));		if (session->scsi.fd == -1)	{		Error(LOG_ERR,			  "ndmpdScsiClose: SCSI device is not open.\n");		reply.error = NDMP_DEV_NOT_OPEN_ERR;		if (ndmpSendReply(connection, NDMP_NO_ERR, (void *)&reply) < 0)			Error(LOG_ERR, "ndmpScsiClose: error sending scsi_close reply.\n");		return;	}	(void) close(session->scsi.fd);	session->scsi.fd = -1;	reply.error = NDMP_NO_ERR;	if (ndmpSendReply(connection, NDMP_NO_ERR, (void *)&reply) < 0)		Error(LOG_ERR, "ndmpdScsiClose: error sending scsi_close reply.\n");}/* * ndmpdScsiGetState * * This handler returns state information for the currently open SCSI device. * Since the implementation only supports the opening of a specific SCSI * device, as opposed to a device that can talk to multiple SCSI targets, * this request is not supported. This request is only appropriate for * implementations that support device files that can target multiple * SCSI devices. * * Parameters: *   connection (input) - connection handle. *   body       (input) - request message body. * * Returns: *   void */voidndmpdScsiGetState(NdmpConnection	connection,			  void*					body __attribute__ ((unused))){	ndmp_scsi_get_state_reply	reply;	Debug(DBG_CAT_SCSI|DBG_FOC_FLOW,		  "ndmpdScsiGetState:\n");	Error(LOG_ERR, "ndmpdScsiGetState: request not yet supported.\n");		reply.error = NDMP_NOT_SUPPORTED_ERR;	if (ndmpSendReply(connection, NDMP_NO_ERR, (void *)&reply) < 0)		Error(LOG_ERR, "ndmpdScsiGetState: error sending scsi_get_state reply.\n");}/* * ndmpdScsiSetTarget * * This handler sets the SCSI target of the SCSI device. * It is only valid to use this request if the opened SCSI device * is capable of talking to multiple SCSI targets. * Since the implementation only supports the opening of a specific SCSI * device, as opposed to a device that can talk to multiple SCSI targets, * this request is not supported. This request is only appropriate for * implementations that support device files that can target multiple * SCSI devices. * * Parameters: *   connection (input) - connection handle. *   body       (input) - request message body. * * Returns: *   void */voidndmpdScsiSetTarget(NdmpConnection	connection,			  void*				body){	ndmp_scsi_set_target_request*	request		= (ndmp_scsi_set_target_request *)body;	ndmp_scsi_set_target_reply		reply;		Debug(DBG_CAT_SCSI|DBG_FOC_FLOW,		  "ndmpdScsiSetTarget: device:%s.\n",		  request->device);	memset((void*)&reply, 0, sizeof(reply));		Error(LOG_ERR, "ndmpdScsiSetTarget: request not yet supported.\n");		reply.error = NDMP_NOT_SUPPORTED_ERR;	if (ndmpSendReply(connection, NDMP_NO_ERR, (void *)&reply) < 0)		Error(LOG_ERR,			  "ndmpdScsiSetTarget: error sending scsi_set_target reply.\n");}/* * ndmpdScsiResetDevice * * This handler resets the currently targeted SCSI device. * * Parameters: *   connection (input) - connection handle. *   body       (input) - request message body. * * Returns: *   void */voidndmpdScsiResetDevice(NdmpConnection	connection,			  void*				body __attribute__ ((unused))){	ndmp_scsi_reset_device_reply	reply;	NdmpdSession*					session = ndmpGetClientData(connection);	struct uscsi_cmd				cmd;		Debug(DBG_CAT_SCSI|DBG_FOC_FLOW,		  "ndmpdScsiResetDevice:\n");	memset((void*)&reply, 0, sizeof(reply));		if (session->scsi.fd == -1)	{		Error(LOG_ERR,			  "ndmpdScsiResetDevice: SCSI device is not open.\n");		reply.error = NDMP_DEV_NOT_OPEN_ERR;		if (ndmpSendReply(connection, NDMP_NO_ERR, (void *)&reply) < 0)			Error(LOG_ERR, "ndmpdScsiResetDevice: error sending scsi_reset_device reply.\n");		return;	}	reply.error = NDMP_NO_ERR;	memset((void*)&cmd, 0, sizeof(cmd));	cmd.uscsi_flags |= USCSI_RESET;	if (ioctl(session->scsi.fd, USCSICMD, &cmd) < 0)	{		Error(LOG_ERR,			  "ndmpdScsiResetDevice: ioctl(USCSICMD) error: %s.\n",			  strerror(errno));		reply.error = NDMP_IO_ERR;	}		if (ndmpSendReply(connection, NDMP_NO_ERR, (void *)&reply) < 0)		Error(LOG_ERR,			  "ndmpdScsiResetDevice: error sending scsi_reset_device reply.\n");}/* * ndmpdScsiResetBus * * This handler resets the currently targeted SCSI bus. * * Request not yet supported. *  * Parameters: *   connection (input) - connection handle. *   body       (input) - request message body. * * Returns: *   void */voidndmpdScsiResetBus(NdmpConnection	connection,			  void*					body __attribute__ ((unused))){	ndmp_scsi_reset_bus_reply		reply;		Debug(DBG_CAT_SCSI|DBG_FOC_FLOW,		  "ndmpdScsiResetBus:\n");	memset((void*)&reply, 0, sizeof(reply));		Error(LOG_ERR, "ndmpdScsiResetBus: request not supported.\n");	reply.error = NDMP_NOT_SUPPORTED_ERR;		if (ndmpSendReply(connection, NDMP_NO_ERR, (void *)&reply) < 0)		Error(LOG_ERR,			  "ndmpdScsiResetBus: error sending scsi_reset_bus reply.\n");}/* * ndmpdScsiExecuteCdb * * This handler sends the CDB to the currently targeted SCSI device. * * Parameters: *   connection (input) - connection handle. *   body       (input) - request message body. * * Returns: *   void */voidndmpdScsiExecuteCdb(NdmpConnection	connection,			  void*					body){	ndmp_execute_cdb_request*	request		= (ndmp_execute_cdb_request *)body;	ndmp_execute_cdb_reply		reply;	NdmpdSession*				session = ndmpGetClientData(connection);		Debug(DBG_CAT_SCSI|DBG_FOC_FLOW,		  "ndmpdScsiExecuteCdb:\n");	memset((void*)&reply, 0, sizeof(reply));		if (session->scsi.fd == -1)	{		memset((void*)&reply, 0, sizeof(reply));				Error(LOG_ERR,			  "ndmpdScsiExecuteCdb: SCSI device is not open.\n");		reply.error = NDMP_DEV_NOT_OPEN_ERR;		if (ndmpSendReply(connection, NDMP_NO_ERR, (void *)&reply) < 0)			Error(LOG_ERR, "ndmpdScsiExecuteCdb: sending scsi_execute_cdb reply.\n");		return;	}	executeCdb(session, session->scsi.fd, request);}voidexecuteCdb(NdmpdSession*				session,		   int							fd,		   ndmp_execute_cdb_request*	request){	ndmp_execute_cdb_reply	reply;	struct uscsi_cmd		cmd;	char					rqBuf[255];		memset((void*)&cmd, 0, sizeof(cmd));	memset((void*)&reply, 0, sizeof(reply));		if (request->flags == NDMP_SCSI_DATA_IN)	{		cmd.uscsi_flags = USCSI_READ;		if ((cmd.uscsi_bufaddr = (caddr_t)malloc(request->datain_len)) == 0)		{			Error(LOG_ERR,				  "executeCdb: malloc error: %s.\n",				  strerror(errno));			reply.error = NDMP_NO_MEM_ERR;			if (ndmpSendReply(session->connection, NDMP_NO_ERR,							  (void *)&reply) < 0)				Error(LOG_ERR,					  "executeCdb: error sending scsi_execute_cdb reply.\n");			return;		}		cmd.uscsi_buflen = request->datain_len;	}	else	{		cmd.uscsi_flags   = USCSI_WRITE;		cmd.uscsi_bufaddr = request->dataout.dataout_val;		cmd.uscsi_buflen  = request->dataout.dataout_len;	}		cmd.uscsi_timeout = request->timeout/1000;	cmd.uscsi_cdb     = (caddr_t) request->cdb.cdb_val;	cmd.uscsi_cdblen  = request->cdb.cdb_len;	cmd.uscsi_rqlen   = sizeof(rqBuf);	cmd.uscsi_rqbuf   = rqBuf;	reply.error = NDMP_NO_ERR;		if (ioctl(fd, USCSICMD, &cmd) < 0)	{		Error(LOG_ERR,			  "executeCdb: ioctl(USCSICMD) error: %s.\n",			  strerror(errno));		reply.error = NDMP_IO_ERR;	}	reply.status = cmd.uscsi_status;	if (request->flags == NDMP_SCSI_DATA_IN)	{		reply.datain.datain_len = request->datain_len - cmd.uscsi_resid;		reply.datain.datain_val = cmd.uscsi_bufaddr;	}	else	{		reply.dataout_len = request->dataout.dataout_len - cmd.uscsi_resid;	}	reply.ext_sense.ext_sense_len = sizeof(rqBuf) - cmd.uscsi_rqresid;	reply.ext_sense.ext_sense_val = rqBuf;		if (ndmpSendReply(session->connection, NDMP_NO_ERR, (void *)&reply) < 0)		Error(LOG_ERR,			  "executeCdb: error sending scsi_execute_cdb reply.\n");}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?