xref: /titanic_50/usr/src/cmd/smserverd/smediad.c (revision 5363f09c424c635028d1466fd25570bebf9d9e8b)
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
57c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
67c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
77c478bd9Sstevel@tonic-gate  * with the License.
87c478bd9Sstevel@tonic-gate  *
97c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
107c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
117c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
127c478bd9Sstevel@tonic-gate  * and limitations under the License.
137c478bd9Sstevel@tonic-gate  *
147c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
157c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
167c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
177c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
187c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
197c478bd9Sstevel@tonic-gate  *
207c478bd9Sstevel@tonic-gate  * CDDL HEADER END
217c478bd9Sstevel@tonic-gate  */
227c478bd9Sstevel@tonic-gate /*
237c478bd9Sstevel@tonic-gate  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
247c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
257c478bd9Sstevel@tonic-gate  */
267c478bd9Sstevel@tonic-gate 
277c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
287c478bd9Sstevel@tonic-gate 
297c478bd9Sstevel@tonic-gate #include <stdio.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
107*5363f09cSarutz  * 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  * ----------------------
122*5363f09cSarutz  * 	The sole function of this descriptor HAD been to inform the server of
123*5363f09cSarutz  * the untimely death of the client. This descriptor is no longer used, though
124*5363f09cSarutz  * it is still created, as libsmedia expects to use it.  This descriptor's
125*5363f09cSarutz  * service procedure had used pthread cancellation(5) to terminate the thread of
126*5363f09cSarutz  * the associated client_door_descriptor.  The client_door_descriptor now
127*5363f09cSarutz  * handles the scenarios where a door_call/client are aborted/terminated.
1287c478bd9Sstevel@tonic-gate  *
129*5363f09cSarutz  * 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
141*5363f09cSarutz  * use the death_door_descriptor.
1427c478bd9Sstevel@tonic-gate  *
143*5363f09cSarutz  * 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.
151*5363f09cSarutz  * 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  * -----------
155*5363f09cSarutz  * 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
158*5363f09cSarutz  * client_door_descriptor. This cookie is passed to the server function that
159*5363f09cSarutz  * handles the client_door_descriptor calls. In our case it is the
160*5363f09cSarutz  * 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.
177*5363f09cSarutz  * 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);
252*5363f09cSarutz 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 
276*5363f09cSarutz static void *sm_server_thread(void *arg);
277*5363f09cSarutz 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) {
440*5363f09cSarutz 		debug(1, "init_server did not do the job. "
441*5363f09cSarutz 		    "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) {
533*5363f09cSarutz 		debug(5, "INQUIRY failed: rv = %d  uscsi_status = "
534*5363f09cSarutz 		    "%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;
9917c478bd9Sstevel@tonic-gate 	FORMG0COUNT(&cdb, sizeof (modeh));
9927c478bd9Sstevel@tonic-gate 	ucmd.uscsi_cdb = (caddr_t)&cdb;
9937c478bd9Sstevel@tonic-gate 	ucmd.uscsi_cdblen = CDB_GROUP0;
9947c478bd9Sstevel@tonic-gate 	ucmd.uscsi_bufaddr = (caddr_t)&modeh;
9957c478bd9Sstevel@tonic-gate 	ucmd.uscsi_buflen = sizeof (modeh);
9967c478bd9Sstevel@tonic-gate 	ucmd.uscsi_timeout = 120;	/* If 0, HBA hangs forever */
9977c478bd9Sstevel@tonic-gate 	ucmd.uscsi_rqlen = RQ_LEN;
9987c478bd9Sstevel@tonic-gate 	ucmd.uscsi_rqbuf = rq_data;
9997c478bd9Sstevel@tonic-gate 	ret_val = do_uscsi_cmd(fd, &ucmd, USCSI_READ|USCSI_RQENABLE);
10007c478bd9Sstevel@tonic-gate 	if (ret_val || ucmd.uscsi_status) {
10017c478bd9Sstevel@tonic-gate 		debug(5, "Modesense failed: %d - %d errno = %d\n",
10027c478bd9Sstevel@tonic-gate 			ret_val, ucmd.uscsi_status, errno);
10037c478bd9Sstevel@tonic-gate 		return (-1);
10047c478bd9Sstevel@tonic-gate 	}
10057c478bd9Sstevel@tonic-gate 
10067c478bd9Sstevel@tonic-gate 
10077c478bd9Sstevel@tonic-gate 	if (modeh.device_specific & W_E_MASK) {
10087c478bd9Sstevel@tonic-gate 		cur_status = SM_WRITE_PROTECT_NOPASSWD;
10097c478bd9Sstevel@tonic-gate 	} else {
10107c478bd9Sstevel@tonic-gate 		cur_status = SM_WRITE_PROTECT_DISABLE;
10117c478bd9Sstevel@tonic-gate 	}
10127c478bd9Sstevel@tonic-gate 	debug(5, "cur status %d\n", cur_status);
10137c478bd9Sstevel@tonic-gate 
10147c478bd9Sstevel@tonic-gate 	return (cur_status);
10157c478bd9Sstevel@tonic-gate }
10167c478bd9Sstevel@tonic-gate 
10177c478bd9Sstevel@tonic-gate static int32_t
10187c478bd9Sstevel@tonic-gate scsi_zip_media_status(int32_t fd)
10197c478bd9Sstevel@tonic-gate {
10207c478bd9Sstevel@tonic-gate 	struct uscsi_cmd ucmd;
10217c478bd9Sstevel@tonic-gate 	uchar_t cdb[12];
10227c478bd9Sstevel@tonic-gate 	int32_t	status;
10237c478bd9Sstevel@tonic-gate 	int32_t mode;
10247c478bd9Sstevel@tonic-gate 	uchar_t data[64];
10257c478bd9Sstevel@tonic-gate 	char rq_data[RQ_LEN];
10267c478bd9Sstevel@tonic-gate 
10277c478bd9Sstevel@tonic-gate 	debug(10, "Getting media status\n");
10287c478bd9Sstevel@tonic-gate 
10297c478bd9Sstevel@tonic-gate 	(void) memset((void *)&ucmd, 0, sizeof (ucmd));
10307c478bd9Sstevel@tonic-gate 	(void) memset((void *)&cdb, 0, sizeof (cdb));
10317c478bd9Sstevel@tonic-gate 
10327c478bd9Sstevel@tonic-gate 	cdb[0] = IOMEGA_NONSENSE_CMD;
10337c478bd9Sstevel@tonic-gate 	cdb[2] = CARTRIDGE_STATUS_PAGE;
10347c478bd9Sstevel@tonic-gate 	cdb[4] = ND_LENGTH;
10357c478bd9Sstevel@tonic-gate 	ucmd.uscsi_cdb = (caddr_t)&cdb;
10367c478bd9Sstevel@tonic-gate 	ucmd.uscsi_cdblen = CDB_GROUP0;
10377c478bd9Sstevel@tonic-gate 	ucmd.uscsi_bufaddr = (caddr_t)data;
10387c478bd9Sstevel@tonic-gate 	ucmd.uscsi_buflen = 64;
10397c478bd9Sstevel@tonic-gate 	ucmd.uscsi_timeout = 120;	/* If 0, HBA hangs forever */
10407c478bd9Sstevel@tonic-gate 	ucmd.uscsi_rqlen = RQ_LEN;
10417c478bd9Sstevel@tonic-gate 	ucmd.uscsi_rqbuf = rq_data;
10427c478bd9Sstevel@tonic-gate 	status = do_uscsi_cmd(fd, &ucmd, USCSI_READ|USCSI_RQENABLE);
10437c478bd9Sstevel@tonic-gate 	if (status || ucmd.uscsi_status) {
1044*5363f09cSarutz 		debug(5, "Cartridge protect operation failed: "
1045*5363f09cSarutz 		    "rv = %d  uscsi_status = %d  errno = %d\n",
10467c478bd9Sstevel@tonic-gate 		    status, ucmd.uscsi_status, errno);
10477c478bd9Sstevel@tonic-gate 		return (-1);
10487c478bd9Sstevel@tonic-gate 	}
10497c478bd9Sstevel@tonic-gate 
10507c478bd9Sstevel@tonic-gate 	if (data[DISK_STATUS_OFFSET + NON_SENSE_HDR_LEN] == 4) {
10517c478bd9Sstevel@tonic-gate 		debug(1, "Disk not present. \n");
10527c478bd9Sstevel@tonic-gate 		return (-1);
10537c478bd9Sstevel@tonic-gate 	}
10547c478bd9Sstevel@tonic-gate 	mode = data[PROTECT_MODE_OFFSET + NON_SENSE_HDR_LEN] & 0xF;
10557c478bd9Sstevel@tonic-gate 
1056*5363f09cSarutz 	debug(5, "MODE 0x%x / %d.\n", mode, mode);
10577c478bd9Sstevel@tonic-gate 
10587c478bd9Sstevel@tonic-gate 	switch (mode) {
10597c478bd9Sstevel@tonic-gate 		case UNLOCK_MODE:
10607c478bd9Sstevel@tonic-gate 			status = SM_WRITE_PROTECT_DISABLE;
10617c478bd9Sstevel@tonic-gate 			break;
10627c478bd9Sstevel@tonic-gate 		case WRITE_PROTECT_MODE:
10637c478bd9Sstevel@tonic-gate 			status = SM_WRITE_PROTECT_NOPASSWD;
10647c478bd9Sstevel@tonic-gate 			break;
10657c478bd9Sstevel@tonic-gate 		case PASSWD_WRITE_PROTECT_MODE:
10667c478bd9Sstevel@tonic-gate 			status = SM_WRITE_PROTECT_PASSWD;
10677c478bd9Sstevel@tonic-gate 			break;
10687c478bd9Sstevel@tonic-gate 		case READ_WRITE_PROTECT_MODE:
10697c478bd9Sstevel@tonic-gate 			status = SM_READ_WRITE_PROTECT;
10707c478bd9Sstevel@tonic-gate 			break;
10717c478bd9Sstevel@tonic-gate 		default :
10727c478bd9Sstevel@tonic-gate 			if (mode & TEMP_UNLOCK_MODE)
10737c478bd9Sstevel@tonic-gate 				status = SM_TEMP_UNLOCK_MODE;
10747c478bd9Sstevel@tonic-gate 			else
10757c478bd9Sstevel@tonic-gate 				status = SM_STATUS_UNKNOWN;
10767c478bd9Sstevel@tonic-gate 			break;
10777c478bd9Sstevel@tonic-gate 	}
10787c478bd9Sstevel@tonic-gate 
10797c478bd9Sstevel@tonic-gate 	debug(5, "status %d \n", status);
10807c478bd9Sstevel@tonic-gate 	return (status);
10817c478bd9Sstevel@tonic-gate }
10827c478bd9Sstevel@tonic-gate 
1083*5363f09cSarutz static int32_t
10847c478bd9Sstevel@tonic-gate scsi_reassign_block(int32_t fd, diskaddr_t block)
10857c478bd9Sstevel@tonic-gate {
10867c478bd9Sstevel@tonic-gate 	uchar_t data[8];
10877c478bd9Sstevel@tonic-gate 	struct uscsi_cmd ucmd;
10887c478bd9Sstevel@tonic-gate 	char cdb[12];
10897c478bd9Sstevel@tonic-gate 	int32_t	ret_val;
10907c478bd9Sstevel@tonic-gate 	char rq_data[RQ_LEN];
10917c478bd9Sstevel@tonic-gate 
10927c478bd9Sstevel@tonic-gate 	debug(5, "SCSI REASSIGN CALLED block = %lld\n", block);
10937c478bd9Sstevel@tonic-gate 
10947c478bd9Sstevel@tonic-gate 	(void) memset((void *) &data, 0, sizeof (data));
10957c478bd9Sstevel@tonic-gate 	(void) memset((void *) &ucmd, 0, sizeof (ucmd));
10967c478bd9Sstevel@tonic-gate 	(void) memset((void *) &cdb, 0, sizeof (cdb));
10977c478bd9Sstevel@tonic-gate 	cdb[0] = SCMD_REASSIGN_BLOCK;
10987c478bd9Sstevel@tonic-gate 	data[3] = 4;
10997c478bd9Sstevel@tonic-gate 	data[4] = ((block & 0xFF000000) >> 24);
11007c478bd9Sstevel@tonic-gate 	data[5] = ((block & 0xFF0000) >> 16);
11017c478bd9Sstevel@tonic-gate 	data[6] = ((block & 0xFF00) >> 8);
11027c478bd9Sstevel@tonic-gate 	data[7] = block & 0xFF;
11037c478bd9Sstevel@tonic-gate 
11047c478bd9Sstevel@tonic-gate 	ucmd.uscsi_cdb = (caddr_t)&cdb;
11057c478bd9Sstevel@tonic-gate 	ucmd.uscsi_cdblen = CDB_GROUP0;
11067c478bd9Sstevel@tonic-gate 	ucmd.uscsi_bufaddr = (caddr_t)data;
11077c478bd9Sstevel@tonic-gate 	ucmd.uscsi_buflen = sizeof (data);
11087c478bd9Sstevel@tonic-gate 	ucmd.uscsi_timeout = 120;	/* If 0, HBA hangs forever */
11097c478bd9Sstevel@tonic-gate 	ucmd.uscsi_rqlen = RQ_LEN;
11107c478bd9Sstevel@tonic-gate 	ucmd.uscsi_rqbuf = rq_data;
11117c478bd9Sstevel@tonic-gate 	ret_val = do_uscsi_cmd(fd, &ucmd, USCSI_WRITE|USCSI_RQENABLE);
11127c478bd9Sstevel@tonic-gate 	if (ret_val || ucmd.uscsi_status) {
11137c478bd9Sstevel@tonic-gate 		debug(5, "Reassign block failed: %d - %d errno = %d\n",
11147c478bd9Sstevel@tonic-gate 			ret_val, ucmd.uscsi_status, errno);
11157c478bd9Sstevel@tonic-gate 		return (-1);
11167c478bd9Sstevel@tonic-gate 	}
11177c478bd9Sstevel@tonic-gate 
11187c478bd9Sstevel@tonic-gate 	return (0);
11197c478bd9Sstevel@tonic-gate }
11207c478bd9Sstevel@tonic-gate 
1121*5363f09cSarutz static int32_t
11227c478bd9Sstevel@tonic-gate get_mode_page(int32_t fd, uchar_t pc, uchar_t page_code,
11237c478bd9Sstevel@tonic-gate     uchar_t *md_data, uchar_t data_len)
11247c478bd9Sstevel@tonic-gate {
11257c478bd9Sstevel@tonic-gate 	struct uscsi_cmd ucmd;
11267c478bd9Sstevel@tonic-gate 	uchar_t cdb[12];
11277c478bd9Sstevel@tonic-gate 	int32_t	ret_val;
11287c478bd9Sstevel@tonic-gate 	char rq_data[RQ_LEN];
11297c478bd9Sstevel@tonic-gate 
1130*5363f09cSarutz 	debug(10, "MODE SENSE(6) - page_code = 0x%x\n", page_code);
11317c478bd9Sstevel@tonic-gate 
11327c478bd9Sstevel@tonic-gate 	(void) memset((void *) md_data, 0, sizeof (data_len));
11337c478bd9Sstevel@tonic-gate 	(void) memset((void *) &ucmd, 0, sizeof (ucmd));
11347c478bd9Sstevel@tonic-gate 	(void) memset((void *) &cdb, 0, sizeof (cdb));
11357c478bd9Sstevel@tonic-gate 	cdb[0] = SCMD_MODE_SENSE;
11367c478bd9Sstevel@tonic-gate 	cdb[2] = (pc << 6) | page_code;
11377c478bd9Sstevel@tonic-gate 	cdb[4] = data_len;
11387c478bd9Sstevel@tonic-gate 
11397c478bd9Sstevel@tonic-gate 	ucmd.uscsi_cdb = (caddr_t)&cdb;
11407c478bd9Sstevel@tonic-gate 	ucmd.uscsi_cdblen = CDB_GROUP0;
11417c478bd9Sstevel@tonic-gate 	ucmd.uscsi_bufaddr = (caddr_t)md_data;
11427c478bd9Sstevel@tonic-gate 	ucmd.uscsi_buflen = data_len;
11437c478bd9Sstevel@tonic-gate 	ucmd.uscsi_timeout = 120;	/* If 0, HBA hangs forever */
11447c478bd9Sstevel@tonic-gate 	ucmd.uscsi_rqlen = RQ_LEN;
11457c478bd9Sstevel@tonic-gate 	ucmd.uscsi_rqbuf = rq_data;
11467c478bd9Sstevel@tonic-gate 	ret_val = do_uscsi_cmd(fd, &ucmd, USCSI_READ|USCSI_RQENABLE);
11477c478bd9Sstevel@tonic-gate 	if (ret_val || ucmd.uscsi_status) {
11487c478bd9Sstevel@tonic-gate 		debug(5, "Modesense failed: %d - %d errno = %d\n",
11497c478bd9Sstevel@tonic-gate 			ret_val, ucmd.uscsi_status, errno);
11507c478bd9Sstevel@tonic-gate 		return (-2);
11517c478bd9Sstevel@tonic-gate 	}
11527c478bd9Sstevel@tonic-gate 
11537c478bd9Sstevel@tonic-gate 	return (0);
11547c478bd9Sstevel@tonic-gate }
11557c478bd9Sstevel@tonic-gate 
11567c478bd9Sstevel@tonic-gate static int32_t
11577c478bd9Sstevel@tonic-gate scsi_zip_write_protect(int32_t fd, smwp_state_t *wp)
11587c478bd9Sstevel@tonic-gate {
11597c478bd9Sstevel@tonic-gate 	struct uscsi_cmd ucmd;
11607c478bd9Sstevel@tonic-gate 	struct scsi_inquiry inq;
11617c478bd9Sstevel@tonic-gate 	uchar_t cdb[12];
11627c478bd9Sstevel@tonic-gate 	int32_t	status;
11637c478bd9Sstevel@tonic-gate 	int32_t new_mode;
11647c478bd9Sstevel@tonic-gate 	char rq_data[RQ_LEN];
11657c478bd9Sstevel@tonic-gate 	int32_t wa_bit;
11667c478bd9Sstevel@tonic-gate 	char *tmp_passwd = NULL;
11677c478bd9Sstevel@tonic-gate 
11687c478bd9Sstevel@tonic-gate 	debug(10, "SCSI ZIP WRITE PROTECT CALLED \n");
11697c478bd9Sstevel@tonic-gate 
11707c478bd9Sstevel@tonic-gate 	/*
11717c478bd9Sstevel@tonic-gate 	 * Do an inquiry and try to figure out if it an
11727c478bd9Sstevel@tonic-gate 	 * ATAPI or SCSI device.
11737c478bd9Sstevel@tonic-gate 	 */
11747c478bd9Sstevel@tonic-gate 
11757c478bd9Sstevel@tonic-gate 	(void) memset((void *) &inq, 0, sizeof (inq));
11767c478bd9Sstevel@tonic-gate 	(void) memset((void *) &ucmd, 0, sizeof (ucmd));
11777c478bd9Sstevel@tonic-gate 	(void) memset((void *) &cdb, 0, sizeof (cdb));
11787c478bd9Sstevel@tonic-gate 	(void) memset((void *) &rq_data, 0, sizeof (rq_data));
11797c478bd9Sstevel@tonic-gate 	cdb[0] = SCMD_INQUIRY;
11807c478bd9Sstevel@tonic-gate 	cdb[4] = sizeof (inq);
11817c478bd9Sstevel@tonic-gate 	ucmd.uscsi_cdb = (caddr_t)&cdb;
11827c478bd9Sstevel@tonic-gate 	ucmd.uscsi_cdblen = CDB_GROUP0;
11837c478bd9Sstevel@tonic-gate 	ucmd.uscsi_bufaddr = (caddr_t)&inq;
11847c478bd9Sstevel@tonic-gate 	ucmd.uscsi_buflen = sizeof (inq);
11857c478bd9Sstevel@tonic-gate 	ucmd.uscsi_timeout = 120;	/* If 0, HBA hangs forever */
11867c478bd9Sstevel@tonic-gate 	ucmd.uscsi_rqlen = RQ_LEN;
11877c478bd9Sstevel@tonic-gate 	ucmd.uscsi_rqbuf = rq_data;
11887c478bd9Sstevel@tonic-gate 	status = do_uscsi_cmd(fd, &ucmd, USCSI_READ|USCSI_RQENABLE);
11897c478bd9Sstevel@tonic-gate 	if (status || ucmd.uscsi_status) {
11907c478bd9Sstevel@tonic-gate 		debug(5, "inquiry failed: %d - %d errno = %d\n",
11917c478bd9Sstevel@tonic-gate 			status, ucmd.uscsi_status, errno);
11927c478bd9Sstevel@tonic-gate 		return (-1);
11937c478bd9Sstevel@tonic-gate 	}
11947c478bd9Sstevel@tonic-gate 
11957c478bd9Sstevel@tonic-gate 	if (inq.inq_ansi > 0) {
11967c478bd9Sstevel@tonic-gate 		wa_bit = 0;
11977c478bd9Sstevel@tonic-gate 		debug(5, "SCSI device\n");
11987c478bd9Sstevel@tonic-gate 	} else {
11997c478bd9Sstevel@tonic-gate 		wa_bit = 1;
12007c478bd9Sstevel@tonic-gate 		debug(5, "ATAPI device\n");
12017c478bd9Sstevel@tonic-gate 	}
12027c478bd9Sstevel@tonic-gate 
12037c478bd9Sstevel@tonic-gate 	switch (wp->sm_new_state) {
12047c478bd9Sstevel@tonic-gate 		case SM_WRITE_PROTECT_DISABLE :
12057c478bd9Sstevel@tonic-gate 			new_mode = 0x0;
12067c478bd9Sstevel@tonic-gate 			break;
12077c478bd9Sstevel@tonic-gate 		case SM_WRITE_PROTECT_NOPASSWD :
12087c478bd9Sstevel@tonic-gate 			new_mode = 0x2;
12097c478bd9Sstevel@tonic-gate 			break;
12107c478bd9Sstevel@tonic-gate 		case SM_WRITE_PROTECT_PASSWD :
12117c478bd9Sstevel@tonic-gate 			new_mode = 0x3;
12127c478bd9Sstevel@tonic-gate 			break;
12137c478bd9Sstevel@tonic-gate 		case SM_READ_WRITE_PROTECT :
12147c478bd9Sstevel@tonic-gate 			new_mode = 0x5;
12157c478bd9Sstevel@tonic-gate 			break;
12167c478bd9Sstevel@tonic-gate 		case SM_TEMP_UNLOCK_MODE :
12177c478bd9Sstevel@tonic-gate 			new_mode = 0x8;
12187c478bd9Sstevel@tonic-gate 			break;
12197c478bd9Sstevel@tonic-gate 		default :
12207c478bd9Sstevel@tonic-gate 			debug(1, "Invalid mode 0x%x specified\n",
12217c478bd9Sstevel@tonic-gate 			wp->sm_new_state);
12227c478bd9Sstevel@tonic-gate 			errno = ENOTSUP;
12237c478bd9Sstevel@tonic-gate 			return (-1);
12247c478bd9Sstevel@tonic-gate 	}
12257c478bd9Sstevel@tonic-gate 
12267c478bd9Sstevel@tonic-gate 
12277c478bd9Sstevel@tonic-gate 	(void) memset((void *)&ucmd, 0, sizeof (ucmd));
12287c478bd9Sstevel@tonic-gate 	(void) memset((void *)&cdb, 0, sizeof (cdb));
12297c478bd9Sstevel@tonic-gate 	(void) memset((void *) &rq_data, 0, sizeof (rq_data));
12307c478bd9Sstevel@tonic-gate 	cdb[0] = IOMEGA_CATRIDGE_PROTECT;
12317c478bd9Sstevel@tonic-gate 	cdb[1] |= new_mode;
12327c478bd9Sstevel@tonic-gate 	if (wa_bit)
12337c478bd9Sstevel@tonic-gate 		cdb[1] |= WA_BIT;
12347c478bd9Sstevel@tonic-gate 	cdb[4] = wp->sm_passwd_len;
12357c478bd9Sstevel@tonic-gate 	ucmd.uscsi_cdb = (caddr_t)&cdb;
12367c478bd9Sstevel@tonic-gate 	ucmd.uscsi_cdblen = CDB_GROUP0;
12377c478bd9Sstevel@tonic-gate 	if (wa_bit && (wp->sm_passwd_len & 1)) {
12387c478bd9Sstevel@tonic-gate 		/*
12397c478bd9Sstevel@tonic-gate 		 * Oops, ATAPI device with an odd length passwd!
12407c478bd9Sstevel@tonic-gate 		 * Allocate a buffer to hold one extra byte.
12417c478bd9Sstevel@tonic-gate 		 */
12427c478bd9Sstevel@tonic-gate 		debug(5, "Odd len passwd for ATAPI device!\n");
12437c478bd9Sstevel@tonic-gate 		errno = 0;
12447c478bd9Sstevel@tonic-gate 		tmp_passwd = (char *)malloc(wp->sm_passwd_len+1);
12457c478bd9Sstevel@tonic-gate 		if (tmp_passwd == NULL) {
12467c478bd9Sstevel@tonic-gate 			if (errno == 0)
12477c478bd9Sstevel@tonic-gate 				errno = ENOMEM;
12487c478bd9Sstevel@tonic-gate 			return (-1);
12497c478bd9Sstevel@tonic-gate 		}
12507c478bd9Sstevel@tonic-gate 		(void) memset(tmp_passwd, 0, wp->sm_passwd_len+1);
12517c478bd9Sstevel@tonic-gate 		(void) memcpy(tmp_passwd, wp->sm_passwd, wp->sm_passwd_len);
12527c478bd9Sstevel@tonic-gate 		ucmd.uscsi_bufaddr = (caddr_t)tmp_passwd;
12537c478bd9Sstevel@tonic-gate 		ucmd.uscsi_buflen = wp->sm_passwd_len+1;
12547c478bd9Sstevel@tonic-gate 	} else {
12557c478bd9Sstevel@tonic-gate 		ucmd.uscsi_bufaddr = (caddr_t)wp->sm_passwd;
12567c478bd9Sstevel@tonic-gate 		ucmd.uscsi_buflen = wp->sm_passwd_len;
12577c478bd9Sstevel@tonic-gate 	}
12587c478bd9Sstevel@tonic-gate 	ucmd.uscsi_timeout = 120;	/* If 0, HBA hangs forever */
12597c478bd9Sstevel@tonic-gate 	ucmd.uscsi_rqlen = RQ_LEN;
12607c478bd9Sstevel@tonic-gate 	ucmd.uscsi_rqbuf = rq_data;
12617c478bd9Sstevel@tonic-gate 	status = do_uscsi_cmd(fd, &ucmd, USCSI_WRITE|USCSI_RQENABLE);
12627c478bd9Sstevel@tonic-gate 	if (tmp_passwd != NULL) {
12637c478bd9Sstevel@tonic-gate 		free(tmp_passwd);
12647c478bd9Sstevel@tonic-gate 	}
12657c478bd9Sstevel@tonic-gate 	if (status || ucmd.uscsi_status) {
1266*5363f09cSarutz 		debug(5, "Cartridge-protect operation failed: rv "
1267*5363f09cSarutz 		    "= %d  uscsi_status = %d  errno = %d\n", status,
1268*5363f09cSarutz 		    ucmd.uscsi_status, errno);
12697c478bd9Sstevel@tonic-gate 		if ((rq_data[2] & 0xF) == KEY_ILLEGAL_REQUEST) {
12707c478bd9Sstevel@tonic-gate 			if (rq_data[12] == 0x26) {
12717c478bd9Sstevel@tonic-gate 				/* Wrong passwd */
1272*5363f09cSarutz 				debug(5, "Protection Request with wrong "
1273*5363f09cSarutz 				    "passwd. errno is being set to EACCES.\n");
12747c478bd9Sstevel@tonic-gate 				errno = EACCES;
12757c478bd9Sstevel@tonic-gate 			}
12767c478bd9Sstevel@tonic-gate 		}
12777c478bd9Sstevel@tonic-gate 		return (-1);
12787c478bd9Sstevel@tonic-gate 	}
12797c478bd9Sstevel@tonic-gate 
12807c478bd9Sstevel@tonic-gate 	return (0);
12817c478bd9Sstevel@tonic-gate }
12827c478bd9Sstevel@tonic-gate 
12837c478bd9Sstevel@tonic-gate /*ARGSUSED*/
12847c478bd9Sstevel@tonic-gate static int32_t
12857c478bd9Sstevel@tonic-gate scsi_write_protect(int32_t fd, smwp_state_t *wp)
12867c478bd9Sstevel@tonic-gate {
12877c478bd9Sstevel@tonic-gate 	errno = ENOTSUP;
12887c478bd9Sstevel@tonic-gate 	return (-1);
12897c478bd9Sstevel@tonic-gate }
12907c478bd9Sstevel@tonic-gate 
1291*5363f09cSarutz /*
1292*5363f09cSarutz  * This thread becomes the server-side thread used in
1293*5363f09cSarutz  * the implementation of a door_call between a client
1294*5363f09cSarutz  * and the Client Door.
1295*5363f09cSarutz  *
1296*5363f09cSarutz  * This thread is customized both by the door_server_create(3c)
1297*5363f09cSarutz  * function sm_door_server_create, as well as by itself.
1298*5363f09cSarutz  *
1299*5363f09cSarutz  * This thread needs to synchronize with the
1300*5363f09cSarutz  * main_servproc[SMEDIA_CNUM_OPEN_FD] door_call in terms of
1301*5363f09cSarutz  * both successful and failure scenarios.  main_servproc
1302*5363f09cSarutz  * locks dd_lock before calling door_create.  This thread
1303*5363f09cSarutz  * then attempts to lock, but will block until main_servproc
1304*5363f09cSarutz  * has either created all doors it requires, or until a
1305*5363f09cSarutz  * door_create has failed (door_create's return and the
1306*5363f09cSarutz  * creation of an associated thread are asynchronous).
1307*5363f09cSarutz  *
1308*5363f09cSarutz  * If door_create failed, this thread will be able to obtain
1309*5363f09cSarutz  * dd_lock and call pthread_exit.  If all door_create's succeed,
1310*5363f09cSarutz  * this thread will obtain dd_lock and commence with
1311*5363f09cSarutz  * customizing the thread's attributes.  door_bind is called to
1312*5363f09cSarutz  * bind this thread to the per-door private thread pool, and
1313*5363f09cSarutz  * main_servproc is cond_signal'd to avail it of this fact.
1314*5363f09cSarutz  *
1315*5363f09cSarutz  * Finally, this thread calls door_return, which causes it to
1316*5363f09cSarutz  * commence its lifetime as a server-side thread in implementation
1317*5363f09cSarutz  * of a Client Door door_call.
1318*5363f09cSarutz  */
13197c478bd9Sstevel@tonic-gate static void *
1320*5363f09cSarutz sm_server_thread(void *arg)
13217c478bd9Sstevel@tonic-gate {
13227c478bd9Sstevel@tonic-gate 	door_data_t	*door_dp;
13237c478bd9Sstevel@tonic-gate 	struct		sigaction act;
1324*5363f09cSarutz 	int		i;
1325*5363f09cSarutz 	int		err;
13267c478bd9Sstevel@tonic-gate 
13277c478bd9Sstevel@tonic-gate 	door_dp = (door_data_t *)arg;
13287c478bd9Sstevel@tonic-gate 
13297c478bd9Sstevel@tonic-gate 	if (door_dp == NULL) {
1330*5363f09cSarutz 		fatal("sm_server_thread[%d]: argument is NULL!!\n",
13317c478bd9Sstevel@tonic-gate 		    pthread_self());
13327c478bd9Sstevel@tonic-gate 		exit(-1);
13337c478bd9Sstevel@tonic-gate 	}
13347c478bd9Sstevel@tonic-gate 
1335*5363f09cSarutz 	/* Wait for Client Door to be created */
13367c478bd9Sstevel@tonic-gate 	(void) mutex_lock(&door_dp->dd_lock);
1337*5363f09cSarutz 	if (door_dp->dd_cdoor_descriptor < 0) {
1338*5363f09cSarutz 		debug(5, "sm_server_thread[%d]: door_create() failed",
1339*5363f09cSarutz 		    pthread_self());
1340*5363f09cSarutz 		(void) mutex_unlock(&door_dp->dd_lock);
1341*5363f09cSarutz 		pthread_exit((void *)-2);
1342*5363f09cSarutz 	}
13437c478bd9Sstevel@tonic-gate 	(void) mutex_unlock(&door_dp->dd_lock);
13447c478bd9Sstevel@tonic-gate 
13457c478bd9Sstevel@tonic-gate 	for (i = 0; i < N_BADSIGS; i++) {
13467c478bd9Sstevel@tonic-gate 		act.sa_sigaction = server_badsig_handler;
13477c478bd9Sstevel@tonic-gate 		(void) sigemptyset(&act.sa_mask);
13487c478bd9Sstevel@tonic-gate 		act.sa_flags = SA_SIGINFO;
13497c478bd9Sstevel@tonic-gate 		if (sigaction(badsigs[i], &act, NULL) == -1)
13507c478bd9Sstevel@tonic-gate 			warning(gettext(SIGACT_FAILED), strsignal(badsigs[i]),
13517c478bd9Sstevel@tonic-gate 			    strerror(errno));
13527c478bd9Sstevel@tonic-gate 	}
13537c478bd9Sstevel@tonic-gate 	if (sigemptyset(&door_dp->dd_newset) != 0)
13547c478bd9Sstevel@tonic-gate 		warning(gettext("sigemptyset failed. errno = %d\n"),
13557c478bd9Sstevel@tonic-gate 		    errno);
1356*5363f09cSarutz 	if ((err = pthread_sigmask(SIG_BLOCK, &door_dp->dd_newset, NULL)) != 0)
1357*5363f09cSarutz 		warning(gettext("pthread_sigmask failed = %d\n"), err);
13587c478bd9Sstevel@tonic-gate 
1359*5363f09cSarutz 	/* Bind thread with pool associated with Client Door */
13607c478bd9Sstevel@tonic-gate 
1361*5363f09cSarutz 	if (door_bind(door_dp->dd_cdoor_descriptor) < 0) {
13627c478bd9Sstevel@tonic-gate 		fatal("door_bind");
13637c478bd9Sstevel@tonic-gate 		exit(-1);
13647c478bd9Sstevel@tonic-gate 	}
1365*5363f09cSarutz 	debug(5, "thr[%d] bound to Client Door[%d]", pthread_self(),
1366*5363f09cSarutz 	    door_dp->dd_cdoor_descriptor);
1367*5363f09cSarutz 
13687c478bd9Sstevel@tonic-gate 	/*
1369*5363f09cSarutz 	 * Set these two cancellation(5) attributes.  Ensure that the
1370*5363f09cSarutz 	 * pthread we create has cancellation(5) DISABLED and DEFERRED,
1371*5363f09cSarutz 	 * as our implementation is based on this.  DEFERRED is the
1372*5363f09cSarutz 	 * default, but set it anyways, in case the defaults change in
1373*5363f09cSarutz 	 * the future.
13747c478bd9Sstevel@tonic-gate 	 */
1375*5363f09cSarutz 	if ((err = pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL)) != 0)
1376*5363f09cSarutz 		warning(gettext("pthread_setcancelstate(PTHREAD_CANCEL_DISABLE)"
1377*5363f09cSarutz 		    " failed = %d\n"), err);
1378*5363f09cSarutz 	if ((err = pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED,
1379*5363f09cSarutz 	    NULL)) != 0)
1380*5363f09cSarutz 		warning(gettext("pthread_setcanceltype(DEFERRED) "
1381*5363f09cSarutz 		    "failed = %d\n"), err);
1382*5363f09cSarutz 
1383*5363f09cSarutz 	/* Inform main_servproc that door_bind() is complete. */
13847c478bd9Sstevel@tonic-gate 	(void) cond_signal(&door_dp->dd_cv_bind);
1385*5363f09cSarutz 
1386*5363f09cSarutz 	/*
1387*5363f09cSarutz 	 * Per doors protocol, transfer control to the doors-runtime in
1388*5363f09cSarutz 	 * order to make this thread available to answer future door_call()'s.
1389*5363f09cSarutz 	 */
13907c478bd9Sstevel@tonic-gate 	(void) door_return(NULL, 0, NULL, 0);
13917c478bd9Sstevel@tonic-gate 	return (NULL);
13927c478bd9Sstevel@tonic-gate }
13937c478bd9Sstevel@tonic-gate 
1394*5363f09cSarutz /*
1395*5363f09cSarutz  * This function cleans up all per-connection resources.
1396*5363f09cSarutz  *
1397*5363f09cSarutz  * This function is called when the Client Door's service procedure
1398*5363f09cSarutz  * (client_servproc) is called w/ DOOR_UNREF_DATA, which is the
1399*5363f09cSarutz  * doors protocol convention stating that the number of file
1400*5363f09cSarutz  * descriptors referring to this door has dropped to one.
1401*5363f09cSarutz  * client_servproc is passed DOOR_UNREF_DATA because the Client Door
1402*5363f09cSarutz  * was door_create'd with the DOOR_UNREF bitflag.
1403*5363f09cSarutz  */
14047c478bd9Sstevel@tonic-gate static void
14057c478bd9Sstevel@tonic-gate cleanup(door_data_t *door_dp)
14067c478bd9Sstevel@tonic-gate {
1407*5363f09cSarutz 	/* do door_revoke() of Death Door */
1408*5363f09cSarutz 	if (door_dp->dd_ddoor_descriptor >= 0) {
1409*5363f09cSarutz 		debug(1, "cleanup[%d]: door_revoke() Death Door[%d]",
1410*5363f09cSarutz 		    pthread_self(), door_dp->dd_ddoor_descriptor);
14117c478bd9Sstevel@tonic-gate 
1412*5363f09cSarutz 		if (door_revoke(door_dp->dd_ddoor_descriptor) < 0) {
1413*5363f09cSarutz 			warning(gettext("cleanup[%d]: door_revoke() of Death "
1414*5363f09cSarutz 			    "Door(%d) failed = %d"), pthread_self(),
1415*5363f09cSarutz 			    door_dp->dd_ddoor_descriptor, errno);
1416*5363f09cSarutz 		} else {
1417*5363f09cSarutz 			door_dp->dd_ddoor_descriptor = -1;
14187c478bd9Sstevel@tonic-gate 		}
1419*5363f09cSarutz 	}
1420*5363f09cSarutz 
1421*5363f09cSarutz 	/* release memory that is shared between client and (our) server */
1422*5363f09cSarutz 	if (door_dp->dd_buffd >= 0) {
1423*5363f09cSarutz 		debug(1, "cleanup[%d]: release shared memory", pthread_self());
14247c478bd9Sstevel@tonic-gate 		(void) munmap(door_dp->dd_buf, door_dp->dd_buf_len);
14257c478bd9Sstevel@tonic-gate 		(void) close(door_dp->dd_buffd);
1426*5363f09cSarutz 
1427*5363f09cSarutz 		door_dp->dd_buffd = -1;
14287c478bd9Sstevel@tonic-gate 		door_dp->dd_buf = NULL;
14297c478bd9Sstevel@tonic-gate 		door_dp->dd_buf_len = 0;
14307c478bd9Sstevel@tonic-gate 	}
14317c478bd9Sstevel@tonic-gate 
1432*5363f09cSarutz 	/* close the (target) device that the Client is operating on */
1433*5363f09cSarutz 	if (door_dp->dd_fd >= 0) {
1434*5363f09cSarutz 		debug(1, "cleanup[%d]: close(%d) target device", pthread_self(),
1435*5363f09cSarutz 		    door_dp->dd_fd);
14367c478bd9Sstevel@tonic-gate 		if (close(door_dp->dd_fd) < 0) {
1437*5363f09cSarutz 			warning(gettext("cleanup[%d]: close() of target device"
1438*5363f09cSarutz 			    "failed = %d\n"), pthread_self(), errno);
14397c478bd9Sstevel@tonic-gate 		}
14407c478bd9Sstevel@tonic-gate 	}
14417c478bd9Sstevel@tonic-gate 
1442*5363f09cSarutz 	/*
1443*5363f09cSarutz 	 * Unbind the current thread from the Client Door's private
1444*5363f09cSarutz 	 * thread pool.
1445*5363f09cSarutz 	 */
1446*5363f09cSarutz 	debug(1, "cleanup[%d]: door_unbind() of Client Door[%d]",
1447*5363f09cSarutz 	    pthread_self(), door_dp->dd_cdoor_descriptor);
1448*5363f09cSarutz 	if (door_unbind() < 0)
1449*5363f09cSarutz 		warning("door_unbind() of Client Door[%d] failed = "
1450*5363f09cSarutz 		    "%d", door_dp->dd_cdoor_descriptor, errno);
1451*5363f09cSarutz 
1452*5363f09cSarutz 	/* Disallow any future requests to the Client Door */
1453*5363f09cSarutz 	if (door_dp->dd_cdoor_descriptor >= 0) {
1454*5363f09cSarutz 		debug(1, "cleanup[%d]: door_revoke() Client Door[%d]",
1455*5363f09cSarutz 		    pthread_self(), door_dp->dd_cdoor_descriptor);
1456*5363f09cSarutz 
1457*5363f09cSarutz 		if (door_revoke(door_dp->dd_cdoor_descriptor) < 0) {
1458*5363f09cSarutz 			warning(gettext("cleanup[%d]: door_revoke() of "
1459*5363f09cSarutz 			    "Client Door[%d] failed = %d"), pthread_self(),
1460*5363f09cSarutz 			    door_dp->dd_cdoor_descriptor, errno);
1461*5363f09cSarutz 		}
1462*5363f09cSarutz 	}
1463*5363f09cSarutz 
1464*5363f09cSarutz 	free(door_dp);
1465*5363f09cSarutz 	debug(5, "cleanup[%d] ...exiting\n", pthread_self());
1466*5363f09cSarutz }
1467*5363f09cSarutz 
1468*5363f09cSarutz /*
1469*5363f09cSarutz  * This is the door_server_create(3c) function used to customize
1470*5363f09cSarutz  * creation of the threads used in the handling of our daemon's
1471*5363f09cSarutz  * door_call(3c)'s.
1472*5363f09cSarutz  *
1473*5363f09cSarutz  * This function is called synchronously as part of door_create(3c).
1474*5363f09cSarutz  * Note that door_create(), however, is not synchronous; it can return
1475*5363f09cSarutz  * with the created door file descriptor before any associated
1476*5363f09cSarutz  * thread has been created.  As a result, synchronization is needed
1477*5363f09cSarutz  * between door_create() caller and the created pthread.  This is
1478*5363f09cSarutz  * needed both when each activity succeeds or when either activity
1479*5363f09cSarutz  * fails.
1480*5363f09cSarutz  *
1481*5363f09cSarutz  * Specifically, this function ensures that each "connection"
1482*5363f09cSarutz  * with the client creates only one thread in the per-door,
1483*5363f09cSarutz  * private thread pool.  This function locks dd_threadlock and
1484*5363f09cSarutz  * then calls pthread_create().  If that succeeds, dd_thread
1485*5363f09cSarutz  * is assigned the thread id, and dd_threadlock is unlocked.
1486*5363f09cSarutz  * Any per-connection door_create that causes control to flow
1487*5363f09cSarutz  * to this function will eventually find that dd_thread is
1488*5363f09cSarutz  * non-zero, and control will exit this function.
1489*5363f09cSarutz  *
1490*5363f09cSarutz  * In the current implementation, the door_create for the Client Door
1491*5363f09cSarutz  * is called first, and the Death Door is door_create'd second.
1492*5363f09cSarutz  * As a result, the following function can safely make the static
1493*5363f09cSarutz  * assumption that the first door (within a connection) is the
1494*5363f09cSarutz  * Client Door.  A connection's Client Door and Death Door share
1495*5363f09cSarutz  * the same thread as well as the same door_data_t instance.
1496*5363f09cSarutz  */
14977c478bd9Sstevel@tonic-gate static void
1498*5363f09cSarutz sm_door_server_create(door_info_t *dip)
14997c478bd9Sstevel@tonic-gate {
15007c478bd9Sstevel@tonic-gate 	door_data_t	*door_dp;
15017c478bd9Sstevel@tonic-gate 	pthread_t	tid;
15027c478bd9Sstevel@tonic-gate 	pthread_attr_t	attr;
15037c478bd9Sstevel@tonic-gate 	int		ret_val;
1504*5363f09cSarutz 	int		err;
15057c478bd9Sstevel@tonic-gate 
15067c478bd9Sstevel@tonic-gate 	if (dip == NULL) {
15077c478bd9Sstevel@tonic-gate 		return;
15087c478bd9Sstevel@tonic-gate 	}
1509360e6f5eSmathue 	door_dp = (door_data_t *)(uintptr_t)dip->di_data;
15107c478bd9Sstevel@tonic-gate 
1511*5363f09cSarutz 	debug(10, "sm_door_server_create[%d]: entering...\n", pthread_self());
15127c478bd9Sstevel@tonic-gate 
15137c478bd9Sstevel@tonic-gate 	/* create one thread for this door */
15147c478bd9Sstevel@tonic-gate 
15157c478bd9Sstevel@tonic-gate 	(void) mutex_lock(&door_dp->dd_threadlock);
15167c478bd9Sstevel@tonic-gate 
15177c478bd9Sstevel@tonic-gate 	if (door_dp->dd_thread != 0) {
1518*5363f09cSarutz 		debug(8, "sm_door_server_create[%d]: Exiting without creating "
1519*5363f09cSarutz 		    "thread.\n", pthread_self());
15207c478bd9Sstevel@tonic-gate 		(void) mutex_unlock(&door_dp->dd_threadlock);
15217c478bd9Sstevel@tonic-gate 		return;
15227c478bd9Sstevel@tonic-gate 	}
15237c478bd9Sstevel@tonic-gate 
15247c478bd9Sstevel@tonic-gate 	(void) pthread_attr_init(&attr);
15257c478bd9Sstevel@tonic-gate 
1526*5363f09cSarutz 	if ((err = pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM)) != 0)
1527*5363f09cSarutz 		warning(gettext("pthread_attr_setscope failed = %d\n"), err);
1528*5363f09cSarutz 	if ((err = pthread_attr_setdetachstate(&attr,
1529*5363f09cSarutz 	    PTHREAD_CREATE_DETACHED)) != 0)
1530*5363f09cSarutz 		warning(gettext("pthread_attr_setdetachstate failed = %d\n"),
1531*5363f09cSarutz 		    err);
1532*5363f09cSarutz 
1533*5363f09cSarutz 	ret_val = pthread_create(&tid, &attr, sm_server_thread,
1534*5363f09cSarutz 	    (void *)(uintptr_t)(dip->di_data));
15357c478bd9Sstevel@tonic-gate 	if (ret_val != 0) {
1536*5363f09cSarutz 		warning(gettext("sm_door_server_create[%d]: pthread_create "
1537*5363f09cSarutz 		    "failed = %d\n"), pthread_self(), ret_val);
15387c478bd9Sstevel@tonic-gate 		(void) mutex_unlock(&door_dp->dd_threadlock);
15397c478bd9Sstevel@tonic-gate 		(void) pthread_attr_destroy(&attr);
15407c478bd9Sstevel@tonic-gate 		return;
15417c478bd9Sstevel@tonic-gate 	}
15427c478bd9Sstevel@tonic-gate 	(void) pthread_attr_destroy(&attr);
15437c478bd9Sstevel@tonic-gate 	door_dp->dd_thread = tid;
15447c478bd9Sstevel@tonic-gate 
15457c478bd9Sstevel@tonic-gate 	(void) mutex_unlock(&door_dp->dd_threadlock);
1546*5363f09cSarutz 	debug(5, "Exiting sm_door_server_create[%d] after creating thr[%d].\n",
1547*5363f09cSarutz 	    pthread_self(), tid);
15487c478bd9Sstevel@tonic-gate }
15497c478bd9Sstevel@tonic-gate 
15507c478bd9Sstevel@tonic-gate static void
15517c478bd9Sstevel@tonic-gate door_ret_err(smedia_reterror_t *reterror, int32_t err)
15527c478bd9Sstevel@tonic-gate {
15537c478bd9Sstevel@tonic-gate 	reterror->cnum = SMEDIA_CNUM_ERROR;
15547c478bd9Sstevel@tonic-gate 	reterror->errnum = err;
15557c478bd9Sstevel@tonic-gate 	(void) door_return((char *)reterror, sizeof (smedia_reterror_t), 0, 0);
15567c478bd9Sstevel@tonic-gate }
15577c478bd9Sstevel@tonic-gate 
15587c478bd9Sstevel@tonic-gate static void
15597c478bd9Sstevel@tonic-gate my_door_return(char *data_ptr, size_t data_size,
15607c478bd9Sstevel@tonic-gate 	door_desc_t *desc_ptr, uint_t num_desc)
15617c478bd9Sstevel@tonic-gate {
15627c478bd9Sstevel@tonic-gate 	(void) door_return(data_ptr, data_size, desc_ptr, num_desc);
15637c478bd9Sstevel@tonic-gate }
15647c478bd9Sstevel@tonic-gate 
15657c478bd9Sstevel@tonic-gate static int32_t
15667c478bd9Sstevel@tonic-gate raw_read(door_data_t *door_dp, smedia_services_t *req)
15677c478bd9Sstevel@tonic-gate {
15687c478bd9Sstevel@tonic-gate 	struct uscsi_cmd	ucmd;
15697c478bd9Sstevel@tonic-gate 	union scsi_cdb		cdb;
15707c478bd9Sstevel@tonic-gate 	int32_t			ret_val;
15717c478bd9Sstevel@tonic-gate 	int32_t			num_sectors, sector_size;
15727c478bd9Sstevel@tonic-gate 	int32_t			rc_data[2];
15737c478bd9Sstevel@tonic-gate 	char			rq_data[RQ_LEN];
15747c478bd9Sstevel@tonic-gate 
15757c478bd9Sstevel@tonic-gate 	(void) memset((void *) &rc_data, 0, sizeof (rc_data));
15767c478bd9Sstevel@tonic-gate 	(void) memset((void *) &ucmd, 0, sizeof (ucmd));
15777c478bd9Sstevel@tonic-gate 	(void) memset((void *) &cdb, 0, sizeof (union scsi_cdb));
15787c478bd9Sstevel@tonic-gate 
15797c478bd9Sstevel@tonic-gate 	if (door_dp->dd_sector_size == 0) {
15807c478bd9Sstevel@tonic-gate 		sector_size = get_sector_size(door_dp->dd_fd);
15817c478bd9Sstevel@tonic-gate 		door_dp->dd_sector_size = sector_size;
15827c478bd9Sstevel@tonic-gate 	} else sector_size = door_dp->dd_sector_size;
15837c478bd9Sstevel@tonic-gate 
15847c478bd9Sstevel@tonic-gate 	if ((req->reqraw_read.nbytes > door_dp->dd_buf_len) ||
15857c478bd9Sstevel@tonic-gate 		(door_dp->dd_buf == NULL)) {
15867c478bd9Sstevel@tonic-gate 		errno = EINVAL;
15877c478bd9Sstevel@tonic-gate 		return (-1);
15887c478bd9Sstevel@tonic-gate 	}
15897c478bd9Sstevel@tonic-gate 	if ((!req->reqraw_read.nbytes) ||
15907c478bd9Sstevel@tonic-gate 		(req->reqraw_read.nbytes % sector_size)) {
15917c478bd9Sstevel@tonic-gate 		errno = EINVAL;
15927c478bd9Sstevel@tonic-gate 		return (-1);
15937c478bd9Sstevel@tonic-gate 	}
15947c478bd9Sstevel@tonic-gate 
15957c478bd9Sstevel@tonic-gate 	(void) memset((void *) &cdb, 0, sizeof (cdb));
15967c478bd9Sstevel@tonic-gate 	num_sectors = (uint32_t)req->reqraw_read.nbytes/sector_size;
15977c478bd9Sstevel@tonic-gate 
15987c478bd9Sstevel@tonic-gate 	cdb.scc_cmd = SCMD_READ_G1;
15997c478bd9Sstevel@tonic-gate 	FORMG1ADDR(&cdb, (uint32_t)req->reqraw_read.blockno);
16007c478bd9Sstevel@tonic-gate 	FORMG1COUNT(&cdb, num_sectors);
16017c478bd9Sstevel@tonic-gate 
16027c478bd9Sstevel@tonic-gate 	ucmd.uscsi_cdb = (caddr_t)&cdb;
16037c478bd9Sstevel@tonic-gate 	ucmd.uscsi_cdblen = CDB_GROUP1;
16047c478bd9Sstevel@tonic-gate 	ucmd.uscsi_bufaddr = (caddr_t)door_dp->dd_buf;
16057c478bd9Sstevel@tonic-gate 	ucmd.uscsi_buflen = (uint32_t)req->reqraw_read.nbytes;
16067c478bd9Sstevel@tonic-gate 	ucmd.uscsi_timeout = 120;	/* If 0, HBA hangs forever */
16077c478bd9Sstevel@tonic-gate 	ucmd.uscsi_rqlen = RQ_LEN;
16087c478bd9Sstevel@tonic-gate 	ucmd.uscsi_rqbuf = rq_data;
16097c478bd9Sstevel@tonic-gate 	ret_val = do_uscsi_cmd(door_dp->dd_fd,
16107c478bd9Sstevel@tonic-gate 		&ucmd, USCSI_READ|USCSI_RQENABLE);
16117c478bd9Sstevel@tonic-gate 	if (ret_val || ucmd.uscsi_status) {
16127c478bd9Sstevel@tonic-gate 		debug(5, "read failed: %d - %d errno = %d\n",
16137c478bd9Sstevel@tonic-gate 			ret_val, ucmd.uscsi_status, errno);
16147c478bd9Sstevel@tonic-gate 		debug(5, "buflen = 0x%x resid = 0x%x sector size = %d\n",
16157c478bd9Sstevel@tonic-gate 			ucmd.uscsi_buflen, ucmd.uscsi_resid, sector_size);
16167c478bd9Sstevel@tonic-gate 		debug(5, "cdb addr: %x %x %x %x \n", cdb.g1_addr3,
16177c478bd9Sstevel@tonic-gate 			cdb.g1_addr2, cdb.g1_addr1, cdb.g1_addr0);
16187c478bd9Sstevel@tonic-gate 		debug(5, "cdb count: %x %x\n", cdb.g1_count1,
16197c478bd9Sstevel@tonic-gate 			cdb.g1_count0);
16207c478bd9Sstevel@tonic-gate 		return (-1);
16217c478bd9Sstevel@tonic-gate 	}
16227c478bd9Sstevel@tonic-gate 	ret_val = ucmd.uscsi_buflen - ucmd.uscsi_resid;
16237c478bd9Sstevel@tonic-gate 	return (ret_val);
16247c478bd9Sstevel@tonic-gate }
16257c478bd9Sstevel@tonic-gate 
16267c478bd9Sstevel@tonic-gate static int32_t
16277c478bd9Sstevel@tonic-gate raw_write(door_data_t *door_dp, smedia_services_t *req)
16287c478bd9Sstevel@tonic-gate {
16297c478bd9Sstevel@tonic-gate 	struct uscsi_cmd	ucmd;
16307c478bd9Sstevel@tonic-gate 	union scsi_cdb		cdb;
16317c478bd9Sstevel@tonic-gate 	int32_t			ret_val;
16327c478bd9Sstevel@tonic-gate 	int32_t			num_sectors, sector_size;
16337c478bd9Sstevel@tonic-gate 	int32_t			rc_data[2];
16347c478bd9Sstevel@tonic-gate 	char			rq_data[RQ_LEN];
16357c478bd9Sstevel@tonic-gate 
16367c478bd9Sstevel@tonic-gate 	(void) memset((void *) &rc_data, 0, sizeof (rc_data));
16377c478bd9Sstevel@tonic-gate 	(void) memset((void *) &ucmd, 0, sizeof (ucmd));
16387c478bd9Sstevel@tonic-gate 	(void) memset((void *) &cdb, 0, sizeof (union scsi_cdb));
16397c478bd9Sstevel@tonic-gate 
16407c478bd9Sstevel@tonic-gate 	if (door_dp->dd_sector_size == 0) {
16417c478bd9Sstevel@tonic-gate 		sector_size = get_sector_size(door_dp->dd_fd);
16427c478bd9Sstevel@tonic-gate 		door_dp->dd_sector_size = sector_size;
16437c478bd9Sstevel@tonic-gate 	} else sector_size = door_dp->dd_sector_size;
16447c478bd9Sstevel@tonic-gate 
16457c478bd9Sstevel@tonic-gate 
16467c478bd9Sstevel@tonic-gate 	if ((req->reqraw_write.nbytes > door_dp->dd_buf_len) ||
16477c478bd9Sstevel@tonic-gate 		(door_dp->dd_buf == NULL)) {
16487c478bd9Sstevel@tonic-gate 		errno = EINVAL;
16497c478bd9Sstevel@tonic-gate 		return (-1);
16507c478bd9Sstevel@tonic-gate 	}
16517c478bd9Sstevel@tonic-gate 	if ((req->reqraw_write.nbytes % sector_size)) {
16527c478bd9Sstevel@tonic-gate 		errno = EINVAL;
16537c478bd9Sstevel@tonic-gate 		return (-1);
16547c478bd9Sstevel@tonic-gate 	}
16557c478bd9Sstevel@tonic-gate 
16567c478bd9Sstevel@tonic-gate 	(void) memset((void *) &cdb, 0, sizeof (cdb));
16577c478bd9Sstevel@tonic-gate 	num_sectors = (uint32_t)req->reqraw_write.nbytes/sector_size;
16587c478bd9Sstevel@tonic-gate 
16597c478bd9Sstevel@tonic-gate 	cdb.scc_cmd = SCMD_WRITE_G1;
16607c478bd9Sstevel@tonic-gate 	FORMG1ADDR(&cdb, (uint32_t)req->reqraw_write.blockno);
16617c478bd9Sstevel@tonic-gate 	FORMG1COUNT(&cdb, num_sectors);
16627c478bd9Sstevel@tonic-gate 
16637c478bd9Sstevel@tonic-gate 	ucmd.uscsi_cdb = (caddr_t)&cdb;
16647c478bd9Sstevel@tonic-gate 	ucmd.uscsi_cdblen = CDB_GROUP1;
16657c478bd9Sstevel@tonic-gate 	ucmd.uscsi_bufaddr = (caddr_t)door_dp->dd_buf;
16667c478bd9Sstevel@tonic-gate 	ucmd.uscsi_buflen = (uint32_t)req->reqraw_write.nbytes;
16677c478bd9Sstevel@tonic-gate 	ucmd.uscsi_timeout = 120;	/* If 0, HBA hangs forever */
16687c478bd9Sstevel@tonic-gate 	ucmd.uscsi_rqlen = RQ_LEN;
16697c478bd9Sstevel@tonic-gate 	ucmd.uscsi_rqbuf = rq_data;
16707c478bd9Sstevel@tonic-gate 	ret_val = do_uscsi_cmd(door_dp->dd_fd,
16717c478bd9Sstevel@tonic-gate 		&ucmd, USCSI_WRITE|USCSI_RQENABLE);
16727c478bd9Sstevel@tonic-gate 	if (ret_val || ucmd.uscsi_status) {
16737c478bd9Sstevel@tonic-gate 		debug(5, "write failed: %d - %d errno = %d\n",
16747c478bd9Sstevel@tonic-gate 			ret_val, ucmd.uscsi_status, errno);
16757c478bd9Sstevel@tonic-gate 		debug(5, "buflen = 0x%x resid = 0x%x sector size = %d\n",
16767c478bd9Sstevel@tonic-gate 			ucmd.uscsi_buflen, ucmd.uscsi_resid, sector_size);
16777c478bd9Sstevel@tonic-gate 		debug(5, "cdb addr: %x %x %x %x \n", cdb.g1_addr3,
16787c478bd9Sstevel@tonic-gate 			cdb.g1_addr2, cdb.g1_addr1, cdb.g1_addr0);
16797c478bd9Sstevel@tonic-gate 		debug(5, "cdb count: %x %x\n", cdb.g1_count1,
16807c478bd9Sstevel@tonic-gate 			cdb.g1_count0);
16817c478bd9Sstevel@tonic-gate 		return (-1);
16827c478bd9Sstevel@tonic-gate 	}
16837c478bd9Sstevel@tonic-gate 	ret_val = ucmd.uscsi_buflen - ucmd.uscsi_resid;
16847c478bd9Sstevel@tonic-gate 	return (ret_val);
16857c478bd9Sstevel@tonic-gate }
16867c478bd9Sstevel@tonic-gate 
16877c478bd9Sstevel@tonic-gate static int32_t
16887c478bd9Sstevel@tonic-gate set_protection_status(door_data_t *door_dp, smedia_services_t *req)
16897c478bd9Sstevel@tonic-gate {
16907c478bd9Sstevel@tonic-gate 	int32_t			ret_val, saved_errno, status;
16917c478bd9Sstevel@tonic-gate 	struct scsi_inquiry	inq;
16927c478bd9Sstevel@tonic-gate 	char			vid[9];
16937c478bd9Sstevel@tonic-gate 	char			pid[17];
16947c478bd9Sstevel@tonic-gate 	struct passwd		*pwd;
16957c478bd9Sstevel@tonic-gate 	char			uname[MAXUGNAME + 1];
16967c478bd9Sstevel@tonic-gate 	char			*new_state, *old_state;
16977c478bd9Sstevel@tonic-gate 
16987c478bd9Sstevel@tonic-gate 	/*
16997c478bd9Sstevel@tonic-gate 	 * Read the current protection state before modifiying.
17007c478bd9Sstevel@tonic-gate 	 * Needed for audit purposes.
17017c478bd9Sstevel@tonic-gate 	 */
17027c478bd9Sstevel@tonic-gate 	switch (get_device_type_scsi(door_dp->dd_fd, &inq)) {
17037c478bd9Sstevel@tonic-gate 	case SCSI_IOMEGA:
17047c478bd9Sstevel@tonic-gate 		status = scsi_zip_media_status(door_dp->dd_fd);
17057c478bd9Sstevel@tonic-gate 		ret_val = scsi_zip_write_protect(door_dp->dd_fd,
17067c478bd9Sstevel@tonic-gate 			&req->reqset_protection_status.prot_state);
17077c478bd9Sstevel@tonic-gate 		break;
17087c478bd9Sstevel@tonic-gate 	case SCSI_FLOPPY:
17097c478bd9Sstevel@tonic-gate 		info("Formatting floppy");
17107c478bd9Sstevel@tonic-gate 		status = scsi_floppy_media_status(door_dp->dd_fd);
17117c478bd9Sstevel@tonic-gate 		ret_val = scsi_floppy_write_protect(door_dp->dd_fd,
17127c478bd9Sstevel@tonic-gate 			&req->reqset_protection_status.prot_state);
17137c478bd9Sstevel@tonic-gate 		break;
17147c478bd9Sstevel@tonic-gate 	case SCSI_GENERIC:
17157c478bd9Sstevel@tonic-gate 		status = scsi_media_status(door_dp->dd_fd);
17167c478bd9Sstevel@tonic-gate 		ret_val = scsi_write_protect(door_dp->dd_fd,
17177c478bd9Sstevel@tonic-gate 			&req->reqset_protection_status.prot_state);
17187c478bd9Sstevel@tonic-gate 		break;
17197c478bd9Sstevel@tonic-gate 	}
17207c478bd9Sstevel@tonic-gate 
17217c478bd9Sstevel@tonic-gate 	saved_errno = errno;
17227c478bd9Sstevel@tonic-gate 	new_state = xlate_state(
17237c478bd9Sstevel@tonic-gate 	    req->reqset_protection_status.prot_state.sm_new_state);
17247c478bd9Sstevel@tonic-gate 	old_state = xlate_state(status);
17257c478bd9Sstevel@tonic-gate 
17267c478bd9Sstevel@tonic-gate 	if (can_audit()) {
17277c478bd9Sstevel@tonic-gate 		(void) audit_save_me(door_dp);
17287c478bd9Sstevel@tonic-gate 		door_dp->audit_text[0] = 0;
17297c478bd9Sstevel@tonic-gate 		door_dp->audit_text1[0] = 0;
17307c478bd9Sstevel@tonic-gate 		door_dp->audit_event = AUE_smserverd;
17317c478bd9Sstevel@tonic-gate 	}
17327c478bd9Sstevel@tonic-gate 	(void) strlcpy(vid, inq.inq_vid, sizeof (vid));
17337c478bd9Sstevel@tonic-gate 	(void) strlcpy(pid, inq.inq_pid, sizeof (pid));
17347c478bd9Sstevel@tonic-gate 	if (ret_val < 0) {
17357c478bd9Sstevel@tonic-gate 	    if (errno == EACCES) {
17367c478bd9Sstevel@tonic-gate 		pwd = getpwuid(door_dp->dd_cred.dc_ruid);
17377c478bd9Sstevel@tonic-gate 		if (pwd != NULL) {
17387c478bd9Sstevel@tonic-gate 			(void) strlcpy(uname,
17397c478bd9Sstevel@tonic-gate 				pwd->pw_name, MAXUGNAME);
17407c478bd9Sstevel@tonic-gate 		} else uname[0] = 0;
17417c478bd9Sstevel@tonic-gate 
17427c478bd9Sstevel@tonic-gate 		if (can_audit()) {
17437c478bd9Sstevel@tonic-gate 			(void) snprintf(door_dp->audit_text,
17447c478bd9Sstevel@tonic-gate 				sizeof (door_dp->audit_text),
17457c478bd9Sstevel@tonic-gate 				dgettext(TEXT_DOMAIN, "from %s to %s"),
17467c478bd9Sstevel@tonic-gate 				old_state, new_state);
17477c478bd9Sstevel@tonic-gate 
17487c478bd9Sstevel@tonic-gate 			(void) snprintf(door_dp->audit_text1,
17497c478bd9Sstevel@tonic-gate 				sizeof (door_dp->audit_text1),
17507c478bd9Sstevel@tonic-gate 				"%s %s (%d,%d)", vid, pid,
17517c478bd9Sstevel@tonic-gate 				(int)major(door_dp->dd_stat.st_rdev),
17527c478bd9Sstevel@tonic-gate 				(int)minor(door_dp->dd_stat.st_rdev));
17537c478bd9Sstevel@tonic-gate 
17547c478bd9Sstevel@tonic-gate 			door_dp->audit_sorf = 1;
17557c478bd9Sstevel@tonic-gate 			if (audit_audit(door_dp) == -1)
17567c478bd9Sstevel@tonic-gate 			    warning("Error in writing audit info\n");
17577c478bd9Sstevel@tonic-gate 		}
17587c478bd9Sstevel@tonic-gate 	    } /* errno == EACCES */
17597c478bd9Sstevel@tonic-gate 	    errno = saved_errno;
17607c478bd9Sstevel@tonic-gate 	    return (-1);
17617c478bd9Sstevel@tonic-gate 	}
17627c478bd9Sstevel@tonic-gate 	if (can_audit()) {
17637c478bd9Sstevel@tonic-gate 		(void) snprintf(door_dp->audit_text,
17647c478bd9Sstevel@tonic-gate 			sizeof (door_dp->audit_text),
17657c478bd9Sstevel@tonic-gate 			dgettext(TEXT_DOMAIN, "from %s to %s"),
17667c478bd9Sstevel@tonic-gate 			old_state, new_state);
17677c478bd9Sstevel@tonic-gate 
17687c478bd9Sstevel@tonic-gate 		(void) snprintf(door_dp->audit_text1,
17697c478bd9Sstevel@tonic-gate 			sizeof (door_dp->audit_text1),
17707c478bd9Sstevel@tonic-gate 			"%s %s (%d,%d)", vid, pid,
17717c478bd9Sstevel@tonic-gate 			(int)major(door_dp->dd_stat.st_rdev),
17727c478bd9Sstevel@tonic-gate 			(int)minor(door_dp->dd_stat.st_rdev));
17737c478bd9Sstevel@tonic-gate 
17747c478bd9Sstevel@tonic-gate 		door_dp->audit_sorf = 0;
17757c478bd9Sstevel@tonic-gate 		if (audit_audit(door_dp) == -1)
17767c478bd9Sstevel@tonic-gate 		    warning("Error in writing audit info\n");
17777c478bd9Sstevel@tonic-gate 	}
17787c478bd9Sstevel@tonic-gate 	errno = saved_errno;
17797c478bd9Sstevel@tonic-gate 	return (0);
17807c478bd9Sstevel@tonic-gate }
17817c478bd9Sstevel@tonic-gate 
17827c478bd9Sstevel@tonic-gate static int32_t
17837c478bd9Sstevel@tonic-gate set_shfd(door_data_t *door_dp, int32_t fd, smedia_services_t *req)
17847c478bd9Sstevel@tonic-gate {
17857c478bd9Sstevel@tonic-gate 	void	*fbuf;
1786*5363f09cSarutz 	int32_t ret_val = 0;
17877c478bd9Sstevel@tonic-gate 
1788*5363f09cSarutz 	if ((door_dp->dd_buffd != -1) && (door_dp->dd_buf != NULL)) {
1789*5363f09cSarutz 		ret_val = munmap(door_dp->dd_buf, door_dp->dd_buf_len);
17907c478bd9Sstevel@tonic-gate 		if (ret_val == -1)
1791*5363f09cSarutz 			warning(gettext("munmap failed. errno=%d\n"),
17927c478bd9Sstevel@tonic-gate 			    errno);
17937c478bd9Sstevel@tonic-gate 		(void) close(door_dp->dd_buffd);
1794*5363f09cSarutz 
17957c478bd9Sstevel@tonic-gate 		door_dp->dd_buffd = -1;
17967c478bd9Sstevel@tonic-gate 		door_dp->dd_buf = 0;
17977c478bd9Sstevel@tonic-gate 		door_dp->dd_buf_len = 0;
17987c478bd9Sstevel@tonic-gate 	}
1799*5363f09cSarutz 
18007c478bd9Sstevel@tonic-gate 	fbuf = mmap(0, req->reqset_shfd.fdbuf_len,
18017c478bd9Sstevel@tonic-gate 	    PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
1802*5363f09cSarutz 	if (fbuf == MAP_FAILED) {
1803*5363f09cSarutz 		ret_val = errno;
18047c478bd9Sstevel@tonic-gate 		debug(5, "mmap failed. errno=%d\n", errno);
1805*5363f09cSarutz 		return (ret_val);
18067c478bd9Sstevel@tonic-gate 	}
18077c478bd9Sstevel@tonic-gate 	door_dp->dd_buffd = fd;
18087c478bd9Sstevel@tonic-gate 	door_dp->dd_buf = fbuf;
18097c478bd9Sstevel@tonic-gate 	door_dp->dd_buf_len = req->reqset_shfd.fdbuf_len;
1810*5363f09cSarutz 
18117c478bd9Sstevel@tonic-gate 	return (0);
18127c478bd9Sstevel@tonic-gate }
18137c478bd9Sstevel@tonic-gate 
18147c478bd9Sstevel@tonic-gate static int32_t
18157c478bd9Sstevel@tonic-gate reassign_block(door_data_t *door_dp, smedia_services_t *req)
18167c478bd9Sstevel@tonic-gate {
18177c478bd9Sstevel@tonic-gate 	struct uscsi_cmd	ucmd;
18187c478bd9Sstevel@tonic-gate 	union scsi_cdb		cdb;
18197c478bd9Sstevel@tonic-gate 	int32_t			ret_val;
18207c478bd9Sstevel@tonic-gate 	int32_t			sector_size;
18217c478bd9Sstevel@tonic-gate 	char			*read_buf;
18227c478bd9Sstevel@tonic-gate 	uchar_t			mode_data[MD_LEN];
18237c478bd9Sstevel@tonic-gate 
18247c478bd9Sstevel@tonic-gate 	if (get_mode_page(door_dp->dd_fd, 0, 1,
18257c478bd9Sstevel@tonic-gate 	    mode_data, MD_LEN) < 0) {
18267c478bd9Sstevel@tonic-gate 		debug(5, "Mode sense failed\n");
18277c478bd9Sstevel@tonic-gate 		ret_val =  scsi_reassign_block(door_dp->dd_fd,
18287c478bd9Sstevel@tonic-gate 		    req->reqreassign_block.blockno);
18297c478bd9Sstevel@tonic-gate 		if (ret_val != 0)
18307c478bd9Sstevel@tonic-gate 			return (-1);
18317c478bd9Sstevel@tonic-gate 		return (0);
18327c478bd9Sstevel@tonic-gate 	}
18337c478bd9Sstevel@tonic-gate 
18347c478bd9Sstevel@tonic-gate 	/*
18357c478bd9Sstevel@tonic-gate 	 * No need to check if enough data is returned for
18367c478bd9Sstevel@tonic-gate 	 * AWRE bit or not.
18377c478bd9Sstevel@tonic-gate 	 * It will be 0 otherwise which needs to reassign the block.
18387c478bd9Sstevel@tonic-gate 	 */
18397c478bd9Sstevel@tonic-gate 	if (!(mode_data[AWRE_OFFSET] & AWRE)) {
18407c478bd9Sstevel@tonic-gate 		debug(5, "AWRE bit not set\n");
18417c478bd9Sstevel@tonic-gate 		ret_val =  scsi_reassign_block(door_dp->dd_fd,
18427c478bd9Sstevel@tonic-gate 			req->reqreassign_block.blockno);
18437c478bd9Sstevel@tonic-gate 		if (ret_val != 0)
18447c478bd9Sstevel@tonic-gate 			return (-1);
18457c478bd9Sstevel@tonic-gate 		return (0);
18467c478bd9Sstevel@tonic-gate 	}
18477c478bd9Sstevel@tonic-gate 	sector_size = (mode_data[BLOCK_LEN_OFFSET] << 16) |
18487c478bd9Sstevel@tonic-gate 		(mode_data[BLOCK_LEN_OFFSET + 1] << 8) |
18497c478bd9Sstevel@tonic-gate 		mode_data[BLOCK_LEN_OFFSET + 2];
18507c478bd9Sstevel@tonic-gate 
18517c478bd9Sstevel@tonic-gate 	debug(5, "REASSIGN BLOCK: sec size = 0x%x\n", sector_size);
18527c478bd9Sstevel@tonic-gate 	read_buf = (char *)malloc(sector_size);
18537c478bd9Sstevel@tonic-gate 	if (read_buf == NULL) {
18547c478bd9Sstevel@tonic-gate 		/* Alloc failed. Atleast reassign the block */
18557c478bd9Sstevel@tonic-gate 		ret_val =  scsi_reassign_block(door_dp->dd_fd,
18567c478bd9Sstevel@tonic-gate 			req->reqreassign_block.blockno);
18577c478bd9Sstevel@tonic-gate 		if (ret_val != 0)
18587c478bd9Sstevel@tonic-gate 			return (-1);
18597c478bd9Sstevel@tonic-gate 		return (0);
18607c478bd9Sstevel@tonic-gate 	}
18617c478bd9Sstevel@tonic-gate 
18627c478bd9Sstevel@tonic-gate 	(void) memset(read_buf, 0, sector_size);
18637c478bd9Sstevel@tonic-gate 	/* Read the sector */
18647c478bd9Sstevel@tonic-gate 	debug(5, "Reading the block %d\n",
18657c478bd9Sstevel@tonic-gate 		(uint32_t)req->reqreassign_block.blockno);
18667c478bd9Sstevel@tonic-gate 
18677c478bd9Sstevel@tonic-gate 	(void) memset((void *) &ucmd, 0, sizeof (ucmd));
18687c478bd9Sstevel@tonic-gate 	(void) memset((void *) &cdb, 0, sizeof (union scsi_cdb));
18697c478bd9Sstevel@tonic-gate 
18707c478bd9Sstevel@tonic-gate 	cdb.scc_cmd = SCMD_READ_G1;
18717c478bd9Sstevel@tonic-gate 	FORMG1ADDR(&cdb, req->reqreassign_block.blockno);
18727c478bd9Sstevel@tonic-gate 	FORMG1COUNT(&cdb, 1);	/* One block */
18737c478bd9Sstevel@tonic-gate 
18747c478bd9Sstevel@tonic-gate 	ucmd.uscsi_cdb = (caddr_t)&cdb;
18757c478bd9Sstevel@tonic-gate 	ucmd.uscsi_cdblen = CDB_GROUP1;
18767c478bd9Sstevel@tonic-gate 	ucmd.uscsi_bufaddr = (caddr_t)read_buf;
18777c478bd9Sstevel@tonic-gate 	ucmd.uscsi_buflen = sector_size;
18787c478bd9Sstevel@tonic-gate 	ucmd.uscsi_timeout = 120;	/* If 0, HBA hangs forever */
18797c478bd9Sstevel@tonic-gate 	(void) do_uscsi_cmd(door_dp->dd_fd, &ucmd, USCSI_READ);
18807c478bd9Sstevel@tonic-gate 
18817c478bd9Sstevel@tonic-gate 	/* Write the data back */
18827c478bd9Sstevel@tonic-gate 
18837c478bd9Sstevel@tonic-gate 	debug(5, "Writing the block %d\n",
18847c478bd9Sstevel@tonic-gate 		(uint32_t)req->reqreassign_block.blockno);
18857c478bd9Sstevel@tonic-gate 	(void) memset((void *) &ucmd, 0, sizeof (ucmd));
18867c478bd9Sstevel@tonic-gate 	(void) memset((void *) &cdb, 0, sizeof (cdb));
18877c478bd9Sstevel@tonic-gate 
18887c478bd9Sstevel@tonic-gate 	cdb.scc_cmd = SCMD_WRITE_G1;
18897c478bd9Sstevel@tonic-gate 	FORMG1ADDR(&cdb, req->reqreassign_block.blockno);
18907c478bd9Sstevel@tonic-gate 	FORMG1COUNT(&cdb, 1);	/* One block */
18917c478bd9Sstevel@tonic-gate 
18927c478bd9Sstevel@tonic-gate 	ucmd.uscsi_cdb = (caddr_t)&cdb;
18937c478bd9Sstevel@tonic-gate 	ucmd.uscsi_cdblen = CDB_GROUP1;
18947c478bd9Sstevel@tonic-gate 	ucmd.uscsi_bufaddr = (caddr_t)read_buf;
18957c478bd9Sstevel@tonic-gate 	ucmd.uscsi_buflen = sector_size;
18967c478bd9Sstevel@tonic-gate 	ucmd.uscsi_timeout = 120;	/* If 0, HBA hangs forever */
18977c478bd9Sstevel@tonic-gate 	ret_val = do_uscsi_cmd(door_dp->dd_fd, &ucmd, USCSI_WRITE);
18987c478bd9Sstevel@tonic-gate 	free(read_buf);
18997c478bd9Sstevel@tonic-gate 	if (ret_val || ucmd.uscsi_status) {
19007c478bd9Sstevel@tonic-gate 		debug(5, "Reassign failed: %d - %d errno = %d\n",
19017c478bd9Sstevel@tonic-gate 			ret_val, ucmd.uscsi_status, errno);
19027c478bd9Sstevel@tonic-gate 		ret_val = scsi_reassign_block(door_dp->dd_fd,
19037c478bd9Sstevel@tonic-gate 			req->reqreassign_block.blockno);
19047c478bd9Sstevel@tonic-gate 		if (ret_val != 0)
19057c478bd9Sstevel@tonic-gate 			return (-1);
19067c478bd9Sstevel@tonic-gate 		return (0);
19077c478bd9Sstevel@tonic-gate 	}
19087c478bd9Sstevel@tonic-gate 
19097c478bd9Sstevel@tonic-gate 	return (0);
19107c478bd9Sstevel@tonic-gate }
19117c478bd9Sstevel@tonic-gate 
19127c478bd9Sstevel@tonic-gate static void
19137c478bd9Sstevel@tonic-gate close_door_descs(door_desc_t *dp, uint_t ndesc)
19147c478bd9Sstevel@tonic-gate {
19157c478bd9Sstevel@tonic-gate 	while (ndesc > 0) {
19167c478bd9Sstevel@tonic-gate 		int fd = dp->d_data.d_desc.d_descriptor;
19177c478bd9Sstevel@tonic-gate 		if (dp->d_attributes & DOOR_DESCRIPTOR)
19187c478bd9Sstevel@tonic-gate 			(void) close(fd);
19197c478bd9Sstevel@tonic-gate 		dp++;
19207c478bd9Sstevel@tonic-gate 		ndesc--;
19217c478bd9Sstevel@tonic-gate 	}
19227c478bd9Sstevel@tonic-gate }
19237c478bd9Sstevel@tonic-gate 
1924*5363f09cSarutz /*
1925*5363f09cSarutz  * This is a Death Door's service procedure.
1926*5363f09cSarutz  *
1927*5363f09cSarutz  * This procedure is a NOP because the Death Door functionality
1928*5363f09cSarutz  * is no longer used and will be removed in the future.
1929*5363f09cSarutz  */
1930*5363f09cSarutz /*ARGSUSED*/
19317c478bd9Sstevel@tonic-gate static void
1932*5363f09cSarutz death_servproc(void *cookie, char *argp, size_t arg_size,
1933*5363f09cSarutz     door_desc_t *dp, uint_t ndesc)
1934*5363f09cSarutz {
1935*5363f09cSarutz 	debug(1, "death_servproc[%d]: argp = 0x%p  "
1936*5363f09cSarutz 	    "Death Door[%d]\n", pthread_self(), (void *)argp,
1937*5363f09cSarutz 	    ((door_data_t *)cookie)->dd_ddoor_descriptor);
1938*5363f09cSarutz 
1939*5363f09cSarutz 	(void) door_return(NULL, 0, NULL, 0);
1940*5363f09cSarutz }
1941*5363f09cSarutz 
1942*5363f09cSarutz /*
1943*5363f09cSarutz  * This is a Client Door's service procedure.
1944*5363f09cSarutz  *
1945*5363f09cSarutz  * This procedure is specified in the door_create() of a Client Door,
1946*5363f09cSarutz  * and its functionality represents the bulk of services that the
1947*5363f09cSarutz  * rpc.smserverd daemon offers.
1948*5363f09cSarutz  */
1949*5363f09cSarutz static void
1950*5363f09cSarutz client_servproc(void *cookie, char *argp, size_t arg_size,
19517c478bd9Sstevel@tonic-gate     door_desc_t *dp, uint_t ndesc)
19527c478bd9Sstevel@tonic-gate {
19537c478bd9Sstevel@tonic-gate 	smedia_services_t	*req;
19547c478bd9Sstevel@tonic-gate 	smedia_services_t	rmsvc;
19557c478bd9Sstevel@tonic-gate 	smedia_reterror_t	reterror;
19567c478bd9Sstevel@tonic-gate 	smedia_retraw_read_t	retraw_read;
19577c478bd9Sstevel@tonic-gate 	struct scsi_inquiry	inq;
19587c478bd9Sstevel@tonic-gate 	struct dk_minfo		media_info;
19597c478bd9Sstevel@tonic-gate 	struct dk_geom		dkgeom;
19607c478bd9Sstevel@tonic-gate 	int32_t			status;
19617c478bd9Sstevel@tonic-gate 	uchar_t			data[18];
19627c478bd9Sstevel@tonic-gate 	int32_t			completed = 0;
19637c478bd9Sstevel@tonic-gate 	door_data_t		*door_dp;
19647c478bd9Sstevel@tonic-gate 	size_t			retbuf_size;
19657c478bd9Sstevel@tonic-gate 	struct uscsi_cmd	ucmd;
19667c478bd9Sstevel@tonic-gate 	union scsi_cdb		cdb;
19677c478bd9Sstevel@tonic-gate 	int32_t			ret_val, err;
19687c478bd9Sstevel@tonic-gate 	char			rq_data[RQ_LEN];
1969*5363f09cSarutz 	uint_t			nexpected_desc;
19707c478bd9Sstevel@tonic-gate 	struct vtoc		vtoc;
19717c478bd9Sstevel@tonic-gate 
19727c478bd9Sstevel@tonic-gate 	door_dp = (door_data_t *)cookie;
19737c478bd9Sstevel@tonic-gate 	req = (smedia_services_t *)((void *)argp);
19747c478bd9Sstevel@tonic-gate 
1975*5363f09cSarutz 	debug(10, "client_servproc[%d]...\n", pthread_self());
19767c478bd9Sstevel@tonic-gate 
19777c478bd9Sstevel@tonic-gate 	if (argp == DOOR_UNREF_DATA) {
1978*5363f09cSarutz 		debug(5, "client_servproc[%d]: req = DOOR_UNREF_DATA\n",
19797c478bd9Sstevel@tonic-gate 		    pthread_self());
19807c478bd9Sstevel@tonic-gate 		debug(5, "Client has exited. Cleaning up resources\n");
1981*5363f09cSarutz 
19827c478bd9Sstevel@tonic-gate 		(void) mutex_lock(&svcstate_lock);
19837c478bd9Sstevel@tonic-gate 		svccount--;
19847c478bd9Sstevel@tonic-gate 		(void) mutex_unlock(&svcstate_lock);
1985*5363f09cSarutz 
19867c478bd9Sstevel@tonic-gate 		cleanup(door_dp);
1987*5363f09cSarutz 		return;
19887c478bd9Sstevel@tonic-gate 	}
1989*5363f09cSarutz 
19907c478bd9Sstevel@tonic-gate 	(void) mutex_lock(&svcstate_lock);
19917c478bd9Sstevel@tonic-gate 	svcstate = _SERVED;
19927c478bd9Sstevel@tonic-gate 	(void) mutex_unlock(&svcstate_lock);
19937c478bd9Sstevel@tonic-gate 
19947c478bd9Sstevel@tonic-gate 	rmsvc.in.cnum = req->in.cnum;
1995*5363f09cSarutz 	debug(5, "client_servproc[%d]: req = %s\n", pthread_self(),
19967c478bd9Sstevel@tonic-gate 	    xlate_cnum(req->in.cnum));
19977c478bd9Sstevel@tonic-gate 
19987c478bd9Sstevel@tonic-gate 	/*
19997c478bd9Sstevel@tonic-gate 	 * Our caller may have passed more descriptors than we expected.
20007c478bd9Sstevel@tonic-gate 	 * If so, we silently close (and ignore) them.
20017c478bd9Sstevel@tonic-gate 	 */
2002*5363f09cSarutz 	nexpected_desc = (req->in.cnum == SMEDIA_CNUM_SET_SHFD) ? 1 : 0;
2003*5363f09cSarutz 	if (ndesc > nexpected_desc) {
2004*5363f09cSarutz 		close_door_descs(dp + nexpected_desc, ndesc - nexpected_desc);
2005*5363f09cSarutz 	}
20067c478bd9Sstevel@tonic-gate 
20077c478bd9Sstevel@tonic-gate 	switch (req->in.cnum) {
20087c478bd9Sstevel@tonic-gate 	default:
2009*5363f09cSarutz 		debug(5, "client_servproc: unknown command %d\n", req->in.cnum);
20107c478bd9Sstevel@tonic-gate 		door_ret_err(&reterror, ENOTSUP);
20117c478bd9Sstevel@tonic-gate 		break;
20127c478bd9Sstevel@tonic-gate 
20137c478bd9Sstevel@tonic-gate 	case SMEDIA_CNUM_SET_SHFD:
20147c478bd9Sstevel@tonic-gate 		if (ndesc == 0)
20157c478bd9Sstevel@tonic-gate 			door_ret_err(&reterror, EINVAL);
20167c478bd9Sstevel@tonic-gate 		/*
2017*5363f09cSarutz 		 * Allocate shared memory for this connection.
2018*5363f09cSarutz 		 * If this connection already has shared memory,
2019*5363f09cSarutz 		 * deallocate before doing the allocation.
20207c478bd9Sstevel@tonic-gate 		 */
2021*5363f09cSarutz 		ret_val = set_shfd(door_dp, dp->d_data.d_desc.d_descriptor,
2022*5363f09cSarutz 		    req);
20237c478bd9Sstevel@tonic-gate 		if (ret_val == 0) {
20247c478bd9Sstevel@tonic-gate 			reterror.cnum = SMEDIA_CNUM_SET_SHFD;
20257c478bd9Sstevel@tonic-gate 			reterror.errnum = 0;
2026*5363f09cSarutz 
20277c478bd9Sstevel@tonic-gate 			my_door_return((char *)&reterror,
20287c478bd9Sstevel@tonic-gate 				sizeof (smedia_reterror_t), 0, 0);
20297c478bd9Sstevel@tonic-gate 		} else {
20307c478bd9Sstevel@tonic-gate 			(void) close(dp->d_data.d_desc.d_descriptor);
2031*5363f09cSarutz 			door_ret_err(&reterror, ret_val);
20327c478bd9Sstevel@tonic-gate 		}
20337c478bd9Sstevel@tonic-gate 		break;
20347c478bd9Sstevel@tonic-gate 
20357c478bd9Sstevel@tonic-gate 	case SMEDIA_CNUM_RAW_READ:
20367c478bd9Sstevel@tonic-gate 		debug(10, " arg size = %d blk num=0x%x nbytes = 0x%x \n",
20377c478bd9Sstevel@tonic-gate 			(int)arg_size,
20387c478bd9Sstevel@tonic-gate 			(uint32_t)req->reqraw_read.blockno,
20397c478bd9Sstevel@tonic-gate 			req->reqraw_read.nbytes);
20407c478bd9Sstevel@tonic-gate 		retbuf_size = sizeof (smedia_retraw_read_t);
20417c478bd9Sstevel@tonic-gate 		if (req->reqraw_read.nbytes == 0) {
20427c478bd9Sstevel@tonic-gate 			/* Nothing to write */
20437c478bd9Sstevel@tonic-gate 			rmsvc.retraw_write.nbytes = 0;
20447c478bd9Sstevel@tonic-gate 			my_door_return((char *)&rmsvc,
20457c478bd9Sstevel@tonic-gate 				sizeof (smedia_retraw_write_t), 0, 0);
20467c478bd9Sstevel@tonic-gate 		}
20477c478bd9Sstevel@tonic-gate 		retraw_read.cnum = SMEDIA_CNUM_RAW_READ;
20487c478bd9Sstevel@tonic-gate 		ret_val = raw_read(door_dp, req);
20497c478bd9Sstevel@tonic-gate 		if (ret_val == -1) {
20507c478bd9Sstevel@tonic-gate 			door_ret_err(&reterror, errno);
20517c478bd9Sstevel@tonic-gate 		}
20527c478bd9Sstevel@tonic-gate 		retraw_read.nbytes = ret_val;
20537c478bd9Sstevel@tonic-gate 		my_door_return((char *)&retraw_read, retbuf_size, 0, 0);
20547c478bd9Sstevel@tonic-gate 		break;
20557c478bd9Sstevel@tonic-gate 
20567c478bd9Sstevel@tonic-gate 	case	SMEDIA_CNUM_USCSI_CMD:
20577c478bd9Sstevel@tonic-gate 		retbuf_size = sizeof (smedia_retuscsi_cmd_t);
20587c478bd9Sstevel@tonic-gate 		rmsvc.retuscsi_cmd.cnum = SMEDIA_CNUM_USCSI_CMD;
20597c478bd9Sstevel@tonic-gate 		ucmd.uscsi_flags = req->requscsi_cmd.uscsi_flags;
20607c478bd9Sstevel@tonic-gate 		ucmd.uscsi_cdb = (caddr_t)&req->requscsi_cmd.uscsi_cdb;
20617c478bd9Sstevel@tonic-gate 		ucmd.uscsi_cdblen = req->requscsi_cmd.uscsi_cdblen;
20627c478bd9Sstevel@tonic-gate 		ucmd.uscsi_bufaddr = (caddr_t)door_dp->dd_buf;
20637c478bd9Sstevel@tonic-gate 		ucmd.uscsi_buflen = req->requscsi_cmd.uscsi_buflen;
20647c478bd9Sstevel@tonic-gate 		ucmd.uscsi_timeout = req->requscsi_cmd.uscsi_timeout;
20657c478bd9Sstevel@tonic-gate 		ucmd.uscsi_rqlen = req->requscsi_cmd.uscsi_rqlen;
20667c478bd9Sstevel@tonic-gate 		ucmd.uscsi_rqbuf = (caddr_t)&rmsvc.retuscsi_cmd.uscsi_rqbuf;
2067*5363f09cSarutz 		debug(5, "USCSI CMD 0x%x requested.\n",
20687c478bd9Sstevel@tonic-gate 		    req->requscsi_cmd.uscsi_cdb[0]);
20697c478bd9Sstevel@tonic-gate 		/*
20707c478bd9Sstevel@tonic-gate 		 * Check the device type and invalid flags specified.
20717c478bd9Sstevel@tonic-gate 		 * We permit operations only on CDROM devices types.
20727c478bd9Sstevel@tonic-gate 		 */
2073*5363f09cSarutz 		errno = invalid_uscsi_operation(door_dp, &ucmd);
20747c478bd9Sstevel@tonic-gate 		if (errno) {
20757c478bd9Sstevel@tonic-gate 			door_ret_err(&reterror, errno);
20767c478bd9Sstevel@tonic-gate 		}
20777c478bd9Sstevel@tonic-gate 
20787c478bd9Sstevel@tonic-gate 		if ((req->requscsi_cmd.uscsi_buflen) &&
20797c478bd9Sstevel@tonic-gate 		    ((req->requscsi_cmd.uscsi_buflen > door_dp->dd_buf_len) ||
20807c478bd9Sstevel@tonic-gate 		    (door_dp->dd_buf == NULL))) {
2081*5363f09cSarutz 			debug(5, "uscsi_cmd failed: uscsi_buflen=0x%x "
2082*5363f09cSarutz 			    "dd_buf_len=0x%x dd_buf=0x%p\n",
20837c478bd9Sstevel@tonic-gate 			    req->requscsi_cmd.uscsi_buflen,
20847c478bd9Sstevel@tonic-gate 			    door_dp->dd_buf_len,
20857c478bd9Sstevel@tonic-gate 			    door_dp->dd_buf);
20867c478bd9Sstevel@tonic-gate 			errno = EINVAL;
20877c478bd9Sstevel@tonic-gate 			door_ret_err(&reterror, errno);
20887c478bd9Sstevel@tonic-gate 		}
20897c478bd9Sstevel@tonic-gate 		ret_val = do_uscsi_cmd(door_dp->dd_fd,
20907c478bd9Sstevel@tonic-gate 			&ucmd, req->requscsi_cmd.uscsi_flags);
20917c478bd9Sstevel@tonic-gate 		rmsvc.retuscsi_cmd.uscsi_status = ucmd.uscsi_status;
20927c478bd9Sstevel@tonic-gate 		rmsvc.retuscsi_cmd.uscsi_resid = ucmd.uscsi_resid;
20937c478bd9Sstevel@tonic-gate 		rmsvc.retuscsi_cmd.uscsi_rqstatus = ucmd.uscsi_rqstatus;
20947c478bd9Sstevel@tonic-gate 		rmsvc.retuscsi_cmd.uscsi_rqresid = ucmd.uscsi_rqresid;
20957c478bd9Sstevel@tonic-gate 		rmsvc.retuscsi_cmd.uscsi_retval = ret_val;
20967c478bd9Sstevel@tonic-gate 		rmsvc.retuscsi_cmd.uscsi_errno = errno;
20977c478bd9Sstevel@tonic-gate 		if (ret_val || ucmd.uscsi_status) {
20987c478bd9Sstevel@tonic-gate 			debug(5, "uscsi_cmd failed: %d - %d errno = %d\n",
20997c478bd9Sstevel@tonic-gate 				ret_val, ucmd.uscsi_status, errno);
21007c478bd9Sstevel@tonic-gate 		}
21017c478bd9Sstevel@tonic-gate 		my_door_return((char *)&rmsvc, retbuf_size, 0, 0);
21027c478bd9Sstevel@tonic-gate 		break;
21037c478bd9Sstevel@tonic-gate 
21047c478bd9Sstevel@tonic-gate 	case SMEDIA_CNUM_RAW_WRITE:
21057c478bd9Sstevel@tonic-gate 		if (req->reqraw_write.nbytes == 0) {
21067c478bd9Sstevel@tonic-gate 			/* Nothing to write */
21077c478bd9Sstevel@tonic-gate 			rmsvc.retraw_write.nbytes = 0;
21087c478bd9Sstevel@tonic-gate 			my_door_return((char *)&rmsvc,
21097c478bd9Sstevel@tonic-gate 				sizeof (smedia_retraw_write_t), 0, 0);
21107c478bd9Sstevel@tonic-gate 		}
21117c478bd9Sstevel@tonic-gate 		ret_val = raw_write(door_dp, req);
21127c478bd9Sstevel@tonic-gate 		if (ret_val == -1)
21137c478bd9Sstevel@tonic-gate 			door_ret_err(&reterror, errno);
21147c478bd9Sstevel@tonic-gate 		rmsvc.retraw_write.nbytes = ret_val;
21157c478bd9Sstevel@tonic-gate 		my_door_return((char *)&rmsvc, sizeof (smedia_retraw_write_t),
21167c478bd9Sstevel@tonic-gate 			0, 0);
21177c478bd9Sstevel@tonic-gate 		break;
21187c478bd9Sstevel@tonic-gate 
21197c478bd9Sstevel@tonic-gate 	case SMEDIA_CNUM_GET_DEVICE_INFO:
21207c478bd9Sstevel@tonic-gate 
21217c478bd9Sstevel@tonic-gate 		(void) memset((void *) &inq, 0, sizeof (inq));
21227c478bd9Sstevel@tonic-gate 		(void) memset((void *) &ucmd, 0, sizeof (ucmd));
21237c478bd9Sstevel@tonic-gate 		(void) memset((void *) &cdb, 0, sizeof (union scsi_cdb));
21247c478bd9Sstevel@tonic-gate 		cdb.scc_cmd = SCMD_INQUIRY;
21257c478bd9Sstevel@tonic-gate 		FORMG0COUNT(&cdb, sizeof (inq));
21267c478bd9Sstevel@tonic-gate 		ucmd.uscsi_cdb = (caddr_t)&cdb;
21277c478bd9Sstevel@tonic-gate 		ucmd.uscsi_cdblen = CDB_GROUP0;
21287c478bd9Sstevel@tonic-gate 		ucmd.uscsi_bufaddr = (caddr_t)&inq;
21297c478bd9Sstevel@tonic-gate 		ucmd.uscsi_buflen = sizeof (inq);
21307c478bd9Sstevel@tonic-gate 		ucmd.uscsi_timeout = 120;	/* If 0, HBA hangs forever */
21317c478bd9Sstevel@tonic-gate 		ucmd.uscsi_rqlen = RQ_LEN;
21327c478bd9Sstevel@tonic-gate 		ucmd.uscsi_rqbuf = rq_data;
21337c478bd9Sstevel@tonic-gate 		ret_val = do_uscsi_cmd(door_dp->dd_fd,
21347c478bd9Sstevel@tonic-gate 			&ucmd, USCSI_READ|USCSI_RQENABLE);
21357c478bd9Sstevel@tonic-gate 		if (ret_val || ucmd.uscsi_status) {
21367c478bd9Sstevel@tonic-gate 			debug(5, "inquiry failed: %d - %d errno = %d\n",
21377c478bd9Sstevel@tonic-gate 				ret_val, ucmd.uscsi_status, errno);
21387c478bd9Sstevel@tonic-gate 			door_ret_err(&reterror, errno);
21397c478bd9Sstevel@tonic-gate 		}
21407c478bd9Sstevel@tonic-gate 
21417c478bd9Sstevel@tonic-gate 		debug(5, "%s\n", inq.inq_vid);
21427c478bd9Sstevel@tonic-gate 		debug(5, "%s\n", rmsvc.retget_device_info.sm_vendor_name);
21437c478bd9Sstevel@tonic-gate 
21447c478bd9Sstevel@tonic-gate 		(void) strlcpy(rmsvc.retget_device_info.sm_vendor_name,
21457c478bd9Sstevel@tonic-gate 			inq.inq_vid, 8);
21467c478bd9Sstevel@tonic-gate 		rmsvc.retget_device_info.sm_vendor_name[8] = 0;
21477c478bd9Sstevel@tonic-gate 		(void) strlcpy(rmsvc.retget_device_info.sm_product_name,
21487c478bd9Sstevel@tonic-gate 			inq.inq_pid, 16);
21497c478bd9Sstevel@tonic-gate 		rmsvc.retget_device_info.sm_product_name[16] = 0;
21507c478bd9Sstevel@tonic-gate 		(void) strlcpy(rmsvc.retget_device_info.sm_firmware_version,
21517c478bd9Sstevel@tonic-gate 			inq.inq_revision, 4);
21527c478bd9Sstevel@tonic-gate 		rmsvc.retget_device_info.sm_firmware_version[4] = ' ';
21537c478bd9Sstevel@tonic-gate 		(void) strlcpy(
21547c478bd9Sstevel@tonic-gate 			&rmsvc.retget_device_info.sm_firmware_version[5],
21557c478bd9Sstevel@tonic-gate 				inq.inq_serial, 12);
21567c478bd9Sstevel@tonic-gate 		rmsvc.retget_device_info.sm_product_name[17] = 0;
21577c478bd9Sstevel@tonic-gate 
21587c478bd9Sstevel@tonic-gate 		rmsvc.retget_device_info.sm_interface_type = IF_SCSI;
21597c478bd9Sstevel@tonic-gate 
2160*5363f09cSarutz 		debug(5, "Vendor name = %s\n",
2161*5363f09cSarutz 		    rmsvc.retget_device_info.sm_vendor_name);
2162*5363f09cSarutz 		debug(5, "product name = %s\n",
2163*5363f09cSarutz 		    rmsvc.retget_device_info.sm_product_name);
2164*5363f09cSarutz 		debug(5, "Firmware revision = %s\n",
2165*5363f09cSarutz 		    rmsvc.retget_device_info.sm_firmware_version);
2166*5363f09cSarutz 
21677c478bd9Sstevel@tonic-gate 		my_door_return((char *)&rmsvc.retget_device_info,
21687c478bd9Sstevel@tonic-gate 			sizeof (smedia_retget_device_info_t), 0, 0);
21697c478bd9Sstevel@tonic-gate 		break;
21707c478bd9Sstevel@tonic-gate 
21717c478bd9Sstevel@tonic-gate 	case	SMEDIA_CNUM_GET_MEDIUM_PROPERTY:
21727c478bd9Sstevel@tonic-gate 
21737c478bd9Sstevel@tonic-gate 		(void) memset((void *)&rmsvc.retget_medium_property.smprop,
21747c478bd9Sstevel@tonic-gate 			0, sizeof (smmedium_prop_t));
21757c478bd9Sstevel@tonic-gate 
21767c478bd9Sstevel@tonic-gate 		ret_val = ioctl(door_dp->dd_fd, DKIOCGMEDIAINFO, &media_info);
21777c478bd9Sstevel@tonic-gate 
21787c478bd9Sstevel@tonic-gate 		if (ret_val < 0) {
21797c478bd9Sstevel@tonic-gate 			uint32_t capacity;
21807c478bd9Sstevel@tonic-gate 			uint32_t blocksize;
21817c478bd9Sstevel@tonic-gate 			/*
21827c478bd9Sstevel@tonic-gate 			 * Devices may fail DKIOCGMEDIAINFO if an unformed
21837c478bd9Sstevel@tonic-gate 			 * media is inserted. We can get the capacity
21847c478bd9Sstevel@tonic-gate 			 * information from the SCMD_READ_FORMAT_CAP command.
21857c478bd9Sstevel@tonic-gate 			 */
21867c478bd9Sstevel@tonic-gate 
2187*5363f09cSarutz 			debug(5, "DKIOCGMEDIAINFO failed; using "
2188*5363f09cSarutz 			    "SCMD_READ_FORMAT_CAP");
21897c478bd9Sstevel@tonic-gate 			ret_val = get_media_capacity(door_dp->dd_fd,
21907c478bd9Sstevel@tonic-gate 			    &capacity, &blocksize);
21917c478bd9Sstevel@tonic-gate 
21927c478bd9Sstevel@tonic-gate 			if (ret_val >= 0) {
21937c478bd9Sstevel@tonic-gate 				media_info.dki_lbsize =	blocksize;
21947c478bd9Sstevel@tonic-gate 				media_info.dki_capacity = capacity;
21957c478bd9Sstevel@tonic-gate 			} else {
21967c478bd9Sstevel@tonic-gate 				debug(5, "SCMD_READ_FORMAT_CAP failed");
21977c478bd9Sstevel@tonic-gate 				door_ret_err(&reterror, errno);
21987c478bd9Sstevel@tonic-gate 			}
21997c478bd9Sstevel@tonic-gate 		}
22007c478bd9Sstevel@tonic-gate 		rmsvc.retget_medium_property.smprop.sm_blocksize =
22017c478bd9Sstevel@tonic-gate 		    media_info.dki_lbsize;
22027c478bd9Sstevel@tonic-gate 		rmsvc.retget_medium_property.smprop.sm_capacity =
22037c478bd9Sstevel@tonic-gate 		    media_info.dki_capacity;
22047c478bd9Sstevel@tonic-gate 
22057c478bd9Sstevel@tonic-gate 		rmsvc.retget_medium_property.smprop.sm_media_type =
22067c478bd9Sstevel@tonic-gate 		    media_info.dki_media_type;
22077c478bd9Sstevel@tonic-gate 		/*
22087c478bd9Sstevel@tonic-gate 		 * These devices show as SCSI devices but we need to treat it
22097c478bd9Sstevel@tonic-gate 		 * differently. so we need a seperate class.
22107c478bd9Sstevel@tonic-gate 		 */
22117c478bd9Sstevel@tonic-gate 		if (get_device_type_scsi(door_dp->dd_fd, &inq) == SCSI_FLOPPY) {
22127c478bd9Sstevel@tonic-gate 			rmsvc.retget_medium_property.smprop.sm_media_type =
22137c478bd9Sstevel@tonic-gate 			    SM_SCSI_FLOPPY;
22147c478bd9Sstevel@tonic-gate 		}
22157c478bd9Sstevel@tonic-gate 
22167c478bd9Sstevel@tonic-gate 		/* Check for EFI type because DKIOCGGEOM does not support EFI */
22177c478bd9Sstevel@tonic-gate 		ret_val = ioctl(door_dp->dd_fd, DKIOCGVTOC, &vtoc);
22187c478bd9Sstevel@tonic-gate 		if (!((ret_val < 0) && (errno == ENOTSUP))) {
22197c478bd9Sstevel@tonic-gate 			ret_val = ioctl(door_dp->dd_fd, DKIOCGGEOM, &dkgeom);
22207c478bd9Sstevel@tonic-gate 			if (ret_val < 0)  {
22217c478bd9Sstevel@tonic-gate 				/*
22227c478bd9Sstevel@tonic-gate 				 * DKIOCGGEOM may fail for unformed floppies.
22237c478bd9Sstevel@tonic-gate 				 * We need to generate the appropriate geometry
22247c478bd9Sstevel@tonic-gate 				 * information.
22257c478bd9Sstevel@tonic-gate 				 */
22267c478bd9Sstevel@tonic-gate 				if (rmsvc.retget_medium_property.smprop.
22277c478bd9Sstevel@tonic-gate 				    sm_media_type == SM_SCSI_FLOPPY) {
22287c478bd9Sstevel@tonic-gate 					ret_val = get_floppy_geom(
22297c478bd9Sstevel@tonic-gate 					    door_dp->dd_fd,
22307c478bd9Sstevel@tonic-gate 					    media_info.dki_capacity, &dkgeom);
22317c478bd9Sstevel@tonic-gate 
22327c478bd9Sstevel@tonic-gate 					if (ret_val < 0) {
22337c478bd9Sstevel@tonic-gate 						debug(5, "Cannot determine "
22347c478bd9Sstevel@tonic-gate 						    "media size");
22357c478bd9Sstevel@tonic-gate 						door_ret_err(&reterror, errno);
22367c478bd9Sstevel@tonic-gate 					}
22377c478bd9Sstevel@tonic-gate 				} else {
22387c478bd9Sstevel@tonic-gate #ifdef sparc
22397c478bd9Sstevel@tonic-gate 					debug(5, "DKIOCGGEOM ioctl failed");
22407c478bd9Sstevel@tonic-gate 					door_ret_err(&reterror, errno);
22417c478bd9Sstevel@tonic-gate #else /* !sparc */
22427c478bd9Sstevel@tonic-gate 					/*
22437c478bd9Sstevel@tonic-gate 					 * Try getting Physical geometry on x86.
22447c478bd9Sstevel@tonic-gate 					 */
22457c478bd9Sstevel@tonic-gate 					ret_val = ioctl(door_dp->dd_fd,
22467c478bd9Sstevel@tonic-gate 					    DKIOCG_PHYGEOM, &dkgeom);
22477c478bd9Sstevel@tonic-gate 					if (ret_val < 0) {
22487c478bd9Sstevel@tonic-gate 						debug(5, "DKIOCG_PHYGEOM "
22497c478bd9Sstevel@tonic-gate 						    "ioctl failed");
22507c478bd9Sstevel@tonic-gate 						door_ret_err(&reterror, errno);
22517c478bd9Sstevel@tonic-gate 					}
22527c478bd9Sstevel@tonic-gate #endif /* sparc */
22537c478bd9Sstevel@tonic-gate 				}
22547c478bd9Sstevel@tonic-gate 			}
22557c478bd9Sstevel@tonic-gate 
22567c478bd9Sstevel@tonic-gate 
22577c478bd9Sstevel@tonic-gate 			/*
22587c478bd9Sstevel@tonic-gate 			 * Some faked geometry may not have pcyl filled in so
22597c478bd9Sstevel@tonic-gate 			 * later calculations using this field will be
22607c478bd9Sstevel@tonic-gate 			 * incorrect.  We will substitute it with the number of
22617c478bd9Sstevel@tonic-gate 			 * available cylinders.
22627c478bd9Sstevel@tonic-gate 			 */
22637c478bd9Sstevel@tonic-gate 			if (dkgeom.dkg_pcyl == 0)
22647c478bd9Sstevel@tonic-gate 				rmsvc.retget_medium_property.smprop.sm_pcyl =
22657c478bd9Sstevel@tonic-gate 				    dkgeom.dkg_ncyl;
22667c478bd9Sstevel@tonic-gate 			else
22677c478bd9Sstevel@tonic-gate 				rmsvc.retget_medium_property.smprop.sm_pcyl =
22687c478bd9Sstevel@tonic-gate 				    dkgeom.dkg_pcyl;
22697c478bd9Sstevel@tonic-gate 
22707c478bd9Sstevel@tonic-gate 			rmsvc.retget_medium_property.smprop.sm_nhead =
22717c478bd9Sstevel@tonic-gate 			    dkgeom.dkg_nhead;
22727c478bd9Sstevel@tonic-gate 			rmsvc.retget_medium_property.smprop.sm_nsect =
22737c478bd9Sstevel@tonic-gate 			    dkgeom.dkg_nsect;
22747c478bd9Sstevel@tonic-gate 		}
22757c478bd9Sstevel@tonic-gate 
22767c478bd9Sstevel@tonic-gate 		debug(1, "properties are: lbasize = %d, cap = %llu",
22777c478bd9Sstevel@tonic-gate 		    media_info.dki_lbsize, media_info.dki_capacity);
22787c478bd9Sstevel@tonic-gate 
22797c478bd9Sstevel@tonic-gate 		my_door_return((char *)&rmsvc.retget_medium_property,
22807c478bd9Sstevel@tonic-gate 			sizeof (smedia_retget_medium_property_t), 0, 0);
22817c478bd9Sstevel@tonic-gate 		break;
22827c478bd9Sstevel@tonic-gate 
22837c478bd9Sstevel@tonic-gate 	case	SMEDIA_CNUM_GET_PROTECTION_STATUS:
22847c478bd9Sstevel@tonic-gate 		switch (get_device_type_scsi(door_dp->dd_fd, &inq)) {
22857c478bd9Sstevel@tonic-gate 		case SCSI_FLOPPY:
22867c478bd9Sstevel@tonic-gate 			status = scsi_floppy_media_status(door_dp->dd_fd);
22877c478bd9Sstevel@tonic-gate 			break;
22887c478bd9Sstevel@tonic-gate 		case SCSI_IOMEGA:
22897c478bd9Sstevel@tonic-gate 			status = scsi_zip_media_status(door_dp->dd_fd);
22907c478bd9Sstevel@tonic-gate 			break;
22917c478bd9Sstevel@tonic-gate 		case SCSI_GENERIC:
22927c478bd9Sstevel@tonic-gate 			status = scsi_media_status(door_dp->dd_fd);
22937c478bd9Sstevel@tonic-gate 			break;
22947c478bd9Sstevel@tonic-gate 		default:
22957c478bd9Sstevel@tonic-gate 			door_ret_err(&reterror, errno);
22967c478bd9Sstevel@tonic-gate 		}
22977c478bd9Sstevel@tonic-gate 		if (status < 0)
22987c478bd9Sstevel@tonic-gate 			door_ret_err(&reterror, errno);
22997c478bd9Sstevel@tonic-gate 
23007c478bd9Sstevel@tonic-gate 		rmsvc.retget_protection_status.prot_state.sm_new_state  =
23017c478bd9Sstevel@tonic-gate 			status;
23027c478bd9Sstevel@tonic-gate 
23037c478bd9Sstevel@tonic-gate 		my_door_return((char *)&rmsvc.retget_protection_status,
23047c478bd9Sstevel@tonic-gate 			sizeof (smedia_retget_protection_status_t), 0, 0);
23057c478bd9Sstevel@tonic-gate 		break;
23067c478bd9Sstevel@tonic-gate 
23077c478bd9Sstevel@tonic-gate 	case	SMEDIA_CNUM_SET_PROTECTION_STATUS:
23087c478bd9Sstevel@tonic-gate 
23097c478bd9Sstevel@tonic-gate 		ret_val = set_protection_status(door_dp, req);
23107c478bd9Sstevel@tonic-gate 		if (ret_val == -1)
23117c478bd9Sstevel@tonic-gate 			door_ret_err(&reterror, errno);
23127c478bd9Sstevel@tonic-gate 		else
23137c478bd9Sstevel@tonic-gate 			my_door_return((char *)&rmsvc.retset_protection_status,
23147c478bd9Sstevel@tonic-gate 				sizeof (smedia_retset_protection_status_t),
23157c478bd9Sstevel@tonic-gate 				0, 0);
23167c478bd9Sstevel@tonic-gate 		break;
23177c478bd9Sstevel@tonic-gate 
23187c478bd9Sstevel@tonic-gate 	case SMEDIA_CNUM_FORMAT:
23197c478bd9Sstevel@tonic-gate 		switch (get_device_type_scsi(door_dp->dd_fd, &inq)) {
23207c478bd9Sstevel@tonic-gate 		case SCSI_FLOPPY:
23217c478bd9Sstevel@tonic-gate 			info("formatting floppy");
23227c478bd9Sstevel@tonic-gate 			err = scsi_floppy_format(door_dp->dd_fd,
23237c478bd9Sstevel@tonic-gate 				req->reqformat.flavor, req->reqformat.mode);
23247c478bd9Sstevel@tonic-gate 
23257c478bd9Sstevel@tonic-gate 			break;
23267c478bd9Sstevel@tonic-gate 		case SCSI_IOMEGA:
23277c478bd9Sstevel@tonic-gate 			err = scsi_zip_format(door_dp->dd_fd,
23287c478bd9Sstevel@tonic-gate 				req->reqformat.flavor, req->reqformat.mode);
23297c478bd9Sstevel@tonic-gate 			break;
23307c478bd9Sstevel@tonic-gate 		case SCSI_GENERIC:
23317c478bd9Sstevel@tonic-gate 			err = scsi_format(door_dp->dd_fd,
23327c478bd9Sstevel@tonic-gate 				req->reqformat.flavor, req->reqformat.mode);
23337c478bd9Sstevel@tonic-gate 			break;
23347c478bd9Sstevel@tonic-gate 		default:
23357c478bd9Sstevel@tonic-gate 			door_ret_err(&reterror, ENOTSUP);
23367c478bd9Sstevel@tonic-gate 		}
23377c478bd9Sstevel@tonic-gate 
23387c478bd9Sstevel@tonic-gate 		if (err)
23397c478bd9Sstevel@tonic-gate 			door_ret_err(&reterror, errno);
23407c478bd9Sstevel@tonic-gate 		my_door_return((char *)&rmsvc.retformat,
23417c478bd9Sstevel@tonic-gate 			sizeof (smedia_retformat_t), 0, 0);
23427c478bd9Sstevel@tonic-gate 
23437c478bd9Sstevel@tonic-gate 		break;
23447c478bd9Sstevel@tonic-gate 
23457c478bd9Sstevel@tonic-gate 	case SMEDIA_CNUM_CHECK_FORMAT_STATUS:
23467c478bd9Sstevel@tonic-gate 
23477c478bd9Sstevel@tonic-gate 		(void) memset((void *) &cdb, 0, sizeof (union scsi_cdb));
23487c478bd9Sstevel@tonic-gate 		(void) memset((void *) &ucmd, 0, sizeof (ucmd));
23497c478bd9Sstevel@tonic-gate 		(void) memset((void *) &data, 0, sizeof (data));
23507c478bd9Sstevel@tonic-gate 		cdb.scc_cmd = SCMD_REQUEST_SENSE;
23517c478bd9Sstevel@tonic-gate 		cdb.g0_count0 = sizeof (data);
23527c478bd9Sstevel@tonic-gate 		ucmd.uscsi_cdb = (caddr_t)&cdb;
23537c478bd9Sstevel@tonic-gate 		ucmd.uscsi_cdblen = CDB_GROUP0;
23547c478bd9Sstevel@tonic-gate 		ucmd.uscsi_bufaddr = (caddr_t)&data;
23557c478bd9Sstevel@tonic-gate 		ucmd.uscsi_buflen = sizeof (data);
23567c478bd9Sstevel@tonic-gate 		ucmd.uscsi_timeout = 120;	/* If 0, HBA hangs forever */
23577c478bd9Sstevel@tonic-gate 		ucmd.uscsi_rqlen = RQ_LEN;
23587c478bd9Sstevel@tonic-gate 		ucmd.uscsi_rqbuf = rq_data;
23597c478bd9Sstevel@tonic-gate 		ret_val = do_uscsi_cmd(door_dp->dd_fd,
23607c478bd9Sstevel@tonic-gate 			&ucmd, USCSI_READ|USCSI_RQENABLE);
23617c478bd9Sstevel@tonic-gate 		if (ret_val || ucmd.uscsi_status) {
23627c478bd9Sstevel@tonic-gate 			debug(5, "Request sense failed: %d - %d errno = %d\n",
23637c478bd9Sstevel@tonic-gate 				ret_val, ucmd.uscsi_status, errno);
23647c478bd9Sstevel@tonic-gate 			door_ret_err(&reterror, errno);
23657c478bd9Sstevel@tonic-gate 		}
23667c478bd9Sstevel@tonic-gate 
23677c478bd9Sstevel@tonic-gate 		if ((data[0] & 0x7F) == DEFERRED_ERROR) {
23687c478bd9Sstevel@tonic-gate 		/* Deffered error. The format must have failed */
23697c478bd9Sstevel@tonic-gate 			debug(5, "format failed!\n");
23707c478bd9Sstevel@tonic-gate 			door_ret_err(&reterror, EIO);
23717c478bd9Sstevel@tonic-gate 		}
23727c478bd9Sstevel@tonic-gate 
23737c478bd9Sstevel@tonic-gate 		if (data[SKSV_OFFSET] & SKSV_FIELD) {
23747c478bd9Sstevel@tonic-gate 			completed =
23757c478bd9Sstevel@tonic-gate 				(data[FORMAT_PROGRESS_INDICATOR_OFFSET_0] << 8)
23767c478bd9Sstevel@tonic-gate 				| data[FORMAT_PROGRESS_INDICATOR_OFFSET_1];
23777c478bd9Sstevel@tonic-gate 			completed = (completed*100/65536);
23787c478bd9Sstevel@tonic-gate 		} else {
23797c478bd9Sstevel@tonic-gate 			completed = (100);
23807c478bd9Sstevel@tonic-gate 		}
23817c478bd9Sstevel@tonic-gate 		rmsvc.retcheck_format_status.percent_complete = completed;
23827c478bd9Sstevel@tonic-gate 		my_door_return((char *)&rmsvc.retcheck_format_status,
23837c478bd9Sstevel@tonic-gate 			sizeof (smedia_retcheck_format_status_t), 0, 0);
23847c478bd9Sstevel@tonic-gate 		break;
23857c478bd9Sstevel@tonic-gate 
23867c478bd9Sstevel@tonic-gate 	case SMEDIA_CNUM_REASSIGN_BLOCK:
23877c478bd9Sstevel@tonic-gate 
23887c478bd9Sstevel@tonic-gate 		ret_val = reassign_block(door_dp, req);
23897c478bd9Sstevel@tonic-gate 		if (ret_val == -1)
23907c478bd9Sstevel@tonic-gate 			door_ret_err(&reterror, errno);
23917c478bd9Sstevel@tonic-gate 		my_door_return((char *)&rmsvc.retreassign_block,
23927c478bd9Sstevel@tonic-gate 			sizeof (smedia_retreassign_block_t), 0, 0);
23937c478bd9Sstevel@tonic-gate 		break;
23947c478bd9Sstevel@tonic-gate 
23957c478bd9Sstevel@tonic-gate 	}	/* end of switch */
23967c478bd9Sstevel@tonic-gate 
23977c478bd9Sstevel@tonic-gate 	debug(10, "Exiting client server...\n");
23987c478bd9Sstevel@tonic-gate 	my_door_return((char *)&reterror, sizeof (smedia_reterror_t), 0, 0);
23997c478bd9Sstevel@tonic-gate }
24007c478bd9Sstevel@tonic-gate 
2401*5363f09cSarutz /*
2402*5363f09cSarutz  * This is the service procedure for the door that is associated with
2403*5363f09cSarutz  * the (doorfs) filesystem Door that is created at 'smedia_service'.
2404*5363f09cSarutz  */
24057c478bd9Sstevel@tonic-gate /*ARGSUSED*/
24067c478bd9Sstevel@tonic-gate static void
2407*5363f09cSarutz main_servproc(void *server_data, char *argp, size_t arg_size,
24087c478bd9Sstevel@tonic-gate     door_desc_t *dp, uint_t ndesc)
24097c478bd9Sstevel@tonic-gate {
24107c478bd9Sstevel@tonic-gate 	smedia_services_t	*req;
24117c478bd9Sstevel@tonic-gate 	door_cred_t	door_credentials;
24127c478bd9Sstevel@tonic-gate 	int		ret_val;
24137c478bd9Sstevel@tonic-gate 	door_data_t	*ddata;
24147c478bd9Sstevel@tonic-gate 	smedia_reterror_t	reterror;
24157c478bd9Sstevel@tonic-gate 	smedia_reterror_t	retok;
24167c478bd9Sstevel@tonic-gate 	struct	stat	stat;
24177c478bd9Sstevel@tonic-gate 	door_desc_t	*didpp;
24187c478bd9Sstevel@tonic-gate 	struct dk_cinfo dkinfo;
2419*5363f09cSarutz 	uint_t		nexpected_desc;
24207c478bd9Sstevel@tonic-gate 
2421*5363f09cSarutz 	debug(10, "Entering main_servproc[%d].\n", pthread_self());
24227c478bd9Sstevel@tonic-gate 
24237c478bd9Sstevel@tonic-gate 	didpp = dp;
24247c478bd9Sstevel@tonic-gate 	(void) mutex_lock(&svcstate_lock);
24257c478bd9Sstevel@tonic-gate 	svcstate = _SERVED;
24267c478bd9Sstevel@tonic-gate 	(void) mutex_unlock(&svcstate_lock);
24277c478bd9Sstevel@tonic-gate 
24287c478bd9Sstevel@tonic-gate 	reterror.cnum = SMEDIA_CNUM_ERROR;
24297c478bd9Sstevel@tonic-gate 	reterror.errnum = SMEDIA_FAILURE;
2430*5363f09cSarutz 
24317c478bd9Sstevel@tonic-gate 	if (argp == NULL) {
24327c478bd9Sstevel@tonic-gate 		debug(5, "argp is NULL\n");
24337c478bd9Sstevel@tonic-gate 		if (ndesc > 0)
24347c478bd9Sstevel@tonic-gate 			close_door_descs(dp, ndesc);
24357c478bd9Sstevel@tonic-gate 		my_door_return((char *)&reterror,
24367c478bd9Sstevel@tonic-gate 		    sizeof (smedia_reterror_t), 0, 0);
24377c478bd9Sstevel@tonic-gate 	}
24387c478bd9Sstevel@tonic-gate 
24397c478bd9Sstevel@tonic-gate 	req = (smedia_services_t *)((void *)argp);
2440*5363f09cSarutz 
24417c478bd9Sstevel@tonic-gate 	retok.cnum = req->in.cnum;
24427c478bd9Sstevel@tonic-gate 	retok.errnum = 0;
24437c478bd9Sstevel@tonic-gate 
24447c478bd9Sstevel@tonic-gate 	debug(5, "req = %s arg_size = 0x%x \n",
24457c478bd9Sstevel@tonic-gate 	    xlate_cnum(req->reqopen.cnum), arg_size);
24467c478bd9Sstevel@tonic-gate 
24477c478bd9Sstevel@tonic-gate 	/*
24487c478bd9Sstevel@tonic-gate 	 * Our caller may have passed more descriptors than we expected.
24497c478bd9Sstevel@tonic-gate 	 * If so, we silently close (and ignore) them.
24507c478bd9Sstevel@tonic-gate 	 */
2451*5363f09cSarutz 	nexpected_desc = (req->in.cnum == SMEDIA_CNUM_OPEN_FD) ? 1 : 0;
2452*5363f09cSarutz 	if (ndesc > nexpected_desc) {
2453*5363f09cSarutz 		close_door_descs(dp + nexpected_desc, ndesc - nexpected_desc);
2454*5363f09cSarutz 	}
24557c478bd9Sstevel@tonic-gate 
24567c478bd9Sstevel@tonic-gate 	switch (req->in.cnum) {
24577c478bd9Sstevel@tonic-gate 	default:
2458*5363f09cSarutz 		debug(5, "main_servproc: unknown command 0x%x\n",
2459*5363f09cSarutz 		    req->reqopen.cnum);
24607c478bd9Sstevel@tonic-gate 		break;
24617c478bd9Sstevel@tonic-gate 
24627c478bd9Sstevel@tonic-gate 	case SMEDIA_CNUM_PING:
24637c478bd9Sstevel@tonic-gate 		/*
24647c478bd9Sstevel@tonic-gate 		 * This service is to indicate that server is up and
24657c478bd9Sstevel@tonic-gate 		 * running. It is usually called from another instance of
24667c478bd9Sstevel@tonic-gate 		 * server that is started.
24677c478bd9Sstevel@tonic-gate 		 */
24687c478bd9Sstevel@tonic-gate 		reterror.cnum = SMEDIA_CNUM_PING;
24697c478bd9Sstevel@tonic-gate 		reterror.errnum = 0;
24707c478bd9Sstevel@tonic-gate 		my_door_return((char *)&reterror,
24717c478bd9Sstevel@tonic-gate 		    sizeof (smedia_reterror_t), 0, 0);
24727c478bd9Sstevel@tonic-gate 		break;
24737c478bd9Sstevel@tonic-gate 
24747c478bd9Sstevel@tonic-gate 
24757c478bd9Sstevel@tonic-gate 	case SMEDIA_CNUM_OPEN_FD:
24767c478bd9Sstevel@tonic-gate 
24777c478bd9Sstevel@tonic-gate 		debug(5, "ndesc = %d\n", ndesc);
24787c478bd9Sstevel@tonic-gate 		if (ndesc == 0) {
24797c478bd9Sstevel@tonic-gate 			my_door_return((char *)&reterror,
24807c478bd9Sstevel@tonic-gate 			    sizeof (smedia_reterror_t), 0, 0);
24817c478bd9Sstevel@tonic-gate 		}
2482*5363f09cSarutz 		debug(5, "Checking file descriptor of target device\n");
24837c478bd9Sstevel@tonic-gate 		if (fstat(didpp->d_data.d_desc.d_descriptor, &stat) < 0) {
2484*5363f09cSarutz 			warning(gettext("main_servproc:fstat failed. "
2485*5363f09cSarutz 			    "errno = %d\n"), errno);
24867c478bd9Sstevel@tonic-gate 			(void) close(didpp->d_data.d_desc.d_descriptor);
24877c478bd9Sstevel@tonic-gate 			my_door_return((char *)&reterror,
24887c478bd9Sstevel@tonic-gate 			    sizeof (smedia_reterror_t), 0, 0);
24897c478bd9Sstevel@tonic-gate 		}
24907c478bd9Sstevel@tonic-gate 		debug(5, "descriptor = %d st_mode = 0x%lx\n",
24917c478bd9Sstevel@tonic-gate 		    didpp->d_data.d_desc.d_descriptor,
24927c478bd9Sstevel@tonic-gate 		    stat.st_mode);
24937c478bd9Sstevel@tonic-gate 
24947c478bd9Sstevel@tonic-gate 		/* Obtain the credentials of the user */
24957c478bd9Sstevel@tonic-gate 		ret_val = door_cred(&door_credentials);
24967c478bd9Sstevel@tonic-gate 		if (ret_val < 0) {
2497*5363f09cSarutz 			warning(gettext("main_servproc:door_cred "
2498*5363f09cSarutz 			    "failed. errno = %d\n"), errno);
24997c478bd9Sstevel@tonic-gate 			(void) close(didpp->d_data.d_desc.d_descriptor);
25007c478bd9Sstevel@tonic-gate 			my_door_return((char *)&reterror,
25017c478bd9Sstevel@tonic-gate 			    sizeof (smedia_reterror_t), 0, 0);
25027c478bd9Sstevel@tonic-gate 		}
25037c478bd9Sstevel@tonic-gate 		if (ioctl(didpp->d_data.d_desc.d_descriptor, DKIOCINFO,
25047c478bd9Sstevel@tonic-gate 			&dkinfo) == -1) {
2505*5363f09cSarutz 			warning(gettext("main_servproc:DKIOCINFO failed. "
2506*5363f09cSarutz 			    "errno = %d\n"), errno);
25077c478bd9Sstevel@tonic-gate 			(void) close(didpp->d_data.d_desc.d_descriptor);
25087c478bd9Sstevel@tonic-gate 			my_door_return((char *)&reterror,
25097c478bd9Sstevel@tonic-gate 			    sizeof (smedia_reterror_t), 0, 0);
25107c478bd9Sstevel@tonic-gate 		}
25117c478bd9Sstevel@tonic-gate 
25127c478bd9Sstevel@tonic-gate 		ddata = (door_data_t *)calloc(1, sizeof (door_data_t));
25137c478bd9Sstevel@tonic-gate 		if (ddata == NULL) {
2514*5363f09cSarutz 			warning(gettext("main_servproc:calloc failed. "
2515*5363f09cSarutz 			    "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 		ddata->dd_stat = stat;
25217c478bd9Sstevel@tonic-gate 		ddata->dd_cred = door_credentials;
25227c478bd9Sstevel@tonic-gate 		ddata->dd_fd = didpp->d_data.d_desc.d_descriptor;
25237c478bd9Sstevel@tonic-gate 		ddata->dd_buf = NULL;
25247c478bd9Sstevel@tonic-gate 		ddata->dd_buf_len = 0;
25257c478bd9Sstevel@tonic-gate 		ddata->dd_buffd = -1;
25267c478bd9Sstevel@tonic-gate 		ddata->dd_sector_size = 0;
25277c478bd9Sstevel@tonic-gate 		ddata->dd_dkinfo = dkinfo;
2528*5363f09cSarutz 		debug(5, "ddata = 0x%p \n", (void *)ddata);
25297c478bd9Sstevel@tonic-gate 
2530*5363f09cSarutz 		/* specify a function that'll customize our door threads */
2531*5363f09cSarutz 		(void) door_server_create(sm_door_server_create);
25327c478bd9Sstevel@tonic-gate 		debug(5, "door_server_create called.\n");
25337c478bd9Sstevel@tonic-gate 
25347c478bd9Sstevel@tonic-gate 		(void) mutex_lock(&ddata->dd_lock);
25357c478bd9Sstevel@tonic-gate 
2536*5363f09cSarutz 		/* create Client Door */
2537*5363f09cSarutz 		ddata->dd_cdoor_descriptor =
2538*5363f09cSarutz 		    door_create(client_servproc,
2539*5363f09cSarutz 		    (void *)ddata, DOOR_PRIVATE | DOOR_NO_CANCEL | DOOR_UNREF);
2540*5363f09cSarutz 
2541*5363f09cSarutz 		if (ddata->dd_cdoor_descriptor < 0) {
2542*5363f09cSarutz 			/* then door_create() failed */
2543*5363f09cSarutz 			int err = errno;
2544*5363f09cSarutz 
2545*5363f09cSarutz 			(void) mutex_unlock(&ddata->dd_lock);
2546*5363f09cSarutz 
2547*5363f09cSarutz 			warning(gettext("main_servproc: door_create of Client "
2548*5363f09cSarutz 			    "Door failed = %d\n"), err);
25497c478bd9Sstevel@tonic-gate 			free(ddata);
2550*5363f09cSarutz 
2551*5363f09cSarutz 			/* close target device */
25527c478bd9Sstevel@tonic-gate 			(void) close(didpp->d_data.d_desc.d_descriptor);
2553*5363f09cSarutz 			my_door_return((char *)&reterror,
2554*5363f09cSarutz 			    sizeof (smedia_reterror_t), 0, 0);
25557c478bd9Sstevel@tonic-gate 		}
2556*5363f09cSarutz 
2557*5363f09cSarutz 		/* create Death Door */
2558*5363f09cSarutz 		ddata->dd_ddoor_descriptor =
2559*5363f09cSarutz 		    door_create(death_servproc, (void *)ddata,
2560*5363f09cSarutz 		    DOOR_REFUSE_DESC | DOOR_NO_CANCEL);
2561*5363f09cSarutz 		if (ddata->dd_ddoor_descriptor < 0) {
2562*5363f09cSarutz 			warning(gettext("main_servproc: door_create of Death "
2563*5363f09cSarutz 			    "Door failed = %d\n"), errno);
2564*5363f09cSarutz 		} else {
2565*5363f09cSarutz 			(void) door_setparam(ddata->dd_ddoor_descriptor,
2566*5363f09cSarutz 			    DOOR_PARAM_DATA_MAX, 0);
25677c478bd9Sstevel@tonic-gate 		}
2568*5363f09cSarutz 
2569*5363f09cSarutz 		debug(5, "main_servproc[%d]: Client Door = %d, "
2570*5363f09cSarutz 		    "Death Door = %d", pthread_self(),
2571*5363f09cSarutz 		    ddata->dd_cdoor_descriptor, ddata->dd_ddoor_descriptor);
25727c478bd9Sstevel@tonic-gate 
25737c478bd9Sstevel@tonic-gate 		audit_init(ddata);
25747c478bd9Sstevel@tonic-gate 
2575*5363f09cSarutz 		/* wait until sm_server_thread does door_bind() */
25767c478bd9Sstevel@tonic-gate 		(void) cond_wait(&ddata->dd_cv_bind, &ddata->dd_lock);
2577*5363f09cSarutz 
25787c478bd9Sstevel@tonic-gate 		(void) mutex_unlock(&ddata->dd_lock);
25797c478bd9Sstevel@tonic-gate 
25807c478bd9Sstevel@tonic-gate 		(void) mutex_lock(&svcstate_lock);
25817c478bd9Sstevel@tonic-gate 		svccount++;
25827c478bd9Sstevel@tonic-gate 		(void) mutex_unlock(&svcstate_lock);
25837c478bd9Sstevel@tonic-gate 
2584*5363f09cSarutz 		if (ddata->dd_ddoor_descriptor < 0) {
2585*5363f09cSarutz 			/* Return only the Client Door to the client. */
2586*5363f09cSarutz 			ddata->dd_cdoor.d_attributes = (DOOR_DESCRIPTOR);
2587*5363f09cSarutz 			my_door_return((char *)&reterror,
2588*5363f09cSarutz 			    sizeof (smedia_reterror_t), &ddata->dd_desc[0], 1);
2589*5363f09cSarutz 		} else {
2590*5363f09cSarutz 			/*
2591*5363f09cSarutz 			 * Return the Client Door and Death Door
2592*5363f09cSarutz 			 * to the client.
2593*5363f09cSarutz 			 */
2594*5363f09cSarutz 			debug(5, "retok.cnum = 0x%x\n", retok.cnum);
2595*5363f09cSarutz 			ddata->dd_cdoor.d_attributes = (DOOR_DESCRIPTOR);
2596*5363f09cSarutz 			ddata->dd_ddoor.d_attributes = (DOOR_DESCRIPTOR);
2597*5363f09cSarutz 			my_door_return((char *)&retok,
2598*5363f09cSarutz 			    sizeof (smedia_reterror_t), &ddata->dd_desc[0], 2);
2599*5363f09cSarutz 		}
26007c478bd9Sstevel@tonic-gate 		break;
26017c478bd9Sstevel@tonic-gate 	}
26027c478bd9Sstevel@tonic-gate 
2603*5363f09cSarutz 	debug(10, "exiting main_servproc. \n");
26047c478bd9Sstevel@tonic-gate 	my_door_return((char *)&reterror, sizeof (smedia_reterror_t), 0, 0);
26057c478bd9Sstevel@tonic-gate }
26067c478bd9Sstevel@tonic-gate 
26077c478bd9Sstevel@tonic-gate /* ARGSUSED */
26087c478bd9Sstevel@tonic-gate static void
26097c478bd9Sstevel@tonic-gate term_handler(int sig, siginfo_t *siginfo, void *sigctx)
26107c478bd9Sstevel@tonic-gate {
26117c478bd9Sstevel@tonic-gate 	warning(gettext("thread[%d]: Received signal %d. Ignoring it.\n"),
26127c478bd9Sstevel@tonic-gate 	    pthread_self(),
26137c478bd9Sstevel@tonic-gate 	    sig);
26147c478bd9Sstevel@tonic-gate }
26157c478bd9Sstevel@tonic-gate 
26167c478bd9Sstevel@tonic-gate /* ARGSUSED */
26177c478bd9Sstevel@tonic-gate static void
26187c478bd9Sstevel@tonic-gate hup_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 sig_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 badsig_handler(int sig, siginfo_t *siginfo, void *sigctx)
26377c478bd9Sstevel@tonic-gate {
26387c478bd9Sstevel@tonic-gate 	fatal(BADSIG_MSG, pthread_self(), sig, siginfo->si_addr,
26397c478bd9Sstevel@tonic-gate 	    siginfo->si_trapno,
26407c478bd9Sstevel@tonic-gate 	    siginfo->si_pc);
26417c478bd9Sstevel@tonic-gate }
26427c478bd9Sstevel@tonic-gate 
26437c478bd9Sstevel@tonic-gate /*ARGSUSED*/
2644*5363f09cSarutz static void *
26457c478bd9Sstevel@tonic-gate init_server(void *argp)
26467c478bd9Sstevel@tonic-gate {
26477c478bd9Sstevel@tonic-gate 	int	i, fd;
26487c478bd9Sstevel@tonic-gate 	struct	sigaction	act;
26497c478bd9Sstevel@tonic-gate 	struct	rlimit		rlim;
26507c478bd9Sstevel@tonic-gate 
26517c478bd9Sstevel@tonic-gate 	debug(10, "init_server  running\n");
26527c478bd9Sstevel@tonic-gate 
26537c478bd9Sstevel@tonic-gate 	(void) setlocale(LC_ALL, "");
26547c478bd9Sstevel@tonic-gate #if !defined(TEXT_DOMAIN)
26557c478bd9Sstevel@tonic-gate #define	TEXT_DOMAIN "SYS_TEST"
26567c478bd9Sstevel@tonic-gate #endif
26577c478bd9Sstevel@tonic-gate 	(void) textdomain(TEXT_DOMAIN);
26587c478bd9Sstevel@tonic-gate 
26597c478bd9Sstevel@tonic-gate 
26607c478bd9Sstevel@tonic-gate 	if (geteuid() != 0) fatal("Must be root to execute smserverd\n");
26617c478bd9Sstevel@tonic-gate 
26627c478bd9Sstevel@tonic-gate 
26637c478bd9Sstevel@tonic-gate 	/*
26647c478bd9Sstevel@tonic-gate 	 * setup signal handlers.
26657c478bd9Sstevel@tonic-gate 	 */
26667c478bd9Sstevel@tonic-gate 
26677c478bd9Sstevel@tonic-gate 	for (i = 0; i < N_BADSIGS; i++) {
26687c478bd9Sstevel@tonic-gate 		act.sa_sigaction = badsig_handler;
26697c478bd9Sstevel@tonic-gate 		(void) sigemptyset(&act.sa_mask);
26707c478bd9Sstevel@tonic-gate 		act.sa_flags = SA_SIGINFO;
26717c478bd9Sstevel@tonic-gate 		if (sigaction(badsigs[i], &act, NULL) == -1)
26727c478bd9Sstevel@tonic-gate 			warning(gettext(SIGACT_FAILED), strsignal(badsigs[i]),
26737c478bd9Sstevel@tonic-gate 				strerror(errno));
26747c478bd9Sstevel@tonic-gate 	}
26757c478bd9Sstevel@tonic-gate 
26767c478bd9Sstevel@tonic-gate 	/*
26777c478bd9Sstevel@tonic-gate 	 * Ignore SIGHUP until all the initialization is done.
26787c478bd9Sstevel@tonic-gate 	 */
26797c478bd9Sstevel@tonic-gate 	act.sa_handler = SIG_IGN;
26807c478bd9Sstevel@tonic-gate 	(void) sigemptyset(&act.sa_mask);
26817c478bd9Sstevel@tonic-gate 	act.sa_flags = 0;
26827c478bd9Sstevel@tonic-gate 	if (sigaction(SIGHUP, &act, NULL) == -1)
26837c478bd9Sstevel@tonic-gate 		warning(gettext(SIGACT_FAILED), strsignal(SIGHUP),
26847c478bd9Sstevel@tonic-gate 			strerror(errno));
26857c478bd9Sstevel@tonic-gate 	/*
26867c478bd9Sstevel@tonic-gate 	 * Increase file descriptor limit to the most it can possibly
26877c478bd9Sstevel@tonic-gate 	 * be.
26887c478bd9Sstevel@tonic-gate 	 */
26897c478bd9Sstevel@tonic-gate 	if (getrlimit(RLIMIT_NOFILE, &rlim) < 0) {
26907c478bd9Sstevel@tonic-gate 		warning(gettext("getrlimit for fd's failed; %m\n"));
26917c478bd9Sstevel@tonic-gate 	}
26927c478bd9Sstevel@tonic-gate 
26937c478bd9Sstevel@tonic-gate 	rlim.rlim_cur = rlim.rlim_max;
26947c478bd9Sstevel@tonic-gate 
26957c478bd9Sstevel@tonic-gate 	if (setrlimit(RLIMIT_NOFILE, &rlim) < 0) {
26967c478bd9Sstevel@tonic-gate 		warning(gettext("setrlimit for fd's failed; %m\n"));
26977c478bd9Sstevel@tonic-gate 	}
26987c478bd9Sstevel@tonic-gate 
2699*5363f09cSarutz 	server_door = door_create(main_servproc, (void *)&server_data, 0);
27007c478bd9Sstevel@tonic-gate 	if (server_door == -1) {
27017c478bd9Sstevel@tonic-gate 		debug(1, "main door_create");
27027c478bd9Sstevel@tonic-gate 		exit(1);
27037c478bd9Sstevel@tonic-gate 	}
27047c478bd9Sstevel@tonic-gate 
27057c478bd9Sstevel@tonic-gate 	(void) unlink(smedia_service);
27067c478bd9Sstevel@tonic-gate 	fd = open(smedia_service, O_RDWR|O_CREAT|O_EXCL, 0644);
27077c478bd9Sstevel@tonic-gate 	if (fd < 0) {
27087c478bd9Sstevel@tonic-gate 		debug(5, "could not open %s.\n", smedia_service);
27097c478bd9Sstevel@tonic-gate 		exit(1);
27107c478bd9Sstevel@tonic-gate 	}
27117c478bd9Sstevel@tonic-gate 	(void) close(fd);
27127c478bd9Sstevel@tonic-gate 	server_fd = fattach(server_door, smedia_service);
27137c478bd9Sstevel@tonic-gate 	if (server_fd == -1) {
27147c478bd9Sstevel@tonic-gate 		debug(1, "main fattach");
27157c478bd9Sstevel@tonic-gate 		exit(1);
27167c478bd9Sstevel@tonic-gate 	}
27177c478bd9Sstevel@tonic-gate 	server_data.sd_door = server_door;
27187c478bd9Sstevel@tonic-gate 	server_data.sd_fd = server_fd;
27197c478bd9Sstevel@tonic-gate 
27207c478bd9Sstevel@tonic-gate 	/*
27217c478bd9Sstevel@tonic-gate 	 * setup signal handlers for post-init
27227c478bd9Sstevel@tonic-gate 	 */
27237c478bd9Sstevel@tonic-gate 
27247c478bd9Sstevel@tonic-gate 	act.sa_sigaction = hup_handler;
27257c478bd9Sstevel@tonic-gate 	(void) sigemptyset(&act.sa_mask);
27267c478bd9Sstevel@tonic-gate 	act.sa_flags = SA_SIGINFO;
27277c478bd9Sstevel@tonic-gate 	if (sigaction(SIGHUP, &act, NULL) == -1)
27287c478bd9Sstevel@tonic-gate 		warning(gettext(SIGACT_FAILED), strsignal(SIGHUP),
27297c478bd9Sstevel@tonic-gate 		    strerror(errno));
27307c478bd9Sstevel@tonic-gate 
27317c478bd9Sstevel@tonic-gate 	act.sa_sigaction = term_handler;
27327c478bd9Sstevel@tonic-gate 	(void) sigemptyset(&act.sa_mask);
27337c478bd9Sstevel@tonic-gate 	act.sa_flags = SA_SIGINFO;
27347c478bd9Sstevel@tonic-gate 	if (sigaction(SIGTERM, &act, NULL) == -1)
27357c478bd9Sstevel@tonic-gate 		warning(gettext(SIGACT_FAILED), strsignal(SIGTERM),
27367c478bd9Sstevel@tonic-gate 		    strerror(errno));
27377c478bd9Sstevel@tonic-gate 
27387c478bd9Sstevel@tonic-gate 	act.sa_sigaction = sig_handler;
27397c478bd9Sstevel@tonic-gate 	(void) sigemptyset(&act.sa_mask);
27407c478bd9Sstevel@tonic-gate 	act.sa_flags = SA_SIGINFO;
27417c478bd9Sstevel@tonic-gate 	if (sigaction(SIGINT, &act, NULL) == -1)
27427c478bd9Sstevel@tonic-gate 		warning(gettext(SIGACT_FAILED), strsignal(SIGHUP),
27437c478bd9Sstevel@tonic-gate 		    strerror(errno));
27447c478bd9Sstevel@tonic-gate 
27457c478bd9Sstevel@tonic-gate 	act.sa_sigaction = sig_handler;
27467c478bd9Sstevel@tonic-gate 	(void) sigemptyset(&act.sa_mask);
27477c478bd9Sstevel@tonic-gate 	act.sa_flags = SA_SIGINFO;
27487c478bd9Sstevel@tonic-gate 	if (sigaction(SIGQUIT, &act, NULL) == -1)
27497c478bd9Sstevel@tonic-gate 		warning(gettext(SIGACT_FAILED), strsignal(SIGHUP),
27507c478bd9Sstevel@tonic-gate 		    strerror(errno));
27517c478bd9Sstevel@tonic-gate 	debug(10, "init_server completed successfully\n");
27527c478bd9Sstevel@tonic-gate 
27537c478bd9Sstevel@tonic-gate 	server_data.sd_init_state = INIT_DONE;
27547c478bd9Sstevel@tonic-gate 	return (NULL);
27557c478bd9Sstevel@tonic-gate }
27567c478bd9Sstevel@tonic-gate 
27577c478bd9Sstevel@tonic-gate static int
27587c478bd9Sstevel@tonic-gate server_exists()
27597c478bd9Sstevel@tonic-gate {
27607c478bd9Sstevel@tonic-gate 	door_arg_t		darg;
27617c478bd9Sstevel@tonic-gate 	smedia_reqping_t	req_ping;
27627c478bd9Sstevel@tonic-gate 	smedia_retping_t	*ret_ping;
27637c478bd9Sstevel@tonic-gate 	int			doorh;
27647c478bd9Sstevel@tonic-gate 	door_info_t		dinfo;
27657c478bd9Sstevel@tonic-gate 	char    rbuf[sizeof (smedia_services_t) + sizeof (door_desc_t)];
27667c478bd9Sstevel@tonic-gate 
27677c478bd9Sstevel@tonic-gate 	doorh = open(smedia_service, O_RDONLY);
27687c478bd9Sstevel@tonic-gate 	if (doorh < 0)
27697c478bd9Sstevel@tonic-gate 		return (0);
27707c478bd9Sstevel@tonic-gate 	if (door_info(doorh, &dinfo) < 0) {
27717c478bd9Sstevel@tonic-gate 		(void) close(doorh);
27727c478bd9Sstevel@tonic-gate 		return (0);
27737c478bd9Sstevel@tonic-gate 	}
27747c478bd9Sstevel@tonic-gate 	if (dinfo.di_attributes & DOOR_REVOKED) {
27757c478bd9Sstevel@tonic-gate 		(void) close(doorh);
27767c478bd9Sstevel@tonic-gate 		return (0);
27777c478bd9Sstevel@tonic-gate 	}
27787c478bd9Sstevel@tonic-gate 
27797c478bd9Sstevel@tonic-gate 	req_ping.cnum = SMEDIA_CNUM_PING;
27807c478bd9Sstevel@tonic-gate 
27817c478bd9Sstevel@tonic-gate 	darg.data_ptr = (char *)&req_ping;
27827c478bd9Sstevel@tonic-gate 	darg.data_size = sizeof (smedia_reqping_t);
27837c478bd9Sstevel@tonic-gate 	darg.desc_ptr = NULL;
27847c478bd9Sstevel@tonic-gate 	darg.desc_num = 0;
27857c478bd9Sstevel@tonic-gate 	darg.rbuf = rbuf;
27867c478bd9Sstevel@tonic-gate 	darg.rsize = sizeof (rbuf);
27877c478bd9Sstevel@tonic-gate 
27887c478bd9Sstevel@tonic-gate 	if (door_call(doorh, &darg) < 0) {
27897c478bd9Sstevel@tonic-gate 		(void) close(doorh);
27907c478bd9Sstevel@tonic-gate 		return (0);
27917c478bd9Sstevel@tonic-gate 	}
27927c478bd9Sstevel@tonic-gate 	ret_ping = (smedia_retping_t *)((void *)darg.data_ptr);
27937c478bd9Sstevel@tonic-gate 	if (ret_ping->cnum != SMEDIA_CNUM_PING) {
27947c478bd9Sstevel@tonic-gate 		(void) close(doorh);
27957c478bd9Sstevel@tonic-gate 		return (0);
27967c478bd9Sstevel@tonic-gate 	}
27977c478bd9Sstevel@tonic-gate 
27987c478bd9Sstevel@tonic-gate 	(void) close(doorh);
27997c478bd9Sstevel@tonic-gate 	return (1);
28007c478bd9Sstevel@tonic-gate }
28017c478bd9Sstevel@tonic-gate 
28027c478bd9Sstevel@tonic-gate static int
28037c478bd9Sstevel@tonic-gate get_run_level()
28047c478bd9Sstevel@tonic-gate {
28057c478bd9Sstevel@tonic-gate 	int	run_level;
28067c478bd9Sstevel@tonic-gate 	struct utmpx	*utmpp;
28077c478bd9Sstevel@tonic-gate 
28087c478bd9Sstevel@tonic-gate 	setutxent();
28097c478bd9Sstevel@tonic-gate 	while ((utmpp = getutxent()) != NULL) {
28107c478bd9Sstevel@tonic-gate 		if (utmpp->ut_type == RUN_LVL) {
28117c478bd9Sstevel@tonic-gate 			run_level = atoi(
28127c478bd9Sstevel@tonic-gate 				&utmpp->ut_line[strlen("run-level ")]);
28137c478bd9Sstevel@tonic-gate 		}
28147c478bd9Sstevel@tonic-gate 	}
28157c478bd9Sstevel@tonic-gate 	return (run_level);
28167c478bd9Sstevel@tonic-gate }
28177c478bd9Sstevel@tonic-gate 
28187c478bd9Sstevel@tonic-gate /*ARGSUSED*/
28197c478bd9Sstevel@tonic-gate static void *
28207c478bd9Sstevel@tonic-gate closedown(void *arg)
28217c478bd9Sstevel@tonic-gate {
28227c478bd9Sstevel@tonic-gate 
28237c478bd9Sstevel@tonic-gate 	int	current_run_level;
28247c478bd9Sstevel@tonic-gate 
28257c478bd9Sstevel@tonic-gate 	/*CONSTCOND*/
28267c478bd9Sstevel@tonic-gate #ifndef lint
28277c478bd9Sstevel@tonic-gate 	while (1) {
28287c478bd9Sstevel@tonic-gate #endif
28297c478bd9Sstevel@tonic-gate 		(void) sleep(SVC_CLOSEDOWN/2);
28307c478bd9Sstevel@tonic-gate 
28317c478bd9Sstevel@tonic-gate 		/*
28327c478bd9Sstevel@tonic-gate 		 * If the server was started at init level 1
28337c478bd9Sstevel@tonic-gate 		 * and the current init level is 1 then
28347c478bd9Sstevel@tonic-gate 		 * do not exit from server. This server will run
28357c478bd9Sstevel@tonic-gate 		 * until it is explicitly stopped by the user.
28367c478bd9Sstevel@tonic-gate 		 */
28377c478bd9Sstevel@tonic-gate 		if (svcstart_level == 1) {
28387c478bd9Sstevel@tonic-gate 			current_run_level = get_run_level();
28397c478bd9Sstevel@tonic-gate 			if (current_run_level == 1)
28407c478bd9Sstevel@tonic-gate #ifndef lint
28417c478bd9Sstevel@tonic-gate 				continue;
28427c478bd9Sstevel@tonic-gate #else
28437c478bd9Sstevel@tonic-gate 				return (NULL);
28447c478bd9Sstevel@tonic-gate #endif
28457c478bd9Sstevel@tonic-gate 			/*
28467c478bd9Sstevel@tonic-gate 			 * who ever started the server at level 1 has
28477c478bd9Sstevel@tonic-gate 			 * forgotten to stop the server. we will kill ourself.
28487c478bd9Sstevel@tonic-gate 			 */
28497c478bd9Sstevel@tonic-gate 			debug(5,
28507c478bd9Sstevel@tonic-gate 			"Terminating the server started at init level 1\n");
28517c478bd9Sstevel@tonic-gate 			exit(0);
28527c478bd9Sstevel@tonic-gate 		}
28537c478bd9Sstevel@tonic-gate 
28547c478bd9Sstevel@tonic-gate 		if (mutex_trylock(&svcstate_lock) != 0)
28557c478bd9Sstevel@tonic-gate #ifndef lint
28567c478bd9Sstevel@tonic-gate 			continue;
28577c478bd9Sstevel@tonic-gate #else
28587c478bd9Sstevel@tonic-gate 			return (NULL);
28597c478bd9Sstevel@tonic-gate #endif
28607c478bd9Sstevel@tonic-gate 		if (svcstate == _IDLE && svccount == 0) {
28617c478bd9Sstevel@tonic-gate 			int size;
28627c478bd9Sstevel@tonic-gate 			int i, openfd = 0;
28637c478bd9Sstevel@tonic-gate 
28647c478bd9Sstevel@tonic-gate 			size = svc_max_pollfd;
28657c478bd9Sstevel@tonic-gate 			for (i = 0; i < size && openfd < 2; i++)
28667c478bd9Sstevel@tonic-gate 				if (svc_pollfd[i].fd >= 0)
28677c478bd9Sstevel@tonic-gate 					openfd++;
28687c478bd9Sstevel@tonic-gate 			if (openfd <= 1) {
28697c478bd9Sstevel@tonic-gate 				debug(5,
28707c478bd9Sstevel@tonic-gate 				"Exiting the server from closedown routine.\n");
28717c478bd9Sstevel@tonic-gate 				exit(0);
28727c478bd9Sstevel@tonic-gate 			}
28737c478bd9Sstevel@tonic-gate 		} else
28747c478bd9Sstevel@tonic-gate 			svcstate = _IDLE;
28757c478bd9Sstevel@tonic-gate 
28767c478bd9Sstevel@tonic-gate 		(void) mutex_unlock(&svcstate_lock);
28777c478bd9Sstevel@tonic-gate #ifndef lint
28787c478bd9Sstevel@tonic-gate 	}
28797c478bd9Sstevel@tonic-gate #else
28807c478bd9Sstevel@tonic-gate 	return (NULL);
28817c478bd9Sstevel@tonic-gate #endif
28827c478bd9Sstevel@tonic-gate 
28837c478bd9Sstevel@tonic-gate }
28847c478bd9Sstevel@tonic-gate 
28857c478bd9Sstevel@tonic-gate static void
28867c478bd9Sstevel@tonic-gate usage()
28877c478bd9Sstevel@tonic-gate {
28887c478bd9Sstevel@tonic-gate 	warning(gettext("usage: %s [-L loglevel] level of debug information\n"),
28897c478bd9Sstevel@tonic-gate 		prog_name);
28907c478bd9Sstevel@tonic-gate }
28917c478bd9Sstevel@tonic-gate 
28927c478bd9Sstevel@tonic-gate 
28937c478bd9Sstevel@tonic-gate /*ARGSUSED*/
2894360e6f5eSmathue int
28957c478bd9Sstevel@tonic-gate main(int argc, char **argv)
28967c478bd9Sstevel@tonic-gate {
28977c478bd9Sstevel@tonic-gate 	int c;
28987c478bd9Sstevel@tonic-gate 	pthread_attr_t	attr;
28997c478bd9Sstevel@tonic-gate 
29007c478bd9Sstevel@tonic-gate 	(void) setlocale(LC_ALL, "");
29017c478bd9Sstevel@tonic-gate #if !defined(TEXT_DOMAIN)
29027c478bd9Sstevel@tonic-gate #define	TEXT_DOMAIN "SYS_TEST"
29037c478bd9Sstevel@tonic-gate #endif
29047c478bd9Sstevel@tonic-gate 	(void) textdomain(TEXT_DOMAIN);
29057c478bd9Sstevel@tonic-gate 
29067c478bd9Sstevel@tonic-gate 	prog_name = argv[0];
29077c478bd9Sstevel@tonic-gate 
29087c478bd9Sstevel@tonic-gate 	(void) sigset(SIGPIPE, SIG_IGN);
29097c478bd9Sstevel@tonic-gate 
29107c478bd9Sstevel@tonic-gate 	while ((c = getopt(argc, argv, "L:")) != -1) {
29117c478bd9Sstevel@tonic-gate 		switch (c) {
29127c478bd9Sstevel@tonic-gate 		case 'L':
29137c478bd9Sstevel@tonic-gate 			debug_level = atoi((char *)optarg);
29147c478bd9Sstevel@tonic-gate 			break;
29157c478bd9Sstevel@tonic-gate 		default:
29167c478bd9Sstevel@tonic-gate 			usage();
29177c478bd9Sstevel@tonic-gate 			break;
29187c478bd9Sstevel@tonic-gate 		}
29197c478bd9Sstevel@tonic-gate 	}
29207c478bd9Sstevel@tonic-gate 
29217c478bd9Sstevel@tonic-gate 	/*
29227c478bd9Sstevel@tonic-gate 	 * If stdin looks like a TLI endpoint, we assume
29237c478bd9Sstevel@tonic-gate 	 * that we were started by a port monitor. If
29247c478bd9Sstevel@tonic-gate 	 * t_getstate fails with TBADF, this is not a
29257c478bd9Sstevel@tonic-gate 	 * TLI endpoint.
29267c478bd9Sstevel@tonic-gate 	 */
29277c478bd9Sstevel@tonic-gate 	if (t_getstate(0) != -1 || t_errno != TBADF) {
29287c478bd9Sstevel@tonic-gate 		char *netid;
29297c478bd9Sstevel@tonic-gate 		struct netconfig *nconf = NULL;
29307c478bd9Sstevel@tonic-gate 		SVCXPRT *transp;
29317c478bd9Sstevel@tonic-gate 		int pmclose;
29327c478bd9Sstevel@tonic-gate 
29337c478bd9Sstevel@tonic-gate 		openlog(prog_name, LOG_PID, LOG_DAEMON);
29347c478bd9Sstevel@tonic-gate 
29357c478bd9Sstevel@tonic-gate 		debug(1, gettext("server started by port monitor.\n"));
29367c478bd9Sstevel@tonic-gate 		if ((netid = getenv("NLSPROVIDER")) == NULL) {
29377c478bd9Sstevel@tonic-gate 		/* started from inetd */
29387c478bd9Sstevel@tonic-gate 			pmclose = 1;
29397c478bd9Sstevel@tonic-gate 		} else {
29407c478bd9Sstevel@tonic-gate 			if ((nconf = getnetconfigent(netid)) == NULL)
29417c478bd9Sstevel@tonic-gate 				syslog(LOG_ERR, gettext(
29427c478bd9Sstevel@tonic-gate 					"cannot get transport info"));
29437c478bd9Sstevel@tonic-gate 
29447c478bd9Sstevel@tonic-gate 			pmclose = (t_getstate(0) != T_DATAXFER);
29457c478bd9Sstevel@tonic-gate 		}
29467c478bd9Sstevel@tonic-gate 		if ((transp = svc_tli_create(0, nconf, NULL, 0, 0)) == NULL) {
29477c478bd9Sstevel@tonic-gate 			syslog(LOG_ERR, gettext("cannot create server handle"));
29487c478bd9Sstevel@tonic-gate 			exit(1);
29497c478bd9Sstevel@tonic-gate 		}
29507c478bd9Sstevel@tonic-gate 		if (nconf)
29517c478bd9Sstevel@tonic-gate 			freenetconfigent(nconf);
29527c478bd9Sstevel@tonic-gate 		if (!svc_reg(transp, SMSERVERPROG, SMSERVERVERS,
29537c478bd9Sstevel@tonic-gate 			smserverprog_1, 0)) {
29547c478bd9Sstevel@tonic-gate 			syslog(LOG_ERR, gettext(
29557c478bd9Sstevel@tonic-gate 			"unable to register (SMSERVERPROG, SMSERVERVERS)."));
29567c478bd9Sstevel@tonic-gate 			exit(1);
29577c478bd9Sstevel@tonic-gate 		}
29587c478bd9Sstevel@tonic-gate 		svcstart_level = get_run_level();
29597c478bd9Sstevel@tonic-gate 		if (pmclose) {
29607c478bd9Sstevel@tonic-gate 			(void) pthread_attr_init(&attr);
29617c478bd9Sstevel@tonic-gate 			(void) pthread_attr_setscope(&attr,
29627c478bd9Sstevel@tonic-gate 				PTHREAD_SCOPE_SYSTEM | PTHREAD_CREATE_DETACHED);
29637c478bd9Sstevel@tonic-gate 			if (pthread_create(NULL, &attr, closedown, NULL) != 0) {
29647c478bd9Sstevel@tonic-gate 				syslog(LOG_ERR, gettext(
29657c478bd9Sstevel@tonic-gate 					"cannot create closedown thread"));
29667c478bd9Sstevel@tonic-gate 				exit(1);
29677c478bd9Sstevel@tonic-gate 			}
29687c478bd9Sstevel@tonic-gate 			(void) pthread_attr_destroy(&attr);
29697c478bd9Sstevel@tonic-gate 		}
29707c478bd9Sstevel@tonic-gate 		svc_run();
29717c478bd9Sstevel@tonic-gate 		exit(1);
29727c478bd9Sstevel@tonic-gate 		/* NOTREACHED */
29737c478bd9Sstevel@tonic-gate 	} else {
29747c478bd9Sstevel@tonic-gate 		/*
29757c478bd9Sstevel@tonic-gate 		 * Started by library or manually.
29767c478bd9Sstevel@tonic-gate 		 */
29777c478bd9Sstevel@tonic-gate 		/*
29787c478bd9Sstevel@tonic-gate 		 * Check to see if the server is already running.
29797c478bd9Sstevel@tonic-gate 		 * There is no need to log messages in the syslog file
29807c478bd9Sstevel@tonic-gate 		 * because server will get launched each time libsmedia
29817c478bd9Sstevel@tonic-gate 		 * library calls are made at init 1 level.
29827c478bd9Sstevel@tonic-gate 		 * We ensure that only one copy will run.
29837c478bd9Sstevel@tonic-gate 		 */
29847c478bd9Sstevel@tonic-gate 		debug(1, gettext("server started manually.\n"));
29857c478bd9Sstevel@tonic-gate 		if (server_exists()) {
29867c478bd9Sstevel@tonic-gate 			exit(0);
29877c478bd9Sstevel@tonic-gate 		}
29887c478bd9Sstevel@tonic-gate 		svcstart_level = get_run_level();
29897c478bd9Sstevel@tonic-gate 		(void) pthread_attr_init(&attr);
29907c478bd9Sstevel@tonic-gate 		(void) pthread_attr_setscope(&attr,
29917c478bd9Sstevel@tonic-gate 			PTHREAD_SCOPE_SYSTEM | PTHREAD_CREATE_DETACHED);
29927c478bd9Sstevel@tonic-gate 		if (pthread_create(NULL, &attr, closedown, NULL) != 0) {
29937c478bd9Sstevel@tonic-gate 			syslog(LOG_ERR, gettext(
29947c478bd9Sstevel@tonic-gate 				"cannot create closedown thread"));
29957c478bd9Sstevel@tonic-gate 			exit(1);
29967c478bd9Sstevel@tonic-gate 		}
29977c478bd9Sstevel@tonic-gate 		(void) pthread_attr_destroy(&attr);
29987c478bd9Sstevel@tonic-gate 		(void) init_server(NULL);
29997c478bd9Sstevel@tonic-gate 		for (;;) (void) pause();
30007c478bd9Sstevel@tonic-gate 	}
3001360e6f5eSmathue 	return (0);
30027c478bd9Sstevel@tonic-gate }
30037c478bd9Sstevel@tonic-gate 
30047c478bd9Sstevel@tonic-gate 
30057c478bd9Sstevel@tonic-gate /*ARGSUSED*/
30067c478bd9Sstevel@tonic-gate static int32_t
30077c478bd9Sstevel@tonic-gate scsi_floppy_write_protect(int32_t fd, smwp_state_t *wp)
30087c478bd9Sstevel@tonic-gate {
30097c478bd9Sstevel@tonic-gate 	debug(5, "Invalid mode\n");
30107c478bd9Sstevel@tonic-gate 	errno = ENOTSUP;
30117c478bd9Sstevel@tonic-gate 
30127c478bd9Sstevel@tonic-gate 	return (-1);
30137c478bd9Sstevel@tonic-gate }
30147c478bd9Sstevel@tonic-gate 
30157c478bd9Sstevel@tonic-gate /*
30167c478bd9Sstevel@tonic-gate  * Generate standard geometry information for SCSI floppy devices. And
30177c478bd9Sstevel@tonic-gate  * register the geometry with the SCSI driver. This will expand as more
30187c478bd9Sstevel@tonic-gate  * formats are added.
30197c478bd9Sstevel@tonic-gate  */
30207c478bd9Sstevel@tonic-gate 
30217c478bd9Sstevel@tonic-gate /*ARGSUSED*/
30227c478bd9Sstevel@tonic-gate static int32_t
30237c478bd9Sstevel@tonic-gate get_floppy_geom(int32_t fd, uint32_t capacity, struct dk_geom *dkgeom)
30247c478bd9Sstevel@tonic-gate {
30257c478bd9Sstevel@tonic-gate 
30267c478bd9Sstevel@tonic-gate 
30277c478bd9Sstevel@tonic-gate 	debug(5, "get_floppy_geom: capacity = 0x%x\n", capacity);
30287c478bd9Sstevel@tonic-gate 
30297c478bd9Sstevel@tonic-gate 	switch (capacity) {
30307c478bd9Sstevel@tonic-gate 
30317c478bd9Sstevel@tonic-gate 		case 0x5A0:
30327c478bd9Sstevel@tonic-gate 			/* Double Density 720K */
30337c478bd9Sstevel@tonic-gate 			dkgeom->dkg_pcyl = 80;
30347c478bd9Sstevel@tonic-gate 			dkgeom->dkg_ncyl = 80;
30357c478bd9Sstevel@tonic-gate 			dkgeom->dkg_nhead = 2;
30367c478bd9Sstevel@tonic-gate 			dkgeom->dkg_nsect = 9;
30377c478bd9Sstevel@tonic-gate 			break;
30387c478bd9Sstevel@tonic-gate 		case 0x4D0:
30397c478bd9Sstevel@tonic-gate 			/* High Density 1.25MB */
30407c478bd9Sstevel@tonic-gate 			dkgeom->dkg_pcyl = 77;
30417c478bd9Sstevel@tonic-gate 			dkgeom->dkg_ncyl = 77;
30427c478bd9Sstevel@tonic-gate 			dkgeom->dkg_nhead = 2;
30437c478bd9Sstevel@tonic-gate 			dkgeom->dkg_nsect = 9;
30447c478bd9Sstevel@tonic-gate 			break;
30457c478bd9Sstevel@tonic-gate 		case 0xB40:
30467c478bd9Sstevel@tonic-gate 			/* High Density 1.44MB */
30477c478bd9Sstevel@tonic-gate 
30487c478bd9Sstevel@tonic-gate 			dkgeom->dkg_pcyl = 80;
30497c478bd9Sstevel@tonic-gate 			dkgeom->dkg_ncyl = 80;
30507c478bd9Sstevel@tonic-gate 			dkgeom->dkg_nhead = 2;
30517c478bd9Sstevel@tonic-gate 			dkgeom->dkg_nsect = 18;
30527c478bd9Sstevel@tonic-gate 			break;
30537c478bd9Sstevel@tonic-gate 		case 0x3C300:
30547c478bd9Sstevel@tonic-gate 			/* Ultra High density ls-120 120MB */
30557c478bd9Sstevel@tonic-gate 			dkgeom->dkg_pcyl = 963;
30567c478bd9Sstevel@tonic-gate 			dkgeom->dkg_ncyl = 963;
30577c478bd9Sstevel@tonic-gate 			dkgeom->dkg_nhead = 8;
30587c478bd9Sstevel@tonic-gate 			dkgeom->dkg_nsect = 32;
30597c478bd9Sstevel@tonic-gate 			break;
30607c478bd9Sstevel@tonic-gate 		default:
30617c478bd9Sstevel@tonic-gate 			debug(5, "unknown capacity type %d\n", capacity);
30627c478bd9Sstevel@tonic-gate 			return (-1);
30637c478bd9Sstevel@tonic-gate 
30647c478bd9Sstevel@tonic-gate 	}
30657c478bd9Sstevel@tonic-gate 	debug(5, "get_floppy_geom: setting cyl = %d, nsect = %d, head = %d",
30667c478bd9Sstevel@tonic-gate 		dkgeom->dkg_pcyl, dkgeom->dkg_nhead, dkgeom->dkg_nsect);
30677c478bd9Sstevel@tonic-gate 	return (0);
30687c478bd9Sstevel@tonic-gate 
30697c478bd9Sstevel@tonic-gate }
30707c478bd9Sstevel@tonic-gate /* ARGSUSED */
3071*5363f09cSarutz static int32_t
30727c478bd9Sstevel@tonic-gate scsi_floppy_format(int32_t fd, uint_t flavor, uint_t mode)
30737c478bd9Sstevel@tonic-gate {
30747c478bd9Sstevel@tonic-gate 	struct uscsi_cmd ucmd;
30757c478bd9Sstevel@tonic-gate 	uchar_t		cdb[12];
30767c478bd9Sstevel@tonic-gate 	int32_t		ret_val;
30777c478bd9Sstevel@tonic-gate 	uint32_t	capacity, blocksize;
30787c478bd9Sstevel@tonic-gate 	uchar_t		data[12];
30797c478bd9Sstevel@tonic-gate 	char 		rq_data[RQ_LEN];
30807c478bd9Sstevel@tonic-gate 	int		i;
30817c478bd9Sstevel@tonic-gate 	struct dk_geom	dkgeom;
30827c478bd9Sstevel@tonic-gate 
30837c478bd9Sstevel@tonic-gate 	debug(5, "scsi_floppy_format:\n");
30847c478bd9Sstevel@tonic-gate 
30857c478bd9Sstevel@tonic-gate 	if ((mode != SM_FORMAT_IMMEDIATE) && (mode != SM_FORMAT_BLOCKED)) {
30867c478bd9Sstevel@tonic-gate 		errno = ENOTSUP;
30877c478bd9Sstevel@tonic-gate 
30887c478bd9Sstevel@tonic-gate 		return (-1);
30897c478bd9Sstevel@tonic-gate 	}
30907c478bd9Sstevel@tonic-gate 
30917c478bd9Sstevel@tonic-gate 	switch (flavor) {
30927c478bd9Sstevel@tonic-gate 		case SM_FORMAT_QUICK :
30937c478bd9Sstevel@tonic-gate 			debug(1, "Format not supported\n");
30947c478bd9Sstevel@tonic-gate 			errno = ENOTSUP;
30957c478bd9Sstevel@tonic-gate 			return (-1);
30967c478bd9Sstevel@tonic-gate 		case SM_FORMAT_FORCE :
30977c478bd9Sstevel@tonic-gate 			break;
30987c478bd9Sstevel@tonic-gate 		case SM_FORMAT_LONG :
30997c478bd9Sstevel@tonic-gate 			break;
31007c478bd9Sstevel@tonic-gate 
31017c478bd9Sstevel@tonic-gate 		default :
31027c478bd9Sstevel@tonic-gate 			debug(1, "Format option not specified!!\n");
31037c478bd9Sstevel@tonic-gate 			errno = ENOTSUP;
31047c478bd9Sstevel@tonic-gate 			return (-1);
31057c478bd9Sstevel@tonic-gate 	}
31067c478bd9Sstevel@tonic-gate 
31077c478bd9Sstevel@tonic-gate 	ret_val = get_media_capacity(fd, &capacity, &blocksize);
31087c478bd9Sstevel@tonic-gate 
31097c478bd9Sstevel@tonic-gate 	if (capacity >= 0x3C300) {
31107c478bd9Sstevel@tonic-gate 		/*
31117c478bd9Sstevel@tonic-gate 		 * It's an LS-120 media, it does not support track
31127c478bd9Sstevel@tonic-gate 		 * formatting.
31137c478bd9Sstevel@tonic-gate 		 */
31147c478bd9Sstevel@tonic-gate 		return (scsi_ls120_format(fd, flavor, capacity, blocksize));
31157c478bd9Sstevel@tonic-gate 	}
31167c478bd9Sstevel@tonic-gate 
31177c478bd9Sstevel@tonic-gate 	ret_val = get_floppy_geom(fd, capacity, &dkgeom);
31187c478bd9Sstevel@tonic-gate 		if (ret_val) {
31197c478bd9Sstevel@tonic-gate 			errno = ENOTSUP;
31207c478bd9Sstevel@tonic-gate 			return (-1);
31217c478bd9Sstevel@tonic-gate 		}
31227c478bd9Sstevel@tonic-gate 
31237c478bd9Sstevel@tonic-gate 	(void) memset((void *)&data, 0, sizeof (data));
31247c478bd9Sstevel@tonic-gate 	(void) memset((void *)&ucmd, 0, sizeof (ucmd));
31257c478bd9Sstevel@tonic-gate 	(void) memset((void *)&cdb, 0, sizeof (cdb));
31267c478bd9Sstevel@tonic-gate 
31277c478bd9Sstevel@tonic-gate 	/* retrieve size discriptor of inserted media */
31287c478bd9Sstevel@tonic-gate 	cdb[0] = SCMD_FORMAT;	/* format */
31297c478bd9Sstevel@tonic-gate 
31307c478bd9Sstevel@tonic-gate 	/*
31317c478bd9Sstevel@tonic-gate 	 * Defect list sent by initiator is a complete list of defects.
31327c478bd9Sstevel@tonic-gate 	 */
31337c478bd9Sstevel@tonic-gate 
31347c478bd9Sstevel@tonic-gate 	cdb[1] = (FMTDATA | 0x7);
31357c478bd9Sstevel@tonic-gate 
31367c478bd9Sstevel@tonic-gate 	cdb[8] = 0xC;   /* parameter list length */
31377c478bd9Sstevel@tonic-gate 	data[3] = 0x8;	/* should be always 8 */
31387c478bd9Sstevel@tonic-gate 
31397c478bd9Sstevel@tonic-gate 	data[4] = (uchar_t)(capacity >> 24);
31407c478bd9Sstevel@tonic-gate 	data[5] = (uchar_t)(capacity >> 16);
31417c478bd9Sstevel@tonic-gate 	data[6] = (uchar_t)(capacity >> 8);
31427c478bd9Sstevel@tonic-gate 	data[7] = (uchar_t)capacity;
31437c478bd9Sstevel@tonic-gate 
31447c478bd9Sstevel@tonic-gate 	data[9] = (uchar_t)(blocksize >> 16);
31457c478bd9Sstevel@tonic-gate 	data[10] = (uchar_t)(blocksize >> 8);
31467c478bd9Sstevel@tonic-gate 	data[11] = (uchar_t)blocksize;
31477c478bd9Sstevel@tonic-gate 
31487c478bd9Sstevel@tonic-gate 	ucmd.uscsi_cdb = (caddr_t)&cdb;
31497c478bd9Sstevel@tonic-gate 	ucmd.uscsi_cdblen = CDB_GROUP5;
31507c478bd9Sstevel@tonic-gate 	ucmd.uscsi_bufaddr = (caddr_t)data;
31517c478bd9Sstevel@tonic-gate 	ucmd.uscsi_buflen = sizeof (data);
31527c478bd9Sstevel@tonic-gate 	ucmd.uscsi_timeout = 0x15;
31537c478bd9Sstevel@tonic-gate 	ucmd.uscsi_rqlen = RQ_LEN;
31547c478bd9Sstevel@tonic-gate 	ucmd.uscsi_rqbuf = rq_data;
31557c478bd9Sstevel@tonic-gate 
31567c478bd9Sstevel@tonic-gate 	debug(5, "cdb: %x %x %x ... %x", cdb[0], cdb[1], cdb[2], cdb[8]);
31577c478bd9Sstevel@tonic-gate 	debug(5, "data: %x %x %x %x\n", data[0], data[1], data[2], data[3]);
31587c478bd9Sstevel@tonic-gate 	debug(5, "    : %x %x %x %x\n", data[4], data[5], data[6], data[7]);
31597c478bd9Sstevel@tonic-gate 	debug(5, "    : %x %x %x %x\n", data[8], data[9], data[10], data[11]);
31607c478bd9Sstevel@tonic-gate 
31617c478bd9Sstevel@tonic-gate 	for (i = 0; i < dkgeom.dkg_pcyl; i++) {	/* number of tracks */
31627c478bd9Sstevel@tonic-gate 		data[1] = (0xb0 | FOV);
31637c478bd9Sstevel@tonic-gate 		cdb[2] = i;
31647c478bd9Sstevel@tonic-gate 
31657c478bd9Sstevel@tonic-gate 		(void) fflush(stdout);
31667c478bd9Sstevel@tonic-gate 		ret_val = do_uscsi_cmd(fd, &ucmd, USCSI_WRITE|USCSI_RQENABLE);
31677c478bd9Sstevel@tonic-gate 		info("format side 0 returned : 0x%x\n", ret_val);
31687c478bd9Sstevel@tonic-gate 
31697c478bd9Sstevel@tonic-gate 		if (ret_val || ucmd.uscsi_status) {
31707c478bd9Sstevel@tonic-gate 			debug(5, "Retrieving media info failed: %d - %d\n",
31717c478bd9Sstevel@tonic-gate 			    ret_val, ucmd.uscsi_status);
31727c478bd9Sstevel@tonic-gate 			if ((rq_data[2] == KEY_DATA_PROTECT) &&
31737c478bd9Sstevel@tonic-gate 			    (rq_data[12] == 0x30) && (rq_data[13] == 0)) {
31747c478bd9Sstevel@tonic-gate 				debug(5, "Invalid command for media\n");
31757c478bd9Sstevel@tonic-gate 				errno = EINVAL;
31767c478bd9Sstevel@tonic-gate 			}
31777c478bd9Sstevel@tonic-gate 
31787c478bd9Sstevel@tonic-gate 			if ((rq_data[2] == KEY_NOT_READY) &&
31797c478bd9Sstevel@tonic-gate 			    (rq_data[12] == 0x30)) {
31807c478bd9Sstevel@tonic-gate 				debug(5, "Incompatible media.\n");
31817c478bd9Sstevel@tonic-gate 				errno = EINVAL;
31827c478bd9Sstevel@tonic-gate 			}
31837c478bd9Sstevel@tonic-gate 
31847c478bd9Sstevel@tonic-gate 			return (-1);
31857c478bd9Sstevel@tonic-gate 		}
31867c478bd9Sstevel@tonic-gate 		data[1] = (0xb0 | FOV) + 1;
31877c478bd9Sstevel@tonic-gate 		ret_val = do_uscsi_cmd(fd, &ucmd, USCSI_WRITE|USCSI_RQENABLE);
31887c478bd9Sstevel@tonic-gate 		info("format side 1 returned : 0x%x\n", ret_val);
31897c478bd9Sstevel@tonic-gate 
31907c478bd9Sstevel@tonic-gate 		if (ret_val || ucmd.uscsi_status) {
31917c478bd9Sstevel@tonic-gate 			debug(5, "Retrieving media info failed: %d - %d\n",
31927c478bd9Sstevel@tonic-gate 			    ret_val, ucmd.uscsi_status);
31937c478bd9Sstevel@tonic-gate 			if ((rq_data[2] == KEY_DATA_PROTECT) &&
31947c478bd9Sstevel@tonic-gate 			    (rq_data[12] == 0x30) && (rq_data[13] == 0)) {
31957c478bd9Sstevel@tonic-gate 				(void) info("Invalid command for media\n");
31967c478bd9Sstevel@tonic-gate 				errno = EINVAL;
31977c478bd9Sstevel@tonic-gate 			}
31987c478bd9Sstevel@tonic-gate 
31997c478bd9Sstevel@tonic-gate 			if ((rq_data[2] == KEY_NOT_READY) &&
32007c478bd9Sstevel@tonic-gate 			    (rq_data[12] == 0x30)) {
32017c478bd9Sstevel@tonic-gate 				debug(5, "Incompatible media.\n");
32027c478bd9Sstevel@tonic-gate 				errno = EINVAL;
32037c478bd9Sstevel@tonic-gate 			}
32047c478bd9Sstevel@tonic-gate 
32057c478bd9Sstevel@tonic-gate 			return (-1);
32067c478bd9Sstevel@tonic-gate 		}
32077c478bd9Sstevel@tonic-gate 	}
32087c478bd9Sstevel@tonic-gate 
32097c478bd9Sstevel@tonic-gate 	debug(5, "formatting done!");
32107c478bd9Sstevel@tonic-gate 	return (0);
32117c478bd9Sstevel@tonic-gate }
32127c478bd9Sstevel@tonic-gate 
32137c478bd9Sstevel@tonic-gate 
32147c478bd9Sstevel@tonic-gate /* ARGSUSED */
3215*5363f09cSarutz static int32_t
32167c478bd9Sstevel@tonic-gate scsi_floppy_media_status(int32_t fd)
32177c478bd9Sstevel@tonic-gate {
32187c478bd9Sstevel@tonic-gate 	struct mode_header_g1 modeh;
32197c478bd9Sstevel@tonic-gate 	struct uscsi_cmd ucmd;
32207c478bd9Sstevel@tonic-gate 	uchar_t cdb[10];
32217c478bd9Sstevel@tonic-gate 	int32_t ret_val;
32227c478bd9Sstevel@tonic-gate 	int32_t cur_status;
32237c478bd9Sstevel@tonic-gate 	char rq_data[RQ_LEN];
32247c478bd9Sstevel@tonic-gate 
32257c478bd9Sstevel@tonic-gate 	debug(5, "SCSI MEDIA STATUS CALLED \n");
32267c478bd9Sstevel@tonic-gate 
32277c478bd9Sstevel@tonic-gate 	(void) memset((void *) &modeh, 0, sizeof (modeh));
32287c478bd9Sstevel@tonic-gate 	(void) memset((void *) &ucmd, 0, sizeof (ucmd));
32297c478bd9Sstevel@tonic-gate 	(void) memset(cdb, 0, sizeof (cdb));
32307c478bd9Sstevel@tonic-gate 	/*
32317c478bd9Sstevel@tonic-gate 	 * issue 10 byte mode sense (0x5A)
32327c478bd9Sstevel@tonic-gate 	 */
32337c478bd9Sstevel@tonic-gate 	cdb[0] = SCMD_MODE_SENSE_G1;
32347c478bd9Sstevel@tonic-gate 	cdb[7] = sizeof (modeh) >> 8;
32357c478bd9Sstevel@tonic-gate 	cdb[8] = sizeof (modeh) & 0xff;
32367c478bd9Sstevel@tonic-gate 
32377c478bd9Sstevel@tonic-gate 	ucmd.uscsi_cdb = (caddr_t)cdb;
32387c478bd9Sstevel@tonic-gate 	ucmd.uscsi_cdblen = CDB_GROUP1;
32397c478bd9Sstevel@tonic-gate 	ucmd.uscsi_bufaddr = (caddr_t)&modeh;
32407c478bd9Sstevel@tonic-gate 	ucmd.uscsi_buflen = sizeof (modeh);
32417c478bd9Sstevel@tonic-gate 	ucmd.uscsi_timeout = 120;	/* If 0, HBA hangs forever */
32427c478bd9Sstevel@tonic-gate 	ucmd.uscsi_rqlen = RQ_LEN;
32437c478bd9Sstevel@tonic-gate 	ucmd.uscsi_rqbuf = rq_data;
32447c478bd9Sstevel@tonic-gate 	ret_val = do_uscsi_cmd(fd, &ucmd, USCSI_READ|USCSI_RQENABLE);
32457c478bd9Sstevel@tonic-gate 	if (ret_val || ucmd.uscsi_status) {
32467c478bd9Sstevel@tonic-gate 		/*
32477c478bd9Sstevel@tonic-gate 		 * UFI devices may not respond to the 0 mode page.
32487c478bd9Sstevel@tonic-gate 		 * retry with the error recovery page(0x01)
32497c478bd9Sstevel@tonic-gate 		 */
32507c478bd9Sstevel@tonic-gate 		if (ucmd.uscsi_status & STATUS_CHECK) {
32517c478bd9Sstevel@tonic-gate 			cdb[2] = 0x1;	/* page code */
32527c478bd9Sstevel@tonic-gate 			ret_val = do_uscsi_cmd(fd, &ucmd,
32537c478bd9Sstevel@tonic-gate 					USCSI_READ|USCSI_RQENABLE);
32547c478bd9Sstevel@tonic-gate 		}
32557c478bd9Sstevel@tonic-gate 		if (ret_val || ucmd.uscsi_status) {
32567c478bd9Sstevel@tonic-gate 			debug(1, "Modesense failed: %d - %d\n",
32577c478bd9Sstevel@tonic-gate 				ret_val, ucmd.uscsi_status);
32587c478bd9Sstevel@tonic-gate 			return (-1);
32597c478bd9Sstevel@tonic-gate 		}
32607c478bd9Sstevel@tonic-gate 	}
32617c478bd9Sstevel@tonic-gate 	debug(5, "Modesense succeeded: 0x%x\n", modeh.device_specific);
32627c478bd9Sstevel@tonic-gate 
32637c478bd9Sstevel@tonic-gate 	if (modeh.device_specific & 0x80) {
32647c478bd9Sstevel@tonic-gate 		cur_status = SM_WRITE_PROTECT_NOPASSWD;
32657c478bd9Sstevel@tonic-gate 	} else {
32667c478bd9Sstevel@tonic-gate 		cur_status = SM_WRITE_PROTECT_DISABLE;
32677c478bd9Sstevel@tonic-gate 	}
32687c478bd9Sstevel@tonic-gate 	return (cur_status);
32697c478bd9Sstevel@tonic-gate }
3270