xref: /titanic_54/usr/src/cmd/smserverd/smediad.c (revision 910cba4f2f1e94daf355ee8635285732ac47326c)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5004388ebScasper  * Common Development and Distribution License (the "License").
6004388ebScasper  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
217c478bd9Sstevel@tonic-gate /*
22004388ebScasper  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
237c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
247c478bd9Sstevel@tonic-gate  */
257c478bd9Sstevel@tonic-gate 
267c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
277c478bd9Sstevel@tonic-gate 
287c478bd9Sstevel@tonic-gate #include <stdio.h>
29004388ebScasper #include <stdio_ext.h>
307c478bd9Sstevel@tonic-gate #include <errno.h>
317c478bd9Sstevel@tonic-gate #include <ctype.h>
327c478bd9Sstevel@tonic-gate #include <syslog.h>
337c478bd9Sstevel@tonic-gate #include <signal.h>
347c478bd9Sstevel@tonic-gate #include <limits.h>
357c478bd9Sstevel@tonic-gate #include <unistd.h>
367c478bd9Sstevel@tonic-gate #include <sys/types.h>
377c478bd9Sstevel@tonic-gate #include <sys/mman.h>
387c478bd9Sstevel@tonic-gate #include <stdlib.h>
397c478bd9Sstevel@tonic-gate #include <sys/stat.h>
407c478bd9Sstevel@tonic-gate #include <sys/mkdev.h>
417c478bd9Sstevel@tonic-gate #include <fcntl.h>
427c478bd9Sstevel@tonic-gate #include <sys/scsi/scsi.h>
437c478bd9Sstevel@tonic-gate #include <sys/scsi/generic/commands.h>
447c478bd9Sstevel@tonic-gate #include <string.h>
457c478bd9Sstevel@tonic-gate #include <door.h>
467c478bd9Sstevel@tonic-gate #include <pwd.h>
477c478bd9Sstevel@tonic-gate #include <thread.h>
487c478bd9Sstevel@tonic-gate #include <synch.h>
497c478bd9Sstevel@tonic-gate #include <pthread.h>
507c478bd9Sstevel@tonic-gate #include <locale.h>
517c478bd9Sstevel@tonic-gate #include <sys/resource.h>
527c478bd9Sstevel@tonic-gate #include <netconfig.h>
537c478bd9Sstevel@tonic-gate #include <sys/smedia.h>
547c478bd9Sstevel@tonic-gate #include "smserver.h"
557c478bd9Sstevel@tonic-gate #include <rpc/rpc.h>
567c478bd9Sstevel@tonic-gate #include "smed.h"
577c478bd9Sstevel@tonic-gate #include "myaudit.h"
587c478bd9Sstevel@tonic-gate #include <bsm/libbsm.h>
597c478bd9Sstevel@tonic-gate #include <bsm/audit_uevents.h>
607c478bd9Sstevel@tonic-gate #include <utmpx.h>
617c478bd9Sstevel@tonic-gate 
627c478bd9Sstevel@tonic-gate 
637c478bd9Sstevel@tonic-gate /*
647c478bd9Sstevel@tonic-gate  * The comments below would help in understanding what is being attempted
657c478bd9Sstevel@tonic-gate  * in the server.
667c478bd9Sstevel@tonic-gate  *
677c478bd9Sstevel@tonic-gate  * The server can be started either by inetd or by the client directly.
687c478bd9Sstevel@tonic-gate  * Normally the server is started by inetd when the client invokes the
697c478bd9Sstevel@tonic-gate  * appropriate libsmedia library call(smedia_get_handle).
707c478bd9Sstevel@tonic-gate  * However since the inetd runs only at init level 2 and above a mechanism
717c478bd9Sstevel@tonic-gate  * is provided for the server to be started if an attempt is made to use
727c478bd9Sstevel@tonic-gate  * the libsmedia calls in maintenence mode(init level 1).
737c478bd9Sstevel@tonic-gate  * The main() routine determines how the server was invoked and takes
747c478bd9Sstevel@tonic-gate  * the necessary action.
757c478bd9Sstevel@tonic-gate  * When started by inetd it registers itself as an RPC program.
767c478bd9Sstevel@tonic-gate  * The server also implements a mechanism by which it removes itself
777c478bd9Sstevel@tonic-gate  * after a period of inactivity. The period of inactivity is specified
787c478bd9Sstevel@tonic-gate  * by SVC_CLOSEDOWN which is set at 180 secs.
797c478bd9Sstevel@tonic-gate  * The logic of detecting inactivity is as follows:
807c478bd9Sstevel@tonic-gate  *
817c478bd9Sstevel@tonic-gate  * Two variables svcstate and svccount are used to determine if the server
827c478bd9Sstevel@tonic-gate  * is IDLE.
837c478bd9Sstevel@tonic-gate  * The svcstate is set to 1(_SERVED) when ever the server does any operation
847c478bd9Sstevel@tonic-gate  * on behalf of the client.
857c478bd9Sstevel@tonic-gate  * The svccount indicates the number of active clients who have established
867c478bd9Sstevel@tonic-gate  * a connection with the server. A connection is established when the
877c478bd9Sstevel@tonic-gate  * libsmedia call smedia_get_handle() succeeds.
887c478bd9Sstevel@tonic-gate  * The connection is broken when the client calls smedia_free_handle() OR
897c478bd9Sstevel@tonic-gate  * exits.
907c478bd9Sstevel@tonic-gate  * A thread called closedown is started up when server is started.
917c478bd9Sstevel@tonic-gate  * This thread runs periodically and monitors both svcstate and svccount.
927c478bd9Sstevel@tonic-gate  * If svcstate is IDLE and svccount is 0 then server exits.
937c478bd9Sstevel@tonic-gate  * The svcstate is set to IDLE by the closedown thread. It is set to _SERVED
947c478bd9Sstevel@tonic-gate  * by server. It is possible for the state to be _SERVED and the svccount
957c478bd9Sstevel@tonic-gate  * to be 0. The server could be kept busy by client calls of smedia_get_handle
967c478bd9Sstevel@tonic-gate  * that do not succeed. This is the reason for using both svcstate and svccount
977c478bd9Sstevel@tonic-gate  * to determine the true server state.
987c478bd9Sstevel@tonic-gate  *
997c478bd9Sstevel@tonic-gate  * The communication between client and server is thru door calls.
1007c478bd9Sstevel@tonic-gate  * Below are the door descriptors available to communicate to the server.
1017c478bd9Sstevel@tonic-gate  *
1027c478bd9Sstevel@tonic-gate  * main_door_descriptor:
1037c478bd9Sstevel@tonic-gate  * ---------------------
1047c478bd9Sstevel@tonic-gate  * 	This is a predefined descriptor used by client to establish a
1057c478bd9Sstevel@tonic-gate  * connection with the server. This descriptor is available to the client
1067c478bd9Sstevel@tonic-gate  * as /var/adm/smedia_svc
1075363f09cSarutz  * The client uses the main_door_descriptor to obtain a dedicated
1087c478bd9Sstevel@tonic-gate  * client_door_descriptor for itself. The smedia_get_handle call communicates
1097c478bd9Sstevel@tonic-gate  * to the server using the main_door_descriptor and obtains the
1107c478bd9Sstevel@tonic-gate  * client_door_descriptor which is stored in the handle structure.
1117c478bd9Sstevel@tonic-gate  * All other libsmedia calls use the client_door_descriptor to communicate
1127c478bd9Sstevel@tonic-gate  * with the server.
1137c478bd9Sstevel@tonic-gate  *
1147c478bd9Sstevel@tonic-gate  * client_door_descriptor:
1157c478bd9Sstevel@tonic-gate  * -----------------------
1167c478bd9Sstevel@tonic-gate  *	This is the door descriptor that is used by the clients to
1177c478bd9Sstevel@tonic-gate  * request server to perform the necessary tasks. This door descriptor is
1187c478bd9Sstevel@tonic-gate  * available only to the client for whom it was created.
1197c478bd9Sstevel@tonic-gate  *
1207c478bd9Sstevel@tonic-gate  * death_door_descriptor:
1217c478bd9Sstevel@tonic-gate  * ----------------------
1225363f09cSarutz  * 	The sole function of this descriptor HAD been to inform the server of
1235363f09cSarutz  * the untimely death of the client. This descriptor is no longer used, though
1245363f09cSarutz  * it is still created, as libsmedia expects to use it.  This descriptor's
1255363f09cSarutz  * service procedure had used pthread cancellation(5) to terminate the thread of
1265363f09cSarutz  * the associated client_door_descriptor.  The client_door_descriptor now
1275363f09cSarutz  * handles the scenarios where a door_call/client are aborted/terminated.
1287c478bd9Sstevel@tonic-gate  *
1295363f09cSarutz  * main_servproc()
1307c478bd9Sstevel@tonic-gate  * -------------
1317c478bd9Sstevel@tonic-gate  *	This is the routine associated with the main_door_descriptor.
1327c478bd9Sstevel@tonic-gate  * This is the routine that handles the smedia_get_handle() call
1337c478bd9Sstevel@tonic-gate  * of the client. If the door call to this routine succeeds it creates a
1347c478bd9Sstevel@tonic-gate  * client_door_descriptor that is used by the client in subsequent library
1357c478bd9Sstevel@tonic-gate  * calls.
1367c478bd9Sstevel@tonic-gate  * This client_door_descriptor is passed to the client thru the door_return
1377c478bd9Sstevel@tonic-gate  * call. This client_door_descriptor cannot be used by any other process other
1387c478bd9Sstevel@tonic-gate  * than the client process that obtained it.
1397c478bd9Sstevel@tonic-gate  * In addition to the client_door_descriptor a death_door_descriptor is also
1407c478bd9Sstevel@tonic-gate  * created by the main server and passed on to the client. The client does not
1415363f09cSarutz  * use the death_door_descriptor.
1427c478bd9Sstevel@tonic-gate  *
1435363f09cSarutz  * client_servproc()
1447c478bd9Sstevel@tonic-gate  * ---------------
1457c478bd9Sstevel@tonic-gate  *	This is the routine that handles the libsmedia calls of the
1467c478bd9Sstevel@tonic-gate  * client. In the current implementation the server takes control of the
1477c478bd9Sstevel@tonic-gate  * number of threads that handle the door calls. This is done by creating the
1487c478bd9Sstevel@tonic-gate  * door descriptor as DOOR_PRIVATE.
1497c478bd9Sstevel@tonic-gate  * The server runs only one thread per handle. This makes the implementation
1507c478bd9Sstevel@tonic-gate  * simple as we do not have to use mutex to make the code MT safe.
1515363f09cSarutz  * The server thread has a data structure door_data_t associated with it.
1527c478bd9Sstevel@tonic-gate  *
1537c478bd9Sstevel@tonic-gate  * door_data_t
1547c478bd9Sstevel@tonic-gate  * -----------
1555363f09cSarutz  * This is the data structure that is created by the main_servproc when it
1567c478bd9Sstevel@tonic-gate  * creates the client_door_descriptor. The door mechanism has a way to associate
1577c478bd9Sstevel@tonic-gate  * a cookie with the door descriptor. door_data_t is the cookie for the
1585363f09cSarutz  * client_door_descriptor. This cookie is passed to the server function that
1595363f09cSarutz  * handles the client_door_descriptor calls. In our case it is the
1605363f09cSarutz  * client_servproc routine.
1617c478bd9Sstevel@tonic-gate  * The key elements of the door_data_t are the following:
1627c478bd9Sstevel@tonic-gate  *
1637c478bd9Sstevel@tonic-gate  *	dd_fd		file descriptor for the device.
1647c478bd9Sstevel@tonic-gate  *	dd_buf		The shared memory buffer between client-server.
1657c478bd9Sstevel@tonic-gate  *	dd_thread	The thread that handles the door_calls.
1667c478bd9Sstevel@tonic-gate  *
1677c478bd9Sstevel@tonic-gate  * signal handling:
1687c478bd9Sstevel@tonic-gate  * ----------------
1697c478bd9Sstevel@tonic-gate  *		The main purpose of trapping the signals is to exit gracefully
1707c478bd9Sstevel@tonic-gate  * from the server after recording the appropriate message in the syslog.
1717c478bd9Sstevel@tonic-gate  * This will help the administrator to determine the cause of failure of the
1727c478bd9Sstevel@tonic-gate  * server by examining the log file.
1737c478bd9Sstevel@tonic-gate  *
1747c478bd9Sstevel@tonic-gate  * cleanup()
1757c478bd9Sstevel@tonic-gate  * ---------
1767c478bd9Sstevel@tonic-gate  *	This routine frees up all the resources allocated for the client.
1775363f09cSarutz  * Resources include the file descriptor, shared memory, threads.
1787c478bd9Sstevel@tonic-gate  *
1797c478bd9Sstevel@tonic-gate  * shared memory
1807c478bd9Sstevel@tonic-gate  * -------------
1817c478bd9Sstevel@tonic-gate  *	In order to reduce the overheads of moving large amounts of data
1827c478bd9Sstevel@tonic-gate  * during raw read/write operations, the server uses the mmapped data of
1837c478bd9Sstevel@tonic-gate  * client. The smedia_raw_read, smedia_raw_write library calls mmap the
1847c478bd9Sstevel@tonic-gate  * memory and pass on the file descriptor that maps the memory to the server.
1857c478bd9Sstevel@tonic-gate  * The server subsequently uses this mmapped memory during the IO.
1867c478bd9Sstevel@tonic-gate  * If the mmapped memory changes in size, the server is informed and it
1877c478bd9Sstevel@tonic-gate  * remaps the memory to the changed size.
1887c478bd9Sstevel@tonic-gate  */
1897c478bd9Sstevel@tonic-gate #ifdef DEBUG
1907c478bd9Sstevel@tonic-gate #define	DEFAULT_VERBOSE		1
1917c478bd9Sstevel@tonic-gate #define	DEFAULT_DEBUG		1
1927c478bd9Sstevel@tonic-gate #else
1937c478bd9Sstevel@tonic-gate #define	DEFAULT_VERBOSE		0
1947c478bd9Sstevel@tonic-gate #define	DEFAULT_DEBUG		0
1957c478bd9Sstevel@tonic-gate #endif
1967c478bd9Sstevel@tonic-gate 
1977c478bd9Sstevel@tonic-gate #define	N_BADSIGS		(sizeof (badsigs)/sizeof (badsigs[0]))
1987c478bd9Sstevel@tonic-gate #define	MD_LEN			30
1997c478bd9Sstevel@tonic-gate #define	MAXUGNAME		10
2007c478bd9Sstevel@tonic-gate #define	SVC_CLOSEDOWN 		180
2017c478bd9Sstevel@tonic-gate 
2027c478bd9Sstevel@tonic-gate /*
2037c478bd9Sstevel@tonic-gate  * We will NOT be permitting the following USCI cmd options.
2047c478bd9Sstevel@tonic-gate  *
2057c478bd9Sstevel@tonic-gate  * RESET of target
2067c478bd9Sstevel@tonic-gate  * RESET of  Bus.
2077c478bd9Sstevel@tonic-gate  * Tagged commands to device
2087c478bd9Sstevel@tonic-gate  * Explicitly setting SYNC/ASYNC mode of operations.
2097c478bd9Sstevel@tonic-gate  * POLLED MODE of operation.
2107c478bd9Sstevel@tonic-gate  * Explicitly setting NO DISCONNECT features.
2117c478bd9Sstevel@tonic-gate  * use of RESERVED flags.
2127c478bd9Sstevel@tonic-gate  */
2137c478bd9Sstevel@tonic-gate #define	FORBIDDEN_FLAGS		(USCSI_RESET | USCSI_RESET_ALL | USCSI_RENEGOT \
2147c478bd9Sstevel@tonic-gate 				| USCSI_ASYNC  | USCSI_SYNC | USCSI_NOINTR | \
2157c478bd9Sstevel@tonic-gate 				USCSI_NOTAG | USCSI_NOPARITY | USCSI_NODISCON \
2167c478bd9Sstevel@tonic-gate 				| USCSI_RESERVED)
2177c478bd9Sstevel@tonic-gate 
2187c478bd9Sstevel@tonic-gate /* States a server can be in wrt request */
2197c478bd9Sstevel@tonic-gate 
2207c478bd9Sstevel@tonic-gate #define	_IDLE 0
2217c478bd9Sstevel@tonic-gate #define	_SERVED 1
2227c478bd9Sstevel@tonic-gate 
2237c478bd9Sstevel@tonic-gate static char		*prog_name;
2247c478bd9Sstevel@tonic-gate static int svcstate = _IDLE;	/* Set when a request is serviced */
2257c478bd9Sstevel@tonic-gate static int svccount = 0;	/* Number of requests being serviced */
2267c478bd9Sstevel@tonic-gate static int svcstart_level = 0;	/* init level when server was started */
2277c478bd9Sstevel@tonic-gate static mutex_t svcstate_lock;	/* lock for svcstate, svccount */
2287c478bd9Sstevel@tonic-gate 
2297c478bd9Sstevel@tonic-gate extern	void smserverprog_1(struct svc_req *, SVCXPRT *);
2307c478bd9Sstevel@tonic-gate 
2317c478bd9Sstevel@tonic-gate /*
2327c478bd9Sstevel@tonic-gate  * Log messages
2337c478bd9Sstevel@tonic-gate  */
2347c478bd9Sstevel@tonic-gate #define	SIGACT_FAILED	"Failed to install signal handler for %s: %s"
2357c478bd9Sstevel@tonic-gate #define	BADSIG_MSG	"Thread %d Caught signal %d addr=%p trapno=%d pc=%p"
2367c478bd9Sstevel@tonic-gate 
2377c478bd9Sstevel@tonic-gate static int	badsigs[] = {SIGSEGV, SIGBUS, SIGFPE, SIGILL};
2387c478bd9Sstevel@tonic-gate 
2397c478bd9Sstevel@tonic-gate /* global variables */
2407c478bd9Sstevel@tonic-gate int		verbose		= DEFAULT_VERBOSE;
2417c478bd9Sstevel@tonic-gate int		debug_level	= DEFAULT_DEBUG;
2427c478bd9Sstevel@tonic-gate char		*smediad_devdir = DEFAULT_SMEDIAD_DEVDIR;
2437c478bd9Sstevel@tonic-gate 
2447c478bd9Sstevel@tonic-gate thread_key_t	door_key;
2457c478bd9Sstevel@tonic-gate 
2467c478bd9Sstevel@tonic-gate server_data_t	server_data;
2477c478bd9Sstevel@tonic-gate 
2487c478bd9Sstevel@tonic-gate static int	server_door, server_fd;
2497c478bd9Sstevel@tonic-gate 
2507c478bd9Sstevel@tonic-gate static int32_t do_uscsi_cmd(int32_t file, struct uscsi_cmd *uscsi_cmd,
2517c478bd9Sstevel@tonic-gate 		int32_t flag);
2525363f09cSarutz static void client_servproc(void *cookie, char *argp, size_t arg_size,
2537c478bd9Sstevel@tonic-gate 		door_desc_t *dp, uint_t ndesc);
2547c478bd9Sstevel@tonic-gate static void cleanup(door_data_t *);
2557c478bd9Sstevel@tonic-gate static void *init_server(void *);
2567c478bd9Sstevel@tonic-gate static int32_t scsi_reassign_block(int32_t fd, diskaddr_t);
2577c478bd9Sstevel@tonic-gate static int32_t get_mode_page(int32_t fd, uchar_t pc, uchar_t page_code,
2587c478bd9Sstevel@tonic-gate 	uchar_t *md_data, uchar_t data_len);
2597c478bd9Sstevel@tonic-gate static int32_t get_device_type(char *v_name);
2607c478bd9Sstevel@tonic-gate static int32_t get_device_type_scsi(int32_t fd, struct scsi_inquiry *inq);
2617c478bd9Sstevel@tonic-gate 
2627c478bd9Sstevel@tonic-gate static int32_t scsi_format(int32_t fd, uint_t flavor, uint_t mode);
2637c478bd9Sstevel@tonic-gate static int32_t scsi_media_status(int32_t fd);
2647c478bd9Sstevel@tonic-gate static int32_t scsi_write_protect(int32_t fd, smwp_state_t *wp);
2657c478bd9Sstevel@tonic-gate static int32_t scsi_floppy_media_status(int32_t fd);
2667c478bd9Sstevel@tonic-gate static int32_t scsi_floppy_write_protect(int32_t fd, smwp_state_t *wp);
2677c478bd9Sstevel@tonic-gate static int32_t scsi_floppy_format(int32_t, uint_t, uint_t);
2687c478bd9Sstevel@tonic-gate static int32_t get_floppy_geom(int32_t fd, uint32_t capacity,
2697c478bd9Sstevel@tonic-gate 			struct dk_geom *dkgeom);
2707c478bd9Sstevel@tonic-gate static int32_t get_media_capacity(int32_t fd, uint32_t *capacity,
2717c478bd9Sstevel@tonic-gate 			uint32_t *blocksize);
2727c478bd9Sstevel@tonic-gate 
2737c478bd9Sstevel@tonic-gate static int32_t scsi_ls120_format(uint_t fd, uint_t flavor, uint32_t capacity,
2747c478bd9Sstevel@tonic-gate 			uint32_t blocksize);
2757c478bd9Sstevel@tonic-gate 
2765363f09cSarutz static void *sm_server_thread(void *arg);
2775363f09cSarutz static void sm_door_server_create(door_info_t *dip);
2787c478bd9Sstevel@tonic-gate static void term_handler(int sig, siginfo_t *siginfo, void *sigctx);
2797c478bd9Sstevel@tonic-gate static void hup_handler(int sig, siginfo_t *siginfo, void *sigctx);
2807c478bd9Sstevel@tonic-gate static void sig_handler(int sig, siginfo_t *siginfo, void *sigctx);
2817c478bd9Sstevel@tonic-gate static void badsig_handler(int sig, siginfo_t *siginfo, void *sigctx);
2827c478bd9Sstevel@tonic-gate static void server_badsig_handler(int sig, siginfo_t *siginfo, void *sigctx);
2837c478bd9Sstevel@tonic-gate static char *xlate_state(int32_t);
2847c478bd9Sstevel@tonic-gate static uint32_t	get_sector_size(int fd);
2857c478bd9Sstevel@tonic-gate static int32_t raw_read(door_data_t *door_dp, smedia_services_t *req);
2867c478bd9Sstevel@tonic-gate static int32_t raw_write(door_data_t *door_dp, smedia_services_t *req);
2877c478bd9Sstevel@tonic-gate static int32_t reassign_block(door_data_t *door_dp, smedia_services_t *req);
2887c478bd9Sstevel@tonic-gate static int32_t set_protection_status(door_data_t *door_dp,
2897c478bd9Sstevel@tonic-gate 			smedia_services_t *req);
2907c478bd9Sstevel@tonic-gate static int32_t set_shfd(door_data_t *door_dp, int32_t fd,
2917c478bd9Sstevel@tonic-gate 			smedia_services_t *req);
2927c478bd9Sstevel@tonic-gate 
2937c478bd9Sstevel@tonic-gate static void door_ret_err(smedia_reterror_t *reterror, int32_t err);
2947c478bd9Sstevel@tonic-gate static void my_door_return(char *data_ptr, size_t data_size,
2957c478bd9Sstevel@tonic-gate 			door_desc_t *desc_ptr, uint_t num_desc);
2967c478bd9Sstevel@tonic-gate static int32_t invalid_uscsi_operation(door_data_t *, struct uscsi_cmd *);
2977c478bd9Sstevel@tonic-gate 
2987c478bd9Sstevel@tonic-gate #define	W_E_MASK	0x80
2997c478bd9Sstevel@tonic-gate 
3007c478bd9Sstevel@tonic-gate static smserver_info server_info;
3017c478bd9Sstevel@tonic-gate 
3027c478bd9Sstevel@tonic-gate static int32_t
3037c478bd9Sstevel@tonic-gate invalid_uscsi_operation(door_data_t *door_dp, struct uscsi_cmd *ucmd)
3047c478bd9Sstevel@tonic-gate {
3057c478bd9Sstevel@tonic-gate 
3067c478bd9Sstevel@tonic-gate 	if (door_dp->dd_dkinfo.dki_ctype != DKC_CDROM) {
3077c478bd9Sstevel@tonic-gate 		debug(5,
3087c478bd9Sstevel@tonic-gate 		"Invalid device type(0x%x) found for uscsi cmd.\n",
3097c478bd9Sstevel@tonic-gate 			door_dp->dd_dkinfo.dki_ctype);
3107c478bd9Sstevel@tonic-gate 		errno = EINVAL;
3117c478bd9Sstevel@tonic-gate 		return (EINVAL);
3127c478bd9Sstevel@tonic-gate 	}
3137c478bd9Sstevel@tonic-gate 	if (ucmd->uscsi_flags & FORBIDDEN_FLAGS) {
3147c478bd9Sstevel@tonic-gate 		debug(5,
3157c478bd9Sstevel@tonic-gate 		"Invalid flags(0x%x) set in uscsi cmd. cdb[0]=0x%x\n",
3167c478bd9Sstevel@tonic-gate 		ucmd->uscsi_flags,  ucmd->uscsi_cdb[0]);
3177c478bd9Sstevel@tonic-gate 		errno = EINVAL;
3187c478bd9Sstevel@tonic-gate 		return (EINVAL);
3197c478bd9Sstevel@tonic-gate 	}
3207c478bd9Sstevel@tonic-gate 	if (ucmd->uscsi_cdb[0] == SCMD_COPY ||
3217c478bd9Sstevel@tonic-gate 	    ucmd->uscsi_cdb[0] == SCMD_COPY_VERIFY ||
3227c478bd9Sstevel@tonic-gate 	    ucmd->uscsi_cdb[0] == SCMD_COMPARE ||
3237c478bd9Sstevel@tonic-gate 	    ucmd->uscsi_cdb[0] == SCMD_WRITE_BUFFER) {
3247c478bd9Sstevel@tonic-gate 		debug(5,
3257c478bd9Sstevel@tonic-gate 		"Invalid command(0x%x) found in cdb.\n",
3267c478bd9Sstevel@tonic-gate 		ucmd->uscsi_cdb[0]);
3277c478bd9Sstevel@tonic-gate 		errno = EINVAL;
3287c478bd9Sstevel@tonic-gate 		return (EINVAL);
3297c478bd9Sstevel@tonic-gate 	}
3307c478bd9Sstevel@tonic-gate 	return (0);
3317c478bd9Sstevel@tonic-gate }
3327c478bd9Sstevel@tonic-gate 
3337c478bd9Sstevel@tonic-gate static uint32_t
3347c478bd9Sstevel@tonic-gate get_sector_size(int fd)
3357c478bd9Sstevel@tonic-gate {
3367c478bd9Sstevel@tonic-gate 	uint32_t	sector_size;
3377c478bd9Sstevel@tonic-gate 	struct uscsi_cmd	ucmd;
3387c478bd9Sstevel@tonic-gate 	union scsi_cdb		cdb;
3397c478bd9Sstevel@tonic-gate 	int32_t		ret_val;
3407c478bd9Sstevel@tonic-gate 	uint32_t rc_data[2];
3417c478bd9Sstevel@tonic-gate 	char rq_data[RQ_LEN];
3427c478bd9Sstevel@tonic-gate 
3437c478bd9Sstevel@tonic-gate 	cdb.scc_cmd = SCMD_READ_CAPACITY;
3447c478bd9Sstevel@tonic-gate 	ucmd.uscsi_cdb = (caddr_t)&cdb;
3457c478bd9Sstevel@tonic-gate 	ucmd.uscsi_cdblen = CDB_GROUP1;
3467c478bd9Sstevel@tonic-gate 	ucmd.uscsi_bufaddr = (caddr_t)&rc_data;
3477c478bd9Sstevel@tonic-gate 	ucmd.uscsi_buflen = sizeof (rc_data);
3487c478bd9Sstevel@tonic-gate 	ucmd.uscsi_timeout = 120; /* If 0, HBA hangs forever */
3497c478bd9Sstevel@tonic-gate 	ucmd.uscsi_rqlen = RQ_LEN;
3507c478bd9Sstevel@tonic-gate 	ucmd.uscsi_rqbuf = rq_data;
3517c478bd9Sstevel@tonic-gate 
3527c478bd9Sstevel@tonic-gate 	ret_val = do_uscsi_cmd(fd,
3537c478bd9Sstevel@tonic-gate 		&ucmd, USCSI_READ|USCSI_RQENABLE);
3547c478bd9Sstevel@tonic-gate 	if (ret_val || ucmd.uscsi_status) {
3557c478bd9Sstevel@tonic-gate 		debug(5, "Read capacity : %d - %d errno = %d\n",
3567c478bd9Sstevel@tonic-gate 			ret_val, ucmd.uscsi_status, errno);
3577c478bd9Sstevel@tonic-gate 		sector_size = 512;
3587c478bd9Sstevel@tonic-gate 	} else {
3597c478bd9Sstevel@tonic-gate 		sector_size = ntohl(rc_data[1]);
3607c478bd9Sstevel@tonic-gate 	}
3617c478bd9Sstevel@tonic-gate 	debug(5, "sector size = 0x%x(%d)\n",
3627c478bd9Sstevel@tonic-gate 		sector_size, sector_size);
3637c478bd9Sstevel@tonic-gate 	return (sector_size);
3647c478bd9Sstevel@tonic-gate }
3657c478bd9Sstevel@tonic-gate 
3667c478bd9Sstevel@tonic-gate static char *
3677c478bd9Sstevel@tonic-gate xlate_state(int32_t state)
3687c478bd9Sstevel@tonic-gate {
3697c478bd9Sstevel@tonic-gate 	switch (state) {
3707c478bd9Sstevel@tonic-gate 
3717c478bd9Sstevel@tonic-gate 	case SM_WRITE_PROTECT_DISABLE:
3727c478bd9Sstevel@tonic-gate 		return ("PROTECTION_DISABLED");
3737c478bd9Sstevel@tonic-gate 	case SM_WRITE_PROTECT_PASSWD:
3747c478bd9Sstevel@tonic-gate 		return ("WRITE_PROTECT_PASSWD");
3757c478bd9Sstevel@tonic-gate 	case SM_WRITE_PROTECT_NOPASSWD:
3767c478bd9Sstevel@tonic-gate 		return ("WRITE_PROTECT_NOPASSWD");
3777c478bd9Sstevel@tonic-gate 	case SM_READ_WRITE_PROTECT:
3787c478bd9Sstevel@tonic-gate 		return ("READ_WRITE_PROTECT");
3797c478bd9Sstevel@tonic-gate 	case SM_TEMP_UNLOCK_MODE:
3807c478bd9Sstevel@tonic-gate 		return ("PROTECTION DISABLED");
3817c478bd9Sstevel@tonic-gate 	default:
3827c478bd9Sstevel@tonic-gate 		return ("UNKNOWN_STATE");
3837c478bd9Sstevel@tonic-gate 	}
3847c478bd9Sstevel@tonic-gate }
3857c478bd9Sstevel@tonic-gate 
3867c478bd9Sstevel@tonic-gate static char *
3877c478bd9Sstevel@tonic-gate xlate_cnum(smedia_callnumber_t cnum)
3887c478bd9Sstevel@tonic-gate {
3897c478bd9Sstevel@tonic-gate 	switch (cnum) {
3907c478bd9Sstevel@tonic-gate 
3917c478bd9Sstevel@tonic-gate 	case SMEDIA_CNUM_OPEN_FD:
3927c478bd9Sstevel@tonic-gate 		return ("SMEDIA_CNUM_OPEN_FD");
3937c478bd9Sstevel@tonic-gate 	case SMEDIA_CNUM_GET_DEVICE_INFO:
3947c478bd9Sstevel@tonic-gate 		return ("SMEDIA_CNUM_GET_DEVICE_INFO");
3957c478bd9Sstevel@tonic-gate 	case SMEDIA_CNUM_GET_MEDIUM_PROPERTY:
3967c478bd9Sstevel@tonic-gate 		return ("SMEDIA_CNUM_GET_MEDIUM_PROPERTY");
3977c478bd9Sstevel@tonic-gate 	case SMEDIA_CNUM_GET_PROTECTION_STATUS:
3987c478bd9Sstevel@tonic-gate 		return ("SMEDIA_CNUM_GET_PROTECTION_STATUS");
3997c478bd9Sstevel@tonic-gate 	case SMEDIA_CNUM_SET_PROTECTION_STATUS:
4007c478bd9Sstevel@tonic-gate 		return ("SMEDIA_CNUM_SET_PROTECTION_STATUS");
4017c478bd9Sstevel@tonic-gate 	case SMEDIA_CNUM_RAW_READ:
4027c478bd9Sstevel@tonic-gate 		return ("SMEDIA_CNUM_RAW_READ");
4037c478bd9Sstevel@tonic-gate 	case SMEDIA_CNUM_RAW_WRITE:
4047c478bd9Sstevel@tonic-gate 		return (" SMEDIA_CNUM_RAW_WRITE");
4057c478bd9Sstevel@tonic-gate 	case SMEDIA_CNUM_FORMAT:
4067c478bd9Sstevel@tonic-gate 		return ("SMEDIA_CNUM_FORMAT");
4077c478bd9Sstevel@tonic-gate 	case SMEDIA_CNUM_CHECK_FORMAT_STATUS:
4087c478bd9Sstevel@tonic-gate 		return ("SMEDIA_CNUM_CHECK_FORMAT_STATUS");
4097c478bd9Sstevel@tonic-gate 	case SMEDIA_CNUM_EJECT:
4107c478bd9Sstevel@tonic-gate 		return ("SMEDIA_CNUM_EJECT");
4117c478bd9Sstevel@tonic-gate 	case SMEDIA_CNUM_REASSIGN_BLOCK:
4127c478bd9Sstevel@tonic-gate 		return ("SMEDIA_CNUM_REASSIGN_BLOCK");
4137c478bd9Sstevel@tonic-gate 	case SMEDIA_CNUM_SET_SHFD:
4147c478bd9Sstevel@tonic-gate 		return ("SMEDIA_CNUM_SET_SHFD");
4157c478bd9Sstevel@tonic-gate 	case SMEDIA_CNUM_PING:
4167c478bd9Sstevel@tonic-gate 		return ("SMEDIA_CNUM_PING");
4177c478bd9Sstevel@tonic-gate 	case SMEDIA_CNUM_USCSI_CMD:
4187c478bd9Sstevel@tonic-gate 		return ("SMEDIA_CNUM_USCSI_CMD");
4197c478bd9Sstevel@tonic-gate 	default:
4207c478bd9Sstevel@tonic-gate 		return ("UNKNOWN_CNUM");
4217c478bd9Sstevel@tonic-gate 	}
4227c478bd9Sstevel@tonic-gate }
4237c478bd9Sstevel@tonic-gate 
4247c478bd9Sstevel@tonic-gate /*ARGSUSED*/
4257c478bd9Sstevel@tonic-gate smserver_info *
4267c478bd9Sstevel@tonic-gate smserverproc_get_serverinfo_1(void *argp, CLIENT *clnt)
4277c478bd9Sstevel@tonic-gate {
4287c478bd9Sstevel@tonic-gate 	(void) mutex_lock(&svcstate_lock);
4297c478bd9Sstevel@tonic-gate 	svcstate = _SERVED;
4307c478bd9Sstevel@tonic-gate 	(void) mutex_unlock(&svcstate_lock);
4317c478bd9Sstevel@tonic-gate 	server_info.vernum = SMSERVERVERS;
4327c478bd9Sstevel@tonic-gate 	server_info.status = 0;
4337c478bd9Sstevel@tonic-gate 	(void) mutex_lock(&server_data.sd_init_lock);
4347c478bd9Sstevel@tonic-gate 	if (server_data.sd_init_state == INIT_NOT_DONE) {
4357c478bd9Sstevel@tonic-gate 		server_data.sd_init_state = INIT_IN_PROGRESS;
4367c478bd9Sstevel@tonic-gate 		debug(5, "Initialising server\n");
4377c478bd9Sstevel@tonic-gate 		(void) init_server(NULL);
4387c478bd9Sstevel@tonic-gate 	}
4397c478bd9Sstevel@tonic-gate 	if (server_data.sd_init_state != INIT_DONE) {
4405363f09cSarutz 		debug(1, "init_server did not do the job. "
4415363f09cSarutz 		    "init_state=%d\n", server_data.sd_init_state);
4427c478bd9Sstevel@tonic-gate 		server_data.sd_init_state = INIT_NOT_DONE;
4437c478bd9Sstevel@tonic-gate 		(void) mutex_unlock(&server_data.sd_init_lock);
4447c478bd9Sstevel@tonic-gate 		server_info.status = -1;
4457c478bd9Sstevel@tonic-gate 		return (&server_info);
4467c478bd9Sstevel@tonic-gate 	}
4477c478bd9Sstevel@tonic-gate 	(void) mutex_unlock(&server_data.sd_init_lock);
4487c478bd9Sstevel@tonic-gate 
4497c478bd9Sstevel@tonic-gate 	debug(5, "smserverproc thread %d running....\n", pthread_self());
4507c478bd9Sstevel@tonic-gate 	return (&server_info);
4517c478bd9Sstevel@tonic-gate }
4527c478bd9Sstevel@tonic-gate 
4537c478bd9Sstevel@tonic-gate /*ARGSUSED*/
4547c478bd9Sstevel@tonic-gate static void
4557c478bd9Sstevel@tonic-gate server_badsig_handler(int sig, siginfo_t *siginfo, void *sigctx)
4567c478bd9Sstevel@tonic-gate {
4577c478bd9Sstevel@tonic-gate 
4587c478bd9Sstevel@tonic-gate 	fatal(gettext(BADSIG_MSG), pthread_self(), sig, siginfo->si_addr,
4597c478bd9Sstevel@tonic-gate 		siginfo->si_trapno,
4607c478bd9Sstevel@tonic-gate 		siginfo->si_pc);
4617c478bd9Sstevel@tonic-gate }
4627c478bd9Sstevel@tonic-gate 
4637c478bd9Sstevel@tonic-gate static int32_t
4647c478bd9Sstevel@tonic-gate do_uscsi_cmd(int32_t file, struct uscsi_cmd *uscsi_cmd, int32_t	flag)
4657c478bd9Sstevel@tonic-gate {
4667c478bd9Sstevel@tonic-gate 	int32_t	ret_val;
4677c478bd9Sstevel@tonic-gate 
4687c478bd9Sstevel@tonic-gate 	/*
4697c478bd9Sstevel@tonic-gate 	 * Set function flags for driver.
4707c478bd9Sstevel@tonic-gate 	 */
4717c478bd9Sstevel@tonic-gate 	uscsi_cmd->uscsi_flags = USCSI_ISOLATE;
4727c478bd9Sstevel@tonic-gate 
4737c478bd9Sstevel@tonic-gate #ifdef DEBUG
4747c478bd9Sstevel@tonic-gate 	uscsi_cmd->uscsi_flags |= USCSI_DIAGNOSE;
4757c478bd9Sstevel@tonic-gate #else
4767c478bd9Sstevel@tonic-gate 	uscsi_cmd->uscsi_flags |= USCSI_SILENT;
4777c478bd9Sstevel@tonic-gate #endif /* DEBUG */
4787c478bd9Sstevel@tonic-gate 
4797c478bd9Sstevel@tonic-gate 	uscsi_cmd->uscsi_flags |= flag;
4807c478bd9Sstevel@tonic-gate 
4817c478bd9Sstevel@tonic-gate 	errno = 0;
4827c478bd9Sstevel@tonic-gate 	ret_val = ioctl(file, USCSICMD, uscsi_cmd);
4837c478bd9Sstevel@tonic-gate 	if (ret_val == 0 && uscsi_cmd->uscsi_status == 0) {
4847c478bd9Sstevel@tonic-gate 		return (ret_val);
4857c478bd9Sstevel@tonic-gate 	}
4867c478bd9Sstevel@tonic-gate 	if (!errno)
4877c478bd9Sstevel@tonic-gate 		errno = EIO;
4887c478bd9Sstevel@tonic-gate 	return (-1);
4897c478bd9Sstevel@tonic-gate }
4907c478bd9Sstevel@tonic-gate 
4917c478bd9Sstevel@tonic-gate static int32_t
4927c478bd9Sstevel@tonic-gate get_device_type(char *v_name)
4937c478bd9Sstevel@tonic-gate {
4947c478bd9Sstevel@tonic-gate 	int32_t i;
4957c478bd9Sstevel@tonic-gate 
4967c478bd9Sstevel@tonic-gate 	for (i = 0; i < 8; i++) {
4977c478bd9Sstevel@tonic-gate 		v_name[i] = toupper(v_name[i]);
4987c478bd9Sstevel@tonic-gate 	}
4997c478bd9Sstevel@tonic-gate 	if (strstr(v_name, "IOMEGA")) {
5007c478bd9Sstevel@tonic-gate 		return (SCSI_IOMEGA);
5017c478bd9Sstevel@tonic-gate 	}
5027c478bd9Sstevel@tonic-gate 	if (strstr(v_name, "FD") ||
5037c478bd9Sstevel@tonic-gate 	    strstr(v_name, "LS-120")) {
5047c478bd9Sstevel@tonic-gate 		return (SCSI_FLOPPY);
5057c478bd9Sstevel@tonic-gate 	}
5067c478bd9Sstevel@tonic-gate 	return (SCSI_GENERIC);
5077c478bd9Sstevel@tonic-gate 
5087c478bd9Sstevel@tonic-gate }
5097c478bd9Sstevel@tonic-gate 
5107c478bd9Sstevel@tonic-gate static int32_t
5117c478bd9Sstevel@tonic-gate get_device_type_scsi(int32_t fd, struct scsi_inquiry *inq)
5127c478bd9Sstevel@tonic-gate {
5137c478bd9Sstevel@tonic-gate 	int32_t dev_type;
5147c478bd9Sstevel@tonic-gate 	struct uscsi_cmd ucmd;
5157c478bd9Sstevel@tonic-gate 	union scsi_cdb  cdb;
5167c478bd9Sstevel@tonic-gate 	int32_t	ret_val;
5177c478bd9Sstevel@tonic-gate 	char rq_data[RQ_LEN];
5187c478bd9Sstevel@tonic-gate 
5197c478bd9Sstevel@tonic-gate 	(void) memset((void *) inq, 0, sizeof (struct scsi_inquiry));
5207c478bd9Sstevel@tonic-gate 	(void) memset((void *) &ucmd, 0, sizeof (ucmd));
5217c478bd9Sstevel@tonic-gate 	(void) memset((void *) &cdb, 0, sizeof (union scsi_cdb));
5227c478bd9Sstevel@tonic-gate 	cdb.scc_cmd = SCMD_INQUIRY;
5237c478bd9Sstevel@tonic-gate 	FORMG0COUNT(&cdb, sizeof (struct scsi_inquiry));
5247c478bd9Sstevel@tonic-gate 	ucmd.uscsi_cdb = (caddr_t)&cdb;
5257c478bd9Sstevel@tonic-gate 	ucmd.uscsi_cdblen = CDB_GROUP0;
5267c478bd9Sstevel@tonic-gate 	ucmd.uscsi_bufaddr = (caddr_t)inq;
5277c478bd9Sstevel@tonic-gate 	ucmd.uscsi_buflen = sizeof (struct scsi_inquiry);
5287c478bd9Sstevel@tonic-gate 	ucmd.uscsi_timeout = 120;	/* If 0, HBA hangs forever */
5297c478bd9Sstevel@tonic-gate 	ucmd.uscsi_rqlen = RQ_LEN;
5307c478bd9Sstevel@tonic-gate 	ucmd.uscsi_rqbuf = rq_data;
5317c478bd9Sstevel@tonic-gate 	ret_val = do_uscsi_cmd(fd, &ucmd, USCSI_READ|USCSI_RQENABLE);
5327c478bd9Sstevel@tonic-gate 	if (ret_val || ucmd.uscsi_status) {
5335363f09cSarutz 		debug(5, "INQUIRY failed: rv = %d  uscsi_status = "
5345363f09cSarutz 		    "%d  errno = %d\n", ret_val, ucmd.uscsi_status, errno);
5357c478bd9Sstevel@tonic-gate 		return (-1);
5367c478bd9Sstevel@tonic-gate 	}
5377c478bd9Sstevel@tonic-gate 
5387c478bd9Sstevel@tonic-gate 	dev_type = get_device_type(inq->inq_vid);
5397c478bd9Sstevel@tonic-gate 
5407c478bd9Sstevel@tonic-gate 	debug(5, "dev_type %d\n", dev_type);
5417c478bd9Sstevel@tonic-gate 	return (dev_type);
5427c478bd9Sstevel@tonic-gate 
5437c478bd9Sstevel@tonic-gate }
5447c478bd9Sstevel@tonic-gate 
5457c478bd9Sstevel@tonic-gate static int32_t
5467c478bd9Sstevel@tonic-gate get_media_capacity(int32_t fd, uint32_t *capacity, uint32_t *blocksize)
5477c478bd9Sstevel@tonic-gate {
5487c478bd9Sstevel@tonic-gate 	struct uscsi_cmd ucmd;
5497c478bd9Sstevel@tonic-gate 	uchar_t cdb[12];
5507c478bd9Sstevel@tonic-gate 	int32_t ret_val;
5517c478bd9Sstevel@tonic-gate 	uchar_t data[20];
5527c478bd9Sstevel@tonic-gate 	char rq_data[RQ_LEN];
5537c478bd9Sstevel@tonic-gate 
5547c478bd9Sstevel@tonic-gate 	debug(5, "get_media_capacity:\n");
5557c478bd9Sstevel@tonic-gate 
5567c478bd9Sstevel@tonic-gate 	(void) memset((void *)&data, 0, sizeof (data));
5577c478bd9Sstevel@tonic-gate 	(void) memset((void *)&ucmd, 0, sizeof (ucmd));
5587c478bd9Sstevel@tonic-gate 	(void) memset((void *)&cdb, 0, sizeof (cdb));
5597c478bd9Sstevel@tonic-gate 
5607c478bd9Sstevel@tonic-gate 	/* retrieve size discriptor of inserted media */
5617c478bd9Sstevel@tonic-gate 	cdb[0] = SCMD_READ_FORMAT_CAP;
5627c478bd9Sstevel@tonic-gate 	cdb[8] = 0x14;  /* data size */
5637c478bd9Sstevel@tonic-gate 
5647c478bd9Sstevel@tonic-gate 	/* Fill in the USCSI fields */
5657c478bd9Sstevel@tonic-gate 	ucmd.uscsi_cdb = (caddr_t)&cdb;
5667c478bd9Sstevel@tonic-gate 	ucmd.uscsi_cdblen = CDB_GROUP5;
5677c478bd9Sstevel@tonic-gate 	ucmd.uscsi_bufaddr = (caddr_t)data;
5687c478bd9Sstevel@tonic-gate 	ucmd.uscsi_buflen = sizeof (data);
5697c478bd9Sstevel@tonic-gate 	ucmd.uscsi_timeout = 120;
5707c478bd9Sstevel@tonic-gate 	ucmd.uscsi_rqlen = RQ_LEN;
5717c478bd9Sstevel@tonic-gate 	ucmd.uscsi_rqbuf = rq_data;
5727c478bd9Sstevel@tonic-gate 	ret_val = do_uscsi_cmd(fd, &ucmd, USCSI_READ|USCSI_RQENABLE);
5737c478bd9Sstevel@tonic-gate 
5747c478bd9Sstevel@tonic-gate 	if (ret_val || ucmd.uscsi_status) {
5757c478bd9Sstevel@tonic-gate 		debug(5, "Retrieving media info failed: %d - %d\n", ret_val,
5767c478bd9Sstevel@tonic-gate 		    ucmd.uscsi_status);
5777c478bd9Sstevel@tonic-gate 
5787c478bd9Sstevel@tonic-gate 		if ((rq_data[2] == KEY_DATA_PROTECT) && (rq_data[12] == 0x30) &&
5797c478bd9Sstevel@tonic-gate 		    (rq_data[13] == 0)) {
5807c478bd9Sstevel@tonic-gate 			(void) debug(1, "Invalid command for media\n");
5817c478bd9Sstevel@tonic-gate 			errno = EINVAL;
5827c478bd9Sstevel@tonic-gate 		}
5837c478bd9Sstevel@tonic-gate 		return (-1);
5847c478bd9Sstevel@tonic-gate 	}
5857c478bd9Sstevel@tonic-gate 
5867c478bd9Sstevel@tonic-gate 	/* No media, bail out */
5877c478bd9Sstevel@tonic-gate 	if (data[8] == 0x3) {
5887c478bd9Sstevel@tonic-gate 		(void) debug(5, "no media in drive\n");
5897c478bd9Sstevel@tonic-gate 		return (-1);
5907c478bd9Sstevel@tonic-gate 	}
5917c478bd9Sstevel@tonic-gate 
5927c478bd9Sstevel@tonic-gate 	/*
5937c478bd9Sstevel@tonic-gate 	 * Generate capacity and blocksize information
5947c478bd9Sstevel@tonic-gate 	 */
5957c478bd9Sstevel@tonic-gate 
5967c478bd9Sstevel@tonic-gate 	*capacity =  (uint32_t)((data[4] << 24) + (data[5] << 16) +
5977c478bd9Sstevel@tonic-gate 	    (data[6] << 8) + data[7]);
5987c478bd9Sstevel@tonic-gate 
5997c478bd9Sstevel@tonic-gate 	debug(1, "capacity is %x %x %x %x = %x", data[4], data[5], data[6],
6007c478bd9Sstevel@tonic-gate 	    data[7], *capacity);
6017c478bd9Sstevel@tonic-gate 
6027c478bd9Sstevel@tonic-gate 	*blocksize = (uint32_t)((data[9] << 16) + (data[10] << 8) + data[11]);
6037c478bd9Sstevel@tonic-gate 
6047c478bd9Sstevel@tonic-gate 	return (0);
6057c478bd9Sstevel@tonic-gate }
6067c478bd9Sstevel@tonic-gate 
6077c478bd9Sstevel@tonic-gate static int32_t
6087c478bd9Sstevel@tonic-gate scsi_zip_format(int32_t fd, uint_t flavor, uint_t mode)
6097c478bd9Sstevel@tonic-gate {
6107c478bd9Sstevel@tonic-gate 	struct uscsi_cmd ucmd;
6117c478bd9Sstevel@tonic-gate 	struct scsi_inquiry inq;
6127c478bd9Sstevel@tonic-gate 	uchar_t cdb[12];
6137c478bd9Sstevel@tonic-gate 	int32_t   ret_val;
6147c478bd9Sstevel@tonic-gate 	uchar_t data[4];
6157c478bd9Sstevel@tonic-gate 	uint32_t rc_data[2];
6167c478bd9Sstevel@tonic-gate 	char rq_data[RQ_LEN];
6177c478bd9Sstevel@tonic-gate 	uint32_t capacity;
6187c478bd9Sstevel@tonic-gate 
6197c478bd9Sstevel@tonic-gate 
6207c478bd9Sstevel@tonic-gate 	if ((mode != SM_FORMAT_IMMEDIATE) &&
6217c478bd9Sstevel@tonic-gate 		(mode != SM_FORMAT_BLOCKED)) {
6227c478bd9Sstevel@tonic-gate 		errno = ENOTSUP;
6237c478bd9Sstevel@tonic-gate 		return (ENOTSUP);
6247c478bd9Sstevel@tonic-gate 	}
6257c478bd9Sstevel@tonic-gate 	/*
6267c478bd9Sstevel@tonic-gate 	 * Do an inquiry and try to figure out if it an
6277c478bd9Sstevel@tonic-gate 	 * IOMEGA JAZ 2GB device.
6287c478bd9Sstevel@tonic-gate 	 */
6297c478bd9Sstevel@tonic-gate 
6307c478bd9Sstevel@tonic-gate 	(void) memset((void *) &inq, 0, sizeof (inq));
6317c478bd9Sstevel@tonic-gate 	(void) memset((void *) &ucmd, 0, sizeof (ucmd));
6327c478bd9Sstevel@tonic-gate 	(void) memset((void *) &cdb, 0, sizeof (cdb));
6337c478bd9Sstevel@tonic-gate 	(void) memset((void *) &rq_data, 0, sizeof (rq_data));
6347c478bd9Sstevel@tonic-gate 	cdb[0] = SCMD_INQUIRY;
6357c478bd9Sstevel@tonic-gate 	cdb[4] = sizeof (inq);
6367c478bd9Sstevel@tonic-gate 	ucmd.uscsi_cdb = (caddr_t)&cdb;
6377c478bd9Sstevel@tonic-gate 	ucmd.uscsi_cdblen = CDB_GROUP0;
6387c478bd9Sstevel@tonic-gate 	ucmd.uscsi_bufaddr = (caddr_t)&inq;
6397c478bd9Sstevel@tonic-gate 	ucmd.uscsi_buflen = sizeof (inq);
6407c478bd9Sstevel@tonic-gate 	ucmd.uscsi_timeout = 120;	/* If 0, HBA hangs forever */
6417c478bd9Sstevel@tonic-gate 	ucmd.uscsi_rqlen = RQ_LEN;
6427c478bd9Sstevel@tonic-gate 	ucmd.uscsi_rqbuf = rq_data;
6437c478bd9Sstevel@tonic-gate 	ret_val = do_uscsi_cmd(fd, &ucmd, USCSI_READ|USCSI_RQENABLE);
6447c478bd9Sstevel@tonic-gate 	if (ret_val || ucmd.uscsi_status) {
6457c478bd9Sstevel@tonic-gate 		debug(5, "inquiry failed: %d - %d errno = %d\n",
6467c478bd9Sstevel@tonic-gate 			ret_val, ucmd.uscsi_status, errno);
6477c478bd9Sstevel@tonic-gate 		return (ucmd.uscsi_status);
6487c478bd9Sstevel@tonic-gate 	}
6497c478bd9Sstevel@tonic-gate 
6507c478bd9Sstevel@tonic-gate 	(void) memset((void *) &rc_data, 0, sizeof (rc_data));
6517c478bd9Sstevel@tonic-gate 	(void) memset((void *) &ucmd, 0, sizeof (ucmd));
6527c478bd9Sstevel@tonic-gate 	(void) memset((void *) &cdb, 0, sizeof (cdb));
6537c478bd9Sstevel@tonic-gate 	cdb[0] = SCMD_READ_CAPACITY;
6547c478bd9Sstevel@tonic-gate 	ucmd.uscsi_cdb = (caddr_t)&cdb;
6557c478bd9Sstevel@tonic-gate 	ucmd.uscsi_cdblen = CDB_GROUP1;
6567c478bd9Sstevel@tonic-gate 	ucmd.uscsi_bufaddr = (caddr_t)&rc_data;
6577c478bd9Sstevel@tonic-gate 	ucmd.uscsi_buflen = sizeof (rc_data);
6587c478bd9Sstevel@tonic-gate 	ucmd.uscsi_timeout = 120;	/* If 0, HBA hangs forever */
6597c478bd9Sstevel@tonic-gate 
6607c478bd9Sstevel@tonic-gate 	ret_val = do_uscsi_cmd(fd, &ucmd, USCSI_READ);
6617c478bd9Sstevel@tonic-gate 	if (ret_val || ucmd.uscsi_status) {
6627c478bd9Sstevel@tonic-gate 		debug(5, "Read capacity : %d - %d errno = %d\n",
6637c478bd9Sstevel@tonic-gate 			ret_val, ucmd.uscsi_status, errno);
6647c478bd9Sstevel@tonic-gate 		return (ucmd.uscsi_status);
6657c478bd9Sstevel@tonic-gate 	}
6667c478bd9Sstevel@tonic-gate 
6677c478bd9Sstevel@tonic-gate 	capacity = ntohl(rc_data[0]);
6687c478bd9Sstevel@tonic-gate 
6697c478bd9Sstevel@tonic-gate 	(void) memset((void *)&data, 0, sizeof (data));
6707c478bd9Sstevel@tonic-gate 	(void) memset((void *)&ucmd, 0, sizeof (ucmd));
6717c478bd9Sstevel@tonic-gate 	(void) memset((void *)&cdb, 0, sizeof (cdb));
6727c478bd9Sstevel@tonic-gate 	cdb[0] =  SCMD_FORMAT;
6737c478bd9Sstevel@tonic-gate 	/*
6747c478bd9Sstevel@tonic-gate 	 * Defect list sent by initiator is a complete list of defects.
6757c478bd9Sstevel@tonic-gate 	 */
6767c478bd9Sstevel@tonic-gate 	cdb[1] = (FMTDATA | CMPLIST);
6777c478bd9Sstevel@tonic-gate 	/*
6787c478bd9Sstevel@tonic-gate 	 * Target should examine the setting of the DPRY, DCRT, STPF, IP
6797c478bd9Sstevel@tonic-gate 	 * and DSP bits.
6807c478bd9Sstevel@tonic-gate 	 */
6817c478bd9Sstevel@tonic-gate 	data[1] = FOV;
6827c478bd9Sstevel@tonic-gate 
6837c478bd9Sstevel@tonic-gate 	switch (flavor) {
6847c478bd9Sstevel@tonic-gate 		case SM_FORMAT_QUICK :
6857c478bd9Sstevel@tonic-gate 			/*
6867c478bd9Sstevel@tonic-gate 			 * Target should not perform any vendor specific
6877c478bd9Sstevel@tonic-gate 			 * medium certification process or format verification
6887c478bd9Sstevel@tonic-gate 			 */
6897c478bd9Sstevel@tonic-gate 			data[1] = (FOV | DCRT);
6907c478bd9Sstevel@tonic-gate 			/*
6917c478bd9Sstevel@tonic-gate 			 * Defect list sent is an addition to the existing
6927c478bd9Sstevel@tonic-gate 			 * list of defects.
6937c478bd9Sstevel@tonic-gate 			 */
6947c478bd9Sstevel@tonic-gate 			cdb[1] =  FMTDATA;
6957c478bd9Sstevel@tonic-gate 			break;
6967c478bd9Sstevel@tonic-gate 		case SM_FORMAT_FORCE :
6977c478bd9Sstevel@tonic-gate 			if (strstr(inq.inq_pid, "jaz")) {
6987c478bd9Sstevel@tonic-gate 				debug(1,
6997c478bd9Sstevel@tonic-gate 				"LONG Format of JAZ media not supported\n");
7007c478bd9Sstevel@tonic-gate 				errno = ENOTSUP;
7017c478bd9Sstevel@tonic-gate 				return (ENOTSUP);
7027c478bd9Sstevel@tonic-gate 			}
7037c478bd9Sstevel@tonic-gate 			/*
7047c478bd9Sstevel@tonic-gate 			 * Formatting a write-protected or read/write
7057c478bd9Sstevel@tonic-gate 			 * protected cartridge is allowed.
7067c478bd9Sstevel@tonic-gate 			 * This is a vendor specific Format Option.
7077c478bd9Sstevel@tonic-gate 			 */
7087c478bd9Sstevel@tonic-gate 			cdb[2] = 0x20;
7097c478bd9Sstevel@tonic-gate 			break;
7107c478bd9Sstevel@tonic-gate 		case SM_FORMAT_LONG :
7117c478bd9Sstevel@tonic-gate 			if (strstr(inq.inq_pid, "jaz")) {
7127c478bd9Sstevel@tonic-gate 				debug(1,
7137c478bd9Sstevel@tonic-gate 				"LONG Format of JAZ media not supported\n");
7147c478bd9Sstevel@tonic-gate 				errno = ENOTSUP;
7157c478bd9Sstevel@tonic-gate 				return (ENOTSUP);
7167c478bd9Sstevel@tonic-gate 			}
7177c478bd9Sstevel@tonic-gate 			/*
7187c478bd9Sstevel@tonic-gate 			 * Defect list sent is an addition to the existing
7197c478bd9Sstevel@tonic-gate 			 * list of defects.
7207c478bd9Sstevel@tonic-gate 			 */
7217c478bd9Sstevel@tonic-gate 			cdb[1] = FMTDATA;
7227c478bd9Sstevel@tonic-gate 			break;
7237c478bd9Sstevel@tonic-gate 		default :
7247c478bd9Sstevel@tonic-gate 			debug(1, "Format option %d not supported!!\n",
7257c478bd9Sstevel@tonic-gate 			flavor);
7267c478bd9Sstevel@tonic-gate 			errno = ENOTSUP;
7277c478bd9Sstevel@tonic-gate 			return (ENOTSUP);
7287c478bd9Sstevel@tonic-gate 	}
7297c478bd9Sstevel@tonic-gate 
7307c478bd9Sstevel@tonic-gate 	if (mode == SM_FORMAT_IMMEDIATE) {
7317c478bd9Sstevel@tonic-gate 		data[1] |= IMMED;
7327c478bd9Sstevel@tonic-gate 		debug(5, "immediate_flag set\n");
7337c478bd9Sstevel@tonic-gate 	}
7347c478bd9Sstevel@tonic-gate 
7357c478bd9Sstevel@tonic-gate 	ucmd.uscsi_cdb = (caddr_t)&cdb;
7367c478bd9Sstevel@tonic-gate 	debug(5, "cdb: %x ", cdb[0]);
7377c478bd9Sstevel@tonic-gate 	debug(5, "%x %x ", cdb[1], cdb[2]);
7387c478bd9Sstevel@tonic-gate 	debug(5, "%x %x %x\n", cdb[3], cdb[4], cdb[5]);
7397c478bd9Sstevel@tonic-gate 	debug(5, "data: %x %x %x %x\n", data[0], data[1], data[2], data[3]);
7407c478bd9Sstevel@tonic-gate 
7417c478bd9Sstevel@tonic-gate 	ucmd.uscsi_cdblen = CDB_GROUP0;
7427c478bd9Sstevel@tonic-gate 	ucmd.uscsi_bufaddr = (caddr_t)data;
7437c478bd9Sstevel@tonic-gate 	ucmd.uscsi_buflen = sizeof (data);
7447c478bd9Sstevel@tonic-gate 	ucmd.uscsi_timeout = FORMAT_TIMEOUT(capacity);
7457c478bd9Sstevel@tonic-gate 	ucmd.uscsi_rqlen = RQ_LEN;
7467c478bd9Sstevel@tonic-gate 	ucmd.uscsi_rqbuf = rq_data;
7477c478bd9Sstevel@tonic-gate 	ret_val = do_uscsi_cmd(fd, &ucmd, USCSI_WRITE|USCSI_RQENABLE);
7487c478bd9Sstevel@tonic-gate 	if (ret_val || ucmd.uscsi_status) {
7497c478bd9Sstevel@tonic-gate 		debug(5, "Format failed : %d - uscsi_status = %d errno = %d\n",
7507c478bd9Sstevel@tonic-gate 			ret_val,
7517c478bd9Sstevel@tonic-gate 			ucmd.uscsi_status, errno);
7527c478bd9Sstevel@tonic-gate 		if ((rq_data[2] == KEY_DATA_PROTECT) ||
7537c478bd9Sstevel@tonic-gate 			(rq_data[2] == KEY_ILLEGAL_REQUEST))
7547c478bd9Sstevel@tonic-gate 			errno = EINVAL;
7557c478bd9Sstevel@tonic-gate 		if ((rq_data[2] == KEY_MEDIUM_ERROR) ||
7567c478bd9Sstevel@tonic-gate 			(rq_data[2] == KEY_HARDWARE_ERROR))
7577c478bd9Sstevel@tonic-gate 			errno = EIO;
7587c478bd9Sstevel@tonic-gate 		return (errno);
7597c478bd9Sstevel@tonic-gate 	}
7607c478bd9Sstevel@tonic-gate 
7617c478bd9Sstevel@tonic-gate 	return (0);
7627c478bd9Sstevel@tonic-gate }
7637c478bd9Sstevel@tonic-gate 
7647c478bd9Sstevel@tonic-gate static int32_t
7657c478bd9Sstevel@tonic-gate scsi_ls120_format(uint_t fd, uint_t flavor, uint32_t capacity,
7667c478bd9Sstevel@tonic-gate     uint32_t blocksize)
7677c478bd9Sstevel@tonic-gate {
7687c478bd9Sstevel@tonic-gate 	struct uscsi_cmd ucmd;
7697c478bd9Sstevel@tonic-gate 	uchar_t cdb[12];
7707c478bd9Sstevel@tonic-gate 	int32_t ret_val;
7717c478bd9Sstevel@tonic-gate 	uchar_t data[12];
7727c478bd9Sstevel@tonic-gate 	char	rq_data[RQ_LEN];
7737c478bd9Sstevel@tonic-gate 
7747c478bd9Sstevel@tonic-gate 	debug(5, "scsi_ls120_format:\n");
7757c478bd9Sstevel@tonic-gate 
7767c478bd9Sstevel@tonic-gate 	(void) memset((void *) &ucmd, 0, sizeof (ucmd));
7777c478bd9Sstevel@tonic-gate 	(void) memset((void *) &cdb, 0, sizeof (cdb));
7787c478bd9Sstevel@tonic-gate 	(void) memset((void *) &rq_data, 0, sizeof (rq_data));
7797c478bd9Sstevel@tonic-gate 
7807c478bd9Sstevel@tonic-gate 	cdb[0] = SCMD_FORMAT;
7817c478bd9Sstevel@tonic-gate 	cdb[1] = (FMTDATA | 0x7);
7827c478bd9Sstevel@tonic-gate 	cdb[8] = 0x0C; /* parameter list length */
7837c478bd9Sstevel@tonic-gate 
7847c478bd9Sstevel@tonic-gate 	data[1] = 0x80;
7857c478bd9Sstevel@tonic-gate 	data[3] = 0x08;
7867c478bd9Sstevel@tonic-gate 
7877c478bd9Sstevel@tonic-gate 
7887c478bd9Sstevel@tonic-gate 	data[4] = (capacity >> 24) & 0xff;
7897c478bd9Sstevel@tonic-gate 	data[5] = (capacity >> 16) & 0xff;
7907c478bd9Sstevel@tonic-gate 	data[6] = (capacity >> 8) & 0xff;
7917c478bd9Sstevel@tonic-gate 	data[7] = capacity & 0xff;
7927c478bd9Sstevel@tonic-gate 
7937c478bd9Sstevel@tonic-gate 
7947c478bd9Sstevel@tonic-gate 	data[9] =  (blocksize >> 16) & 0xff;
7957c478bd9Sstevel@tonic-gate 	data[10] = (blocksize >> 8) & 0xff;
7967c478bd9Sstevel@tonic-gate 	data[11] = blocksize & 0xff;
7977c478bd9Sstevel@tonic-gate 
7987c478bd9Sstevel@tonic-gate 	debug(5, "cdb: %x %x %x ... %x", cdb[0], cdb[1], cdb[2], cdb[8]);
7997c478bd9Sstevel@tonic-gate 	debug(5, "data: %x %x %x %x\n", data[0], data[1], data[2], data[3]);
8007c478bd9Sstevel@tonic-gate 	debug(5, "    : %x %x %x %x\n", data[4], data[5], data[6], data[7]);
8017c478bd9Sstevel@tonic-gate 	debug(5, "    : %x %x %x %x\n", data[8], data[9], data[10], data[11]);
8027c478bd9Sstevel@tonic-gate 
8037c478bd9Sstevel@tonic-gate 	switch (flavor) {
8047c478bd9Sstevel@tonic-gate 		case SM_FORMAT_QUICK :
8057c478bd9Sstevel@tonic-gate 			debug(1, "Format not supported\n");
8067c478bd9Sstevel@tonic-gate 			errno = ENOTSUP;
8077c478bd9Sstevel@tonic-gate 			return (-1);
8087c478bd9Sstevel@tonic-gate 		case SM_FORMAT_FORCE :
8097c478bd9Sstevel@tonic-gate 			break;
8107c478bd9Sstevel@tonic-gate 		case SM_FORMAT_LONG :
8117c478bd9Sstevel@tonic-gate 			break;
8127c478bd9Sstevel@tonic-gate 		default :
8137c478bd9Sstevel@tonic-gate 			debug(1, "Format option not specified!!\n");
8147c478bd9Sstevel@tonic-gate 			errno = ENOTSUP;
8157c478bd9Sstevel@tonic-gate 			return (-1);
8167c478bd9Sstevel@tonic-gate 	}
8177c478bd9Sstevel@tonic-gate 
8187c478bd9Sstevel@tonic-gate 	ucmd.uscsi_cdb = (caddr_t)&cdb;
8197c478bd9Sstevel@tonic-gate 
8207c478bd9Sstevel@tonic-gate 
8217c478bd9Sstevel@tonic-gate 	ucmd.uscsi_cdblen = CDB_GROUP5;
8227c478bd9Sstevel@tonic-gate 	ucmd.uscsi_bufaddr = (caddr_t)data;
8237c478bd9Sstevel@tonic-gate 	ucmd.uscsi_buflen = sizeof (data);
8247c478bd9Sstevel@tonic-gate 	ucmd.uscsi_timeout = 0x12c0;
8257c478bd9Sstevel@tonic-gate 	ucmd.uscsi_rqlen = RQ_LEN;
8267c478bd9Sstevel@tonic-gate 	ucmd.uscsi_rqbuf = rq_data;
8277c478bd9Sstevel@tonic-gate 	(void) fflush(stdout);
8287c478bd9Sstevel@tonic-gate 
8297c478bd9Sstevel@tonic-gate 	ret_val = do_uscsi_cmd(fd, &ucmd, USCSI_WRITE|USCSI_RQENABLE);
8307c478bd9Sstevel@tonic-gate 	if (ret_val || ucmd.uscsi_status) {
8317c478bd9Sstevel@tonic-gate 		debug(1, "Format failed failed: %d - %d\n", ret_val,
8327c478bd9Sstevel@tonic-gate 		    ucmd.uscsi_status);
8337c478bd9Sstevel@tonic-gate 
8347c478bd9Sstevel@tonic-gate 		if ((rq_data[2] == KEY_DATA_PROTECT) &&
8357c478bd9Sstevel@tonic-gate 		    (rq_data[12] == 0x30) && (rq_data[13] == 0)) {
8367c478bd9Sstevel@tonic-gate 
8377c478bd9Sstevel@tonic-gate 			debug(1, "Invalid command for media\n");
8387c478bd9Sstevel@tonic-gate 			errno = EINVAL;
8397c478bd9Sstevel@tonic-gate 		}
8407c478bd9Sstevel@tonic-gate 
8417c478bd9Sstevel@tonic-gate 		if ((rq_data[2] == KEY_NOT_READY) && (rq_data[12] == 0x30)) {
8427c478bd9Sstevel@tonic-gate 			debug(1, "Incompatible media.\n");
8437c478bd9Sstevel@tonic-gate 			errno = EINVAL;
8447c478bd9Sstevel@tonic-gate 		}
8457c478bd9Sstevel@tonic-gate 
8467c478bd9Sstevel@tonic-gate 		return (-1);
8477c478bd9Sstevel@tonic-gate 	}
8487c478bd9Sstevel@tonic-gate 
8497c478bd9Sstevel@tonic-gate 	return (0);
8507c478bd9Sstevel@tonic-gate }
8517c478bd9Sstevel@tonic-gate 
8527c478bd9Sstevel@tonic-gate static int32_t
8537c478bd9Sstevel@tonic-gate scsi_format(int32_t fd, uint_t flavor, uint_t mode)
8547c478bd9Sstevel@tonic-gate {
8557c478bd9Sstevel@tonic-gate 	struct uscsi_cmd ucmd;
8567c478bd9Sstevel@tonic-gate 	struct scsi_inquiry inq;
8577c478bd9Sstevel@tonic-gate 	uchar_t cdb[12];
8587c478bd9Sstevel@tonic-gate 	int32_t   ret_val;
8597c478bd9Sstevel@tonic-gate 	uchar_t data[4];
8607c478bd9Sstevel@tonic-gate 	char rq_data[RQ_LEN];
8617c478bd9Sstevel@tonic-gate 	uint32_t rc_data[2];
8627c478bd9Sstevel@tonic-gate 	uint32_t capacity;
8637c478bd9Sstevel@tonic-gate 
8647c478bd9Sstevel@tonic-gate 
8657c478bd9Sstevel@tonic-gate 
8667c478bd9Sstevel@tonic-gate 	if ((mode != SM_FORMAT_IMMEDIATE) &&
8677c478bd9Sstevel@tonic-gate 		(mode != SM_FORMAT_BLOCKED)) {
8687c478bd9Sstevel@tonic-gate 		errno = ENOTSUP;
8697c478bd9Sstevel@tonic-gate 		return (-1);
8707c478bd9Sstevel@tonic-gate 	}
8717c478bd9Sstevel@tonic-gate 
8727c478bd9Sstevel@tonic-gate 	/*
8737c478bd9Sstevel@tonic-gate 	 * Do an inquiry and try to figure out if it an
8747c478bd9Sstevel@tonic-gate 	 * IOMEGA JAZ 2GB device.
8757c478bd9Sstevel@tonic-gate 	 */
8767c478bd9Sstevel@tonic-gate 
8777c478bd9Sstevel@tonic-gate 	(void) memset((void *) &inq, 0, sizeof (inq));
8787c478bd9Sstevel@tonic-gate 	(void) memset((void *) &ucmd, 0, sizeof (ucmd));
8797c478bd9Sstevel@tonic-gate 	(void) memset((void *) &cdb, 0, sizeof (cdb));
8807c478bd9Sstevel@tonic-gate 	(void) memset((void *) &rq_data, 0, sizeof (rq_data));
8817c478bd9Sstevel@tonic-gate 	cdb[0] = SCMD_INQUIRY;
8827c478bd9Sstevel@tonic-gate 	cdb[4] = sizeof (inq);
8837c478bd9Sstevel@tonic-gate 	ucmd.uscsi_cdb = (caddr_t)&cdb;
8847c478bd9Sstevel@tonic-gate 	ucmd.uscsi_cdblen = CDB_GROUP0;
8857c478bd9Sstevel@tonic-gate 	ucmd.uscsi_bufaddr = (caddr_t)&inq;
8867c478bd9Sstevel@tonic-gate 	ucmd.uscsi_buflen = sizeof (inq);
8877c478bd9Sstevel@tonic-gate 	ucmd.uscsi_timeout = 120;	/* If 0, HBA hangs forever */
8887c478bd9Sstevel@tonic-gate 	ucmd.uscsi_rqlen = RQ_LEN;
8897c478bd9Sstevel@tonic-gate 	ucmd.uscsi_rqbuf = rq_data;
8907c478bd9Sstevel@tonic-gate 	ret_val = do_uscsi_cmd(fd, &ucmd, USCSI_READ|USCSI_RQENABLE);
8917c478bd9Sstevel@tonic-gate 	if (ret_val || ucmd.uscsi_status) {
8927c478bd9Sstevel@tonic-gate 		debug(5, "inquiry failed: %d - %d errno = %d\n",
8937c478bd9Sstevel@tonic-gate 			ret_val, ucmd.uscsi_status, errno);
8947c478bd9Sstevel@tonic-gate 		return (ucmd.uscsi_status);
8957c478bd9Sstevel@tonic-gate 	}
8967c478bd9Sstevel@tonic-gate 
8977c478bd9Sstevel@tonic-gate 	(void) memset((void *) &rc_data, 0, sizeof (rc_data));
8987c478bd9Sstevel@tonic-gate 	(void) memset((void *) &ucmd, 0, sizeof (ucmd));
8997c478bd9Sstevel@tonic-gate 	(void) memset((void *) &cdb, 0, sizeof (cdb));
9007c478bd9Sstevel@tonic-gate 	cdb[0] = SCMD_READ_CAPACITY;
9017c478bd9Sstevel@tonic-gate 	ucmd.uscsi_cdb = (caddr_t)&cdb;
9027c478bd9Sstevel@tonic-gate 	ucmd.uscsi_cdblen = CDB_GROUP1;
9037c478bd9Sstevel@tonic-gate 	ucmd.uscsi_bufaddr = (caddr_t)&rc_data;
9047c478bd9Sstevel@tonic-gate 	ucmd.uscsi_buflen = sizeof (rc_data);
9057c478bd9Sstevel@tonic-gate 	ucmd.uscsi_timeout = 120;	/* If 0, HBA hangs forever */
9067c478bd9Sstevel@tonic-gate 
9077c478bd9Sstevel@tonic-gate 	ret_val = do_uscsi_cmd(fd, &ucmd, USCSI_READ);
9087c478bd9Sstevel@tonic-gate 	if (ret_val || ucmd.uscsi_status) {
9097c478bd9Sstevel@tonic-gate 		debug(5, "Read capacity : %d - %d errno = %d\n",
9107c478bd9Sstevel@tonic-gate 			ret_val, ucmd.uscsi_status, errno);
9117c478bd9Sstevel@tonic-gate 		return (ucmd.uscsi_status);
9127c478bd9Sstevel@tonic-gate 	}
9137c478bd9Sstevel@tonic-gate 
9147c478bd9Sstevel@tonic-gate 	capacity = ntohl(rc_data[0]);
9157c478bd9Sstevel@tonic-gate 
9167c478bd9Sstevel@tonic-gate 	(void) memset((void *)&data, 0, sizeof (data));
9177c478bd9Sstevel@tonic-gate 	(void) memset((void *)&ucmd, 0, sizeof (ucmd));
9187c478bd9Sstevel@tonic-gate 	(void) memset((void *)&cdb, 0, sizeof (cdb));
9197c478bd9Sstevel@tonic-gate 	cdb[0] =  SCMD_FORMAT;
9207c478bd9Sstevel@tonic-gate 	/*
9217c478bd9Sstevel@tonic-gate 	 * Defect list sent is an addition to the existing
9227c478bd9Sstevel@tonic-gate 	 * list of defects.
9237c478bd9Sstevel@tonic-gate 	 */
9247c478bd9Sstevel@tonic-gate 	cdb[1] =  FMTDATA;
9257c478bd9Sstevel@tonic-gate 	/*
9267c478bd9Sstevel@tonic-gate 	 * Target should examine the setting of the DPRY, DCRT, STPF, IP
9277c478bd9Sstevel@tonic-gate 	 * and DSP bits.
9287c478bd9Sstevel@tonic-gate 	 */
9297c478bd9Sstevel@tonic-gate 	data[1] = FOV;
9307c478bd9Sstevel@tonic-gate 
9317c478bd9Sstevel@tonic-gate 	if (mode == SM_FORMAT_IMMEDIATE) {
9327c478bd9Sstevel@tonic-gate 		debug(5,
9337c478bd9Sstevel@tonic-gate 	"SM_FORMAT_IMMEDIATE specified ignored. Performing a long format!\n");
9347c478bd9Sstevel@tonic-gate 	}
9357c478bd9Sstevel@tonic-gate 
9367c478bd9Sstevel@tonic-gate 	switch (flavor) {
9377c478bd9Sstevel@tonic-gate 		case SM_FORMAT_LONG :
9387c478bd9Sstevel@tonic-gate 			if (strstr(inq.inq_pid, "jaz")) {
9397c478bd9Sstevel@tonic-gate 				debug(1,
9407c478bd9Sstevel@tonic-gate 				"LONG Format of JAZ media not supported\n");
9417c478bd9Sstevel@tonic-gate 				errno = ENOTSUP;
9427c478bd9Sstevel@tonic-gate 				return (ENOTSUP);
9437c478bd9Sstevel@tonic-gate 			}
9447c478bd9Sstevel@tonic-gate 			/*
9457c478bd9Sstevel@tonic-gate 			 * Defect list sent is an addition to the existing
9467c478bd9Sstevel@tonic-gate 			 * list of defects.
9477c478bd9Sstevel@tonic-gate 			 */
9487c478bd9Sstevel@tonic-gate 			cdb[1] = FMTDATA;
9497c478bd9Sstevel@tonic-gate 			break;
9507c478bd9Sstevel@tonic-gate 		default :
9517c478bd9Sstevel@tonic-gate 			debug(1, "Format option %d  not supported!!\n",
9527c478bd9Sstevel@tonic-gate 			flavor);
9537c478bd9Sstevel@tonic-gate 			errno = ENOTSUP;
9547c478bd9Sstevel@tonic-gate 			return (ENOTSUP);
9557c478bd9Sstevel@tonic-gate 	}
9567c478bd9Sstevel@tonic-gate 
9577c478bd9Sstevel@tonic-gate 
9587c478bd9Sstevel@tonic-gate 	ucmd.uscsi_cdb = (caddr_t)&cdb;
9597c478bd9Sstevel@tonic-gate 	ucmd.uscsi_cdblen = CDB_GROUP0;
9607c478bd9Sstevel@tonic-gate 	ucmd.uscsi_bufaddr = (caddr_t)data;
9617c478bd9Sstevel@tonic-gate 	ucmd.uscsi_buflen = sizeof (data);
9627c478bd9Sstevel@tonic-gate 	ucmd.uscsi_timeout = FORMAT_TIMEOUT(capacity);
9637c478bd9Sstevel@tonic-gate 	ucmd.uscsi_rqlen = RQ_LEN;
9647c478bd9Sstevel@tonic-gate 	ucmd.uscsi_rqbuf = rq_data;
9657c478bd9Sstevel@tonic-gate 	ret_val = do_uscsi_cmd(fd, &ucmd, USCSI_WRITE|USCSI_RQENABLE);
9667c478bd9Sstevel@tonic-gate 	if (ret_val || ucmd.uscsi_status) {
9677c478bd9Sstevel@tonic-gate 		debug(5, "Format failed failed: %d - %d errno = %d\n",
9687c478bd9Sstevel@tonic-gate 			ret_val, ucmd.uscsi_status, errno);
9697c478bd9Sstevel@tonic-gate 		return (ucmd.uscsi_status);
9707c478bd9Sstevel@tonic-gate 	}
9717c478bd9Sstevel@tonic-gate 
9727c478bd9Sstevel@tonic-gate 	return (0);
9737c478bd9Sstevel@tonic-gate }
9747c478bd9Sstevel@tonic-gate 
9757c478bd9Sstevel@tonic-gate static int32_t
9767c478bd9Sstevel@tonic-gate scsi_media_status(int32_t fd)
9777c478bd9Sstevel@tonic-gate {
9787c478bd9Sstevel@tonic-gate 	struct mode_header modeh;
9797c478bd9Sstevel@tonic-gate 	struct uscsi_cmd ucmd;
9807c478bd9Sstevel@tonic-gate 	union scsi_cdb  cdb;
9817c478bd9Sstevel@tonic-gate 	int32_t ret_val;
9827c478bd9Sstevel@tonic-gate 	int32_t cur_status;
9837c478bd9Sstevel@tonic-gate 	char rq_data[RQ_LEN];
9847c478bd9Sstevel@tonic-gate 
9857c478bd9Sstevel@tonic-gate 	debug(10, "SCSI MEDIA STATUS CALLED \n");
9867c478bd9Sstevel@tonic-gate 
9877c478bd9Sstevel@tonic-gate 	(void) memset((void *) &modeh, 0, sizeof (modeh));
9887c478bd9Sstevel@tonic-gate 	(void) memset((void *) &ucmd, 0, sizeof (ucmd));
9897c478bd9Sstevel@tonic-gate 	(void) memset((void *) &cdb, 0, sizeof (union scsi_cdb));
9907c478bd9Sstevel@tonic-gate 	cdb.scc_cmd = SCMD_MODE_SENSE;
991*910cba4fScg149915 	cdb.cdb_opaque[2] = MODEPAGE_ALLPAGES;
9927c478bd9Sstevel@tonic-gate 	FORMG0COUNT(&cdb, sizeof (modeh));
993*910cba4fScg149915 
9947c478bd9Sstevel@tonic-gate 	ucmd.uscsi_cdb = (caddr_t)&cdb;
9957c478bd9Sstevel@tonic-gate 	ucmd.uscsi_cdblen = CDB_GROUP0;
9967c478bd9Sstevel@tonic-gate 	ucmd.uscsi_bufaddr = (caddr_t)&modeh;
9977c478bd9Sstevel@tonic-gate 	ucmd.uscsi_buflen = sizeof (modeh);
9987c478bd9Sstevel@tonic-gate 	ucmd.uscsi_timeout = 120;	/* If 0, HBA hangs forever */
9997c478bd9Sstevel@tonic-gate 	ucmd.uscsi_rqlen = RQ_LEN;
10007c478bd9Sstevel@tonic-gate 	ucmd.uscsi_rqbuf = rq_data;
10017c478bd9Sstevel@tonic-gate 	ret_val = do_uscsi_cmd(fd, &ucmd, USCSI_READ|USCSI_RQENABLE);
10027c478bd9Sstevel@tonic-gate 	if (ret_val || ucmd.uscsi_status) {
1003*910cba4fScg149915 		debug(5, "Modesense for 0x3f pages failed: %d-%d errno=%d\n",
1004*910cba4fScg149915 			ret_val, ucmd.uscsi_status, errno);
1005*910cba4fScg149915 		cdb.cdb_opaque[2] = 0;
1006*910cba4fScg149915 		ucmd.uscsi_rqlen = RQ_LEN;
1007*910cba4fScg149915 		FORMG0COUNT(&cdb, sizeof (modeh));
1008*910cba4fScg149915 		ret_val = do_uscsi_cmd(fd, &ucmd, USCSI_READ|USCSI_RQENABLE);
1009*910cba4fScg149915 		if (ret_val || ucmd.uscsi_status) {
10107c478bd9Sstevel@tonic-gate 			debug(5, "Modesense failed: %d - %d errno = %d\n",
10117c478bd9Sstevel@tonic-gate 				ret_val, ucmd.uscsi_status, errno);
10127c478bd9Sstevel@tonic-gate 			return (-1);
10137c478bd9Sstevel@tonic-gate 		}
1014*910cba4fScg149915 	}
10157c478bd9Sstevel@tonic-gate 
10167c478bd9Sstevel@tonic-gate 	if (modeh.device_specific & W_E_MASK) {
10177c478bd9Sstevel@tonic-gate 		cur_status = SM_WRITE_PROTECT_NOPASSWD;
10187c478bd9Sstevel@tonic-gate 	} else {
10197c478bd9Sstevel@tonic-gate 		cur_status = SM_WRITE_PROTECT_DISABLE;
10207c478bd9Sstevel@tonic-gate 	}
10217c478bd9Sstevel@tonic-gate 	debug(5, "cur status %d\n", cur_status);
10227c478bd9Sstevel@tonic-gate 
10237c478bd9Sstevel@tonic-gate 	return (cur_status);
10247c478bd9Sstevel@tonic-gate }
10257c478bd9Sstevel@tonic-gate 
10267c478bd9Sstevel@tonic-gate static int32_t
10277c478bd9Sstevel@tonic-gate scsi_zip_media_status(int32_t fd)
10287c478bd9Sstevel@tonic-gate {
10297c478bd9Sstevel@tonic-gate 	struct uscsi_cmd ucmd;
10307c478bd9Sstevel@tonic-gate 	uchar_t cdb[12];
10317c478bd9Sstevel@tonic-gate 	int32_t	status;
10327c478bd9Sstevel@tonic-gate 	int32_t mode;
10337c478bd9Sstevel@tonic-gate 	uchar_t data[64];
10347c478bd9Sstevel@tonic-gate 	char rq_data[RQ_LEN];
10357c478bd9Sstevel@tonic-gate 
10367c478bd9Sstevel@tonic-gate 	debug(10, "Getting media status\n");
10377c478bd9Sstevel@tonic-gate 
10387c478bd9Sstevel@tonic-gate 	(void) memset((void *)&ucmd, 0, sizeof (ucmd));
10397c478bd9Sstevel@tonic-gate 	(void) memset((void *)&cdb, 0, sizeof (cdb));
10407c478bd9Sstevel@tonic-gate 
10417c478bd9Sstevel@tonic-gate 	cdb[0] = IOMEGA_NONSENSE_CMD;
10427c478bd9Sstevel@tonic-gate 	cdb[2] = CARTRIDGE_STATUS_PAGE;
10437c478bd9Sstevel@tonic-gate 	cdb[4] = ND_LENGTH;
10447c478bd9Sstevel@tonic-gate 	ucmd.uscsi_cdb = (caddr_t)&cdb;
10457c478bd9Sstevel@tonic-gate 	ucmd.uscsi_cdblen = CDB_GROUP0;
10467c478bd9Sstevel@tonic-gate 	ucmd.uscsi_bufaddr = (caddr_t)data;
10477c478bd9Sstevel@tonic-gate 	ucmd.uscsi_buflen = 64;
10487c478bd9Sstevel@tonic-gate 	ucmd.uscsi_timeout = 120;	/* If 0, HBA hangs forever */
10497c478bd9Sstevel@tonic-gate 	ucmd.uscsi_rqlen = RQ_LEN;
10507c478bd9Sstevel@tonic-gate 	ucmd.uscsi_rqbuf = rq_data;
10517c478bd9Sstevel@tonic-gate 	status = do_uscsi_cmd(fd, &ucmd, USCSI_READ|USCSI_RQENABLE);
10527c478bd9Sstevel@tonic-gate 	if (status || ucmd.uscsi_status) {
10535363f09cSarutz 		debug(5, "Cartridge protect operation failed: "
10545363f09cSarutz 		    "rv = %d  uscsi_status = %d  errno = %d\n",
10557c478bd9Sstevel@tonic-gate 		    status, ucmd.uscsi_status, errno);
10567c478bd9Sstevel@tonic-gate 		return (-1);
10577c478bd9Sstevel@tonic-gate 	}
10587c478bd9Sstevel@tonic-gate 
10597c478bd9Sstevel@tonic-gate 	if (data[DISK_STATUS_OFFSET + NON_SENSE_HDR_LEN] == 4) {
10607c478bd9Sstevel@tonic-gate 		debug(1, "Disk not present. \n");
10617c478bd9Sstevel@tonic-gate 		return (-1);
10627c478bd9Sstevel@tonic-gate 	}
10637c478bd9Sstevel@tonic-gate 	mode = data[PROTECT_MODE_OFFSET + NON_SENSE_HDR_LEN] & 0xF;
10647c478bd9Sstevel@tonic-gate 
10655363f09cSarutz 	debug(5, "MODE 0x%x / %d.\n", mode, mode);
10667c478bd9Sstevel@tonic-gate 
10677c478bd9Sstevel@tonic-gate 	switch (mode) {
10687c478bd9Sstevel@tonic-gate 		case UNLOCK_MODE:
10697c478bd9Sstevel@tonic-gate 			status = SM_WRITE_PROTECT_DISABLE;
10707c478bd9Sstevel@tonic-gate 			break;
10717c478bd9Sstevel@tonic-gate 		case WRITE_PROTECT_MODE:
10727c478bd9Sstevel@tonic-gate 			status = SM_WRITE_PROTECT_NOPASSWD;
10737c478bd9Sstevel@tonic-gate 			break;
10747c478bd9Sstevel@tonic-gate 		case PASSWD_WRITE_PROTECT_MODE:
10757c478bd9Sstevel@tonic-gate 			status = SM_WRITE_PROTECT_PASSWD;
10767c478bd9Sstevel@tonic-gate 			break;
10777c478bd9Sstevel@tonic-gate 		case READ_WRITE_PROTECT_MODE:
10787c478bd9Sstevel@tonic-gate 			status = SM_READ_WRITE_PROTECT;
10797c478bd9Sstevel@tonic-gate 			break;
10807c478bd9Sstevel@tonic-gate 		default :
10817c478bd9Sstevel@tonic-gate 			if (mode & TEMP_UNLOCK_MODE)
10827c478bd9Sstevel@tonic-gate 				status = SM_TEMP_UNLOCK_MODE;
10837c478bd9Sstevel@tonic-gate 			else
10847c478bd9Sstevel@tonic-gate 				status = SM_STATUS_UNKNOWN;
10857c478bd9Sstevel@tonic-gate 			break;
10867c478bd9Sstevel@tonic-gate 	}
10877c478bd9Sstevel@tonic-gate 
10887c478bd9Sstevel@tonic-gate 	debug(5, "status %d \n", status);
10897c478bd9Sstevel@tonic-gate 	return (status);
10907c478bd9Sstevel@tonic-gate }
10917c478bd9Sstevel@tonic-gate 
10925363f09cSarutz static int32_t
10937c478bd9Sstevel@tonic-gate scsi_reassign_block(int32_t fd, diskaddr_t block)
10947c478bd9Sstevel@tonic-gate {
10957c478bd9Sstevel@tonic-gate 	uchar_t data[8];
10967c478bd9Sstevel@tonic-gate 	struct uscsi_cmd ucmd;
10977c478bd9Sstevel@tonic-gate 	char cdb[12];
10987c478bd9Sstevel@tonic-gate 	int32_t	ret_val;
10997c478bd9Sstevel@tonic-gate 	char rq_data[RQ_LEN];
11007c478bd9Sstevel@tonic-gate 
11017c478bd9Sstevel@tonic-gate 	debug(5, "SCSI REASSIGN CALLED block = %lld\n", block);
11027c478bd9Sstevel@tonic-gate 
11037c478bd9Sstevel@tonic-gate 	(void) memset((void *) &data, 0, sizeof (data));
11047c478bd9Sstevel@tonic-gate 	(void) memset((void *) &ucmd, 0, sizeof (ucmd));
11057c478bd9Sstevel@tonic-gate 	(void) memset((void *) &cdb, 0, sizeof (cdb));
11067c478bd9Sstevel@tonic-gate 	cdb[0] = SCMD_REASSIGN_BLOCK;
11077c478bd9Sstevel@tonic-gate 	data[3] = 4;
11087c478bd9Sstevel@tonic-gate 	data[4] = ((block & 0xFF000000) >> 24);
11097c478bd9Sstevel@tonic-gate 	data[5] = ((block & 0xFF0000) >> 16);
11107c478bd9Sstevel@tonic-gate 	data[6] = ((block & 0xFF00) >> 8);
11117c478bd9Sstevel@tonic-gate 	data[7] = block & 0xFF;
11127c478bd9Sstevel@tonic-gate 
11137c478bd9Sstevel@tonic-gate 	ucmd.uscsi_cdb = (caddr_t)&cdb;
11147c478bd9Sstevel@tonic-gate 	ucmd.uscsi_cdblen = CDB_GROUP0;
11157c478bd9Sstevel@tonic-gate 	ucmd.uscsi_bufaddr = (caddr_t)data;
11167c478bd9Sstevel@tonic-gate 	ucmd.uscsi_buflen = sizeof (data);
11177c478bd9Sstevel@tonic-gate 	ucmd.uscsi_timeout = 120;	/* If 0, HBA hangs forever */
11187c478bd9Sstevel@tonic-gate 	ucmd.uscsi_rqlen = RQ_LEN;
11197c478bd9Sstevel@tonic-gate 	ucmd.uscsi_rqbuf = rq_data;
11207c478bd9Sstevel@tonic-gate 	ret_val = do_uscsi_cmd(fd, &ucmd, USCSI_WRITE|USCSI_RQENABLE);
11217c478bd9Sstevel@tonic-gate 	if (ret_val || ucmd.uscsi_status) {
11227c478bd9Sstevel@tonic-gate 		debug(5, "Reassign block failed: %d - %d errno = %d\n",
11237c478bd9Sstevel@tonic-gate 			ret_val, ucmd.uscsi_status, errno);
11247c478bd9Sstevel@tonic-gate 		return (-1);
11257c478bd9Sstevel@tonic-gate 	}
11267c478bd9Sstevel@tonic-gate 
11277c478bd9Sstevel@tonic-gate 	return (0);
11287c478bd9Sstevel@tonic-gate }
11297c478bd9Sstevel@tonic-gate 
11305363f09cSarutz static int32_t
11317c478bd9Sstevel@tonic-gate get_mode_page(int32_t fd, uchar_t pc, uchar_t page_code,
11327c478bd9Sstevel@tonic-gate     uchar_t *md_data, uchar_t data_len)
11337c478bd9Sstevel@tonic-gate {
11347c478bd9Sstevel@tonic-gate 	struct uscsi_cmd ucmd;
11357c478bd9Sstevel@tonic-gate 	uchar_t cdb[12];
11367c478bd9Sstevel@tonic-gate 	int32_t	ret_val;
11377c478bd9Sstevel@tonic-gate 	char rq_data[RQ_LEN];
11387c478bd9Sstevel@tonic-gate 
11395363f09cSarutz 	debug(10, "MODE SENSE(6) - page_code = 0x%x\n", page_code);
11407c478bd9Sstevel@tonic-gate 
11417c478bd9Sstevel@tonic-gate 	(void) memset((void *) md_data, 0, sizeof (data_len));
11427c478bd9Sstevel@tonic-gate 	(void) memset((void *) &ucmd, 0, sizeof (ucmd));
11437c478bd9Sstevel@tonic-gate 	(void) memset((void *) &cdb, 0, sizeof (cdb));
11447c478bd9Sstevel@tonic-gate 	cdb[0] = SCMD_MODE_SENSE;
11457c478bd9Sstevel@tonic-gate 	cdb[2] = (pc << 6) | page_code;
11467c478bd9Sstevel@tonic-gate 	cdb[4] = data_len;
11477c478bd9Sstevel@tonic-gate 
11487c478bd9Sstevel@tonic-gate 	ucmd.uscsi_cdb = (caddr_t)&cdb;
11497c478bd9Sstevel@tonic-gate 	ucmd.uscsi_cdblen = CDB_GROUP0;
11507c478bd9Sstevel@tonic-gate 	ucmd.uscsi_bufaddr = (caddr_t)md_data;
11517c478bd9Sstevel@tonic-gate 	ucmd.uscsi_buflen = data_len;
11527c478bd9Sstevel@tonic-gate 	ucmd.uscsi_timeout = 120;	/* If 0, HBA hangs forever */
11537c478bd9Sstevel@tonic-gate 	ucmd.uscsi_rqlen = RQ_LEN;
11547c478bd9Sstevel@tonic-gate 	ucmd.uscsi_rqbuf = rq_data;
11557c478bd9Sstevel@tonic-gate 	ret_val = do_uscsi_cmd(fd, &ucmd, USCSI_READ|USCSI_RQENABLE);
11567c478bd9Sstevel@tonic-gate 	if (ret_val || ucmd.uscsi_status) {
11577c478bd9Sstevel@tonic-gate 		debug(5, "Modesense failed: %d - %d errno = %d\n",
11587c478bd9Sstevel@tonic-gate 			ret_val, ucmd.uscsi_status, errno);
11597c478bd9Sstevel@tonic-gate 		return (-2);
11607c478bd9Sstevel@tonic-gate 	}
11617c478bd9Sstevel@tonic-gate 
11627c478bd9Sstevel@tonic-gate 	return (0);
11637c478bd9Sstevel@tonic-gate }
11647c478bd9Sstevel@tonic-gate 
11657c478bd9Sstevel@tonic-gate static int32_t
11667c478bd9Sstevel@tonic-gate scsi_zip_write_protect(int32_t fd, smwp_state_t *wp)
11677c478bd9Sstevel@tonic-gate {
11687c478bd9Sstevel@tonic-gate 	struct uscsi_cmd ucmd;
11697c478bd9Sstevel@tonic-gate 	struct scsi_inquiry inq;
11707c478bd9Sstevel@tonic-gate 	uchar_t cdb[12];
11717c478bd9Sstevel@tonic-gate 	int32_t	status;
11727c478bd9Sstevel@tonic-gate 	int32_t new_mode;
11737c478bd9Sstevel@tonic-gate 	char rq_data[RQ_LEN];
11747c478bd9Sstevel@tonic-gate 	int32_t wa_bit;
11757c478bd9Sstevel@tonic-gate 	char *tmp_passwd = NULL;
11767c478bd9Sstevel@tonic-gate 
11777c478bd9Sstevel@tonic-gate 	debug(10, "SCSI ZIP WRITE PROTECT CALLED \n");
11787c478bd9Sstevel@tonic-gate 
11797c478bd9Sstevel@tonic-gate 	/*
11807c478bd9Sstevel@tonic-gate 	 * Do an inquiry and try to figure out if it an
11817c478bd9Sstevel@tonic-gate 	 * ATAPI or SCSI device.
11827c478bd9Sstevel@tonic-gate 	 */
11837c478bd9Sstevel@tonic-gate 
11847c478bd9Sstevel@tonic-gate 	(void) memset((void *) &inq, 0, sizeof (inq));
11857c478bd9Sstevel@tonic-gate 	(void) memset((void *) &ucmd, 0, sizeof (ucmd));
11867c478bd9Sstevel@tonic-gate 	(void) memset((void *) &cdb, 0, sizeof (cdb));
11877c478bd9Sstevel@tonic-gate 	(void) memset((void *) &rq_data, 0, sizeof (rq_data));
11887c478bd9Sstevel@tonic-gate 	cdb[0] = SCMD_INQUIRY;
11897c478bd9Sstevel@tonic-gate 	cdb[4] = sizeof (inq);
11907c478bd9Sstevel@tonic-gate 	ucmd.uscsi_cdb = (caddr_t)&cdb;
11917c478bd9Sstevel@tonic-gate 	ucmd.uscsi_cdblen = CDB_GROUP0;
11927c478bd9Sstevel@tonic-gate 	ucmd.uscsi_bufaddr = (caddr_t)&inq;
11937c478bd9Sstevel@tonic-gate 	ucmd.uscsi_buflen = sizeof (inq);
11947c478bd9Sstevel@tonic-gate 	ucmd.uscsi_timeout = 120;	/* If 0, HBA hangs forever */
11957c478bd9Sstevel@tonic-gate 	ucmd.uscsi_rqlen = RQ_LEN;
11967c478bd9Sstevel@tonic-gate 	ucmd.uscsi_rqbuf = rq_data;
11977c478bd9Sstevel@tonic-gate 	status = do_uscsi_cmd(fd, &ucmd, USCSI_READ|USCSI_RQENABLE);
11987c478bd9Sstevel@tonic-gate 	if (status || ucmd.uscsi_status) {
11997c478bd9Sstevel@tonic-gate 		debug(5, "inquiry failed: %d - %d errno = %d\n",
12007c478bd9Sstevel@tonic-gate 			status, ucmd.uscsi_status, errno);
12017c478bd9Sstevel@tonic-gate 		return (-1);
12027c478bd9Sstevel@tonic-gate 	}
12037c478bd9Sstevel@tonic-gate 
12047c478bd9Sstevel@tonic-gate 	if (inq.inq_ansi > 0) {
12057c478bd9Sstevel@tonic-gate 		wa_bit = 0;
12067c478bd9Sstevel@tonic-gate 		debug(5, "SCSI device\n");
12077c478bd9Sstevel@tonic-gate 	} else {
12087c478bd9Sstevel@tonic-gate 		wa_bit = 1;
12097c478bd9Sstevel@tonic-gate 		debug(5, "ATAPI device\n");
12107c478bd9Sstevel@tonic-gate 	}
12117c478bd9Sstevel@tonic-gate 
12127c478bd9Sstevel@tonic-gate 	switch (wp->sm_new_state) {
12137c478bd9Sstevel@tonic-gate 		case SM_WRITE_PROTECT_DISABLE :
12147c478bd9Sstevel@tonic-gate 			new_mode = 0x0;
12157c478bd9Sstevel@tonic-gate 			break;
12167c478bd9Sstevel@tonic-gate 		case SM_WRITE_PROTECT_NOPASSWD :
12177c478bd9Sstevel@tonic-gate 			new_mode = 0x2;
12187c478bd9Sstevel@tonic-gate 			break;
12197c478bd9Sstevel@tonic-gate 		case SM_WRITE_PROTECT_PASSWD :
12207c478bd9Sstevel@tonic-gate 			new_mode = 0x3;
12217c478bd9Sstevel@tonic-gate 			break;
12227c478bd9Sstevel@tonic-gate 		case SM_READ_WRITE_PROTECT :
12237c478bd9Sstevel@tonic-gate 			new_mode = 0x5;
12247c478bd9Sstevel@tonic-gate 			break;
12257c478bd9Sstevel@tonic-gate 		case SM_TEMP_UNLOCK_MODE :
12267c478bd9Sstevel@tonic-gate 			new_mode = 0x8;
12277c478bd9Sstevel@tonic-gate 			break;
12287c478bd9Sstevel@tonic-gate 		default :
12297c478bd9Sstevel@tonic-gate 			debug(1, "Invalid mode 0x%x specified\n",
12307c478bd9Sstevel@tonic-gate 			wp->sm_new_state);
12317c478bd9Sstevel@tonic-gate 			errno = ENOTSUP;
12327c478bd9Sstevel@tonic-gate 			return (-1);
12337c478bd9Sstevel@tonic-gate 	}
12347c478bd9Sstevel@tonic-gate 
12357c478bd9Sstevel@tonic-gate 
12367c478bd9Sstevel@tonic-gate 	(void) memset((void *)&ucmd, 0, sizeof (ucmd));
12377c478bd9Sstevel@tonic-gate 	(void) memset((void *)&cdb, 0, sizeof (cdb));
12387c478bd9Sstevel@tonic-gate 	(void) memset((void *) &rq_data, 0, sizeof (rq_data));
12397c478bd9Sstevel@tonic-gate 	cdb[0] = IOMEGA_CATRIDGE_PROTECT;
12407c478bd9Sstevel@tonic-gate 	cdb[1] |= new_mode;
12417c478bd9Sstevel@tonic-gate 	if (wa_bit)
12427c478bd9Sstevel@tonic-gate 		cdb[1] |= WA_BIT;
12437c478bd9Sstevel@tonic-gate 	cdb[4] = wp->sm_passwd_len;
12447c478bd9Sstevel@tonic-gate 	ucmd.uscsi_cdb = (caddr_t)&cdb;
12457c478bd9Sstevel@tonic-gate 	ucmd.uscsi_cdblen = CDB_GROUP0;
12467c478bd9Sstevel@tonic-gate 	if (wa_bit && (wp->sm_passwd_len & 1)) {
12477c478bd9Sstevel@tonic-gate 		/*
12487c478bd9Sstevel@tonic-gate 		 * Oops, ATAPI device with an odd length passwd!
12497c478bd9Sstevel@tonic-gate 		 * Allocate a buffer to hold one extra byte.
12507c478bd9Sstevel@tonic-gate 		 */
12517c478bd9Sstevel@tonic-gate 		debug(5, "Odd len passwd for ATAPI device!\n");
12527c478bd9Sstevel@tonic-gate 		errno = 0;
12537c478bd9Sstevel@tonic-gate 		tmp_passwd = (char *)malloc(wp->sm_passwd_len+1);
12547c478bd9Sstevel@tonic-gate 		if (tmp_passwd == NULL) {
12557c478bd9Sstevel@tonic-gate 			if (errno == 0)
12567c478bd9Sstevel@tonic-gate 				errno = ENOMEM;
12577c478bd9Sstevel@tonic-gate 			return (-1);
12587c478bd9Sstevel@tonic-gate 		}
12597c478bd9Sstevel@tonic-gate 		(void) memset(tmp_passwd, 0, wp->sm_passwd_len+1);
12607c478bd9Sstevel@tonic-gate 		(void) memcpy(tmp_passwd, wp->sm_passwd, wp->sm_passwd_len);
12617c478bd9Sstevel@tonic-gate 		ucmd.uscsi_bufaddr = (caddr_t)tmp_passwd;
12627c478bd9Sstevel@tonic-gate 		ucmd.uscsi_buflen = wp->sm_passwd_len+1;
12637c478bd9Sstevel@tonic-gate 	} else {
12647c478bd9Sstevel@tonic-gate 		ucmd.uscsi_bufaddr = (caddr_t)wp->sm_passwd;
12657c478bd9Sstevel@tonic-gate 		ucmd.uscsi_buflen = wp->sm_passwd_len;
12667c478bd9Sstevel@tonic-gate 	}
12677c478bd9Sstevel@tonic-gate 	ucmd.uscsi_timeout = 120;	/* If 0, HBA hangs forever */
12687c478bd9Sstevel@tonic-gate 	ucmd.uscsi_rqlen = RQ_LEN;
12697c478bd9Sstevel@tonic-gate 	ucmd.uscsi_rqbuf = rq_data;
12707c478bd9Sstevel@tonic-gate 	status = do_uscsi_cmd(fd, &ucmd, USCSI_WRITE|USCSI_RQENABLE);
12717c478bd9Sstevel@tonic-gate 	if (tmp_passwd != NULL) {
12727c478bd9Sstevel@tonic-gate 		free(tmp_passwd);
12737c478bd9Sstevel@tonic-gate 	}
12747c478bd9Sstevel@tonic-gate 	if (status || ucmd.uscsi_status) {
12755363f09cSarutz 		debug(5, "Cartridge-protect operation failed: rv "
12765363f09cSarutz 		    "= %d  uscsi_status = %d  errno = %d\n", status,
12775363f09cSarutz 		    ucmd.uscsi_status, errno);
12787c478bd9Sstevel@tonic-gate 		if ((rq_data[2] & 0xF) == KEY_ILLEGAL_REQUEST) {
12797c478bd9Sstevel@tonic-gate 			if (rq_data[12] == 0x26) {
12807c478bd9Sstevel@tonic-gate 				/* Wrong passwd */
12815363f09cSarutz 				debug(5, "Protection Request with wrong "
12825363f09cSarutz 				    "passwd. errno is being set to EACCES.\n");
12837c478bd9Sstevel@tonic-gate 				errno = EACCES;
12847c478bd9Sstevel@tonic-gate 			}
12857c478bd9Sstevel@tonic-gate 		}
12867c478bd9Sstevel@tonic-gate 		return (-1);
12877c478bd9Sstevel@tonic-gate 	}
12887c478bd9Sstevel@tonic-gate 
12897c478bd9Sstevel@tonic-gate 	return (0);
12907c478bd9Sstevel@tonic-gate }
12917c478bd9Sstevel@tonic-gate 
12927c478bd9Sstevel@tonic-gate /*ARGSUSED*/
12937c478bd9Sstevel@tonic-gate static int32_t
12947c478bd9Sstevel@tonic-gate scsi_write_protect(int32_t fd, smwp_state_t *wp)
12957c478bd9Sstevel@tonic-gate {
12967c478bd9Sstevel@tonic-gate 	errno = ENOTSUP;
12977c478bd9Sstevel@tonic-gate 	return (-1);
12987c478bd9Sstevel@tonic-gate }
12997c478bd9Sstevel@tonic-gate 
13005363f09cSarutz /*
13015363f09cSarutz  * This thread becomes the server-side thread used in
13025363f09cSarutz  * the implementation of a door_call between a client
13035363f09cSarutz  * and the Client Door.
13045363f09cSarutz  *
13055363f09cSarutz  * This thread is customized both by the door_server_create(3c)
13065363f09cSarutz  * function sm_door_server_create, as well as by itself.
13075363f09cSarutz  *
13085363f09cSarutz  * This thread needs to synchronize with the
13095363f09cSarutz  * main_servproc[SMEDIA_CNUM_OPEN_FD] door_call in terms of
13105363f09cSarutz  * both successful and failure scenarios.  main_servproc
13115363f09cSarutz  * locks dd_lock before calling door_create.  This thread
13125363f09cSarutz  * then attempts to lock, but will block until main_servproc
13135363f09cSarutz  * has either created all doors it requires, or until a
13145363f09cSarutz  * door_create has failed (door_create's return and the
13155363f09cSarutz  * creation of an associated thread are asynchronous).
13165363f09cSarutz  *
13175363f09cSarutz  * If door_create failed, this thread will be able to obtain
13185363f09cSarutz  * dd_lock and call pthread_exit.  If all door_create's succeed,
13195363f09cSarutz  * this thread will obtain dd_lock and commence with
13205363f09cSarutz  * customizing the thread's attributes.  door_bind is called to
13215363f09cSarutz  * bind this thread to the per-door private thread pool, and
13225363f09cSarutz  * main_servproc is cond_signal'd to avail it of this fact.
13235363f09cSarutz  *
13245363f09cSarutz  * Finally, this thread calls door_return, which causes it to
13255363f09cSarutz  * commence its lifetime as a server-side thread in implementation
13265363f09cSarutz  * of a Client Door door_call.
13275363f09cSarutz  */
13287c478bd9Sstevel@tonic-gate static void *
13295363f09cSarutz sm_server_thread(void *arg)
13307c478bd9Sstevel@tonic-gate {
13317c478bd9Sstevel@tonic-gate 	door_data_t	*door_dp;
13327c478bd9Sstevel@tonic-gate 	struct		sigaction act;
13335363f09cSarutz 	int		i;
13345363f09cSarutz 	int		err;
13357c478bd9Sstevel@tonic-gate 
13367c478bd9Sstevel@tonic-gate 	door_dp = (door_data_t *)arg;
13377c478bd9Sstevel@tonic-gate 
13387c478bd9Sstevel@tonic-gate 	if (door_dp == NULL) {
13395363f09cSarutz 		fatal("sm_server_thread[%d]: argument is NULL!!\n",
13407c478bd9Sstevel@tonic-gate 		    pthread_self());
13417c478bd9Sstevel@tonic-gate 		exit(-1);
13427c478bd9Sstevel@tonic-gate 	}
13437c478bd9Sstevel@tonic-gate 
13445363f09cSarutz 	/* Wait for Client Door to be created */
13457c478bd9Sstevel@tonic-gate 	(void) mutex_lock(&door_dp->dd_lock);
13465363f09cSarutz 	if (door_dp->dd_cdoor_descriptor < 0) {
13475363f09cSarutz 		debug(5, "sm_server_thread[%d]: door_create() failed",
13485363f09cSarutz 		    pthread_self());
13495363f09cSarutz 		(void) mutex_unlock(&door_dp->dd_lock);
13505363f09cSarutz 		pthread_exit((void *)-2);
13515363f09cSarutz 	}
13527c478bd9Sstevel@tonic-gate 	(void) mutex_unlock(&door_dp->dd_lock);
13537c478bd9Sstevel@tonic-gate 
13547c478bd9Sstevel@tonic-gate 	for (i = 0; i < N_BADSIGS; i++) {
13557c478bd9Sstevel@tonic-gate 		act.sa_sigaction = server_badsig_handler;
13567c478bd9Sstevel@tonic-gate 		(void) sigemptyset(&act.sa_mask);
13577c478bd9Sstevel@tonic-gate 		act.sa_flags = SA_SIGINFO;
13587c478bd9Sstevel@tonic-gate 		if (sigaction(badsigs[i], &act, NULL) == -1)
13597c478bd9Sstevel@tonic-gate 			warning(gettext(SIGACT_FAILED), strsignal(badsigs[i]),
13607c478bd9Sstevel@tonic-gate 			    strerror(errno));
13617c478bd9Sstevel@tonic-gate 	}
13627c478bd9Sstevel@tonic-gate 	if (sigemptyset(&door_dp->dd_newset) != 0)
13637c478bd9Sstevel@tonic-gate 		warning(gettext("sigemptyset failed. errno = %d\n"),
13647c478bd9Sstevel@tonic-gate 		    errno);
13655363f09cSarutz 	if ((err = pthread_sigmask(SIG_BLOCK, &door_dp->dd_newset, NULL)) != 0)
13665363f09cSarutz 		warning(gettext("pthread_sigmask failed = %d\n"), err);
13677c478bd9Sstevel@tonic-gate 
13685363f09cSarutz 	/* Bind thread with pool associated with Client Door */
13697c478bd9Sstevel@tonic-gate 
13705363f09cSarutz 	if (door_bind(door_dp->dd_cdoor_descriptor) < 0) {
13717c478bd9Sstevel@tonic-gate 		fatal("door_bind");
13727c478bd9Sstevel@tonic-gate 		exit(-1);
13737c478bd9Sstevel@tonic-gate 	}
13745363f09cSarutz 	debug(5, "thr[%d] bound to Client Door[%d]", pthread_self(),
13755363f09cSarutz 	    door_dp->dd_cdoor_descriptor);
13765363f09cSarutz 
13777c478bd9Sstevel@tonic-gate 	/*
13785363f09cSarutz 	 * Set these two cancellation(5) attributes.  Ensure that the
13795363f09cSarutz 	 * pthread we create has cancellation(5) DISABLED and DEFERRED,
13805363f09cSarutz 	 * as our implementation is based on this.  DEFERRED is the
13815363f09cSarutz 	 * default, but set it anyways, in case the defaults change in
13825363f09cSarutz 	 * the future.
13837c478bd9Sstevel@tonic-gate 	 */
13845363f09cSarutz 	if ((err = pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL)) != 0)
13855363f09cSarutz 		warning(gettext("pthread_setcancelstate(PTHREAD_CANCEL_DISABLE)"
13865363f09cSarutz 		    " failed = %d\n"), err);
13875363f09cSarutz 	if ((err = pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED,
13885363f09cSarutz 	    NULL)) != 0)
13895363f09cSarutz 		warning(gettext("pthread_setcanceltype(DEFERRED) "
13905363f09cSarutz 		    "failed = %d\n"), err);
13915363f09cSarutz 
13925363f09cSarutz 	/* Inform main_servproc that door_bind() is complete. */
13937c478bd9Sstevel@tonic-gate 	(void) cond_signal(&door_dp->dd_cv_bind);
13945363f09cSarutz 
13955363f09cSarutz 	/*
13965363f09cSarutz 	 * Per doors protocol, transfer control to the doors-runtime in
13975363f09cSarutz 	 * order to make this thread available to answer future door_call()'s.
13985363f09cSarutz 	 */
13997c478bd9Sstevel@tonic-gate 	(void) door_return(NULL, 0, NULL, 0);
14007c478bd9Sstevel@tonic-gate 	return (NULL);
14017c478bd9Sstevel@tonic-gate }
14027c478bd9Sstevel@tonic-gate 
14035363f09cSarutz /*
14045363f09cSarutz  * This function cleans up all per-connection resources.
14055363f09cSarutz  *
14065363f09cSarutz  * This function is called when the Client Door's service procedure
14075363f09cSarutz  * (client_servproc) is called w/ DOOR_UNREF_DATA, which is the
14085363f09cSarutz  * doors protocol convention stating that the number of file
14095363f09cSarutz  * descriptors referring to this door has dropped to one.
14105363f09cSarutz  * client_servproc is passed DOOR_UNREF_DATA because the Client Door
14115363f09cSarutz  * was door_create'd with the DOOR_UNREF bitflag.
14125363f09cSarutz  */
14137c478bd9Sstevel@tonic-gate static void
14147c478bd9Sstevel@tonic-gate cleanup(door_data_t *door_dp)
14157c478bd9Sstevel@tonic-gate {
14165363f09cSarutz 	/* do door_revoke() of Death Door */
14175363f09cSarutz 	if (door_dp->dd_ddoor_descriptor >= 0) {
14185363f09cSarutz 		debug(1, "cleanup[%d]: door_revoke() Death Door[%d]",
14195363f09cSarutz 		    pthread_self(), door_dp->dd_ddoor_descriptor);
14207c478bd9Sstevel@tonic-gate 
14215363f09cSarutz 		if (door_revoke(door_dp->dd_ddoor_descriptor) < 0) {
14225363f09cSarutz 			warning(gettext("cleanup[%d]: door_revoke() of Death "
14235363f09cSarutz 			    "Door(%d) failed = %d"), pthread_self(),
14245363f09cSarutz 			    door_dp->dd_ddoor_descriptor, errno);
14255363f09cSarutz 		} else {
14265363f09cSarutz 			door_dp->dd_ddoor_descriptor = -1;
14277c478bd9Sstevel@tonic-gate 		}
14285363f09cSarutz 	}
14295363f09cSarutz 
14305363f09cSarutz 	/* release memory that is shared between client and (our) server */
14315363f09cSarutz 	if (door_dp->dd_buffd >= 0) {
14325363f09cSarutz 		debug(1, "cleanup[%d]: release shared memory", pthread_self());
14337c478bd9Sstevel@tonic-gate 		(void) munmap(door_dp->dd_buf, door_dp->dd_buf_len);
14347c478bd9Sstevel@tonic-gate 		(void) close(door_dp->dd_buffd);
14355363f09cSarutz 
14365363f09cSarutz 		door_dp->dd_buffd = -1;
14377c478bd9Sstevel@tonic-gate 		door_dp->dd_buf = NULL;
14387c478bd9Sstevel@tonic-gate 		door_dp->dd_buf_len = 0;
14397c478bd9Sstevel@tonic-gate 	}
14407c478bd9Sstevel@tonic-gate 
14415363f09cSarutz 	/* close the (target) device that the Client is operating on */
14425363f09cSarutz 	if (door_dp->dd_fd >= 0) {
14435363f09cSarutz 		debug(1, "cleanup[%d]: close(%d) target device", pthread_self(),
14445363f09cSarutz 		    door_dp->dd_fd);
14457c478bd9Sstevel@tonic-gate 		if (close(door_dp->dd_fd) < 0) {
14465363f09cSarutz 			warning(gettext("cleanup[%d]: close() of target device"
14475363f09cSarutz 			    "failed = %d\n"), pthread_self(), errno);
14487c478bd9Sstevel@tonic-gate 		}
14497c478bd9Sstevel@tonic-gate 	}
14507c478bd9Sstevel@tonic-gate 
14515363f09cSarutz 	/*
14525363f09cSarutz 	 * Unbind the current thread from the Client Door's private
14535363f09cSarutz 	 * thread pool.
14545363f09cSarutz 	 */
14555363f09cSarutz 	debug(1, "cleanup[%d]: door_unbind() of Client Door[%d]",
14565363f09cSarutz 	    pthread_self(), door_dp->dd_cdoor_descriptor);
14575363f09cSarutz 	if (door_unbind() < 0)
14585363f09cSarutz 		warning("door_unbind() of Client Door[%d] failed = "
14595363f09cSarutz 		    "%d", door_dp->dd_cdoor_descriptor, errno);
14605363f09cSarutz 
14615363f09cSarutz 	/* Disallow any future requests to the Client Door */
14625363f09cSarutz 	if (door_dp->dd_cdoor_descriptor >= 0) {
14635363f09cSarutz 		debug(1, "cleanup[%d]: door_revoke() Client Door[%d]",
14645363f09cSarutz 		    pthread_self(), door_dp->dd_cdoor_descriptor);
14655363f09cSarutz 
14665363f09cSarutz 		if (door_revoke(door_dp->dd_cdoor_descriptor) < 0) {
14675363f09cSarutz 			warning(gettext("cleanup[%d]: door_revoke() of "
14685363f09cSarutz 			    "Client Door[%d] failed = %d"), pthread_self(),
14695363f09cSarutz 			    door_dp->dd_cdoor_descriptor, errno);
14705363f09cSarutz 		}
14715363f09cSarutz 	}
14725363f09cSarutz 
14735363f09cSarutz 	free(door_dp);
14745363f09cSarutz 	debug(5, "cleanup[%d] ...exiting\n", pthread_self());
14755363f09cSarutz }
14765363f09cSarutz 
14775363f09cSarutz /*
14785363f09cSarutz  * This is the door_server_create(3c) function used to customize
14795363f09cSarutz  * creation of the threads used in the handling of our daemon's
14805363f09cSarutz  * door_call(3c)'s.
14815363f09cSarutz  *
14825363f09cSarutz  * This function is called synchronously as part of door_create(3c).
14835363f09cSarutz  * Note that door_create(), however, is not synchronous; it can return
14845363f09cSarutz  * with the created door file descriptor before any associated
14855363f09cSarutz  * thread has been created.  As a result, synchronization is needed
14865363f09cSarutz  * between door_create() caller and the created pthread.  This is
14875363f09cSarutz  * needed both when each activity succeeds or when either activity
14885363f09cSarutz  * fails.
14895363f09cSarutz  *
14905363f09cSarutz  * Specifically, this function ensures that each "connection"
14915363f09cSarutz  * with the client creates only one thread in the per-door,
14925363f09cSarutz  * private thread pool.  This function locks dd_threadlock and
14935363f09cSarutz  * then calls pthread_create().  If that succeeds, dd_thread
14945363f09cSarutz  * is assigned the thread id, and dd_threadlock is unlocked.
14955363f09cSarutz  * Any per-connection door_create that causes control to flow
14965363f09cSarutz  * to this function will eventually find that dd_thread is
14975363f09cSarutz  * non-zero, and control will exit this function.
14985363f09cSarutz  *
14995363f09cSarutz  * In the current implementation, the door_create for the Client Door
15005363f09cSarutz  * is called first, and the Death Door is door_create'd second.
15015363f09cSarutz  * As a result, the following function can safely make the static
15025363f09cSarutz  * assumption that the first door (within a connection) is the
15035363f09cSarutz  * Client Door.  A connection's Client Door and Death Door share
15045363f09cSarutz  * the same thread as well as the same door_data_t instance.
15055363f09cSarutz  */
15067c478bd9Sstevel@tonic-gate static void
15075363f09cSarutz sm_door_server_create(door_info_t *dip)
15087c478bd9Sstevel@tonic-gate {
15097c478bd9Sstevel@tonic-gate 	door_data_t	*door_dp;
15107c478bd9Sstevel@tonic-gate 	pthread_t	tid;
15117c478bd9Sstevel@tonic-gate 	pthread_attr_t	attr;
15127c478bd9Sstevel@tonic-gate 	int		ret_val;
15135363f09cSarutz 	int		err;
15147c478bd9Sstevel@tonic-gate 
15157c478bd9Sstevel@tonic-gate 	if (dip == NULL) {
15167c478bd9Sstevel@tonic-gate 		return;
15177c478bd9Sstevel@tonic-gate 	}
1518360e6f5eSmathue 	door_dp = (door_data_t *)(uintptr_t)dip->di_data;
15197c478bd9Sstevel@tonic-gate 
15205363f09cSarutz 	debug(10, "sm_door_server_create[%d]: entering...\n", pthread_self());
15217c478bd9Sstevel@tonic-gate 
15227c478bd9Sstevel@tonic-gate 	/* create one thread for this door */
15237c478bd9Sstevel@tonic-gate 
15247c478bd9Sstevel@tonic-gate 	(void) mutex_lock(&door_dp->dd_threadlock);
15257c478bd9Sstevel@tonic-gate 
15267c478bd9Sstevel@tonic-gate 	if (door_dp->dd_thread != 0) {
15275363f09cSarutz 		debug(8, "sm_door_server_create[%d]: Exiting without creating "
15285363f09cSarutz 		    "thread.\n", pthread_self());
15297c478bd9Sstevel@tonic-gate 		(void) mutex_unlock(&door_dp->dd_threadlock);
15307c478bd9Sstevel@tonic-gate 		return;
15317c478bd9Sstevel@tonic-gate 	}
15327c478bd9Sstevel@tonic-gate 
15337c478bd9Sstevel@tonic-gate 	(void) pthread_attr_init(&attr);
15347c478bd9Sstevel@tonic-gate 
15355363f09cSarutz 	if ((err = pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM)) != 0)
15365363f09cSarutz 		warning(gettext("pthread_attr_setscope failed = %d\n"), err);
15375363f09cSarutz 	if ((err = pthread_attr_setdetachstate(&attr,
15385363f09cSarutz 	    PTHREAD_CREATE_DETACHED)) != 0)
15395363f09cSarutz 		warning(gettext("pthread_attr_setdetachstate failed = %d\n"),
15405363f09cSarutz 		    err);
15415363f09cSarutz 
15425363f09cSarutz 	ret_val = pthread_create(&tid, &attr, sm_server_thread,
15435363f09cSarutz 	    (void *)(uintptr_t)(dip->di_data));
15447c478bd9Sstevel@tonic-gate 	if (ret_val != 0) {
15455363f09cSarutz 		warning(gettext("sm_door_server_create[%d]: pthread_create "
15465363f09cSarutz 		    "failed = %d\n"), pthread_self(), ret_val);
15477c478bd9Sstevel@tonic-gate 		(void) mutex_unlock(&door_dp->dd_threadlock);
15487c478bd9Sstevel@tonic-gate 		(void) pthread_attr_destroy(&attr);
15497c478bd9Sstevel@tonic-gate 		return;
15507c478bd9Sstevel@tonic-gate 	}
15517c478bd9Sstevel@tonic-gate 	(void) pthread_attr_destroy(&attr);
15527c478bd9Sstevel@tonic-gate 	door_dp->dd_thread = tid;
15537c478bd9Sstevel@tonic-gate 
15547c478bd9Sstevel@tonic-gate 	(void) mutex_unlock(&door_dp->dd_threadlock);
15555363f09cSarutz 	debug(5, "Exiting sm_door_server_create[%d] after creating thr[%d].\n",
15565363f09cSarutz 	    pthread_self(), tid);
15577c478bd9Sstevel@tonic-gate }
15587c478bd9Sstevel@tonic-gate 
15597c478bd9Sstevel@tonic-gate static void
15607c478bd9Sstevel@tonic-gate door_ret_err(smedia_reterror_t *reterror, int32_t err)
15617c478bd9Sstevel@tonic-gate {
15627c478bd9Sstevel@tonic-gate 	reterror->cnum = SMEDIA_CNUM_ERROR;
15637c478bd9Sstevel@tonic-gate 	reterror->errnum = err;
15647c478bd9Sstevel@tonic-gate 	(void) door_return((char *)reterror, sizeof (smedia_reterror_t), 0, 0);
15657c478bd9Sstevel@tonic-gate }
15667c478bd9Sstevel@tonic-gate 
15677c478bd9Sstevel@tonic-gate static void
15687c478bd9Sstevel@tonic-gate my_door_return(char *data_ptr, size_t data_size,
15697c478bd9Sstevel@tonic-gate 	door_desc_t *desc_ptr, uint_t num_desc)
15707c478bd9Sstevel@tonic-gate {
15717c478bd9Sstevel@tonic-gate 	(void) door_return(data_ptr, data_size, desc_ptr, num_desc);
15727c478bd9Sstevel@tonic-gate }
15737c478bd9Sstevel@tonic-gate 
15747c478bd9Sstevel@tonic-gate static int32_t
15757c478bd9Sstevel@tonic-gate raw_read(door_data_t *door_dp, smedia_services_t *req)
15767c478bd9Sstevel@tonic-gate {
15777c478bd9Sstevel@tonic-gate 	struct uscsi_cmd	ucmd;
15787c478bd9Sstevel@tonic-gate 	union scsi_cdb		cdb;
15797c478bd9Sstevel@tonic-gate 	int32_t			ret_val;
15807c478bd9Sstevel@tonic-gate 	int32_t			num_sectors, sector_size;
15817c478bd9Sstevel@tonic-gate 	int32_t			rc_data[2];
15827c478bd9Sstevel@tonic-gate 	char			rq_data[RQ_LEN];
15837c478bd9Sstevel@tonic-gate 
15847c478bd9Sstevel@tonic-gate 	(void) memset((void *) &rc_data, 0, sizeof (rc_data));
15857c478bd9Sstevel@tonic-gate 	(void) memset((void *) &ucmd, 0, sizeof (ucmd));
15867c478bd9Sstevel@tonic-gate 	(void) memset((void *) &cdb, 0, sizeof (union scsi_cdb));
15877c478bd9Sstevel@tonic-gate 
15887c478bd9Sstevel@tonic-gate 	if (door_dp->dd_sector_size == 0) {
15897c478bd9Sstevel@tonic-gate 		sector_size = get_sector_size(door_dp->dd_fd);
15907c478bd9Sstevel@tonic-gate 		door_dp->dd_sector_size = sector_size;
15917c478bd9Sstevel@tonic-gate 	} else sector_size = door_dp->dd_sector_size;
15927c478bd9Sstevel@tonic-gate 
15937c478bd9Sstevel@tonic-gate 	if ((req->reqraw_read.nbytes > door_dp->dd_buf_len) ||
15947c478bd9Sstevel@tonic-gate 		(door_dp->dd_buf == NULL)) {
15957c478bd9Sstevel@tonic-gate 		errno = EINVAL;
15967c478bd9Sstevel@tonic-gate 		return (-1);
15977c478bd9Sstevel@tonic-gate 	}
15987c478bd9Sstevel@tonic-gate 	if ((!req->reqraw_read.nbytes) ||
15997c478bd9Sstevel@tonic-gate 		(req->reqraw_read.nbytes % sector_size)) {
16007c478bd9Sstevel@tonic-gate 		errno = EINVAL;
16017c478bd9Sstevel@tonic-gate 		return (-1);
16027c478bd9Sstevel@tonic-gate 	}
16037c478bd9Sstevel@tonic-gate 
16047c478bd9Sstevel@tonic-gate 	(void) memset((void *) &cdb, 0, sizeof (cdb));
16057c478bd9Sstevel@tonic-gate 	num_sectors = (uint32_t)req->reqraw_read.nbytes/sector_size;
16067c478bd9Sstevel@tonic-gate 
16077c478bd9Sstevel@tonic-gate 	cdb.scc_cmd = SCMD_READ_G1;
16087c478bd9Sstevel@tonic-gate 	FORMG1ADDR(&cdb, (uint32_t)req->reqraw_read.blockno);
16097c478bd9Sstevel@tonic-gate 	FORMG1COUNT(&cdb, num_sectors);
16107c478bd9Sstevel@tonic-gate 
16117c478bd9Sstevel@tonic-gate 	ucmd.uscsi_cdb = (caddr_t)&cdb;
16127c478bd9Sstevel@tonic-gate 	ucmd.uscsi_cdblen = CDB_GROUP1;
16137c478bd9Sstevel@tonic-gate 	ucmd.uscsi_bufaddr = (caddr_t)door_dp->dd_buf;
16147c478bd9Sstevel@tonic-gate 	ucmd.uscsi_buflen = (uint32_t)req->reqraw_read.nbytes;
16157c478bd9Sstevel@tonic-gate 	ucmd.uscsi_timeout = 120;	/* If 0, HBA hangs forever */
16167c478bd9Sstevel@tonic-gate 	ucmd.uscsi_rqlen = RQ_LEN;
16177c478bd9Sstevel@tonic-gate 	ucmd.uscsi_rqbuf = rq_data;
16187c478bd9Sstevel@tonic-gate 	ret_val = do_uscsi_cmd(door_dp->dd_fd,
16197c478bd9Sstevel@tonic-gate 		&ucmd, USCSI_READ|USCSI_RQENABLE);
16207c478bd9Sstevel@tonic-gate 	if (ret_val || ucmd.uscsi_status) {
16217c478bd9Sstevel@tonic-gate 		debug(5, "read failed: %d - %d errno = %d\n",
16227c478bd9Sstevel@tonic-gate 			ret_val, ucmd.uscsi_status, errno);
16237c478bd9Sstevel@tonic-gate 		debug(5, "buflen = 0x%x resid = 0x%x sector size = %d\n",
16247c478bd9Sstevel@tonic-gate 			ucmd.uscsi_buflen, ucmd.uscsi_resid, sector_size);
16257c478bd9Sstevel@tonic-gate 		debug(5, "cdb addr: %x %x %x %x \n", cdb.g1_addr3,
16267c478bd9Sstevel@tonic-gate 			cdb.g1_addr2, cdb.g1_addr1, cdb.g1_addr0);
16277c478bd9Sstevel@tonic-gate 		debug(5, "cdb count: %x %x\n", cdb.g1_count1,
16287c478bd9Sstevel@tonic-gate 			cdb.g1_count0);
16297c478bd9Sstevel@tonic-gate 		return (-1);
16307c478bd9Sstevel@tonic-gate 	}
16317c478bd9Sstevel@tonic-gate 	ret_val = ucmd.uscsi_buflen - ucmd.uscsi_resid;
16327c478bd9Sstevel@tonic-gate 	return (ret_val);
16337c478bd9Sstevel@tonic-gate }
16347c478bd9Sstevel@tonic-gate 
16357c478bd9Sstevel@tonic-gate static int32_t
16367c478bd9Sstevel@tonic-gate raw_write(door_data_t *door_dp, smedia_services_t *req)
16377c478bd9Sstevel@tonic-gate {
16387c478bd9Sstevel@tonic-gate 	struct uscsi_cmd	ucmd;
16397c478bd9Sstevel@tonic-gate 	union scsi_cdb		cdb;
16407c478bd9Sstevel@tonic-gate 	int32_t			ret_val;
16417c478bd9Sstevel@tonic-gate 	int32_t			num_sectors, sector_size;
16427c478bd9Sstevel@tonic-gate 	int32_t			rc_data[2];
16437c478bd9Sstevel@tonic-gate 	char			rq_data[RQ_LEN];
16447c478bd9Sstevel@tonic-gate 
16457c478bd9Sstevel@tonic-gate 	(void) memset((void *) &rc_data, 0, sizeof (rc_data));
16467c478bd9Sstevel@tonic-gate 	(void) memset((void *) &ucmd, 0, sizeof (ucmd));
16477c478bd9Sstevel@tonic-gate 	(void) memset((void *) &cdb, 0, sizeof (union scsi_cdb));
16487c478bd9Sstevel@tonic-gate 
16497c478bd9Sstevel@tonic-gate 	if (door_dp->dd_sector_size == 0) {
16507c478bd9Sstevel@tonic-gate 		sector_size = get_sector_size(door_dp->dd_fd);
16517c478bd9Sstevel@tonic-gate 		door_dp->dd_sector_size = sector_size;
16527c478bd9Sstevel@tonic-gate 	} else sector_size = door_dp->dd_sector_size;
16537c478bd9Sstevel@tonic-gate 
16547c478bd9Sstevel@tonic-gate 
16557c478bd9Sstevel@tonic-gate 	if ((req->reqraw_write.nbytes > door_dp->dd_buf_len) ||
16567c478bd9Sstevel@tonic-gate 		(door_dp->dd_buf == NULL)) {
16577c478bd9Sstevel@tonic-gate 		errno = EINVAL;
16587c478bd9Sstevel@tonic-gate 		return (-1);
16597c478bd9Sstevel@tonic-gate 	}
16607c478bd9Sstevel@tonic-gate 	if ((req->reqraw_write.nbytes % sector_size)) {
16617c478bd9Sstevel@tonic-gate 		errno = EINVAL;
16627c478bd9Sstevel@tonic-gate 		return (-1);
16637c478bd9Sstevel@tonic-gate 	}
16647c478bd9Sstevel@tonic-gate 
16657c478bd9Sstevel@tonic-gate 	(void) memset((void *) &cdb, 0, sizeof (cdb));
16667c478bd9Sstevel@tonic-gate 	num_sectors = (uint32_t)req->reqraw_write.nbytes/sector_size;
16677c478bd9Sstevel@tonic-gate 
16687c478bd9Sstevel@tonic-gate 	cdb.scc_cmd = SCMD_WRITE_G1;
16697c478bd9Sstevel@tonic-gate 	FORMG1ADDR(&cdb, (uint32_t)req->reqraw_write.blockno);
16707c478bd9Sstevel@tonic-gate 	FORMG1COUNT(&cdb, num_sectors);
16717c478bd9Sstevel@tonic-gate 
16727c478bd9Sstevel@tonic-gate 	ucmd.uscsi_cdb = (caddr_t)&cdb;
16737c478bd9Sstevel@tonic-gate 	ucmd.uscsi_cdblen = CDB_GROUP1;
16747c478bd9Sstevel@tonic-gate 	ucmd.uscsi_bufaddr = (caddr_t)door_dp->dd_buf;
16757c478bd9Sstevel@tonic-gate 	ucmd.uscsi_buflen = (uint32_t)req->reqraw_write.nbytes;
16767c478bd9Sstevel@tonic-gate 	ucmd.uscsi_timeout = 120;	/* If 0, HBA hangs forever */
16777c478bd9Sstevel@tonic-gate 	ucmd.uscsi_rqlen = RQ_LEN;
16787c478bd9Sstevel@tonic-gate 	ucmd.uscsi_rqbuf = rq_data;
16797c478bd9Sstevel@tonic-gate 	ret_val = do_uscsi_cmd(door_dp->dd_fd,
16807c478bd9Sstevel@tonic-gate 		&ucmd, USCSI_WRITE|USCSI_RQENABLE);
16817c478bd9Sstevel@tonic-gate 	if (ret_val || ucmd.uscsi_status) {
16827c478bd9Sstevel@tonic-gate 		debug(5, "write failed: %d - %d errno = %d\n",
16837c478bd9Sstevel@tonic-gate 			ret_val, ucmd.uscsi_status, errno);
16847c478bd9Sstevel@tonic-gate 		debug(5, "buflen = 0x%x resid = 0x%x sector size = %d\n",
16857c478bd9Sstevel@tonic-gate 			ucmd.uscsi_buflen, ucmd.uscsi_resid, sector_size);
16867c478bd9Sstevel@tonic-gate 		debug(5, "cdb addr: %x %x %x %x \n", cdb.g1_addr3,
16877c478bd9Sstevel@tonic-gate 			cdb.g1_addr2, cdb.g1_addr1, cdb.g1_addr0);
16887c478bd9Sstevel@tonic-gate 		debug(5, "cdb count: %x %x\n", cdb.g1_count1,
16897c478bd9Sstevel@tonic-gate 			cdb.g1_count0);
16907c478bd9Sstevel@tonic-gate 		return (-1);
16917c478bd9Sstevel@tonic-gate 	}
16927c478bd9Sstevel@tonic-gate 	ret_val = ucmd.uscsi_buflen - ucmd.uscsi_resid;
16937c478bd9Sstevel@tonic-gate 	return (ret_val);
16947c478bd9Sstevel@tonic-gate }
16957c478bd9Sstevel@tonic-gate 
16967c478bd9Sstevel@tonic-gate static int32_t
16977c478bd9Sstevel@tonic-gate set_protection_status(door_data_t *door_dp, smedia_services_t *req)
16987c478bd9Sstevel@tonic-gate {
16997c478bd9Sstevel@tonic-gate 	int32_t			ret_val, saved_errno, status;
17007c478bd9Sstevel@tonic-gate 	struct scsi_inquiry	inq;
17017c478bd9Sstevel@tonic-gate 	char			vid[9];
17027c478bd9Sstevel@tonic-gate 	char			pid[17];
17037c478bd9Sstevel@tonic-gate 	struct passwd		*pwd;
17047c478bd9Sstevel@tonic-gate 	char			uname[MAXUGNAME + 1];
17057c478bd9Sstevel@tonic-gate 	char			*new_state, *old_state;
17067c478bd9Sstevel@tonic-gate 
17077c478bd9Sstevel@tonic-gate 	/*
17087c478bd9Sstevel@tonic-gate 	 * Read the current protection state before modifiying.
17097c478bd9Sstevel@tonic-gate 	 * Needed for audit purposes.
17107c478bd9Sstevel@tonic-gate 	 */
17117c478bd9Sstevel@tonic-gate 	switch (get_device_type_scsi(door_dp->dd_fd, &inq)) {
17127c478bd9Sstevel@tonic-gate 	case SCSI_IOMEGA:
17137c478bd9Sstevel@tonic-gate 		status = scsi_zip_media_status(door_dp->dd_fd);
17147c478bd9Sstevel@tonic-gate 		ret_val = scsi_zip_write_protect(door_dp->dd_fd,
17157c478bd9Sstevel@tonic-gate 			&req->reqset_protection_status.prot_state);
17167c478bd9Sstevel@tonic-gate 		break;
17177c478bd9Sstevel@tonic-gate 	case SCSI_FLOPPY:
17187c478bd9Sstevel@tonic-gate 		info("Formatting floppy");
17197c478bd9Sstevel@tonic-gate 		status = scsi_floppy_media_status(door_dp->dd_fd);
17207c478bd9Sstevel@tonic-gate 		ret_val = scsi_floppy_write_protect(door_dp->dd_fd,
17217c478bd9Sstevel@tonic-gate 			&req->reqset_protection_status.prot_state);
17227c478bd9Sstevel@tonic-gate 		break;
17237c478bd9Sstevel@tonic-gate 	case SCSI_GENERIC:
17247c478bd9Sstevel@tonic-gate 		status = scsi_media_status(door_dp->dd_fd);
17257c478bd9Sstevel@tonic-gate 		ret_val = scsi_write_protect(door_dp->dd_fd,
17267c478bd9Sstevel@tonic-gate 			&req->reqset_protection_status.prot_state);
17277c478bd9Sstevel@tonic-gate 		break;
17287c478bd9Sstevel@tonic-gate 	}
17297c478bd9Sstevel@tonic-gate 
17307c478bd9Sstevel@tonic-gate 	saved_errno = errno;
17317c478bd9Sstevel@tonic-gate 	new_state = xlate_state(
17327c478bd9Sstevel@tonic-gate 	    req->reqset_protection_status.prot_state.sm_new_state);
17337c478bd9Sstevel@tonic-gate 	old_state = xlate_state(status);
17347c478bd9Sstevel@tonic-gate 
17357c478bd9Sstevel@tonic-gate 	if (can_audit()) {
17367c478bd9Sstevel@tonic-gate 		(void) audit_save_me(door_dp);
17377c478bd9Sstevel@tonic-gate 		door_dp->audit_text[0] = 0;
17387c478bd9Sstevel@tonic-gate 		door_dp->audit_text1[0] = 0;
17397c478bd9Sstevel@tonic-gate 		door_dp->audit_event = AUE_smserverd;
17407c478bd9Sstevel@tonic-gate 	}
17417c478bd9Sstevel@tonic-gate 	(void) strlcpy(vid, inq.inq_vid, sizeof (vid));
17427c478bd9Sstevel@tonic-gate 	(void) strlcpy(pid, inq.inq_pid, sizeof (pid));
17437c478bd9Sstevel@tonic-gate 	if (ret_val < 0) {
17447c478bd9Sstevel@tonic-gate 	    if (errno == EACCES) {
17457c478bd9Sstevel@tonic-gate 		pwd = getpwuid(door_dp->dd_cred.dc_ruid);
17467c478bd9Sstevel@tonic-gate 		if (pwd != NULL) {
17477c478bd9Sstevel@tonic-gate 			(void) strlcpy(uname,
17487c478bd9Sstevel@tonic-gate 				pwd->pw_name, MAXUGNAME);
17497c478bd9Sstevel@tonic-gate 		} else uname[0] = 0;
17507c478bd9Sstevel@tonic-gate 
17517c478bd9Sstevel@tonic-gate 		if (can_audit()) {
17527c478bd9Sstevel@tonic-gate 			(void) snprintf(door_dp->audit_text,
17537c478bd9Sstevel@tonic-gate 				sizeof (door_dp->audit_text),
17547c478bd9Sstevel@tonic-gate 				dgettext(TEXT_DOMAIN, "from %s to %s"),
17557c478bd9Sstevel@tonic-gate 				old_state, new_state);
17567c478bd9Sstevel@tonic-gate 
17577c478bd9Sstevel@tonic-gate 			(void) snprintf(door_dp->audit_text1,
17587c478bd9Sstevel@tonic-gate 				sizeof (door_dp->audit_text1),
17597c478bd9Sstevel@tonic-gate 				"%s %s (%d,%d)", vid, pid,
17607c478bd9Sstevel@tonic-gate 				(int)major(door_dp->dd_stat.st_rdev),
17617c478bd9Sstevel@tonic-gate 				(int)minor(door_dp->dd_stat.st_rdev));
17627c478bd9Sstevel@tonic-gate 
17637c478bd9Sstevel@tonic-gate 			door_dp->audit_sorf = 1;
17647c478bd9Sstevel@tonic-gate 			if (audit_audit(door_dp) == -1)
17657c478bd9Sstevel@tonic-gate 			    warning("Error in writing audit info\n");
17667c478bd9Sstevel@tonic-gate 		}
17677c478bd9Sstevel@tonic-gate 	    } /* errno == EACCES */
17687c478bd9Sstevel@tonic-gate 	    errno = saved_errno;
17697c478bd9Sstevel@tonic-gate 	    return (-1);
17707c478bd9Sstevel@tonic-gate 	}
17717c478bd9Sstevel@tonic-gate 	if (can_audit()) {
17727c478bd9Sstevel@tonic-gate 		(void) snprintf(door_dp->audit_text,
17737c478bd9Sstevel@tonic-gate 			sizeof (door_dp->audit_text),
17747c478bd9Sstevel@tonic-gate 			dgettext(TEXT_DOMAIN, "from %s to %s"),
17757c478bd9Sstevel@tonic-gate 			old_state, new_state);
17767c478bd9Sstevel@tonic-gate 
17777c478bd9Sstevel@tonic-gate 		(void) snprintf(door_dp->audit_text1,
17787c478bd9Sstevel@tonic-gate 			sizeof (door_dp->audit_text1),
17797c478bd9Sstevel@tonic-gate 			"%s %s (%d,%d)", vid, pid,
17807c478bd9Sstevel@tonic-gate 			(int)major(door_dp->dd_stat.st_rdev),
17817c478bd9Sstevel@tonic-gate 			(int)minor(door_dp->dd_stat.st_rdev));
17827c478bd9Sstevel@tonic-gate 
17837c478bd9Sstevel@tonic-gate 		door_dp->audit_sorf = 0;
17847c478bd9Sstevel@tonic-gate 		if (audit_audit(door_dp) == -1)
17857c478bd9Sstevel@tonic-gate 		    warning("Error in writing audit info\n");
17867c478bd9Sstevel@tonic-gate 	}
17877c478bd9Sstevel@tonic-gate 	errno = saved_errno;
17887c478bd9Sstevel@tonic-gate 	return (0);
17897c478bd9Sstevel@tonic-gate }
17907c478bd9Sstevel@tonic-gate 
17917c478bd9Sstevel@tonic-gate static int32_t
17927c478bd9Sstevel@tonic-gate set_shfd(door_data_t *door_dp, int32_t fd, smedia_services_t *req)
17937c478bd9Sstevel@tonic-gate {
17947c478bd9Sstevel@tonic-gate 	void	*fbuf;
17955363f09cSarutz 	int32_t ret_val = 0;
17967c478bd9Sstevel@tonic-gate 
17975363f09cSarutz 	if ((door_dp->dd_buffd != -1) && (door_dp->dd_buf != NULL)) {
17985363f09cSarutz 		ret_val = munmap(door_dp->dd_buf, door_dp->dd_buf_len);
17997c478bd9Sstevel@tonic-gate 		if (ret_val == -1)
18005363f09cSarutz 			warning(gettext("munmap failed. errno=%d\n"),
18017c478bd9Sstevel@tonic-gate 			    errno);
18027c478bd9Sstevel@tonic-gate 		(void) close(door_dp->dd_buffd);
18035363f09cSarutz 
18047c478bd9Sstevel@tonic-gate 		door_dp->dd_buffd = -1;
18057c478bd9Sstevel@tonic-gate 		door_dp->dd_buf = 0;
18067c478bd9Sstevel@tonic-gate 		door_dp->dd_buf_len = 0;
18077c478bd9Sstevel@tonic-gate 	}
18085363f09cSarutz 
18097c478bd9Sstevel@tonic-gate 	fbuf = mmap(0, req->reqset_shfd.fdbuf_len,
18107c478bd9Sstevel@tonic-gate 	    PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
18115363f09cSarutz 	if (fbuf == MAP_FAILED) {
18125363f09cSarutz 		ret_val = errno;
18137c478bd9Sstevel@tonic-gate 		debug(5, "mmap failed. errno=%d\n", errno);
18145363f09cSarutz 		return (ret_val);
18157c478bd9Sstevel@tonic-gate 	}
18167c478bd9Sstevel@tonic-gate 	door_dp->dd_buffd = fd;
18177c478bd9Sstevel@tonic-gate 	door_dp->dd_buf = fbuf;
18187c478bd9Sstevel@tonic-gate 	door_dp->dd_buf_len = req->reqset_shfd.fdbuf_len;
18195363f09cSarutz 
18207c478bd9Sstevel@tonic-gate 	return (0);
18217c478bd9Sstevel@tonic-gate }
18227c478bd9Sstevel@tonic-gate 
18237c478bd9Sstevel@tonic-gate static int32_t
18247c478bd9Sstevel@tonic-gate reassign_block(door_data_t *door_dp, smedia_services_t *req)
18257c478bd9Sstevel@tonic-gate {
18267c478bd9Sstevel@tonic-gate 	struct uscsi_cmd	ucmd;
18277c478bd9Sstevel@tonic-gate 	union scsi_cdb		cdb;
18287c478bd9Sstevel@tonic-gate 	int32_t			ret_val;
18297c478bd9Sstevel@tonic-gate 	int32_t			sector_size;
18307c478bd9Sstevel@tonic-gate 	char			*read_buf;
18317c478bd9Sstevel@tonic-gate 	uchar_t			mode_data[MD_LEN];
18327c478bd9Sstevel@tonic-gate 
18337c478bd9Sstevel@tonic-gate 	if (get_mode_page(door_dp->dd_fd, 0, 1,
18347c478bd9Sstevel@tonic-gate 	    mode_data, MD_LEN) < 0) {
18357c478bd9Sstevel@tonic-gate 		debug(5, "Mode sense failed\n");
18367c478bd9Sstevel@tonic-gate 		ret_val =  scsi_reassign_block(door_dp->dd_fd,
18377c478bd9Sstevel@tonic-gate 		    req->reqreassign_block.blockno);
18387c478bd9Sstevel@tonic-gate 		if (ret_val != 0)
18397c478bd9Sstevel@tonic-gate 			return (-1);
18407c478bd9Sstevel@tonic-gate 		return (0);
18417c478bd9Sstevel@tonic-gate 	}
18427c478bd9Sstevel@tonic-gate 
18437c478bd9Sstevel@tonic-gate 	/*
18447c478bd9Sstevel@tonic-gate 	 * No need to check if enough data is returned for
18457c478bd9Sstevel@tonic-gate 	 * AWRE bit or not.
18467c478bd9Sstevel@tonic-gate 	 * It will be 0 otherwise which needs to reassign the block.
18477c478bd9Sstevel@tonic-gate 	 */
18487c478bd9Sstevel@tonic-gate 	if (!(mode_data[AWRE_OFFSET] & AWRE)) {
18497c478bd9Sstevel@tonic-gate 		debug(5, "AWRE bit not set\n");
18507c478bd9Sstevel@tonic-gate 		ret_val =  scsi_reassign_block(door_dp->dd_fd,
18517c478bd9Sstevel@tonic-gate 			req->reqreassign_block.blockno);
18527c478bd9Sstevel@tonic-gate 		if (ret_val != 0)
18537c478bd9Sstevel@tonic-gate 			return (-1);
18547c478bd9Sstevel@tonic-gate 		return (0);
18557c478bd9Sstevel@tonic-gate 	}
18567c478bd9Sstevel@tonic-gate 	sector_size = (mode_data[BLOCK_LEN_OFFSET] << 16) |
18577c478bd9Sstevel@tonic-gate 		(mode_data[BLOCK_LEN_OFFSET + 1] << 8) |
18587c478bd9Sstevel@tonic-gate 		mode_data[BLOCK_LEN_OFFSET + 2];
18597c478bd9Sstevel@tonic-gate 
18607c478bd9Sstevel@tonic-gate 	debug(5, "REASSIGN BLOCK: sec size = 0x%x\n", sector_size);
18617c478bd9Sstevel@tonic-gate 	read_buf = (char *)malloc(sector_size);
18627c478bd9Sstevel@tonic-gate 	if (read_buf == NULL) {
18637c478bd9Sstevel@tonic-gate 		/* Alloc failed. Atleast reassign the block */
18647c478bd9Sstevel@tonic-gate 		ret_val =  scsi_reassign_block(door_dp->dd_fd,
18657c478bd9Sstevel@tonic-gate 			req->reqreassign_block.blockno);
18667c478bd9Sstevel@tonic-gate 		if (ret_val != 0)
18677c478bd9Sstevel@tonic-gate 			return (-1);
18687c478bd9Sstevel@tonic-gate 		return (0);
18697c478bd9Sstevel@tonic-gate 	}
18707c478bd9Sstevel@tonic-gate 
18717c478bd9Sstevel@tonic-gate 	(void) memset(read_buf, 0, sector_size);
18727c478bd9Sstevel@tonic-gate 	/* Read the sector */
18737c478bd9Sstevel@tonic-gate 	debug(5, "Reading the block %d\n",
18747c478bd9Sstevel@tonic-gate 		(uint32_t)req->reqreassign_block.blockno);
18757c478bd9Sstevel@tonic-gate 
18767c478bd9Sstevel@tonic-gate 	(void) memset((void *) &ucmd, 0, sizeof (ucmd));
18777c478bd9Sstevel@tonic-gate 	(void) memset((void *) &cdb, 0, sizeof (union scsi_cdb));
18787c478bd9Sstevel@tonic-gate 
18797c478bd9Sstevel@tonic-gate 	cdb.scc_cmd = SCMD_READ_G1;
18807c478bd9Sstevel@tonic-gate 	FORMG1ADDR(&cdb, req->reqreassign_block.blockno);
18817c478bd9Sstevel@tonic-gate 	FORMG1COUNT(&cdb, 1);	/* One block */
18827c478bd9Sstevel@tonic-gate 
18837c478bd9Sstevel@tonic-gate 	ucmd.uscsi_cdb = (caddr_t)&cdb;
18847c478bd9Sstevel@tonic-gate 	ucmd.uscsi_cdblen = CDB_GROUP1;
18857c478bd9Sstevel@tonic-gate 	ucmd.uscsi_bufaddr = (caddr_t)read_buf;
18867c478bd9Sstevel@tonic-gate 	ucmd.uscsi_buflen = sector_size;
18877c478bd9Sstevel@tonic-gate 	ucmd.uscsi_timeout = 120;	/* If 0, HBA hangs forever */
18887c478bd9Sstevel@tonic-gate 	(void) do_uscsi_cmd(door_dp->dd_fd, &ucmd, USCSI_READ);
18897c478bd9Sstevel@tonic-gate 
18907c478bd9Sstevel@tonic-gate 	/* Write the data back */
18917c478bd9Sstevel@tonic-gate 
18927c478bd9Sstevel@tonic-gate 	debug(5, "Writing the block %d\n",
18937c478bd9Sstevel@tonic-gate 		(uint32_t)req->reqreassign_block.blockno);
18947c478bd9Sstevel@tonic-gate 	(void) memset((void *) &ucmd, 0, sizeof (ucmd));
18957c478bd9Sstevel@tonic-gate 	(void) memset((void *) &cdb, 0, sizeof (cdb));
18967c478bd9Sstevel@tonic-gate 
18977c478bd9Sstevel@tonic-gate 	cdb.scc_cmd = SCMD_WRITE_G1;
18987c478bd9Sstevel@tonic-gate 	FORMG1ADDR(&cdb, req->reqreassign_block.blockno);
18997c478bd9Sstevel@tonic-gate 	FORMG1COUNT(&cdb, 1);	/* One block */
19007c478bd9Sstevel@tonic-gate 
19017c478bd9Sstevel@tonic-gate 	ucmd.uscsi_cdb = (caddr_t)&cdb;
19027c478bd9Sstevel@tonic-gate 	ucmd.uscsi_cdblen = CDB_GROUP1;
19037c478bd9Sstevel@tonic-gate 	ucmd.uscsi_bufaddr = (caddr_t)read_buf;
19047c478bd9Sstevel@tonic-gate 	ucmd.uscsi_buflen = sector_size;
19057c478bd9Sstevel@tonic-gate 	ucmd.uscsi_timeout = 120;	/* If 0, HBA hangs forever */
19067c478bd9Sstevel@tonic-gate 	ret_val = do_uscsi_cmd(door_dp->dd_fd, &ucmd, USCSI_WRITE);
19077c478bd9Sstevel@tonic-gate 	free(read_buf);
19087c478bd9Sstevel@tonic-gate 	if (ret_val || ucmd.uscsi_status) {
19097c478bd9Sstevel@tonic-gate 		debug(5, "Reassign failed: %d - %d errno = %d\n",
19107c478bd9Sstevel@tonic-gate 			ret_val, ucmd.uscsi_status, errno);
19117c478bd9Sstevel@tonic-gate 		ret_val = scsi_reassign_block(door_dp->dd_fd,
19127c478bd9Sstevel@tonic-gate 			req->reqreassign_block.blockno);
19137c478bd9Sstevel@tonic-gate 		if (ret_val != 0)
19147c478bd9Sstevel@tonic-gate 			return (-1);
19157c478bd9Sstevel@tonic-gate 		return (0);
19167c478bd9Sstevel@tonic-gate 	}
19177c478bd9Sstevel@tonic-gate 
19187c478bd9Sstevel@tonic-gate 	return (0);
19197c478bd9Sstevel@tonic-gate }
19207c478bd9Sstevel@tonic-gate 
19217c478bd9Sstevel@tonic-gate static void
19227c478bd9Sstevel@tonic-gate close_door_descs(door_desc_t *dp, uint_t ndesc)
19237c478bd9Sstevel@tonic-gate {
19247c478bd9Sstevel@tonic-gate 	while (ndesc > 0) {
19257c478bd9Sstevel@tonic-gate 		int fd = dp->d_data.d_desc.d_descriptor;
19267c478bd9Sstevel@tonic-gate 		if (dp->d_attributes & DOOR_DESCRIPTOR)
19277c478bd9Sstevel@tonic-gate 			(void) close(fd);
19287c478bd9Sstevel@tonic-gate 		dp++;
19297c478bd9Sstevel@tonic-gate 		ndesc--;
19307c478bd9Sstevel@tonic-gate 	}
19317c478bd9Sstevel@tonic-gate }
19327c478bd9Sstevel@tonic-gate 
19335363f09cSarutz /*
19345363f09cSarutz  * This is a Death Door's service procedure.
19355363f09cSarutz  *
19365363f09cSarutz  * This procedure is a NOP because the Death Door functionality
19375363f09cSarutz  * is no longer used and will be removed in the future.
19385363f09cSarutz  */
19395363f09cSarutz /*ARGSUSED*/
19407c478bd9Sstevel@tonic-gate static void
19415363f09cSarutz death_servproc(void *cookie, char *argp, size_t arg_size,
19425363f09cSarutz     door_desc_t *dp, uint_t ndesc)
19435363f09cSarutz {
19445363f09cSarutz 	debug(1, "death_servproc[%d]: argp = 0x%p  "
19455363f09cSarutz 	    "Death Door[%d]\n", pthread_self(), (void *)argp,
19465363f09cSarutz 	    ((door_data_t *)cookie)->dd_ddoor_descriptor);
19475363f09cSarutz 
19485363f09cSarutz 	(void) door_return(NULL, 0, NULL, 0);
19495363f09cSarutz }
19505363f09cSarutz 
19515363f09cSarutz /*
19525363f09cSarutz  * This is a Client Door's service procedure.
19535363f09cSarutz  *
19545363f09cSarutz  * This procedure is specified in the door_create() of a Client Door,
19555363f09cSarutz  * and its functionality represents the bulk of services that the
19565363f09cSarutz  * rpc.smserverd daemon offers.
19575363f09cSarutz  */
19585363f09cSarutz static void
19595363f09cSarutz client_servproc(void *cookie, char *argp, size_t arg_size,
19607c478bd9Sstevel@tonic-gate     door_desc_t *dp, uint_t ndesc)
19617c478bd9Sstevel@tonic-gate {
19627c478bd9Sstevel@tonic-gate 	smedia_services_t	*req;
19637c478bd9Sstevel@tonic-gate 	smedia_services_t	rmsvc;
19647c478bd9Sstevel@tonic-gate 	smedia_reterror_t	reterror;
19657c478bd9Sstevel@tonic-gate 	smedia_retraw_read_t	retraw_read;
19667c478bd9Sstevel@tonic-gate 	struct scsi_inquiry	inq;
19677c478bd9Sstevel@tonic-gate 	struct dk_minfo		media_info;
19687c478bd9Sstevel@tonic-gate 	struct dk_geom		dkgeom;
19697c478bd9Sstevel@tonic-gate 	int32_t			status;
19707c478bd9Sstevel@tonic-gate 	uchar_t			data[18];
19717c478bd9Sstevel@tonic-gate 	int32_t			completed = 0;
19727c478bd9Sstevel@tonic-gate 	door_data_t		*door_dp;
19737c478bd9Sstevel@tonic-gate 	size_t			retbuf_size;
19747c478bd9Sstevel@tonic-gate 	struct uscsi_cmd	ucmd;
19757c478bd9Sstevel@tonic-gate 	union scsi_cdb		cdb;
19767c478bd9Sstevel@tonic-gate 	int32_t			ret_val, err;
19777c478bd9Sstevel@tonic-gate 	char			rq_data[RQ_LEN];
19785363f09cSarutz 	uint_t			nexpected_desc;
19797c478bd9Sstevel@tonic-gate 	struct vtoc		vtoc;
19807c478bd9Sstevel@tonic-gate 
19817c478bd9Sstevel@tonic-gate 	door_dp = (door_data_t *)cookie;
19827c478bd9Sstevel@tonic-gate 	req = (smedia_services_t *)((void *)argp);
19837c478bd9Sstevel@tonic-gate 
19845363f09cSarutz 	debug(10, "client_servproc[%d]...\n", pthread_self());
19857c478bd9Sstevel@tonic-gate 
19867c478bd9Sstevel@tonic-gate 	if (argp == DOOR_UNREF_DATA) {
19875363f09cSarutz 		debug(5, "client_servproc[%d]: req = DOOR_UNREF_DATA\n",
19887c478bd9Sstevel@tonic-gate 		    pthread_self());
19897c478bd9Sstevel@tonic-gate 		debug(5, "Client has exited. Cleaning up resources\n");
19905363f09cSarutz 
19917c478bd9Sstevel@tonic-gate 		(void) mutex_lock(&svcstate_lock);
19927c478bd9Sstevel@tonic-gate 		svccount--;
19937c478bd9Sstevel@tonic-gate 		(void) mutex_unlock(&svcstate_lock);
19945363f09cSarutz 
19957c478bd9Sstevel@tonic-gate 		cleanup(door_dp);
19965363f09cSarutz 		return;
19977c478bd9Sstevel@tonic-gate 	}
19985363f09cSarutz 
19997c478bd9Sstevel@tonic-gate 	(void) mutex_lock(&svcstate_lock);
20007c478bd9Sstevel@tonic-gate 	svcstate = _SERVED;
20017c478bd9Sstevel@tonic-gate 	(void) mutex_unlock(&svcstate_lock);
20027c478bd9Sstevel@tonic-gate 
20037c478bd9Sstevel@tonic-gate 	rmsvc.in.cnum = req->in.cnum;
20045363f09cSarutz 	debug(5, "client_servproc[%d]: req = %s\n", pthread_self(),
20057c478bd9Sstevel@tonic-gate 	    xlate_cnum(req->in.cnum));
20067c478bd9Sstevel@tonic-gate 
20077c478bd9Sstevel@tonic-gate 	/*
20087c478bd9Sstevel@tonic-gate 	 * Our caller may have passed more descriptors than we expected.
20097c478bd9Sstevel@tonic-gate 	 * If so, we silently close (and ignore) them.
20107c478bd9Sstevel@tonic-gate 	 */
20115363f09cSarutz 	nexpected_desc = (req->in.cnum == SMEDIA_CNUM_SET_SHFD) ? 1 : 0;
20125363f09cSarutz 	if (ndesc > nexpected_desc) {
20135363f09cSarutz 		close_door_descs(dp + nexpected_desc, ndesc - nexpected_desc);
20145363f09cSarutz 	}
20157c478bd9Sstevel@tonic-gate 
20167c478bd9Sstevel@tonic-gate 	switch (req->in.cnum) {
20177c478bd9Sstevel@tonic-gate 	default:
20185363f09cSarutz 		debug(5, "client_servproc: unknown command %d\n", req->in.cnum);
20197c478bd9Sstevel@tonic-gate 		door_ret_err(&reterror, ENOTSUP);
20207c478bd9Sstevel@tonic-gate 		break;
20217c478bd9Sstevel@tonic-gate 
20227c478bd9Sstevel@tonic-gate 	case SMEDIA_CNUM_SET_SHFD:
20237c478bd9Sstevel@tonic-gate 		if (ndesc == 0)
20247c478bd9Sstevel@tonic-gate 			door_ret_err(&reterror, EINVAL);
20257c478bd9Sstevel@tonic-gate 		/*
20265363f09cSarutz 		 * Allocate shared memory for this connection.
20275363f09cSarutz 		 * If this connection already has shared memory,
20285363f09cSarutz 		 * deallocate before doing the allocation.
20297c478bd9Sstevel@tonic-gate 		 */
20305363f09cSarutz 		ret_val = set_shfd(door_dp, dp->d_data.d_desc.d_descriptor,
20315363f09cSarutz 		    req);
20327c478bd9Sstevel@tonic-gate 		if (ret_val == 0) {
20337c478bd9Sstevel@tonic-gate 			reterror.cnum = SMEDIA_CNUM_SET_SHFD;
20347c478bd9Sstevel@tonic-gate 			reterror.errnum = 0;
20355363f09cSarutz 
20367c478bd9Sstevel@tonic-gate 			my_door_return((char *)&reterror,
20377c478bd9Sstevel@tonic-gate 				sizeof (smedia_reterror_t), 0, 0);
20387c478bd9Sstevel@tonic-gate 		} else {
20397c478bd9Sstevel@tonic-gate 			(void) close(dp->d_data.d_desc.d_descriptor);
20405363f09cSarutz 			door_ret_err(&reterror, ret_val);
20417c478bd9Sstevel@tonic-gate 		}
20427c478bd9Sstevel@tonic-gate 		break;
20437c478bd9Sstevel@tonic-gate 
20447c478bd9Sstevel@tonic-gate 	case SMEDIA_CNUM_RAW_READ:
20457c478bd9Sstevel@tonic-gate 		debug(10, " arg size = %d blk num=0x%x nbytes = 0x%x \n",
20467c478bd9Sstevel@tonic-gate 			(int)arg_size,
20477c478bd9Sstevel@tonic-gate 			(uint32_t)req->reqraw_read.blockno,
20487c478bd9Sstevel@tonic-gate 			req->reqraw_read.nbytes);
20497c478bd9Sstevel@tonic-gate 		retbuf_size = sizeof (smedia_retraw_read_t);
20507c478bd9Sstevel@tonic-gate 		if (req->reqraw_read.nbytes == 0) {
20517c478bd9Sstevel@tonic-gate 			/* Nothing to write */
20527c478bd9Sstevel@tonic-gate 			rmsvc.retraw_write.nbytes = 0;
20537c478bd9Sstevel@tonic-gate 			my_door_return((char *)&rmsvc,
20547c478bd9Sstevel@tonic-gate 				sizeof (smedia_retraw_write_t), 0, 0);
20557c478bd9Sstevel@tonic-gate 		}
20567c478bd9Sstevel@tonic-gate 		retraw_read.cnum = SMEDIA_CNUM_RAW_READ;
20577c478bd9Sstevel@tonic-gate 		ret_val = raw_read(door_dp, req);
20587c478bd9Sstevel@tonic-gate 		if (ret_val == -1) {
20597c478bd9Sstevel@tonic-gate 			door_ret_err(&reterror, errno);
20607c478bd9Sstevel@tonic-gate 		}
20617c478bd9Sstevel@tonic-gate 		retraw_read.nbytes = ret_val;
20627c478bd9Sstevel@tonic-gate 		my_door_return((char *)&retraw_read, retbuf_size, 0, 0);
20637c478bd9Sstevel@tonic-gate 		break;
20647c478bd9Sstevel@tonic-gate 
20657c478bd9Sstevel@tonic-gate 	case	SMEDIA_CNUM_USCSI_CMD:
20667c478bd9Sstevel@tonic-gate 		retbuf_size = sizeof (smedia_retuscsi_cmd_t);
20677c478bd9Sstevel@tonic-gate 		rmsvc.retuscsi_cmd.cnum = SMEDIA_CNUM_USCSI_CMD;
20687c478bd9Sstevel@tonic-gate 		ucmd.uscsi_flags = req->requscsi_cmd.uscsi_flags;
20697c478bd9Sstevel@tonic-gate 		ucmd.uscsi_cdb = (caddr_t)&req->requscsi_cmd.uscsi_cdb;
20707c478bd9Sstevel@tonic-gate 		ucmd.uscsi_cdblen = req->requscsi_cmd.uscsi_cdblen;
20717c478bd9Sstevel@tonic-gate 		ucmd.uscsi_bufaddr = (caddr_t)door_dp->dd_buf;
20727c478bd9Sstevel@tonic-gate 		ucmd.uscsi_buflen = req->requscsi_cmd.uscsi_buflen;
20737c478bd9Sstevel@tonic-gate 		ucmd.uscsi_timeout = req->requscsi_cmd.uscsi_timeout;
20747c478bd9Sstevel@tonic-gate 		ucmd.uscsi_rqlen = req->requscsi_cmd.uscsi_rqlen;
20757c478bd9Sstevel@tonic-gate 		ucmd.uscsi_rqbuf = (caddr_t)&rmsvc.retuscsi_cmd.uscsi_rqbuf;
20765363f09cSarutz 		debug(5, "USCSI CMD 0x%x requested.\n",
20777c478bd9Sstevel@tonic-gate 		    req->requscsi_cmd.uscsi_cdb[0]);
20787c478bd9Sstevel@tonic-gate 		/*
20797c478bd9Sstevel@tonic-gate 		 * Check the device type and invalid flags specified.
20807c478bd9Sstevel@tonic-gate 		 * We permit operations only on CDROM devices types.
20817c478bd9Sstevel@tonic-gate 		 */
20825363f09cSarutz 		errno = invalid_uscsi_operation(door_dp, &ucmd);
20837c478bd9Sstevel@tonic-gate 		if (errno) {
20847c478bd9Sstevel@tonic-gate 			door_ret_err(&reterror, errno);
20857c478bd9Sstevel@tonic-gate 		}
20867c478bd9Sstevel@tonic-gate 
20877c478bd9Sstevel@tonic-gate 		if ((req->requscsi_cmd.uscsi_buflen) &&
20887c478bd9Sstevel@tonic-gate 		    ((req->requscsi_cmd.uscsi_buflen > door_dp->dd_buf_len) ||
20897c478bd9Sstevel@tonic-gate 		    (door_dp->dd_buf == NULL))) {
20905363f09cSarutz 			debug(5, "uscsi_cmd failed: uscsi_buflen=0x%x "
20915363f09cSarutz 			    "dd_buf_len=0x%x dd_buf=0x%p\n",
20927c478bd9Sstevel@tonic-gate 			    req->requscsi_cmd.uscsi_buflen,
20937c478bd9Sstevel@tonic-gate 			    door_dp->dd_buf_len,
20947c478bd9Sstevel@tonic-gate 			    door_dp->dd_buf);
20957c478bd9Sstevel@tonic-gate 			errno = EINVAL;
20967c478bd9Sstevel@tonic-gate 			door_ret_err(&reterror, errno);
20977c478bd9Sstevel@tonic-gate 		}
20987c478bd9Sstevel@tonic-gate 		ret_val = do_uscsi_cmd(door_dp->dd_fd,
20997c478bd9Sstevel@tonic-gate 			&ucmd, req->requscsi_cmd.uscsi_flags);
21007c478bd9Sstevel@tonic-gate 		rmsvc.retuscsi_cmd.uscsi_status = ucmd.uscsi_status;
21017c478bd9Sstevel@tonic-gate 		rmsvc.retuscsi_cmd.uscsi_resid = ucmd.uscsi_resid;
21027c478bd9Sstevel@tonic-gate 		rmsvc.retuscsi_cmd.uscsi_rqstatus = ucmd.uscsi_rqstatus;
21037c478bd9Sstevel@tonic-gate 		rmsvc.retuscsi_cmd.uscsi_rqresid = ucmd.uscsi_rqresid;
21047c478bd9Sstevel@tonic-gate 		rmsvc.retuscsi_cmd.uscsi_retval = ret_val;
21057c478bd9Sstevel@tonic-gate 		rmsvc.retuscsi_cmd.uscsi_errno = errno;
21067c478bd9Sstevel@tonic-gate 		if (ret_val || ucmd.uscsi_status) {
21077c478bd9Sstevel@tonic-gate 			debug(5, "uscsi_cmd failed: %d - %d errno = %d\n",
21087c478bd9Sstevel@tonic-gate 				ret_val, ucmd.uscsi_status, errno);
21097c478bd9Sstevel@tonic-gate 		}
21107c478bd9Sstevel@tonic-gate 		my_door_return((char *)&rmsvc, retbuf_size, 0, 0);
21117c478bd9Sstevel@tonic-gate 		break;
21127c478bd9Sstevel@tonic-gate 
21137c478bd9Sstevel@tonic-gate 	case SMEDIA_CNUM_RAW_WRITE:
21147c478bd9Sstevel@tonic-gate 		if (req->reqraw_write.nbytes == 0) {
21157c478bd9Sstevel@tonic-gate 			/* Nothing to write */
21167c478bd9Sstevel@tonic-gate 			rmsvc.retraw_write.nbytes = 0;
21177c478bd9Sstevel@tonic-gate 			my_door_return((char *)&rmsvc,
21187c478bd9Sstevel@tonic-gate 				sizeof (smedia_retraw_write_t), 0, 0);
21197c478bd9Sstevel@tonic-gate 		}
21207c478bd9Sstevel@tonic-gate 		ret_val = raw_write(door_dp, req);
21217c478bd9Sstevel@tonic-gate 		if (ret_val == -1)
21227c478bd9Sstevel@tonic-gate 			door_ret_err(&reterror, errno);
21237c478bd9Sstevel@tonic-gate 		rmsvc.retraw_write.nbytes = ret_val;
21247c478bd9Sstevel@tonic-gate 		my_door_return((char *)&rmsvc, sizeof (smedia_retraw_write_t),
21257c478bd9Sstevel@tonic-gate 			0, 0);
21267c478bd9Sstevel@tonic-gate 		break;
21277c478bd9Sstevel@tonic-gate 
21287c478bd9Sstevel@tonic-gate 	case SMEDIA_CNUM_GET_DEVICE_INFO:
21297c478bd9Sstevel@tonic-gate 
21307c478bd9Sstevel@tonic-gate 		(void) memset((void *) &inq, 0, sizeof (inq));
21317c478bd9Sstevel@tonic-gate 		(void) memset((void *) &ucmd, 0, sizeof (ucmd));
21327c478bd9Sstevel@tonic-gate 		(void) memset((void *) &cdb, 0, sizeof (union scsi_cdb));
21337c478bd9Sstevel@tonic-gate 		cdb.scc_cmd = SCMD_INQUIRY;
21347c478bd9Sstevel@tonic-gate 		FORMG0COUNT(&cdb, sizeof (inq));
21357c478bd9Sstevel@tonic-gate 		ucmd.uscsi_cdb = (caddr_t)&cdb;
21367c478bd9Sstevel@tonic-gate 		ucmd.uscsi_cdblen = CDB_GROUP0;
21377c478bd9Sstevel@tonic-gate 		ucmd.uscsi_bufaddr = (caddr_t)&inq;
21387c478bd9Sstevel@tonic-gate 		ucmd.uscsi_buflen = sizeof (inq);
21397c478bd9Sstevel@tonic-gate 		ucmd.uscsi_timeout = 120;	/* If 0, HBA hangs forever */
21407c478bd9Sstevel@tonic-gate 		ucmd.uscsi_rqlen = RQ_LEN;
21417c478bd9Sstevel@tonic-gate 		ucmd.uscsi_rqbuf = rq_data;
21427c478bd9Sstevel@tonic-gate 		ret_val = do_uscsi_cmd(door_dp->dd_fd,
21437c478bd9Sstevel@tonic-gate 			&ucmd, USCSI_READ|USCSI_RQENABLE);
21447c478bd9Sstevel@tonic-gate 		if (ret_val || ucmd.uscsi_status) {
21457c478bd9Sstevel@tonic-gate 			debug(5, "inquiry failed: %d - %d errno = %d\n",
21467c478bd9Sstevel@tonic-gate 				ret_val, ucmd.uscsi_status, errno);
21477c478bd9Sstevel@tonic-gate 			door_ret_err(&reterror, errno);
21487c478bd9Sstevel@tonic-gate 		}
21497c478bd9Sstevel@tonic-gate 
21507c478bd9Sstevel@tonic-gate 		debug(5, "%s\n", inq.inq_vid);
21517c478bd9Sstevel@tonic-gate 		debug(5, "%s\n", rmsvc.retget_device_info.sm_vendor_name);
21527c478bd9Sstevel@tonic-gate 
21537c478bd9Sstevel@tonic-gate 		(void) strlcpy(rmsvc.retget_device_info.sm_vendor_name,
21547c478bd9Sstevel@tonic-gate 			inq.inq_vid, 8);
21557c478bd9Sstevel@tonic-gate 		rmsvc.retget_device_info.sm_vendor_name[8] = 0;
21567c478bd9Sstevel@tonic-gate 		(void) strlcpy(rmsvc.retget_device_info.sm_product_name,
21577c478bd9Sstevel@tonic-gate 			inq.inq_pid, 16);
21587c478bd9Sstevel@tonic-gate 		rmsvc.retget_device_info.sm_product_name[16] = 0;
21597c478bd9Sstevel@tonic-gate 		(void) strlcpy(rmsvc.retget_device_info.sm_firmware_version,
21607c478bd9Sstevel@tonic-gate 			inq.inq_revision, 4);
21617c478bd9Sstevel@tonic-gate 		rmsvc.retget_device_info.sm_firmware_version[4] = ' ';
21627c478bd9Sstevel@tonic-gate 		(void) strlcpy(
21637c478bd9Sstevel@tonic-gate 			&rmsvc.retget_device_info.sm_firmware_version[5],
21647c478bd9Sstevel@tonic-gate 				inq.inq_serial, 12);
21657c478bd9Sstevel@tonic-gate 		rmsvc.retget_device_info.sm_product_name[17] = 0;
21667c478bd9Sstevel@tonic-gate 
21677c478bd9Sstevel@tonic-gate 		rmsvc.retget_device_info.sm_interface_type = IF_SCSI;
21687c478bd9Sstevel@tonic-gate 
21695363f09cSarutz 		debug(5, "Vendor name = %s\n",
21705363f09cSarutz 		    rmsvc.retget_device_info.sm_vendor_name);
21715363f09cSarutz 		debug(5, "product name = %s\n",
21725363f09cSarutz 		    rmsvc.retget_device_info.sm_product_name);
21735363f09cSarutz 		debug(5, "Firmware revision = %s\n",
21745363f09cSarutz 		    rmsvc.retget_device_info.sm_firmware_version);
21755363f09cSarutz 
21767c478bd9Sstevel@tonic-gate 		my_door_return((char *)&rmsvc.retget_device_info,
21777c478bd9Sstevel@tonic-gate 			sizeof (smedia_retget_device_info_t), 0, 0);
21787c478bd9Sstevel@tonic-gate 		break;
21797c478bd9Sstevel@tonic-gate 
21807c478bd9Sstevel@tonic-gate 	case	SMEDIA_CNUM_GET_MEDIUM_PROPERTY:
21817c478bd9Sstevel@tonic-gate 
21827c478bd9Sstevel@tonic-gate 		(void) memset((void *)&rmsvc.retget_medium_property.smprop,
21837c478bd9Sstevel@tonic-gate 			0, sizeof (smmedium_prop_t));
21847c478bd9Sstevel@tonic-gate 
21857c478bd9Sstevel@tonic-gate 		ret_val = ioctl(door_dp->dd_fd, DKIOCGMEDIAINFO, &media_info);
21867c478bd9Sstevel@tonic-gate 
21877c478bd9Sstevel@tonic-gate 		if (ret_val < 0) {
21887c478bd9Sstevel@tonic-gate 			uint32_t capacity;
21897c478bd9Sstevel@tonic-gate 			uint32_t blocksize;
21907c478bd9Sstevel@tonic-gate 			/*
21917c478bd9Sstevel@tonic-gate 			 * Devices may fail DKIOCGMEDIAINFO if an unformed
21927c478bd9Sstevel@tonic-gate 			 * media is inserted. We can get the capacity
21937c478bd9Sstevel@tonic-gate 			 * information from the SCMD_READ_FORMAT_CAP command.
21947c478bd9Sstevel@tonic-gate 			 */
21957c478bd9Sstevel@tonic-gate 
21965363f09cSarutz 			debug(5, "DKIOCGMEDIAINFO failed; using "
21975363f09cSarutz 			    "SCMD_READ_FORMAT_CAP");
21987c478bd9Sstevel@tonic-gate 			ret_val = get_media_capacity(door_dp->dd_fd,
21997c478bd9Sstevel@tonic-gate 			    &capacity, &blocksize);
22007c478bd9Sstevel@tonic-gate 
22017c478bd9Sstevel@tonic-gate 			if (ret_val >= 0) {
22027c478bd9Sstevel@tonic-gate 				media_info.dki_lbsize =	blocksize;
22037c478bd9Sstevel@tonic-gate 				media_info.dki_capacity = capacity;
22047c478bd9Sstevel@tonic-gate 			} else {
22057c478bd9Sstevel@tonic-gate 				debug(5, "SCMD_READ_FORMAT_CAP failed");
22067c478bd9Sstevel@tonic-gate 				door_ret_err(&reterror, errno);
22077c478bd9Sstevel@tonic-gate 			}
22087c478bd9Sstevel@tonic-gate 		}
22097c478bd9Sstevel@tonic-gate 		rmsvc.retget_medium_property.smprop.sm_blocksize =
22107c478bd9Sstevel@tonic-gate 		    media_info.dki_lbsize;
22117c478bd9Sstevel@tonic-gate 		rmsvc.retget_medium_property.smprop.sm_capacity =
22127c478bd9Sstevel@tonic-gate 		    media_info.dki_capacity;
22137c478bd9Sstevel@tonic-gate 
22147c478bd9Sstevel@tonic-gate 		rmsvc.retget_medium_property.smprop.sm_media_type =
22157c478bd9Sstevel@tonic-gate 		    media_info.dki_media_type;
22167c478bd9Sstevel@tonic-gate 		/*
22177c478bd9Sstevel@tonic-gate 		 * These devices show as SCSI devices but we need to treat it
22187c478bd9Sstevel@tonic-gate 		 * differently. so we need a seperate class.
22197c478bd9Sstevel@tonic-gate 		 */
22207c478bd9Sstevel@tonic-gate 		if (get_device_type_scsi(door_dp->dd_fd, &inq) == SCSI_FLOPPY) {
22217c478bd9Sstevel@tonic-gate 			rmsvc.retget_medium_property.smprop.sm_media_type =
22227c478bd9Sstevel@tonic-gate 			    SM_SCSI_FLOPPY;
22237c478bd9Sstevel@tonic-gate 		}
22247c478bd9Sstevel@tonic-gate 
22257c478bd9Sstevel@tonic-gate 		/* Check for EFI type because DKIOCGGEOM does not support EFI */
22267c478bd9Sstevel@tonic-gate 		ret_val = ioctl(door_dp->dd_fd, DKIOCGVTOC, &vtoc);
22277c478bd9Sstevel@tonic-gate 		if (!((ret_val < 0) && (errno == ENOTSUP))) {
22287c478bd9Sstevel@tonic-gate 			ret_val = ioctl(door_dp->dd_fd, DKIOCGGEOM, &dkgeom);
22297c478bd9Sstevel@tonic-gate 			if (ret_val < 0)  {
22307c478bd9Sstevel@tonic-gate 				/*
22317c478bd9Sstevel@tonic-gate 				 * DKIOCGGEOM may fail for unformed floppies.
22327c478bd9Sstevel@tonic-gate 				 * We need to generate the appropriate geometry
22337c478bd9Sstevel@tonic-gate 				 * information.
22347c478bd9Sstevel@tonic-gate 				 */
22357c478bd9Sstevel@tonic-gate 				if (rmsvc.retget_medium_property.smprop.
22367c478bd9Sstevel@tonic-gate 				    sm_media_type == SM_SCSI_FLOPPY) {
22377c478bd9Sstevel@tonic-gate 					ret_val = get_floppy_geom(
22387c478bd9Sstevel@tonic-gate 					    door_dp->dd_fd,
22397c478bd9Sstevel@tonic-gate 					    media_info.dki_capacity, &dkgeom);
22407c478bd9Sstevel@tonic-gate 
22417c478bd9Sstevel@tonic-gate 					if (ret_val < 0) {
22427c478bd9Sstevel@tonic-gate 						debug(5, "Cannot determine "
22437c478bd9Sstevel@tonic-gate 						    "media size");
22447c478bd9Sstevel@tonic-gate 						door_ret_err(&reterror, errno);
22457c478bd9Sstevel@tonic-gate 					}
22467c478bd9Sstevel@tonic-gate 				} else {
22477c478bd9Sstevel@tonic-gate #ifdef sparc
22487c478bd9Sstevel@tonic-gate 					debug(5, "DKIOCGGEOM ioctl failed");
22497c478bd9Sstevel@tonic-gate 					door_ret_err(&reterror, errno);
22507c478bd9Sstevel@tonic-gate #else /* !sparc */
22517c478bd9Sstevel@tonic-gate 					/*
22527c478bd9Sstevel@tonic-gate 					 * Try getting Physical geometry on x86.
22537c478bd9Sstevel@tonic-gate 					 */
22547c478bd9Sstevel@tonic-gate 					ret_val = ioctl(door_dp->dd_fd,
22557c478bd9Sstevel@tonic-gate 					    DKIOCG_PHYGEOM, &dkgeom);
22567c478bd9Sstevel@tonic-gate 					if (ret_val < 0) {
22577c478bd9Sstevel@tonic-gate 						debug(5, "DKIOCG_PHYGEOM "
22587c478bd9Sstevel@tonic-gate 						    "ioctl failed");
22597c478bd9Sstevel@tonic-gate 						door_ret_err(&reterror, errno);
22607c478bd9Sstevel@tonic-gate 					}
22617c478bd9Sstevel@tonic-gate #endif /* sparc */
22627c478bd9Sstevel@tonic-gate 				}
22637c478bd9Sstevel@tonic-gate 			}
22647c478bd9Sstevel@tonic-gate 
22657c478bd9Sstevel@tonic-gate 
22667c478bd9Sstevel@tonic-gate 			/*
22677c478bd9Sstevel@tonic-gate 			 * Some faked geometry may not have pcyl filled in so
22687c478bd9Sstevel@tonic-gate 			 * later calculations using this field will be
22697c478bd9Sstevel@tonic-gate 			 * incorrect.  We will substitute it with the number of
22707c478bd9Sstevel@tonic-gate 			 * available cylinders.
22717c478bd9Sstevel@tonic-gate 			 */
22727c478bd9Sstevel@tonic-gate 			if (dkgeom.dkg_pcyl == 0)
22737c478bd9Sstevel@tonic-gate 				rmsvc.retget_medium_property.smprop.sm_pcyl =
22747c478bd9Sstevel@tonic-gate 				    dkgeom.dkg_ncyl;
22757c478bd9Sstevel@tonic-gate 			else
22767c478bd9Sstevel@tonic-gate 				rmsvc.retget_medium_property.smprop.sm_pcyl =
22777c478bd9Sstevel@tonic-gate 				    dkgeom.dkg_pcyl;
22787c478bd9Sstevel@tonic-gate 
22797c478bd9Sstevel@tonic-gate 			rmsvc.retget_medium_property.smprop.sm_nhead =
22807c478bd9Sstevel@tonic-gate 			    dkgeom.dkg_nhead;
22817c478bd9Sstevel@tonic-gate 			rmsvc.retget_medium_property.smprop.sm_nsect =
22827c478bd9Sstevel@tonic-gate 			    dkgeom.dkg_nsect;
22837c478bd9Sstevel@tonic-gate 		}
22847c478bd9Sstevel@tonic-gate 
22857c478bd9Sstevel@tonic-gate 		debug(1, "properties are: lbasize = %d, cap = %llu",
22867c478bd9Sstevel@tonic-gate 		    media_info.dki_lbsize, media_info.dki_capacity);
22877c478bd9Sstevel@tonic-gate 
22887c478bd9Sstevel@tonic-gate 		my_door_return((char *)&rmsvc.retget_medium_property,
22897c478bd9Sstevel@tonic-gate 			sizeof (smedia_retget_medium_property_t), 0, 0);
22907c478bd9Sstevel@tonic-gate 		break;
22917c478bd9Sstevel@tonic-gate 
22927c478bd9Sstevel@tonic-gate 	case	SMEDIA_CNUM_GET_PROTECTION_STATUS:
22937c478bd9Sstevel@tonic-gate 		switch (get_device_type_scsi(door_dp->dd_fd, &inq)) {
22947c478bd9Sstevel@tonic-gate 		case SCSI_FLOPPY:
22957c478bd9Sstevel@tonic-gate 			status = scsi_floppy_media_status(door_dp->dd_fd);
22967c478bd9Sstevel@tonic-gate 			break;
22977c478bd9Sstevel@tonic-gate 		case SCSI_IOMEGA:
22987c478bd9Sstevel@tonic-gate 			status = scsi_zip_media_status(door_dp->dd_fd);
22997c478bd9Sstevel@tonic-gate 			break;
23007c478bd9Sstevel@tonic-gate 		case SCSI_GENERIC:
23017c478bd9Sstevel@tonic-gate 			status = scsi_media_status(door_dp->dd_fd);
23027c478bd9Sstevel@tonic-gate 			break;
23037c478bd9Sstevel@tonic-gate 		default:
23047c478bd9Sstevel@tonic-gate 			door_ret_err(&reterror, errno);
23057c478bd9Sstevel@tonic-gate 		}
23067c478bd9Sstevel@tonic-gate 		if (status < 0)
23077c478bd9Sstevel@tonic-gate 			door_ret_err(&reterror, errno);
23087c478bd9Sstevel@tonic-gate 
23097c478bd9Sstevel@tonic-gate 		rmsvc.retget_protection_status.prot_state.sm_new_state  =
23107c478bd9Sstevel@tonic-gate 			status;
23117c478bd9Sstevel@tonic-gate 
23127c478bd9Sstevel@tonic-gate 		my_door_return((char *)&rmsvc.retget_protection_status,
23137c478bd9Sstevel@tonic-gate 			sizeof (smedia_retget_protection_status_t), 0, 0);
23147c478bd9Sstevel@tonic-gate 		break;
23157c478bd9Sstevel@tonic-gate 
23167c478bd9Sstevel@tonic-gate 	case	SMEDIA_CNUM_SET_PROTECTION_STATUS:
23177c478bd9Sstevel@tonic-gate 
23187c478bd9Sstevel@tonic-gate 		ret_val = set_protection_status(door_dp, req);
23197c478bd9Sstevel@tonic-gate 		if (ret_val == -1)
23207c478bd9Sstevel@tonic-gate 			door_ret_err(&reterror, errno);
23217c478bd9Sstevel@tonic-gate 		else
23227c478bd9Sstevel@tonic-gate 			my_door_return((char *)&rmsvc.retset_protection_status,
23237c478bd9Sstevel@tonic-gate 				sizeof (smedia_retset_protection_status_t),
23247c478bd9Sstevel@tonic-gate 				0, 0);
23257c478bd9Sstevel@tonic-gate 		break;
23267c478bd9Sstevel@tonic-gate 
23277c478bd9Sstevel@tonic-gate 	case SMEDIA_CNUM_FORMAT:
23287c478bd9Sstevel@tonic-gate 		switch (get_device_type_scsi(door_dp->dd_fd, &inq)) {
23297c478bd9Sstevel@tonic-gate 		case SCSI_FLOPPY:
23307c478bd9Sstevel@tonic-gate 			info("formatting floppy");
23317c478bd9Sstevel@tonic-gate 			err = scsi_floppy_format(door_dp->dd_fd,
23327c478bd9Sstevel@tonic-gate 				req->reqformat.flavor, req->reqformat.mode);
23337c478bd9Sstevel@tonic-gate 
23347c478bd9Sstevel@tonic-gate 			break;
23357c478bd9Sstevel@tonic-gate 		case SCSI_IOMEGA:
23367c478bd9Sstevel@tonic-gate 			err = scsi_zip_format(door_dp->dd_fd,
23377c478bd9Sstevel@tonic-gate 				req->reqformat.flavor, req->reqformat.mode);
23387c478bd9Sstevel@tonic-gate 			break;
23397c478bd9Sstevel@tonic-gate 		case SCSI_GENERIC:
23407c478bd9Sstevel@tonic-gate 			err = scsi_format(door_dp->dd_fd,
23417c478bd9Sstevel@tonic-gate 				req->reqformat.flavor, req->reqformat.mode);
23427c478bd9Sstevel@tonic-gate 			break;
23437c478bd9Sstevel@tonic-gate 		default:
23447c478bd9Sstevel@tonic-gate 			door_ret_err(&reterror, ENOTSUP);
23457c478bd9Sstevel@tonic-gate 		}
23467c478bd9Sstevel@tonic-gate 
23477c478bd9Sstevel@tonic-gate 		if (err)
23487c478bd9Sstevel@tonic-gate 			door_ret_err(&reterror, errno);
23497c478bd9Sstevel@tonic-gate 		my_door_return((char *)&rmsvc.retformat,
23507c478bd9Sstevel@tonic-gate 			sizeof (smedia_retformat_t), 0, 0);
23517c478bd9Sstevel@tonic-gate 
23527c478bd9Sstevel@tonic-gate 		break;
23537c478bd9Sstevel@tonic-gate 
23547c478bd9Sstevel@tonic-gate 	case SMEDIA_CNUM_CHECK_FORMAT_STATUS:
23557c478bd9Sstevel@tonic-gate 
23567c478bd9Sstevel@tonic-gate 		(void) memset((void *) &cdb, 0, sizeof (union scsi_cdb));
23577c478bd9Sstevel@tonic-gate 		(void) memset((void *) &ucmd, 0, sizeof (ucmd));
23587c478bd9Sstevel@tonic-gate 		(void) memset((void *) &data, 0, sizeof (data));
23597c478bd9Sstevel@tonic-gate 		cdb.scc_cmd = SCMD_REQUEST_SENSE;
23607c478bd9Sstevel@tonic-gate 		cdb.g0_count0 = sizeof (data);
23617c478bd9Sstevel@tonic-gate 		ucmd.uscsi_cdb = (caddr_t)&cdb;
23627c478bd9Sstevel@tonic-gate 		ucmd.uscsi_cdblen = CDB_GROUP0;
23637c478bd9Sstevel@tonic-gate 		ucmd.uscsi_bufaddr = (caddr_t)&data;
23647c478bd9Sstevel@tonic-gate 		ucmd.uscsi_buflen = sizeof (data);
23657c478bd9Sstevel@tonic-gate 		ucmd.uscsi_timeout = 120;	/* If 0, HBA hangs forever */
23667c478bd9Sstevel@tonic-gate 		ucmd.uscsi_rqlen = RQ_LEN;
23677c478bd9Sstevel@tonic-gate 		ucmd.uscsi_rqbuf = rq_data;
23687c478bd9Sstevel@tonic-gate 		ret_val = do_uscsi_cmd(door_dp->dd_fd,
23697c478bd9Sstevel@tonic-gate 			&ucmd, USCSI_READ|USCSI_RQENABLE);
23707c478bd9Sstevel@tonic-gate 		if (ret_val || ucmd.uscsi_status) {
23717c478bd9Sstevel@tonic-gate 			debug(5, "Request sense failed: %d - %d errno = %d\n",
23727c478bd9Sstevel@tonic-gate 				ret_val, ucmd.uscsi_status, errno);
23737c478bd9Sstevel@tonic-gate 			door_ret_err(&reterror, errno);
23747c478bd9Sstevel@tonic-gate 		}
23757c478bd9Sstevel@tonic-gate 
23767c478bd9Sstevel@tonic-gate 		if ((data[0] & 0x7F) == DEFERRED_ERROR) {
23777c478bd9Sstevel@tonic-gate 		/* Deffered error. The format must have failed */
23787c478bd9Sstevel@tonic-gate 			debug(5, "format failed!\n");
23797c478bd9Sstevel@tonic-gate 			door_ret_err(&reterror, EIO);
23807c478bd9Sstevel@tonic-gate 		}
23817c478bd9Sstevel@tonic-gate 
23827c478bd9Sstevel@tonic-gate 		if (data[SKSV_OFFSET] & SKSV_FIELD) {
23837c478bd9Sstevel@tonic-gate 			completed =
23847c478bd9Sstevel@tonic-gate 				(data[FORMAT_PROGRESS_INDICATOR_OFFSET_0] << 8)
23857c478bd9Sstevel@tonic-gate 				| data[FORMAT_PROGRESS_INDICATOR_OFFSET_1];
23867c478bd9Sstevel@tonic-gate 			completed = (completed*100/65536);
23877c478bd9Sstevel@tonic-gate 		} else {
23887c478bd9Sstevel@tonic-gate 			completed = (100);
23897c478bd9Sstevel@tonic-gate 		}
23907c478bd9Sstevel@tonic-gate 		rmsvc.retcheck_format_status.percent_complete = completed;
23917c478bd9Sstevel@tonic-gate 		my_door_return((char *)&rmsvc.retcheck_format_status,
23927c478bd9Sstevel@tonic-gate 			sizeof (smedia_retcheck_format_status_t), 0, 0);
23937c478bd9Sstevel@tonic-gate 		break;
23947c478bd9Sstevel@tonic-gate 
23957c478bd9Sstevel@tonic-gate 	case SMEDIA_CNUM_REASSIGN_BLOCK:
23967c478bd9Sstevel@tonic-gate 
23977c478bd9Sstevel@tonic-gate 		ret_val = reassign_block(door_dp, req);
23987c478bd9Sstevel@tonic-gate 		if (ret_val == -1)
23997c478bd9Sstevel@tonic-gate 			door_ret_err(&reterror, errno);
24007c478bd9Sstevel@tonic-gate 		my_door_return((char *)&rmsvc.retreassign_block,
24017c478bd9Sstevel@tonic-gate 			sizeof (smedia_retreassign_block_t), 0, 0);
24027c478bd9Sstevel@tonic-gate 		break;
24037c478bd9Sstevel@tonic-gate 
24047c478bd9Sstevel@tonic-gate 	}	/* end of switch */
24057c478bd9Sstevel@tonic-gate 
24067c478bd9Sstevel@tonic-gate 	debug(10, "Exiting client server...\n");
24077c478bd9Sstevel@tonic-gate 	my_door_return((char *)&reterror, sizeof (smedia_reterror_t), 0, 0);
24087c478bd9Sstevel@tonic-gate }
24097c478bd9Sstevel@tonic-gate 
24105363f09cSarutz /*
24115363f09cSarutz  * This is the service procedure for the door that is associated with
24125363f09cSarutz  * the (doorfs) filesystem Door that is created at 'smedia_service'.
24135363f09cSarutz  */
24147c478bd9Sstevel@tonic-gate /*ARGSUSED*/
24157c478bd9Sstevel@tonic-gate static void
24165363f09cSarutz main_servproc(void *server_data, char *argp, size_t arg_size,
24177c478bd9Sstevel@tonic-gate     door_desc_t *dp, uint_t ndesc)
24187c478bd9Sstevel@tonic-gate {
24197c478bd9Sstevel@tonic-gate 	smedia_services_t	*req;
24207c478bd9Sstevel@tonic-gate 	door_cred_t	door_credentials;
24217c478bd9Sstevel@tonic-gate 	int		ret_val;
24227c478bd9Sstevel@tonic-gate 	door_data_t	*ddata;
24237c478bd9Sstevel@tonic-gate 	smedia_reterror_t	reterror;
24247c478bd9Sstevel@tonic-gate 	smedia_reterror_t	retok;
24257c478bd9Sstevel@tonic-gate 	struct	stat	stat;
24267c478bd9Sstevel@tonic-gate 	door_desc_t	*didpp;
24277c478bd9Sstevel@tonic-gate 	struct dk_cinfo dkinfo;
24285363f09cSarutz 	uint_t		nexpected_desc;
24297c478bd9Sstevel@tonic-gate 
24305363f09cSarutz 	debug(10, "Entering main_servproc[%d].\n", pthread_self());
24317c478bd9Sstevel@tonic-gate 
24327c478bd9Sstevel@tonic-gate 	didpp = dp;
24337c478bd9Sstevel@tonic-gate 	(void) mutex_lock(&svcstate_lock);
24347c478bd9Sstevel@tonic-gate 	svcstate = _SERVED;
24357c478bd9Sstevel@tonic-gate 	(void) mutex_unlock(&svcstate_lock);
24367c478bd9Sstevel@tonic-gate 
24377c478bd9Sstevel@tonic-gate 	reterror.cnum = SMEDIA_CNUM_ERROR;
24387c478bd9Sstevel@tonic-gate 	reterror.errnum = SMEDIA_FAILURE;
24395363f09cSarutz 
24407c478bd9Sstevel@tonic-gate 	if (argp == NULL) {
24417c478bd9Sstevel@tonic-gate 		debug(5, "argp is NULL\n");
24427c478bd9Sstevel@tonic-gate 		if (ndesc > 0)
24437c478bd9Sstevel@tonic-gate 			close_door_descs(dp, ndesc);
24447c478bd9Sstevel@tonic-gate 		my_door_return((char *)&reterror,
24457c478bd9Sstevel@tonic-gate 		    sizeof (smedia_reterror_t), 0, 0);
24467c478bd9Sstevel@tonic-gate 	}
24477c478bd9Sstevel@tonic-gate 
24487c478bd9Sstevel@tonic-gate 	req = (smedia_services_t *)((void *)argp);
24495363f09cSarutz 
24507c478bd9Sstevel@tonic-gate 	retok.cnum = req->in.cnum;
24517c478bd9Sstevel@tonic-gate 	retok.errnum = 0;
24527c478bd9Sstevel@tonic-gate 
24537c478bd9Sstevel@tonic-gate 	debug(5, "req = %s arg_size = 0x%x \n",
24547c478bd9Sstevel@tonic-gate 	    xlate_cnum(req->reqopen.cnum), arg_size);
24557c478bd9Sstevel@tonic-gate 
24567c478bd9Sstevel@tonic-gate 	/*
24577c478bd9Sstevel@tonic-gate 	 * Our caller may have passed more descriptors than we expected.
24587c478bd9Sstevel@tonic-gate 	 * If so, we silently close (and ignore) them.
24597c478bd9Sstevel@tonic-gate 	 */
24605363f09cSarutz 	nexpected_desc = (req->in.cnum == SMEDIA_CNUM_OPEN_FD) ? 1 : 0;
24615363f09cSarutz 	if (ndesc > nexpected_desc) {
24625363f09cSarutz 		close_door_descs(dp + nexpected_desc, ndesc - nexpected_desc);
24635363f09cSarutz 	}
24647c478bd9Sstevel@tonic-gate 
24657c478bd9Sstevel@tonic-gate 	switch (req->in.cnum) {
24667c478bd9Sstevel@tonic-gate 	default:
24675363f09cSarutz 		debug(5, "main_servproc: unknown command 0x%x\n",
24685363f09cSarutz 		    req->reqopen.cnum);
24697c478bd9Sstevel@tonic-gate 		break;
24707c478bd9Sstevel@tonic-gate 
24717c478bd9Sstevel@tonic-gate 	case SMEDIA_CNUM_PING:
24727c478bd9Sstevel@tonic-gate 		/*
24737c478bd9Sstevel@tonic-gate 		 * This service is to indicate that server is up and
24747c478bd9Sstevel@tonic-gate 		 * running. It is usually called from another instance of
24757c478bd9Sstevel@tonic-gate 		 * server that is started.
24767c478bd9Sstevel@tonic-gate 		 */
24777c478bd9Sstevel@tonic-gate 		reterror.cnum = SMEDIA_CNUM_PING;
24787c478bd9Sstevel@tonic-gate 		reterror.errnum = 0;
24797c478bd9Sstevel@tonic-gate 		my_door_return((char *)&reterror,
24807c478bd9Sstevel@tonic-gate 		    sizeof (smedia_reterror_t), 0, 0);
24817c478bd9Sstevel@tonic-gate 		break;
24827c478bd9Sstevel@tonic-gate 
24837c478bd9Sstevel@tonic-gate 
24847c478bd9Sstevel@tonic-gate 	case SMEDIA_CNUM_OPEN_FD:
24857c478bd9Sstevel@tonic-gate 
24867c478bd9Sstevel@tonic-gate 		debug(5, "ndesc = %d\n", ndesc);
24877c478bd9Sstevel@tonic-gate 		if (ndesc == 0) {
24887c478bd9Sstevel@tonic-gate 			my_door_return((char *)&reterror,
24897c478bd9Sstevel@tonic-gate 			    sizeof (smedia_reterror_t), 0, 0);
24907c478bd9Sstevel@tonic-gate 		}
24915363f09cSarutz 		debug(5, "Checking file descriptor of target device\n");
24927c478bd9Sstevel@tonic-gate 		if (fstat(didpp->d_data.d_desc.d_descriptor, &stat) < 0) {
24935363f09cSarutz 			warning(gettext("main_servproc:fstat failed. "
24945363f09cSarutz 			    "errno = %d\n"), errno);
24957c478bd9Sstevel@tonic-gate 			(void) close(didpp->d_data.d_desc.d_descriptor);
24967c478bd9Sstevel@tonic-gate 			my_door_return((char *)&reterror,
24977c478bd9Sstevel@tonic-gate 			    sizeof (smedia_reterror_t), 0, 0);
24987c478bd9Sstevel@tonic-gate 		}
24997c478bd9Sstevel@tonic-gate 		debug(5, "descriptor = %d st_mode = 0x%lx\n",
25007c478bd9Sstevel@tonic-gate 		    didpp->d_data.d_desc.d_descriptor,
25017c478bd9Sstevel@tonic-gate 		    stat.st_mode);
25027c478bd9Sstevel@tonic-gate 
25037c478bd9Sstevel@tonic-gate 		/* Obtain the credentials of the user */
25047c478bd9Sstevel@tonic-gate 		ret_val = door_cred(&door_credentials);
25057c478bd9Sstevel@tonic-gate 		if (ret_val < 0) {
25065363f09cSarutz 			warning(gettext("main_servproc:door_cred "
25075363f09cSarutz 			    "failed. errno = %d\n"), errno);
25087c478bd9Sstevel@tonic-gate 			(void) close(didpp->d_data.d_desc.d_descriptor);
25097c478bd9Sstevel@tonic-gate 			my_door_return((char *)&reterror,
25107c478bd9Sstevel@tonic-gate 			    sizeof (smedia_reterror_t), 0, 0);
25117c478bd9Sstevel@tonic-gate 		}
25127c478bd9Sstevel@tonic-gate 		if (ioctl(didpp->d_data.d_desc.d_descriptor, DKIOCINFO,
25137c478bd9Sstevel@tonic-gate 			&dkinfo) == -1) {
25145363f09cSarutz 			warning(gettext("main_servproc:DKIOCINFO failed. "
25155363f09cSarutz 			    "errno = %d\n"), errno);
25167c478bd9Sstevel@tonic-gate 			(void) close(didpp->d_data.d_desc.d_descriptor);
25177c478bd9Sstevel@tonic-gate 			my_door_return((char *)&reterror,
25187c478bd9Sstevel@tonic-gate 			    sizeof (smedia_reterror_t), 0, 0);
25197c478bd9Sstevel@tonic-gate 		}
25207c478bd9Sstevel@tonic-gate 
25217c478bd9Sstevel@tonic-gate 		ddata = (door_data_t *)calloc(1, sizeof (door_data_t));
25227c478bd9Sstevel@tonic-gate 		if (ddata == NULL) {
25235363f09cSarutz 			warning(gettext("main_servproc:calloc failed. "
25245363f09cSarutz 			    "errno = %d\n"), errno);
25257c478bd9Sstevel@tonic-gate 			(void) close(didpp->d_data.d_desc.d_descriptor);
25267c478bd9Sstevel@tonic-gate 			my_door_return((char *)&reterror,
25277c478bd9Sstevel@tonic-gate 			    sizeof (smedia_reterror_t), 0, 0);
25287c478bd9Sstevel@tonic-gate 		}
25297c478bd9Sstevel@tonic-gate 		ddata->dd_stat = stat;
25307c478bd9Sstevel@tonic-gate 		ddata->dd_cred = door_credentials;
25317c478bd9Sstevel@tonic-gate 		ddata->dd_fd = didpp->d_data.d_desc.d_descriptor;
25327c478bd9Sstevel@tonic-gate 		ddata->dd_buf = NULL;
25337c478bd9Sstevel@tonic-gate 		ddata->dd_buf_len = 0;
25347c478bd9Sstevel@tonic-gate 		ddata->dd_buffd = -1;
25357c478bd9Sstevel@tonic-gate 		ddata->dd_sector_size = 0;
25367c478bd9Sstevel@tonic-gate 		ddata->dd_dkinfo = dkinfo;
25375363f09cSarutz 		debug(5, "ddata = 0x%p \n", (void *)ddata);
25387c478bd9Sstevel@tonic-gate 
25395363f09cSarutz 		/* specify a function that'll customize our door threads */
25405363f09cSarutz 		(void) door_server_create(sm_door_server_create);
25417c478bd9Sstevel@tonic-gate 		debug(5, "door_server_create called.\n");
25427c478bd9Sstevel@tonic-gate 
25437c478bd9Sstevel@tonic-gate 		(void) mutex_lock(&ddata->dd_lock);
25447c478bd9Sstevel@tonic-gate 
25455363f09cSarutz 		/* create Client Door */
25465363f09cSarutz 		ddata->dd_cdoor_descriptor =
25475363f09cSarutz 		    door_create(client_servproc,
25485363f09cSarutz 		    (void *)ddata, DOOR_PRIVATE | DOOR_NO_CANCEL | DOOR_UNREF);
25495363f09cSarutz 
25505363f09cSarutz 		if (ddata->dd_cdoor_descriptor < 0) {
25515363f09cSarutz 			/* then door_create() failed */
25525363f09cSarutz 			int err = errno;
25535363f09cSarutz 
25545363f09cSarutz 			(void) mutex_unlock(&ddata->dd_lock);
25555363f09cSarutz 
25565363f09cSarutz 			warning(gettext("main_servproc: door_create of Client "
25575363f09cSarutz 			    "Door failed = %d\n"), err);
25587c478bd9Sstevel@tonic-gate 			free(ddata);
25595363f09cSarutz 
25605363f09cSarutz 			/* close target device */
25617c478bd9Sstevel@tonic-gate 			(void) close(didpp->d_data.d_desc.d_descriptor);
25625363f09cSarutz 			my_door_return((char *)&reterror,
25635363f09cSarutz 			    sizeof (smedia_reterror_t), 0, 0);
25647c478bd9Sstevel@tonic-gate 		}
25655363f09cSarutz 
25665363f09cSarutz 		/* create Death Door */
25675363f09cSarutz 		ddata->dd_ddoor_descriptor =
25685363f09cSarutz 		    door_create(death_servproc, (void *)ddata,
25695363f09cSarutz 		    DOOR_REFUSE_DESC | DOOR_NO_CANCEL);
25705363f09cSarutz 		if (ddata->dd_ddoor_descriptor < 0) {
25715363f09cSarutz 			warning(gettext("main_servproc: door_create of Death "
25725363f09cSarutz 			    "Door failed = %d\n"), errno);
25735363f09cSarutz 		} else {
25745363f09cSarutz 			(void) door_setparam(ddata->dd_ddoor_descriptor,
25755363f09cSarutz 			    DOOR_PARAM_DATA_MAX, 0);
25767c478bd9Sstevel@tonic-gate 		}
25775363f09cSarutz 
25785363f09cSarutz 		debug(5, "main_servproc[%d]: Client Door = %d, "
25795363f09cSarutz 		    "Death Door = %d", pthread_self(),
25805363f09cSarutz 		    ddata->dd_cdoor_descriptor, ddata->dd_ddoor_descriptor);
25817c478bd9Sstevel@tonic-gate 
25827c478bd9Sstevel@tonic-gate 		audit_init(ddata);
25837c478bd9Sstevel@tonic-gate 
25845363f09cSarutz 		/* wait until sm_server_thread does door_bind() */
25857c478bd9Sstevel@tonic-gate 		(void) cond_wait(&ddata->dd_cv_bind, &ddata->dd_lock);
25865363f09cSarutz 
25877c478bd9Sstevel@tonic-gate 		(void) mutex_unlock(&ddata->dd_lock);
25887c478bd9Sstevel@tonic-gate 
25897c478bd9Sstevel@tonic-gate 		(void) mutex_lock(&svcstate_lock);
25907c478bd9Sstevel@tonic-gate 		svccount++;
25917c478bd9Sstevel@tonic-gate 		(void) mutex_unlock(&svcstate_lock);
25927c478bd9Sstevel@tonic-gate 
25935363f09cSarutz 		if (ddata->dd_ddoor_descriptor < 0) {
25945363f09cSarutz 			/* Return only the Client Door to the client. */
25955363f09cSarutz 			ddata->dd_cdoor.d_attributes = (DOOR_DESCRIPTOR);
25965363f09cSarutz 			my_door_return((char *)&reterror,
25975363f09cSarutz 			    sizeof (smedia_reterror_t), &ddata->dd_desc[0], 1);
25985363f09cSarutz 		} else {
25995363f09cSarutz 			/*
26005363f09cSarutz 			 * Return the Client Door and Death Door
26015363f09cSarutz 			 * to the client.
26025363f09cSarutz 			 */
26035363f09cSarutz 			debug(5, "retok.cnum = 0x%x\n", retok.cnum);
26045363f09cSarutz 			ddata->dd_cdoor.d_attributes = (DOOR_DESCRIPTOR);
26055363f09cSarutz 			ddata->dd_ddoor.d_attributes = (DOOR_DESCRIPTOR);
26065363f09cSarutz 			my_door_return((char *)&retok,
26075363f09cSarutz 			    sizeof (smedia_reterror_t), &ddata->dd_desc[0], 2);
26085363f09cSarutz 		}
26097c478bd9Sstevel@tonic-gate 		break;
26107c478bd9Sstevel@tonic-gate 	}
26117c478bd9Sstevel@tonic-gate 
26125363f09cSarutz 	debug(10, "exiting main_servproc. \n");
26137c478bd9Sstevel@tonic-gate 	my_door_return((char *)&reterror, sizeof (smedia_reterror_t), 0, 0);
26147c478bd9Sstevel@tonic-gate }
26157c478bd9Sstevel@tonic-gate 
26167c478bd9Sstevel@tonic-gate /* ARGSUSED */
26177c478bd9Sstevel@tonic-gate static void
26187c478bd9Sstevel@tonic-gate term_handler(int sig, siginfo_t *siginfo, void *sigctx)
26197c478bd9Sstevel@tonic-gate {
26207c478bd9Sstevel@tonic-gate 	warning(gettext("thread[%d]: Received signal %d. Ignoring it.\n"),
26217c478bd9Sstevel@tonic-gate 	    pthread_self(),
26227c478bd9Sstevel@tonic-gate 	    sig);
26237c478bd9Sstevel@tonic-gate }
26247c478bd9Sstevel@tonic-gate 
26257c478bd9Sstevel@tonic-gate /* ARGSUSED */
26267c478bd9Sstevel@tonic-gate static void
26277c478bd9Sstevel@tonic-gate hup_handler(int sig, siginfo_t *siginfo, void *sigctx)
26287c478bd9Sstevel@tonic-gate {
26297c478bd9Sstevel@tonic-gate 	warning(gettext("thread[%d]: Received signal %d. Ignoring it.\n"),
26307c478bd9Sstevel@tonic-gate 	    pthread_self(),
26317c478bd9Sstevel@tonic-gate 	    sig);
26327c478bd9Sstevel@tonic-gate }
26337c478bd9Sstevel@tonic-gate 
26347c478bd9Sstevel@tonic-gate /*ARGSUSED*/
26357c478bd9Sstevel@tonic-gate static void
26367c478bd9Sstevel@tonic-gate sig_handler(int sig, siginfo_t *siginfo, void *sigctx)
26377c478bd9Sstevel@tonic-gate {
26387c478bd9Sstevel@tonic-gate 	warning(gettext("thread[%d]: Received signal %d. Ignoring it.\n"),
26397c478bd9Sstevel@tonic-gate 	    pthread_self(),
26407c478bd9Sstevel@tonic-gate 	    sig);
26417c478bd9Sstevel@tonic-gate }
26427c478bd9Sstevel@tonic-gate 
26437c478bd9Sstevel@tonic-gate /*ARGSUSED*/
26447c478bd9Sstevel@tonic-gate static void
26457c478bd9Sstevel@tonic-gate badsig_handler(int sig, siginfo_t *siginfo, void *sigctx)
26467c478bd9Sstevel@tonic-gate {
26477c478bd9Sstevel@tonic-gate 	fatal(BADSIG_MSG, pthread_self(), sig, siginfo->si_addr,
26487c478bd9Sstevel@tonic-gate 	    siginfo->si_trapno,
26497c478bd9Sstevel@tonic-gate 	    siginfo->si_pc);
26507c478bd9Sstevel@tonic-gate }
26517c478bd9Sstevel@tonic-gate 
26527c478bd9Sstevel@tonic-gate /*ARGSUSED*/
26535363f09cSarutz static void *
26547c478bd9Sstevel@tonic-gate init_server(void *argp)
26557c478bd9Sstevel@tonic-gate {
26567c478bd9Sstevel@tonic-gate 	int	i, fd;
26577c478bd9Sstevel@tonic-gate 	struct	sigaction	act;
26587c478bd9Sstevel@tonic-gate 	struct	rlimit		rlim;
26597c478bd9Sstevel@tonic-gate 
26607c478bd9Sstevel@tonic-gate 	debug(10, "init_server  running\n");
26617c478bd9Sstevel@tonic-gate 
26627c478bd9Sstevel@tonic-gate 	(void) setlocale(LC_ALL, "");
26637c478bd9Sstevel@tonic-gate #if !defined(TEXT_DOMAIN)
26647c478bd9Sstevel@tonic-gate #define	TEXT_DOMAIN "SYS_TEST"
26657c478bd9Sstevel@tonic-gate #endif
26667c478bd9Sstevel@tonic-gate 	(void) textdomain(TEXT_DOMAIN);
26677c478bd9Sstevel@tonic-gate 
26687c478bd9Sstevel@tonic-gate 
26697c478bd9Sstevel@tonic-gate 	if (geteuid() != 0) fatal("Must be root to execute smserverd\n");
26707c478bd9Sstevel@tonic-gate 
26717c478bd9Sstevel@tonic-gate 
26727c478bd9Sstevel@tonic-gate 	/*
26737c478bd9Sstevel@tonic-gate 	 * setup signal handlers.
26747c478bd9Sstevel@tonic-gate 	 */
26757c478bd9Sstevel@tonic-gate 
26767c478bd9Sstevel@tonic-gate 	for (i = 0; i < N_BADSIGS; i++) {
26777c478bd9Sstevel@tonic-gate 		act.sa_sigaction = badsig_handler;
26787c478bd9Sstevel@tonic-gate 		(void) sigemptyset(&act.sa_mask);
26797c478bd9Sstevel@tonic-gate 		act.sa_flags = SA_SIGINFO;
26807c478bd9Sstevel@tonic-gate 		if (sigaction(badsigs[i], &act, NULL) == -1)
26817c478bd9Sstevel@tonic-gate 			warning(gettext(SIGACT_FAILED), strsignal(badsigs[i]),
26827c478bd9Sstevel@tonic-gate 				strerror(errno));
26837c478bd9Sstevel@tonic-gate 	}
26847c478bd9Sstevel@tonic-gate 
26857c478bd9Sstevel@tonic-gate 	/*
26867c478bd9Sstevel@tonic-gate 	 * Ignore SIGHUP until all the initialization is done.
26877c478bd9Sstevel@tonic-gate 	 */
26887c478bd9Sstevel@tonic-gate 	act.sa_handler = SIG_IGN;
26897c478bd9Sstevel@tonic-gate 	(void) sigemptyset(&act.sa_mask);
26907c478bd9Sstevel@tonic-gate 	act.sa_flags = 0;
26917c478bd9Sstevel@tonic-gate 	if (sigaction(SIGHUP, &act, NULL) == -1)
26927c478bd9Sstevel@tonic-gate 		warning(gettext(SIGACT_FAILED), strsignal(SIGHUP),
26937c478bd9Sstevel@tonic-gate 			strerror(errno));
26947c478bd9Sstevel@tonic-gate 	/*
26957c478bd9Sstevel@tonic-gate 	 * Increase file descriptor limit to the most it can possibly
26967c478bd9Sstevel@tonic-gate 	 * be.
26977c478bd9Sstevel@tonic-gate 	 */
26987c478bd9Sstevel@tonic-gate 	if (getrlimit(RLIMIT_NOFILE, &rlim) < 0) {
26997c478bd9Sstevel@tonic-gate 		warning(gettext("getrlimit for fd's failed; %m\n"));
27007c478bd9Sstevel@tonic-gate 	}
27017c478bd9Sstevel@tonic-gate 
27027c478bd9Sstevel@tonic-gate 	rlim.rlim_cur = rlim.rlim_max;
27037c478bd9Sstevel@tonic-gate 
27047c478bd9Sstevel@tonic-gate 	if (setrlimit(RLIMIT_NOFILE, &rlim) < 0) {
27057c478bd9Sstevel@tonic-gate 		warning(gettext("setrlimit for fd's failed; %m\n"));
27067c478bd9Sstevel@tonic-gate 	}
2707004388ebScasper 	(void) enable_extended_FILE_stdio(-1, -1);
27087c478bd9Sstevel@tonic-gate 
27095363f09cSarutz 	server_door = door_create(main_servproc, (void *)&server_data, 0);
27107c478bd9Sstevel@tonic-gate 	if (server_door == -1) {
27117c478bd9Sstevel@tonic-gate 		debug(1, "main door_create");
27127c478bd9Sstevel@tonic-gate 		exit(1);
27137c478bd9Sstevel@tonic-gate 	}
27147c478bd9Sstevel@tonic-gate 
27157c478bd9Sstevel@tonic-gate 	(void) unlink(smedia_service);
27167c478bd9Sstevel@tonic-gate 	fd = open(smedia_service, O_RDWR|O_CREAT|O_EXCL, 0644);
27177c478bd9Sstevel@tonic-gate 	if (fd < 0) {
27187c478bd9Sstevel@tonic-gate 		debug(5, "could not open %s.\n", smedia_service);
27197c478bd9Sstevel@tonic-gate 		exit(1);
27207c478bd9Sstevel@tonic-gate 	}
27217c478bd9Sstevel@tonic-gate 	(void) close(fd);
27227c478bd9Sstevel@tonic-gate 	server_fd = fattach(server_door, smedia_service);
27237c478bd9Sstevel@tonic-gate 	if (server_fd == -1) {
27247c478bd9Sstevel@tonic-gate 		debug(1, "main fattach");
27257c478bd9Sstevel@tonic-gate 		exit(1);
27267c478bd9Sstevel@tonic-gate 	}
27277c478bd9Sstevel@tonic-gate 	server_data.sd_door = server_door;
27287c478bd9Sstevel@tonic-gate 	server_data.sd_fd = server_fd;
27297c478bd9Sstevel@tonic-gate 
27307c478bd9Sstevel@tonic-gate 	/*
27317c478bd9Sstevel@tonic-gate 	 * setup signal handlers for post-init
27327c478bd9Sstevel@tonic-gate 	 */
27337c478bd9Sstevel@tonic-gate 
27347c478bd9Sstevel@tonic-gate 	act.sa_sigaction = hup_handler;
27357c478bd9Sstevel@tonic-gate 	(void) sigemptyset(&act.sa_mask);
27367c478bd9Sstevel@tonic-gate 	act.sa_flags = SA_SIGINFO;
27377c478bd9Sstevel@tonic-gate 	if (sigaction(SIGHUP, &act, NULL) == -1)
27387c478bd9Sstevel@tonic-gate 		warning(gettext(SIGACT_FAILED), strsignal(SIGHUP),
27397c478bd9Sstevel@tonic-gate 		    strerror(errno));
27407c478bd9Sstevel@tonic-gate 
27417c478bd9Sstevel@tonic-gate 	act.sa_sigaction = term_handler;
27427c478bd9Sstevel@tonic-gate 	(void) sigemptyset(&act.sa_mask);
27437c478bd9Sstevel@tonic-gate 	act.sa_flags = SA_SIGINFO;
27447c478bd9Sstevel@tonic-gate 	if (sigaction(SIGTERM, &act, NULL) == -1)
27457c478bd9Sstevel@tonic-gate 		warning(gettext(SIGACT_FAILED), strsignal(SIGTERM),
27467c478bd9Sstevel@tonic-gate 		    strerror(errno));
27477c478bd9Sstevel@tonic-gate 
27487c478bd9Sstevel@tonic-gate 	act.sa_sigaction = sig_handler;
27497c478bd9Sstevel@tonic-gate 	(void) sigemptyset(&act.sa_mask);
27507c478bd9Sstevel@tonic-gate 	act.sa_flags = SA_SIGINFO;
27517c478bd9Sstevel@tonic-gate 	if (sigaction(SIGINT, &act, NULL) == -1)
27527c478bd9Sstevel@tonic-gate 		warning(gettext(SIGACT_FAILED), strsignal(SIGHUP),
27537c478bd9Sstevel@tonic-gate 		    strerror(errno));
27547c478bd9Sstevel@tonic-gate 
27557c478bd9Sstevel@tonic-gate 	act.sa_sigaction = sig_handler;
27567c478bd9Sstevel@tonic-gate 	(void) sigemptyset(&act.sa_mask);
27577c478bd9Sstevel@tonic-gate 	act.sa_flags = SA_SIGINFO;
27587c478bd9Sstevel@tonic-gate 	if (sigaction(SIGQUIT, &act, NULL) == -1)
27597c478bd9Sstevel@tonic-gate 		warning(gettext(SIGACT_FAILED), strsignal(SIGHUP),
27607c478bd9Sstevel@tonic-gate 		    strerror(errno));
27617c478bd9Sstevel@tonic-gate 	debug(10, "init_server completed successfully\n");
27627c478bd9Sstevel@tonic-gate 
27637c478bd9Sstevel@tonic-gate 	server_data.sd_init_state = INIT_DONE;
27647c478bd9Sstevel@tonic-gate 	return (NULL);
27657c478bd9Sstevel@tonic-gate }
27667c478bd9Sstevel@tonic-gate 
27677c478bd9Sstevel@tonic-gate static int
27687c478bd9Sstevel@tonic-gate server_exists()
27697c478bd9Sstevel@tonic-gate {
27707c478bd9Sstevel@tonic-gate 	door_arg_t		darg;
27717c478bd9Sstevel@tonic-gate 	smedia_reqping_t	req_ping;
27727c478bd9Sstevel@tonic-gate 	smedia_retping_t	*ret_ping;
27737c478bd9Sstevel@tonic-gate 	int			doorh;
27747c478bd9Sstevel@tonic-gate 	door_info_t		dinfo;
27757c478bd9Sstevel@tonic-gate 	char    rbuf[sizeof (smedia_services_t) + sizeof (door_desc_t)];
27767c478bd9Sstevel@tonic-gate 
27777c478bd9Sstevel@tonic-gate 	doorh = open(smedia_service, O_RDONLY);
27787c478bd9Sstevel@tonic-gate 	if (doorh < 0)
27797c478bd9Sstevel@tonic-gate 		return (0);
27807c478bd9Sstevel@tonic-gate 	if (door_info(doorh, &dinfo) < 0) {
27817c478bd9Sstevel@tonic-gate 		(void) close(doorh);
27827c478bd9Sstevel@tonic-gate 		return (0);
27837c478bd9Sstevel@tonic-gate 	}
27847c478bd9Sstevel@tonic-gate 	if (dinfo.di_attributes & DOOR_REVOKED) {
27857c478bd9Sstevel@tonic-gate 		(void) close(doorh);
27867c478bd9Sstevel@tonic-gate 		return (0);
27877c478bd9Sstevel@tonic-gate 	}
27887c478bd9Sstevel@tonic-gate 
27897c478bd9Sstevel@tonic-gate 	req_ping.cnum = SMEDIA_CNUM_PING;
27907c478bd9Sstevel@tonic-gate 
27917c478bd9Sstevel@tonic-gate 	darg.data_ptr = (char *)&req_ping;
27927c478bd9Sstevel@tonic-gate 	darg.data_size = sizeof (smedia_reqping_t);
27937c478bd9Sstevel@tonic-gate 	darg.desc_ptr = NULL;
27947c478bd9Sstevel@tonic-gate 	darg.desc_num = 0;
27957c478bd9Sstevel@tonic-gate 	darg.rbuf = rbuf;
27967c478bd9Sstevel@tonic-gate 	darg.rsize = sizeof (rbuf);
27977c478bd9Sstevel@tonic-gate 
27987c478bd9Sstevel@tonic-gate 	if (door_call(doorh, &darg) < 0) {
27997c478bd9Sstevel@tonic-gate 		(void) close(doorh);
28007c478bd9Sstevel@tonic-gate 		return (0);
28017c478bd9Sstevel@tonic-gate 	}
28027c478bd9Sstevel@tonic-gate 	ret_ping = (smedia_retping_t *)((void *)darg.data_ptr);
28037c478bd9Sstevel@tonic-gate 	if (ret_ping->cnum != SMEDIA_CNUM_PING) {
28047c478bd9Sstevel@tonic-gate 		(void) close(doorh);
28057c478bd9Sstevel@tonic-gate 		return (0);
28067c478bd9Sstevel@tonic-gate 	}
28077c478bd9Sstevel@tonic-gate 
28087c478bd9Sstevel@tonic-gate 	(void) close(doorh);
28097c478bd9Sstevel@tonic-gate 	return (1);
28107c478bd9Sstevel@tonic-gate }
28117c478bd9Sstevel@tonic-gate 
28127c478bd9Sstevel@tonic-gate static int
28137c478bd9Sstevel@tonic-gate get_run_level()
28147c478bd9Sstevel@tonic-gate {
28157c478bd9Sstevel@tonic-gate 	int	run_level;
28167c478bd9Sstevel@tonic-gate 	struct utmpx	*utmpp;
28177c478bd9Sstevel@tonic-gate 
28187c478bd9Sstevel@tonic-gate 	setutxent();
28197c478bd9Sstevel@tonic-gate 	while ((utmpp = getutxent()) != NULL) {
28207c478bd9Sstevel@tonic-gate 		if (utmpp->ut_type == RUN_LVL) {
28217c478bd9Sstevel@tonic-gate 			run_level = atoi(
28227c478bd9Sstevel@tonic-gate 				&utmpp->ut_line[strlen("run-level ")]);
28237c478bd9Sstevel@tonic-gate 		}
28247c478bd9Sstevel@tonic-gate 	}
28257c478bd9Sstevel@tonic-gate 	return (run_level);
28267c478bd9Sstevel@tonic-gate }
28277c478bd9Sstevel@tonic-gate 
28287c478bd9Sstevel@tonic-gate /*ARGSUSED*/
28297c478bd9Sstevel@tonic-gate static void *
28307c478bd9Sstevel@tonic-gate closedown(void *arg)
28317c478bd9Sstevel@tonic-gate {
28327c478bd9Sstevel@tonic-gate 
28337c478bd9Sstevel@tonic-gate 	int	current_run_level;
28347c478bd9Sstevel@tonic-gate 
28357c478bd9Sstevel@tonic-gate 	/*CONSTCOND*/
28367c478bd9Sstevel@tonic-gate #ifndef lint
28377c478bd9Sstevel@tonic-gate 	while (1) {
28387c478bd9Sstevel@tonic-gate #endif
28397c478bd9Sstevel@tonic-gate 		(void) sleep(SVC_CLOSEDOWN/2);
28407c478bd9Sstevel@tonic-gate 
28417c478bd9Sstevel@tonic-gate 		/*
28427c478bd9Sstevel@tonic-gate 		 * If the server was started at init level 1
28437c478bd9Sstevel@tonic-gate 		 * and the current init level is 1 then
28447c478bd9Sstevel@tonic-gate 		 * do not exit from server. This server will run
28457c478bd9Sstevel@tonic-gate 		 * until it is explicitly stopped by the user.
28467c478bd9Sstevel@tonic-gate 		 */
28477c478bd9Sstevel@tonic-gate 		if (svcstart_level == 1) {
28487c478bd9Sstevel@tonic-gate 			current_run_level = get_run_level();
28497c478bd9Sstevel@tonic-gate 			if (current_run_level == 1)
28507c478bd9Sstevel@tonic-gate #ifndef lint
28517c478bd9Sstevel@tonic-gate 				continue;
28527c478bd9Sstevel@tonic-gate #else
28537c478bd9Sstevel@tonic-gate 				return (NULL);
28547c478bd9Sstevel@tonic-gate #endif
28557c478bd9Sstevel@tonic-gate 			/*
28567c478bd9Sstevel@tonic-gate 			 * who ever started the server at level 1 has
28577c478bd9Sstevel@tonic-gate 			 * forgotten to stop the server. we will kill ourself.
28587c478bd9Sstevel@tonic-gate 			 */
28597c478bd9Sstevel@tonic-gate 			debug(5,
28607c478bd9Sstevel@tonic-gate 			"Terminating the server started at init level 1\n");
28617c478bd9Sstevel@tonic-gate 			exit(0);
28627c478bd9Sstevel@tonic-gate 		}
28637c478bd9Sstevel@tonic-gate 
28647c478bd9Sstevel@tonic-gate 		if (mutex_trylock(&svcstate_lock) != 0)
28657c478bd9Sstevel@tonic-gate #ifndef lint
28667c478bd9Sstevel@tonic-gate 			continue;
28677c478bd9Sstevel@tonic-gate #else
28687c478bd9Sstevel@tonic-gate 			return (NULL);
28697c478bd9Sstevel@tonic-gate #endif
28707c478bd9Sstevel@tonic-gate 		if (svcstate == _IDLE && svccount == 0) {
28717c478bd9Sstevel@tonic-gate 			int size;
28727c478bd9Sstevel@tonic-gate 			int i, openfd = 0;
28737c478bd9Sstevel@tonic-gate 
28747c478bd9Sstevel@tonic-gate 			size = svc_max_pollfd;
28757c478bd9Sstevel@tonic-gate 			for (i = 0; i < size && openfd < 2; i++)
28767c478bd9Sstevel@tonic-gate 				if (svc_pollfd[i].fd >= 0)
28777c478bd9Sstevel@tonic-gate 					openfd++;
28787c478bd9Sstevel@tonic-gate 			if (openfd <= 1) {
28797c478bd9Sstevel@tonic-gate 				debug(5,
28807c478bd9Sstevel@tonic-gate 				"Exiting the server from closedown routine.\n");
28817c478bd9Sstevel@tonic-gate 				exit(0);
28827c478bd9Sstevel@tonic-gate 			}
28837c478bd9Sstevel@tonic-gate 		} else
28847c478bd9Sstevel@tonic-gate 			svcstate = _IDLE;
28857c478bd9Sstevel@tonic-gate 
28867c478bd9Sstevel@tonic-gate 		(void) mutex_unlock(&svcstate_lock);
28877c478bd9Sstevel@tonic-gate #ifndef lint
28887c478bd9Sstevel@tonic-gate 	}
28897c478bd9Sstevel@tonic-gate #else
28907c478bd9Sstevel@tonic-gate 	return (NULL);
28917c478bd9Sstevel@tonic-gate #endif
28927c478bd9Sstevel@tonic-gate 
28937c478bd9Sstevel@tonic-gate }
28947c478bd9Sstevel@tonic-gate 
28957c478bd9Sstevel@tonic-gate static void
28967c478bd9Sstevel@tonic-gate usage()
28977c478bd9Sstevel@tonic-gate {
28987c478bd9Sstevel@tonic-gate 	warning(gettext("usage: %s [-L loglevel] level of debug information\n"),
28997c478bd9Sstevel@tonic-gate 		prog_name);
29007c478bd9Sstevel@tonic-gate }
29017c478bd9Sstevel@tonic-gate 
29027c478bd9Sstevel@tonic-gate 
29037c478bd9Sstevel@tonic-gate /*ARGSUSED*/
2904360e6f5eSmathue int
29057c478bd9Sstevel@tonic-gate main(int argc, char **argv)
29067c478bd9Sstevel@tonic-gate {
29077c478bd9Sstevel@tonic-gate 	int c;
29087c478bd9Sstevel@tonic-gate 	pthread_attr_t	attr;
29097c478bd9Sstevel@tonic-gate 
29107c478bd9Sstevel@tonic-gate 	(void) setlocale(LC_ALL, "");
29117c478bd9Sstevel@tonic-gate #if !defined(TEXT_DOMAIN)
29127c478bd9Sstevel@tonic-gate #define	TEXT_DOMAIN "SYS_TEST"
29137c478bd9Sstevel@tonic-gate #endif
29147c478bd9Sstevel@tonic-gate 	(void) textdomain(TEXT_DOMAIN);
29157c478bd9Sstevel@tonic-gate 
29167c478bd9Sstevel@tonic-gate 	prog_name = argv[0];
29177c478bd9Sstevel@tonic-gate 
29187c478bd9Sstevel@tonic-gate 	(void) sigset(SIGPIPE, SIG_IGN);
29197c478bd9Sstevel@tonic-gate 
29207c478bd9Sstevel@tonic-gate 	while ((c = getopt(argc, argv, "L:")) != -1) {
29217c478bd9Sstevel@tonic-gate 		switch (c) {
29227c478bd9Sstevel@tonic-gate 		case 'L':
29237c478bd9Sstevel@tonic-gate 			debug_level = atoi((char *)optarg);
29247c478bd9Sstevel@tonic-gate 			break;
29257c478bd9Sstevel@tonic-gate 		default:
29267c478bd9Sstevel@tonic-gate 			usage();
29277c478bd9Sstevel@tonic-gate 			break;
29287c478bd9Sstevel@tonic-gate 		}
29297c478bd9Sstevel@tonic-gate 	}
29307c478bd9Sstevel@tonic-gate 
29317c478bd9Sstevel@tonic-gate 	/*
29327c478bd9Sstevel@tonic-gate 	 * If stdin looks like a TLI endpoint, we assume
29337c478bd9Sstevel@tonic-gate 	 * that we were started by a port monitor. If
29347c478bd9Sstevel@tonic-gate 	 * t_getstate fails with TBADF, this is not a
29357c478bd9Sstevel@tonic-gate 	 * TLI endpoint.
29367c478bd9Sstevel@tonic-gate 	 */
29377c478bd9Sstevel@tonic-gate 	if (t_getstate(0) != -1 || t_errno != TBADF) {
29387c478bd9Sstevel@tonic-gate 		char *netid;
29397c478bd9Sstevel@tonic-gate 		struct netconfig *nconf = NULL;
29407c478bd9Sstevel@tonic-gate 		SVCXPRT *transp;
29417c478bd9Sstevel@tonic-gate 		int pmclose;
29427c478bd9Sstevel@tonic-gate 
29437c478bd9Sstevel@tonic-gate 		openlog(prog_name, LOG_PID, LOG_DAEMON);
29447c478bd9Sstevel@tonic-gate 
29457c478bd9Sstevel@tonic-gate 		debug(1, gettext("server started by port monitor.\n"));
29467c478bd9Sstevel@tonic-gate 		if ((netid = getenv("NLSPROVIDER")) == NULL) {
29477c478bd9Sstevel@tonic-gate 		/* started from inetd */
29487c478bd9Sstevel@tonic-gate 			pmclose = 1;
29497c478bd9Sstevel@tonic-gate 		} else {
29507c478bd9Sstevel@tonic-gate 			if ((nconf = getnetconfigent(netid)) == NULL)
29517c478bd9Sstevel@tonic-gate 				syslog(LOG_ERR, gettext(
29527c478bd9Sstevel@tonic-gate 					"cannot get transport info"));
29537c478bd9Sstevel@tonic-gate 
29547c478bd9Sstevel@tonic-gate 			pmclose = (t_getstate(0) != T_DATAXFER);
29557c478bd9Sstevel@tonic-gate 		}
29567c478bd9Sstevel@tonic-gate 		if ((transp = svc_tli_create(0, nconf, NULL, 0, 0)) == NULL) {
29577c478bd9Sstevel@tonic-gate 			syslog(LOG_ERR, gettext("cannot create server handle"));
29587c478bd9Sstevel@tonic-gate 			exit(1);
29597c478bd9Sstevel@tonic-gate 		}
29607c478bd9Sstevel@tonic-gate 		if (nconf)
29617c478bd9Sstevel@tonic-gate 			freenetconfigent(nconf);
29627c478bd9Sstevel@tonic-gate 		if (!svc_reg(transp, SMSERVERPROG, SMSERVERVERS,
29637c478bd9Sstevel@tonic-gate 			smserverprog_1, 0)) {
29647c478bd9Sstevel@tonic-gate 			syslog(LOG_ERR, gettext(
29657c478bd9Sstevel@tonic-gate 			"unable to register (SMSERVERPROG, SMSERVERVERS)."));
29667c478bd9Sstevel@tonic-gate 			exit(1);
29677c478bd9Sstevel@tonic-gate 		}
29687c478bd9Sstevel@tonic-gate 		svcstart_level = get_run_level();
29697c478bd9Sstevel@tonic-gate 		if (pmclose) {
29707c478bd9Sstevel@tonic-gate 			(void) pthread_attr_init(&attr);
29717c478bd9Sstevel@tonic-gate 			(void) pthread_attr_setscope(&attr,
29727c478bd9Sstevel@tonic-gate 				PTHREAD_SCOPE_SYSTEM | PTHREAD_CREATE_DETACHED);
29737c478bd9Sstevel@tonic-gate 			if (pthread_create(NULL, &attr, closedown, NULL) != 0) {
29747c478bd9Sstevel@tonic-gate 				syslog(LOG_ERR, gettext(
29757c478bd9Sstevel@tonic-gate 					"cannot create closedown thread"));
29767c478bd9Sstevel@tonic-gate 				exit(1);
29777c478bd9Sstevel@tonic-gate 			}
29787c478bd9Sstevel@tonic-gate 			(void) pthread_attr_destroy(&attr);
29797c478bd9Sstevel@tonic-gate 		}
29807c478bd9Sstevel@tonic-gate 		svc_run();
29817c478bd9Sstevel@tonic-gate 		exit(1);
29827c478bd9Sstevel@tonic-gate 		/* NOTREACHED */
29837c478bd9Sstevel@tonic-gate 	} else {
29847c478bd9Sstevel@tonic-gate 		/*
29857c478bd9Sstevel@tonic-gate 		 * Started by library or manually.
29867c478bd9Sstevel@tonic-gate 		 */
29877c478bd9Sstevel@tonic-gate 		/*
29887c478bd9Sstevel@tonic-gate 		 * Check to see if the server is already running.
29897c478bd9Sstevel@tonic-gate 		 * There is no need to log messages in the syslog file
29907c478bd9Sstevel@tonic-gate 		 * because server will get launched each time libsmedia
29917c478bd9Sstevel@tonic-gate 		 * library calls are made at init 1 level.
29927c478bd9Sstevel@tonic-gate 		 * We ensure that only one copy will run.
29937c478bd9Sstevel@tonic-gate 		 */
29947c478bd9Sstevel@tonic-gate 		debug(1, gettext("server started manually.\n"));
29957c478bd9Sstevel@tonic-gate 		if (server_exists()) {
29967c478bd9Sstevel@tonic-gate 			exit(0);
29977c478bd9Sstevel@tonic-gate 		}
29987c478bd9Sstevel@tonic-gate 		svcstart_level = get_run_level();
29997c478bd9Sstevel@tonic-gate 		(void) pthread_attr_init(&attr);
30007c478bd9Sstevel@tonic-gate 		(void) pthread_attr_setscope(&attr,
30017c478bd9Sstevel@tonic-gate 			PTHREAD_SCOPE_SYSTEM | PTHREAD_CREATE_DETACHED);
30027c478bd9Sstevel@tonic-gate 		if (pthread_create(NULL, &attr, closedown, NULL) != 0) {
30037c478bd9Sstevel@tonic-gate 			syslog(LOG_ERR, gettext(
30047c478bd9Sstevel@tonic-gate 				"cannot create closedown thread"));
30057c478bd9Sstevel@tonic-gate 			exit(1);
30067c478bd9Sstevel@tonic-gate 		}
30077c478bd9Sstevel@tonic-gate 		(void) pthread_attr_destroy(&attr);
30087c478bd9Sstevel@tonic-gate 		(void) init_server(NULL);
30097c478bd9Sstevel@tonic-gate 		for (;;) (void) pause();
30107c478bd9Sstevel@tonic-gate 	}
3011360e6f5eSmathue 	return (0);
30127c478bd9Sstevel@tonic-gate }
30137c478bd9Sstevel@tonic-gate 
30147c478bd9Sstevel@tonic-gate 
30157c478bd9Sstevel@tonic-gate /*ARGSUSED*/
30167c478bd9Sstevel@tonic-gate static int32_t
30177c478bd9Sstevel@tonic-gate scsi_floppy_write_protect(int32_t fd, smwp_state_t *wp)
30187c478bd9Sstevel@tonic-gate {
30197c478bd9Sstevel@tonic-gate 	debug(5, "Invalid mode\n");
30207c478bd9Sstevel@tonic-gate 	errno = ENOTSUP;
30217c478bd9Sstevel@tonic-gate 
30227c478bd9Sstevel@tonic-gate 	return (-1);
30237c478bd9Sstevel@tonic-gate }
30247c478bd9Sstevel@tonic-gate 
30257c478bd9Sstevel@tonic-gate /*
30267c478bd9Sstevel@tonic-gate  * Generate standard geometry information for SCSI floppy devices. And
30277c478bd9Sstevel@tonic-gate  * register the geometry with the SCSI driver. This will expand as more
30287c478bd9Sstevel@tonic-gate  * formats are added.
30297c478bd9Sstevel@tonic-gate  */
30307c478bd9Sstevel@tonic-gate 
30317c478bd9Sstevel@tonic-gate /*ARGSUSED*/
30327c478bd9Sstevel@tonic-gate static int32_t
30337c478bd9Sstevel@tonic-gate get_floppy_geom(int32_t fd, uint32_t capacity, struct dk_geom *dkgeom)
30347c478bd9Sstevel@tonic-gate {
30357c478bd9Sstevel@tonic-gate 
30367c478bd9Sstevel@tonic-gate 
30377c478bd9Sstevel@tonic-gate 	debug(5, "get_floppy_geom: capacity = 0x%x\n", capacity);
30387c478bd9Sstevel@tonic-gate 
30397c478bd9Sstevel@tonic-gate 	switch (capacity) {
30407c478bd9Sstevel@tonic-gate 
30417c478bd9Sstevel@tonic-gate 		case 0x5A0:
30427c478bd9Sstevel@tonic-gate 			/* Double Density 720K */
30437c478bd9Sstevel@tonic-gate 			dkgeom->dkg_pcyl = 80;
30447c478bd9Sstevel@tonic-gate 			dkgeom->dkg_ncyl = 80;
30457c478bd9Sstevel@tonic-gate 			dkgeom->dkg_nhead = 2;
30467c478bd9Sstevel@tonic-gate 			dkgeom->dkg_nsect = 9;
30477c478bd9Sstevel@tonic-gate 			break;
30487c478bd9Sstevel@tonic-gate 		case 0x4D0:
30497c478bd9Sstevel@tonic-gate 			/* High Density 1.25MB */
30507c478bd9Sstevel@tonic-gate 			dkgeom->dkg_pcyl = 77;
30517c478bd9Sstevel@tonic-gate 			dkgeom->dkg_ncyl = 77;
30527c478bd9Sstevel@tonic-gate 			dkgeom->dkg_nhead = 2;
30537c478bd9Sstevel@tonic-gate 			dkgeom->dkg_nsect = 9;
30547c478bd9Sstevel@tonic-gate 			break;
30557c478bd9Sstevel@tonic-gate 		case 0xB40:
30567c478bd9Sstevel@tonic-gate 			/* High Density 1.44MB */
30577c478bd9Sstevel@tonic-gate 
30587c478bd9Sstevel@tonic-gate 			dkgeom->dkg_pcyl = 80;
30597c478bd9Sstevel@tonic-gate 			dkgeom->dkg_ncyl = 80;
30607c478bd9Sstevel@tonic-gate 			dkgeom->dkg_nhead = 2;
30617c478bd9Sstevel@tonic-gate 			dkgeom->dkg_nsect = 18;
30627c478bd9Sstevel@tonic-gate 			break;
30637c478bd9Sstevel@tonic-gate 		case 0x3C300:
30647c478bd9Sstevel@tonic-gate 			/* Ultra High density ls-120 120MB */
30657c478bd9Sstevel@tonic-gate 			dkgeom->dkg_pcyl = 963;
30667c478bd9Sstevel@tonic-gate 			dkgeom->dkg_ncyl = 963;
30677c478bd9Sstevel@tonic-gate 			dkgeom->dkg_nhead = 8;
30687c478bd9Sstevel@tonic-gate 			dkgeom->dkg_nsect = 32;
30697c478bd9Sstevel@tonic-gate 			break;
30707c478bd9Sstevel@tonic-gate 		default:
30717c478bd9Sstevel@tonic-gate 			debug(5, "unknown capacity type %d\n", capacity);
30727c478bd9Sstevel@tonic-gate 			return (-1);
30737c478bd9Sstevel@tonic-gate 
30747c478bd9Sstevel@tonic-gate 	}
30757c478bd9Sstevel@tonic-gate 	debug(5, "get_floppy_geom: setting cyl = %d, nsect = %d, head = %d",
30767c478bd9Sstevel@tonic-gate 		dkgeom->dkg_pcyl, dkgeom->dkg_nhead, dkgeom->dkg_nsect);
30777c478bd9Sstevel@tonic-gate 	return (0);
30787c478bd9Sstevel@tonic-gate 
30797c478bd9Sstevel@tonic-gate }
30807c478bd9Sstevel@tonic-gate /* ARGSUSED */
30815363f09cSarutz static int32_t
30827c478bd9Sstevel@tonic-gate scsi_floppy_format(int32_t fd, uint_t flavor, uint_t mode)
30837c478bd9Sstevel@tonic-gate {
30847c478bd9Sstevel@tonic-gate 	struct uscsi_cmd ucmd;
30857c478bd9Sstevel@tonic-gate 	uchar_t		cdb[12];
30867c478bd9Sstevel@tonic-gate 	int32_t		ret_val;
30877c478bd9Sstevel@tonic-gate 	uint32_t	capacity, blocksize;
30887c478bd9Sstevel@tonic-gate 	uchar_t		data[12];
30897c478bd9Sstevel@tonic-gate 	char 		rq_data[RQ_LEN];
30907c478bd9Sstevel@tonic-gate 	int		i;
30917c478bd9Sstevel@tonic-gate 	struct dk_geom	dkgeom;
30927c478bd9Sstevel@tonic-gate 
30937c478bd9Sstevel@tonic-gate 	debug(5, "scsi_floppy_format:\n");
30947c478bd9Sstevel@tonic-gate 
30957c478bd9Sstevel@tonic-gate 	if ((mode != SM_FORMAT_IMMEDIATE) && (mode != SM_FORMAT_BLOCKED)) {
30967c478bd9Sstevel@tonic-gate 		errno = ENOTSUP;
30977c478bd9Sstevel@tonic-gate 
30987c478bd9Sstevel@tonic-gate 		return (-1);
30997c478bd9Sstevel@tonic-gate 	}
31007c478bd9Sstevel@tonic-gate 
31017c478bd9Sstevel@tonic-gate 	switch (flavor) {
31027c478bd9Sstevel@tonic-gate 		case SM_FORMAT_QUICK :
31037c478bd9Sstevel@tonic-gate 			debug(1, "Format not supported\n");
31047c478bd9Sstevel@tonic-gate 			errno = ENOTSUP;
31057c478bd9Sstevel@tonic-gate 			return (-1);
31067c478bd9Sstevel@tonic-gate 		case SM_FORMAT_FORCE :
31077c478bd9Sstevel@tonic-gate 			break;
31087c478bd9Sstevel@tonic-gate 		case SM_FORMAT_LONG :
31097c478bd9Sstevel@tonic-gate 			break;
31107c478bd9Sstevel@tonic-gate 
31117c478bd9Sstevel@tonic-gate 		default :
31127c478bd9Sstevel@tonic-gate 			debug(1, "Format option not specified!!\n");
31137c478bd9Sstevel@tonic-gate 			errno = ENOTSUP;
31147c478bd9Sstevel@tonic-gate 			return (-1);
31157c478bd9Sstevel@tonic-gate 	}
31167c478bd9Sstevel@tonic-gate 
31177c478bd9Sstevel@tonic-gate 	ret_val = get_media_capacity(fd, &capacity, &blocksize);
31187c478bd9Sstevel@tonic-gate 
31197c478bd9Sstevel@tonic-gate 	if (capacity >= 0x3C300) {
31207c478bd9Sstevel@tonic-gate 		/*
31217c478bd9Sstevel@tonic-gate 		 * It's an LS-120 media, it does not support track
31227c478bd9Sstevel@tonic-gate 		 * formatting.
31237c478bd9Sstevel@tonic-gate 		 */
31247c478bd9Sstevel@tonic-gate 		return (scsi_ls120_format(fd, flavor, capacity, blocksize));
31257c478bd9Sstevel@tonic-gate 	}
31267c478bd9Sstevel@tonic-gate 
31277c478bd9Sstevel@tonic-gate 	ret_val = get_floppy_geom(fd, capacity, &dkgeom);
31287c478bd9Sstevel@tonic-gate 		if (ret_val) {
31297c478bd9Sstevel@tonic-gate 			errno = ENOTSUP;
31307c478bd9Sstevel@tonic-gate 			return (-1);
31317c478bd9Sstevel@tonic-gate 		}
31327c478bd9Sstevel@tonic-gate 
31337c478bd9Sstevel@tonic-gate 	(void) memset((void *)&data, 0, sizeof (data));
31347c478bd9Sstevel@tonic-gate 	(void) memset((void *)&ucmd, 0, sizeof (ucmd));
31357c478bd9Sstevel@tonic-gate 	(void) memset((void *)&cdb, 0, sizeof (cdb));
31367c478bd9Sstevel@tonic-gate 
31377c478bd9Sstevel@tonic-gate 	/* retrieve size discriptor of inserted media */
31387c478bd9Sstevel@tonic-gate 	cdb[0] = SCMD_FORMAT;	/* format */
31397c478bd9Sstevel@tonic-gate 
31407c478bd9Sstevel@tonic-gate 	/*
31417c478bd9Sstevel@tonic-gate 	 * Defect list sent by initiator is a complete list of defects.
31427c478bd9Sstevel@tonic-gate 	 */
31437c478bd9Sstevel@tonic-gate 
31447c478bd9Sstevel@tonic-gate 	cdb[1] = (FMTDATA | 0x7);
31457c478bd9Sstevel@tonic-gate 
31467c478bd9Sstevel@tonic-gate 	cdb[8] = 0xC;   /* parameter list length */
31477c478bd9Sstevel@tonic-gate 	data[3] = 0x8;	/* should be always 8 */
31487c478bd9Sstevel@tonic-gate 
31497c478bd9Sstevel@tonic-gate 	data[4] = (uchar_t)(capacity >> 24);
31507c478bd9Sstevel@tonic-gate 	data[5] = (uchar_t)(capacity >> 16);
31517c478bd9Sstevel@tonic-gate 	data[6] = (uchar_t)(capacity >> 8);
31527c478bd9Sstevel@tonic-gate 	data[7] = (uchar_t)capacity;
31537c478bd9Sstevel@tonic-gate 
31547c478bd9Sstevel@tonic-gate 	data[9] = (uchar_t)(blocksize >> 16);
31557c478bd9Sstevel@tonic-gate 	data[10] = (uchar_t)(blocksize >> 8);
31567c478bd9Sstevel@tonic-gate 	data[11] = (uchar_t)blocksize;
31577c478bd9Sstevel@tonic-gate 
31587c478bd9Sstevel@tonic-gate 	ucmd.uscsi_cdb = (caddr_t)&cdb;
31597c478bd9Sstevel@tonic-gate 	ucmd.uscsi_cdblen = CDB_GROUP5;
31607c478bd9Sstevel@tonic-gate 	ucmd.uscsi_bufaddr = (caddr_t)data;
31617c478bd9Sstevel@tonic-gate 	ucmd.uscsi_buflen = sizeof (data);
31627c478bd9Sstevel@tonic-gate 	ucmd.uscsi_timeout = 0x15;
31637c478bd9Sstevel@tonic-gate 	ucmd.uscsi_rqlen = RQ_LEN;
31647c478bd9Sstevel@tonic-gate 	ucmd.uscsi_rqbuf = rq_data;
31657c478bd9Sstevel@tonic-gate 
31667c478bd9Sstevel@tonic-gate 	debug(5, "cdb: %x %x %x ... %x", cdb[0], cdb[1], cdb[2], cdb[8]);
31677c478bd9Sstevel@tonic-gate 	debug(5, "data: %x %x %x %x\n", data[0], data[1], data[2], data[3]);
31687c478bd9Sstevel@tonic-gate 	debug(5, "    : %x %x %x %x\n", data[4], data[5], data[6], data[7]);
31697c478bd9Sstevel@tonic-gate 	debug(5, "    : %x %x %x %x\n", data[8], data[9], data[10], data[11]);
31707c478bd9Sstevel@tonic-gate 
31717c478bd9Sstevel@tonic-gate 	for (i = 0; i < dkgeom.dkg_pcyl; i++) {	/* number of tracks */
31727c478bd9Sstevel@tonic-gate 		data[1] = (0xb0 | FOV);
31737c478bd9Sstevel@tonic-gate 		cdb[2] = i;
31747c478bd9Sstevel@tonic-gate 
31757c478bd9Sstevel@tonic-gate 		(void) fflush(stdout);
31767c478bd9Sstevel@tonic-gate 		ret_val = do_uscsi_cmd(fd, &ucmd, USCSI_WRITE|USCSI_RQENABLE);
31777c478bd9Sstevel@tonic-gate 		info("format side 0 returned : 0x%x\n", ret_val);
31787c478bd9Sstevel@tonic-gate 
31797c478bd9Sstevel@tonic-gate 		if (ret_val || ucmd.uscsi_status) {
31807c478bd9Sstevel@tonic-gate 			debug(5, "Retrieving media info failed: %d - %d\n",
31817c478bd9Sstevel@tonic-gate 			    ret_val, ucmd.uscsi_status);
31827c478bd9Sstevel@tonic-gate 			if ((rq_data[2] == KEY_DATA_PROTECT) &&
31837c478bd9Sstevel@tonic-gate 			    (rq_data[12] == 0x30) && (rq_data[13] == 0)) {
31847c478bd9Sstevel@tonic-gate 				debug(5, "Invalid command for media\n");
31857c478bd9Sstevel@tonic-gate 				errno = EINVAL;
31867c478bd9Sstevel@tonic-gate 			}
31877c478bd9Sstevel@tonic-gate 
31887c478bd9Sstevel@tonic-gate 			if ((rq_data[2] == KEY_NOT_READY) &&
31897c478bd9Sstevel@tonic-gate 			    (rq_data[12] == 0x30)) {
31907c478bd9Sstevel@tonic-gate 				debug(5, "Incompatible media.\n");
31917c478bd9Sstevel@tonic-gate 				errno = EINVAL;
31927c478bd9Sstevel@tonic-gate 			}
31937c478bd9Sstevel@tonic-gate 
31947c478bd9Sstevel@tonic-gate 			return (-1);
31957c478bd9Sstevel@tonic-gate 		}
31967c478bd9Sstevel@tonic-gate 		data[1] = (0xb0 | FOV) + 1;
31977c478bd9Sstevel@tonic-gate 		ret_val = do_uscsi_cmd(fd, &ucmd, USCSI_WRITE|USCSI_RQENABLE);
31987c478bd9Sstevel@tonic-gate 		info("format side 1 returned : 0x%x\n", ret_val);
31997c478bd9Sstevel@tonic-gate 
32007c478bd9Sstevel@tonic-gate 		if (ret_val || ucmd.uscsi_status) {
32017c478bd9Sstevel@tonic-gate 			debug(5, "Retrieving media info failed: %d - %d\n",
32027c478bd9Sstevel@tonic-gate 			    ret_val, ucmd.uscsi_status);
32037c478bd9Sstevel@tonic-gate 			if ((rq_data[2] == KEY_DATA_PROTECT) &&
32047c478bd9Sstevel@tonic-gate 			    (rq_data[12] == 0x30) && (rq_data[13] == 0)) {
32057c478bd9Sstevel@tonic-gate 				(void) info("Invalid command for media\n");
32067c478bd9Sstevel@tonic-gate 				errno = EINVAL;
32077c478bd9Sstevel@tonic-gate 			}
32087c478bd9Sstevel@tonic-gate 
32097c478bd9Sstevel@tonic-gate 			if ((rq_data[2] == KEY_NOT_READY) &&
32107c478bd9Sstevel@tonic-gate 			    (rq_data[12] == 0x30)) {
32117c478bd9Sstevel@tonic-gate 				debug(5, "Incompatible media.\n");
32127c478bd9Sstevel@tonic-gate 				errno = EINVAL;
32137c478bd9Sstevel@tonic-gate 			}
32147c478bd9Sstevel@tonic-gate 
32157c478bd9Sstevel@tonic-gate 			return (-1);
32167c478bd9Sstevel@tonic-gate 		}
32177c478bd9Sstevel@tonic-gate 	}
32187c478bd9Sstevel@tonic-gate 
32197c478bd9Sstevel@tonic-gate 	debug(5, "formatting done!");
32207c478bd9Sstevel@tonic-gate 	return (0);
32217c478bd9Sstevel@tonic-gate }
32227c478bd9Sstevel@tonic-gate 
32237c478bd9Sstevel@tonic-gate 
32247c478bd9Sstevel@tonic-gate /* ARGSUSED */
32255363f09cSarutz static int32_t
32267c478bd9Sstevel@tonic-gate scsi_floppy_media_status(int32_t fd)
32277c478bd9Sstevel@tonic-gate {
32287c478bd9Sstevel@tonic-gate 	struct mode_header_g1 modeh;
32297c478bd9Sstevel@tonic-gate 	struct uscsi_cmd ucmd;
32307c478bd9Sstevel@tonic-gate 	uchar_t cdb[10];
32317c478bd9Sstevel@tonic-gate 	int32_t ret_val;
32327c478bd9Sstevel@tonic-gate 	int32_t cur_status;
32337c478bd9Sstevel@tonic-gate 	char rq_data[RQ_LEN];
32347c478bd9Sstevel@tonic-gate 
32357c478bd9Sstevel@tonic-gate 	debug(5, "SCSI MEDIA STATUS CALLED \n");
32367c478bd9Sstevel@tonic-gate 
32377c478bd9Sstevel@tonic-gate 	(void) memset((void *) &modeh, 0, sizeof (modeh));
32387c478bd9Sstevel@tonic-gate 	(void) memset((void *) &ucmd, 0, sizeof (ucmd));
32397c478bd9Sstevel@tonic-gate 	(void) memset(cdb, 0, sizeof (cdb));
32407c478bd9Sstevel@tonic-gate 	/*
32417c478bd9Sstevel@tonic-gate 	 * issue 10 byte mode sense (0x5A)
32427c478bd9Sstevel@tonic-gate 	 */
32437c478bd9Sstevel@tonic-gate 	cdb[0] = SCMD_MODE_SENSE_G1;
32447c478bd9Sstevel@tonic-gate 	cdb[7] = sizeof (modeh) >> 8;
32457c478bd9Sstevel@tonic-gate 	cdb[8] = sizeof (modeh) & 0xff;
32467c478bd9Sstevel@tonic-gate 
32477c478bd9Sstevel@tonic-gate 	ucmd.uscsi_cdb = (caddr_t)cdb;
32487c478bd9Sstevel@tonic-gate 	ucmd.uscsi_cdblen = CDB_GROUP1;
32497c478bd9Sstevel@tonic-gate 	ucmd.uscsi_bufaddr = (caddr_t)&modeh;
32507c478bd9Sstevel@tonic-gate 	ucmd.uscsi_buflen = sizeof (modeh);
32517c478bd9Sstevel@tonic-gate 	ucmd.uscsi_timeout = 120;	/* If 0, HBA hangs forever */
32527c478bd9Sstevel@tonic-gate 	ucmd.uscsi_rqlen = RQ_LEN;
32537c478bd9Sstevel@tonic-gate 	ucmd.uscsi_rqbuf = rq_data;
32547c478bd9Sstevel@tonic-gate 	ret_val = do_uscsi_cmd(fd, &ucmd, USCSI_READ|USCSI_RQENABLE);
32557c478bd9Sstevel@tonic-gate 	if (ret_val || ucmd.uscsi_status) {
32567c478bd9Sstevel@tonic-gate 		/*
32577c478bd9Sstevel@tonic-gate 		 * UFI devices may not respond to the 0 mode page.
32587c478bd9Sstevel@tonic-gate 		 * retry with the error recovery page(0x01)
32597c478bd9Sstevel@tonic-gate 		 */
32607c478bd9Sstevel@tonic-gate 		if (ucmd.uscsi_status & STATUS_CHECK) {
32617c478bd9Sstevel@tonic-gate 			cdb[2] = 0x1;	/* page code */
32627c478bd9Sstevel@tonic-gate 			ret_val = do_uscsi_cmd(fd, &ucmd,
32637c478bd9Sstevel@tonic-gate 					USCSI_READ|USCSI_RQENABLE);
32647c478bd9Sstevel@tonic-gate 		}
32657c478bd9Sstevel@tonic-gate 		if (ret_val || ucmd.uscsi_status) {
32667c478bd9Sstevel@tonic-gate 			debug(1, "Modesense failed: %d - %d\n",
32677c478bd9Sstevel@tonic-gate 				ret_val, ucmd.uscsi_status);
32687c478bd9Sstevel@tonic-gate 			return (-1);
32697c478bd9Sstevel@tonic-gate 		}
32707c478bd9Sstevel@tonic-gate 	}
32717c478bd9Sstevel@tonic-gate 	debug(5, "Modesense succeeded: 0x%x\n", modeh.device_specific);
32727c478bd9Sstevel@tonic-gate 
32737c478bd9Sstevel@tonic-gate 	if (modeh.device_specific & 0x80) {
32747c478bd9Sstevel@tonic-gate 		cur_status = SM_WRITE_PROTECT_NOPASSWD;
32757c478bd9Sstevel@tonic-gate 	} else {
32767c478bd9Sstevel@tonic-gate 		cur_status = SM_WRITE_PROTECT_DISABLE;
32777c478bd9Sstevel@tonic-gate 	}
32787c478bd9Sstevel@tonic-gate 	return (cur_status);
32797c478bd9Sstevel@tonic-gate }
3280