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