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