xref: /titanic_53/usr/src/cmd/smserverd/smediad.c (revision 360e6f5e7a29d5950aa1985f56811731715da7e5)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
57c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
67c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
77c478bd9Sstevel@tonic-gate  * with the License.
87c478bd9Sstevel@tonic-gate  *
97c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
107c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
117c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
127c478bd9Sstevel@tonic-gate  * and limitations under the License.
137c478bd9Sstevel@tonic-gate  *
147c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
157c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
167c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
177c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
187c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
197c478bd9Sstevel@tonic-gate  *
207c478bd9Sstevel@tonic-gate  * CDDL HEADER END
217c478bd9Sstevel@tonic-gate  */
227c478bd9Sstevel@tonic-gate /*
237c478bd9Sstevel@tonic-gate  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
247c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
257c478bd9Sstevel@tonic-gate  */
267c478bd9Sstevel@tonic-gate 
277c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
287c478bd9Sstevel@tonic-gate 
297c478bd9Sstevel@tonic-gate #include <stdio.h>
307c478bd9Sstevel@tonic-gate #include <errno.h>
317c478bd9Sstevel@tonic-gate #include <ctype.h>
327c478bd9Sstevel@tonic-gate #include <syslog.h>
337c478bd9Sstevel@tonic-gate #include <signal.h>
347c478bd9Sstevel@tonic-gate #include <limits.h>
357c478bd9Sstevel@tonic-gate #include <unistd.h>
367c478bd9Sstevel@tonic-gate #include <sys/types.h>
377c478bd9Sstevel@tonic-gate #include <sys/mman.h>
387c478bd9Sstevel@tonic-gate #include <stdlib.h>
397c478bd9Sstevel@tonic-gate #include <sys/stat.h>
407c478bd9Sstevel@tonic-gate #include <sys/mkdev.h>
417c478bd9Sstevel@tonic-gate #include <fcntl.h>
427c478bd9Sstevel@tonic-gate #include <sys/scsi/scsi.h>
437c478bd9Sstevel@tonic-gate #include <sys/scsi/generic/commands.h>
447c478bd9Sstevel@tonic-gate #include <string.h>
457c478bd9Sstevel@tonic-gate #include <door.h>
467c478bd9Sstevel@tonic-gate #include <pwd.h>
477c478bd9Sstevel@tonic-gate #include <thread.h>
487c478bd9Sstevel@tonic-gate #include <synch.h>
497c478bd9Sstevel@tonic-gate #include <pthread.h>
507c478bd9Sstevel@tonic-gate #include <locale.h>
517c478bd9Sstevel@tonic-gate #include <sys/resource.h>
527c478bd9Sstevel@tonic-gate #include <netconfig.h>
537c478bd9Sstevel@tonic-gate #include <sys/smedia.h>
547c478bd9Sstevel@tonic-gate #include "smserver.h"
557c478bd9Sstevel@tonic-gate #include <rpc/rpc.h>
567c478bd9Sstevel@tonic-gate #include "smed.h"
577c478bd9Sstevel@tonic-gate #include "myaudit.h"
587c478bd9Sstevel@tonic-gate #include <bsm/libbsm.h>
597c478bd9Sstevel@tonic-gate #include <bsm/audit_uevents.h>
607c478bd9Sstevel@tonic-gate #include <utmpx.h>
617c478bd9Sstevel@tonic-gate 
627c478bd9Sstevel@tonic-gate 
637c478bd9Sstevel@tonic-gate /*
647c478bd9Sstevel@tonic-gate  * The comments below would help in understanding what is being attempted
657c478bd9Sstevel@tonic-gate  * in the server.
667c478bd9Sstevel@tonic-gate  *
677c478bd9Sstevel@tonic-gate  * The server can be started either by inetd or by the client directly.
687c478bd9Sstevel@tonic-gate  * Normally the server is started by inetd when the client invokes the
697c478bd9Sstevel@tonic-gate  * appropriate libsmedia library call(smedia_get_handle).
707c478bd9Sstevel@tonic-gate  * However since the inetd runs only at init level 2 and above a mechanism
717c478bd9Sstevel@tonic-gate  * is provided for the server to be started if an attempt is made to use
727c478bd9Sstevel@tonic-gate  * the libsmedia calls in maintenence mode(init level 1).
737c478bd9Sstevel@tonic-gate  * The main() routine determines how the server was invoked and takes
747c478bd9Sstevel@tonic-gate  * the necessary action.
757c478bd9Sstevel@tonic-gate  * When started by inetd it registers itself as an RPC program.
767c478bd9Sstevel@tonic-gate  * The server also implements a mechanism by which it removes itself
777c478bd9Sstevel@tonic-gate  * after a period of inactivity. The period of inactivity is specified
787c478bd9Sstevel@tonic-gate  * by SVC_CLOSEDOWN which is set at 180 secs.
797c478bd9Sstevel@tonic-gate  * The logic of detecting inactivity is as follows:
807c478bd9Sstevel@tonic-gate  *
817c478bd9Sstevel@tonic-gate  * Two variables svcstate and svccount are used to determine if the server
827c478bd9Sstevel@tonic-gate  * is IDLE.
837c478bd9Sstevel@tonic-gate  * The svcstate is set to 1(_SERVED) when ever the server does any operation
847c478bd9Sstevel@tonic-gate  * on behalf of the client.
857c478bd9Sstevel@tonic-gate  * The svccount indicates the number of active clients who have established
867c478bd9Sstevel@tonic-gate  * a connection with the server. A connection is established when the
877c478bd9Sstevel@tonic-gate  * libsmedia call smedia_get_handle() succeeds.
887c478bd9Sstevel@tonic-gate  * The connection is broken when the client calls smedia_free_handle() OR
897c478bd9Sstevel@tonic-gate  * exits.
907c478bd9Sstevel@tonic-gate  * A thread called closedown is started up when server is started.
917c478bd9Sstevel@tonic-gate  * This thread runs periodically and monitors both svcstate and svccount.
927c478bd9Sstevel@tonic-gate  * If svcstate is IDLE and svccount is 0 then server exits.
937c478bd9Sstevel@tonic-gate  * The svcstate is set to IDLE by the closedown thread. It is set to _SERVED
947c478bd9Sstevel@tonic-gate  * by server. It is possible for the state to be _SERVED and the svccount
957c478bd9Sstevel@tonic-gate  * to be 0. The server could be kept busy by client calls of smedia_get_handle
967c478bd9Sstevel@tonic-gate  * that do not succeed. This is the reason for using both svcstate and svccount
977c478bd9Sstevel@tonic-gate  * to determine the true server state.
987c478bd9Sstevel@tonic-gate  *
997c478bd9Sstevel@tonic-gate  * The communication between client and server is thru door calls.
1007c478bd9Sstevel@tonic-gate  * Below are the door descriptors available to communicate to the server.
1017c478bd9Sstevel@tonic-gate  *
1027c478bd9Sstevel@tonic-gate  * main_door_descriptor:
1037c478bd9Sstevel@tonic-gate  * ---------------------
1047c478bd9Sstevel@tonic-gate  * 	This is a predefined descriptor used by client to establish a
1057c478bd9Sstevel@tonic-gate  * connection with the server. This descriptor is available to the client
1067c478bd9Sstevel@tonic-gate  * as /var/adm/smedia_svc
1077c478bd9Sstevel@tonic-gate  * The client uses the main door_descriptor to obtain a dedicated
1087c478bd9Sstevel@tonic-gate  * client_door_descriptor for itself. The smedia_get_handle call communicates
1097c478bd9Sstevel@tonic-gate  * to the server using the main_door_descriptor and obtains the
1107c478bd9Sstevel@tonic-gate  * client_door_descriptor which is stored in the handle structure.
1117c478bd9Sstevel@tonic-gate  * All other libsmedia calls use the client_door_descriptor to communicate
1127c478bd9Sstevel@tonic-gate  * with the server.
1137c478bd9Sstevel@tonic-gate  *
1147c478bd9Sstevel@tonic-gate  * client_door_descriptor:
1157c478bd9Sstevel@tonic-gate  * -----------------------
1167c478bd9Sstevel@tonic-gate  *	This is the door descriptor that is used by the clients to
1177c478bd9Sstevel@tonic-gate  * request server to perform the necessary tasks. This door descriptor is
1187c478bd9Sstevel@tonic-gate  * available only to the client for whom it was created.
1197c478bd9Sstevel@tonic-gate  *
1207c478bd9Sstevel@tonic-gate  * death_door_descriptor:
1217c478bd9Sstevel@tonic-gate  * ----------------------
1227c478bd9Sstevel@tonic-gate  * 	The sole function of this door descriptor is to inform the server of
1237c478bd9Sstevel@tonic-gate  * the untimely death of the client. This helps the server to do the necessary
1247c478bd9Sstevel@tonic-gate  * cleanups.
1257c478bd9Sstevel@tonic-gate  *
1267c478bd9Sstevel@tonic-gate  * main_server()
1277c478bd9Sstevel@tonic-gate  * -------------
1287c478bd9Sstevel@tonic-gate  *	This is the routine associated with the main_door_descriptor.
1297c478bd9Sstevel@tonic-gate  * This is the routine that handles the smedia_get_handle() call
1307c478bd9Sstevel@tonic-gate  * of the client. If the door call to this routine succeeds it creates a
1317c478bd9Sstevel@tonic-gate  * client_door_descriptor that is used by the client in subsequent library
1327c478bd9Sstevel@tonic-gate  * calls.
1337c478bd9Sstevel@tonic-gate  * This client_door_descriptor is passed to the client thru the door_return
1347c478bd9Sstevel@tonic-gate  * call. This client_door_descriptor cannot be used by any other process other
1357c478bd9Sstevel@tonic-gate  * than the client process that obtained it.
1367c478bd9Sstevel@tonic-gate  * In addition to the client_door_descriptor a death_door_descriptor is also
1377c478bd9Sstevel@tonic-gate  * created by the main server and passed on to the client. The client does not
1387c478bd9Sstevel@tonic-gate  * use the death_door_descriptor at all. It is there to inform the server in
1397c478bd9Sstevel@tonic-gate  * case the client program were to exit without calling smedia_free_handle().
1407c478bd9Sstevel@tonic-gate  *
1417c478bd9Sstevel@tonic-gate  * client_server()
1427c478bd9Sstevel@tonic-gate  * ---------------
1437c478bd9Sstevel@tonic-gate  *	This is the routine that handles the libsmedia calls of the
1447c478bd9Sstevel@tonic-gate  * client. In the current implementation the server takes control of the
1457c478bd9Sstevel@tonic-gate  * number of threads that handle the door calls. This is done by creating the
1467c478bd9Sstevel@tonic-gate  * door descriptor as DOOR_PRIVATE.
1477c478bd9Sstevel@tonic-gate  * The server runs only one thread per handle. This makes the implementation
1487c478bd9Sstevel@tonic-gate  * simple as we do not have to use mutex to make the code MT safe.
1497c478bd9Sstevel@tonic-gate  * The client_server thread has a data structure door_data_t associated with it.
1507c478bd9Sstevel@tonic-gate  *
1517c478bd9Sstevel@tonic-gate  * door_data_t
1527c478bd9Sstevel@tonic-gate  * -----------
1537c478bd9Sstevel@tonic-gate  * This is the data structure that is created by the main_server when it
1547c478bd9Sstevel@tonic-gate  * creates the client_door_descriptor. The door mechanism has a way to associate
1557c478bd9Sstevel@tonic-gate  * a cookie with the door descriptor. door_data_t is the cookie for the
1567c478bd9Sstevel@tonic-gate  * client-door_descriptor. This cookie is passed to the server function that
1577c478bd9Sstevel@tonic-gate  * handles the clinet_door_descriptor calls. In our case it is the client_server
1587c478bd9Sstevel@tonic-gate  * routine.
1597c478bd9Sstevel@tonic-gate  * The key elements of the door_data_t are the following:
1607c478bd9Sstevel@tonic-gate  *
1617c478bd9Sstevel@tonic-gate  *	dd_fd		file descriptor for the device.
1627c478bd9Sstevel@tonic-gate  *	dd_buf		The shared memory buffer between client-server.
1637c478bd9Sstevel@tonic-gate  *	dd_thread	The thread that handles the door_calls.
1647c478bd9Sstevel@tonic-gate  *
1657c478bd9Sstevel@tonic-gate  * signal handling:
1667c478bd9Sstevel@tonic-gate  * ----------------
1677c478bd9Sstevel@tonic-gate  *		The main purpose of trapping the signals is to exit gracefully
1687c478bd9Sstevel@tonic-gate  * from the server after recording the appropriate message in the syslog.
1697c478bd9Sstevel@tonic-gate  * This will help the administrator to determine the cause of failure of the
1707c478bd9Sstevel@tonic-gate  * server by examining the log file.
1717c478bd9Sstevel@tonic-gate  *
1727c478bd9Sstevel@tonic-gate  * cleanup()
1737c478bd9Sstevel@tonic-gate  * ---------
1747c478bd9Sstevel@tonic-gate  *	This routine frees up all the resources allocated for the client.
1757c478bd9Sstevel@tonic-gate  * Resources inlcude the file descriptor, shared memory, threads.
1767c478bd9Sstevel@tonic-gate  *
1777c478bd9Sstevel@tonic-gate  * shared memory
1787c478bd9Sstevel@tonic-gate  * -------------
1797c478bd9Sstevel@tonic-gate  *	In order to reduce the overheads of moving large amounts of data
1807c478bd9Sstevel@tonic-gate  * during raw read/write operations, the server uses the mmapped data of
1817c478bd9Sstevel@tonic-gate  * client. The smedia_raw_read, smedia_raw_write library calls mmap the
1827c478bd9Sstevel@tonic-gate  * memory and pass on the file descriptor that maps the memory to the server.
1837c478bd9Sstevel@tonic-gate  * The server subsequently uses this mmapped memory during the IO.
1847c478bd9Sstevel@tonic-gate  * If the mmapped memory changes in size, the server is informed and it
1857c478bd9Sstevel@tonic-gate  * remaps the memory to the changed size.
1867c478bd9Sstevel@tonic-gate  */
1877c478bd9Sstevel@tonic-gate #ifdef DEBUG
1887c478bd9Sstevel@tonic-gate #define	DEFAULT_VERBOSE		1
1897c478bd9Sstevel@tonic-gate #define	DEFAULT_DEBUG		1
1907c478bd9Sstevel@tonic-gate #else
1917c478bd9Sstevel@tonic-gate #define	DEFAULT_VERBOSE		0
1927c478bd9Sstevel@tonic-gate #define	DEFAULT_DEBUG		0
1937c478bd9Sstevel@tonic-gate #endif
1947c478bd9Sstevel@tonic-gate 
1957c478bd9Sstevel@tonic-gate #define	N_BADSIGS		(sizeof (badsigs)/sizeof (badsigs[0]))
1967c478bd9Sstevel@tonic-gate #define	MD_LEN			30
1977c478bd9Sstevel@tonic-gate #define	MAXUGNAME		10
1987c478bd9Sstevel@tonic-gate #define	SVC_CLOSEDOWN 		180
1997c478bd9Sstevel@tonic-gate 
2007c478bd9Sstevel@tonic-gate /*
2017c478bd9Sstevel@tonic-gate  * We will NOT be permitting the following USCI cmd options.
2027c478bd9Sstevel@tonic-gate  *
2037c478bd9Sstevel@tonic-gate  * RESET of target
2047c478bd9Sstevel@tonic-gate  * RESET of  Bus.
2057c478bd9Sstevel@tonic-gate  * Tagged commands to device
2067c478bd9Sstevel@tonic-gate  * Explicitly setting SYNC/ASYNC mode of operations.
2077c478bd9Sstevel@tonic-gate  * POLLED MODE of operation.
2087c478bd9Sstevel@tonic-gate  * Explicitly setting NO DISCONNECT features.
2097c478bd9Sstevel@tonic-gate  * use of RESERVED flags.
2107c478bd9Sstevel@tonic-gate  */
2117c478bd9Sstevel@tonic-gate #define	FORBIDDEN_FLAGS		(USCSI_RESET | USCSI_RESET_ALL | USCSI_RENEGOT \
2127c478bd9Sstevel@tonic-gate 				| USCSI_ASYNC  | USCSI_SYNC | USCSI_NOINTR | \
2137c478bd9Sstevel@tonic-gate 				USCSI_NOTAG | USCSI_NOPARITY | USCSI_NODISCON \
2147c478bd9Sstevel@tonic-gate 				| USCSI_RESERVED)
2157c478bd9Sstevel@tonic-gate 
2167c478bd9Sstevel@tonic-gate /* States a server can be in wrt request */
2177c478bd9Sstevel@tonic-gate 
2187c478bd9Sstevel@tonic-gate #define	_IDLE 0
2197c478bd9Sstevel@tonic-gate #define	_SERVED 1
2207c478bd9Sstevel@tonic-gate 
2217c478bd9Sstevel@tonic-gate static char		*prog_name;
2227c478bd9Sstevel@tonic-gate static int svcstate = _IDLE;	/* Set when a request is serviced */
2237c478bd9Sstevel@tonic-gate static int svccount = 0;	/* Number of requests being serviced */
2247c478bd9Sstevel@tonic-gate static int svcstart_level = 0;	/* init level when server was started */
2257c478bd9Sstevel@tonic-gate static mutex_t svcstate_lock;	/* lock for svcstate, svccount */
2267c478bd9Sstevel@tonic-gate 
2277c478bd9Sstevel@tonic-gate extern	void smserverprog_1(struct svc_req *, SVCXPRT *);
2287c478bd9Sstevel@tonic-gate 
2297c478bd9Sstevel@tonic-gate /*
2307c478bd9Sstevel@tonic-gate  * Log messages
2317c478bd9Sstevel@tonic-gate  */
2327c478bd9Sstevel@tonic-gate #define	SIGACT_FAILED	"Failed to install signal handler for %s: %s"
2337c478bd9Sstevel@tonic-gate #define	BADSIG_MSG	"Thread %d Caught signal %d addr=%p trapno=%d pc=%p"
2347c478bd9Sstevel@tonic-gate 
2357c478bd9Sstevel@tonic-gate static int	badsigs[] = {SIGSEGV, SIGBUS, SIGFPE, SIGILL};
2367c478bd9Sstevel@tonic-gate 
2377c478bd9Sstevel@tonic-gate /* global variables */
2387c478bd9Sstevel@tonic-gate int		verbose		= DEFAULT_VERBOSE;
2397c478bd9Sstevel@tonic-gate int		debug_level	= DEFAULT_DEBUG;
2407c478bd9Sstevel@tonic-gate char		*smediad_devdir = DEFAULT_SMEDIAD_DEVDIR;
2417c478bd9Sstevel@tonic-gate 
2427c478bd9Sstevel@tonic-gate thread_key_t	door_key;
2437c478bd9Sstevel@tonic-gate 
2447c478bd9Sstevel@tonic-gate server_data_t	server_data;
2457c478bd9Sstevel@tonic-gate 
2467c478bd9Sstevel@tonic-gate static int	server_door, server_fd;
2477c478bd9Sstevel@tonic-gate 
2487c478bd9Sstevel@tonic-gate static int32_t do_uscsi_cmd(int32_t file, struct uscsi_cmd *uscsi_cmd,
2497c478bd9Sstevel@tonic-gate 		int32_t flag);
2507c478bd9Sstevel@tonic-gate static void client_server(void *cookie, char *argp, size_t arg_size,
2517c478bd9Sstevel@tonic-gate 		door_desc_t *dp, uint_t ndesc);
2527c478bd9Sstevel@tonic-gate static void cleanup(door_data_t *);
2537c478bd9Sstevel@tonic-gate static void *init_server(void *);
2547c478bd9Sstevel@tonic-gate static int32_t scsi_reassign_block(int32_t fd, diskaddr_t);
2557c478bd9Sstevel@tonic-gate static int32_t get_mode_page(int32_t fd, uchar_t pc, uchar_t page_code,
2567c478bd9Sstevel@tonic-gate 				uchar_t *md_data, uchar_t data_len);
2577c478bd9Sstevel@tonic-gate static int32_t get_device_type(char *v_name);
2587c478bd9Sstevel@tonic-gate static int32_t get_device_type_scsi(int32_t fd, struct scsi_inquiry *inq);
2597c478bd9Sstevel@tonic-gate 
2607c478bd9Sstevel@tonic-gate static int32_t scsi_format(int32_t fd, uint_t flavor, uint_t mode);
2617c478bd9Sstevel@tonic-gate static int32_t scsi_media_status(int32_t fd);
2627c478bd9Sstevel@tonic-gate static int32_t scsi_write_protect(int32_t fd, smwp_state_t *wp);
2637c478bd9Sstevel@tonic-gate static int32_t scsi_floppy_media_status(int32_t fd);
2647c478bd9Sstevel@tonic-gate static int32_t scsi_floppy_write_protect(int32_t fd, smwp_state_t *wp);
2657c478bd9Sstevel@tonic-gate static int32_t scsi_floppy_format(int32_t, uint_t, uint_t);
2667c478bd9Sstevel@tonic-gate static int32_t get_floppy_geom(int32_t fd, uint32_t capacity,
2677c478bd9Sstevel@tonic-gate 			struct dk_geom *dkgeom);
2687c478bd9Sstevel@tonic-gate static int32_t get_media_capacity(int32_t fd, uint32_t *capacity,
2697c478bd9Sstevel@tonic-gate 			uint32_t *blocksize);
2707c478bd9Sstevel@tonic-gate 
2717c478bd9Sstevel@tonic-gate static int32_t scsi_ls120_format(uint_t fd, uint_t flavor, uint32_t capacity,
2727c478bd9Sstevel@tonic-gate 			uint32_t blocksize);
2737c478bd9Sstevel@tonic-gate 
2747c478bd9Sstevel@tonic-gate static void * my_server_thread(void *arg);
2757c478bd9Sstevel@tonic-gate static void my_create(door_info_t *dip);
2767c478bd9Sstevel@tonic-gate static void term_handler(int sig, siginfo_t *siginfo, void *sigctx);
2777c478bd9Sstevel@tonic-gate static void hup_handler(int sig, siginfo_t *siginfo, void *sigctx);
2787c478bd9Sstevel@tonic-gate static void sig_handler(int sig, siginfo_t *siginfo, void *sigctx);
2797c478bd9Sstevel@tonic-gate static void badsig_handler(int sig, siginfo_t *siginfo, void *sigctx);
2807c478bd9Sstevel@tonic-gate static void server_badsig_handler(int sig, siginfo_t *siginfo, void *sigctx);
2817c478bd9Sstevel@tonic-gate static char *xlate_state(int32_t);
2827c478bd9Sstevel@tonic-gate static uint32_t	get_sector_size(int fd);
2837c478bd9Sstevel@tonic-gate static int32_t raw_read(door_data_t *door_dp, smedia_services_t *req);
2847c478bd9Sstevel@tonic-gate static int32_t raw_write(door_data_t *door_dp, smedia_services_t *req);
2857c478bd9Sstevel@tonic-gate static int32_t reassign_block(door_data_t *door_dp, smedia_services_t *req);
2867c478bd9Sstevel@tonic-gate static int32_t set_protection_status(door_data_t *door_dp,
2877c478bd9Sstevel@tonic-gate 			smedia_services_t *req);
2887c478bd9Sstevel@tonic-gate static int32_t set_shfd(door_data_t *door_dp, int32_t fd,
2897c478bd9Sstevel@tonic-gate 			smedia_services_t *req);
2907c478bd9Sstevel@tonic-gate 
2917c478bd9Sstevel@tonic-gate static void door_ret_err(smedia_reterror_t *reterror, int32_t err);
2927c478bd9Sstevel@tonic-gate static void my_door_return(char *data_ptr, size_t data_size,
2937c478bd9Sstevel@tonic-gate 			door_desc_t *desc_ptr, uint_t num_desc);
2947c478bd9Sstevel@tonic-gate static int32_t invalid_uscsi_operation(door_data_t *, struct uscsi_cmd *);
2957c478bd9Sstevel@tonic-gate 
2967c478bd9Sstevel@tonic-gate #define	W_E_MASK	0x80
2977c478bd9Sstevel@tonic-gate 
2987c478bd9Sstevel@tonic-gate static smserver_info server_info;
2997c478bd9Sstevel@tonic-gate 
3007c478bd9Sstevel@tonic-gate static int32_t
3017c478bd9Sstevel@tonic-gate invalid_uscsi_operation(door_data_t *door_dp, struct uscsi_cmd *ucmd)
3027c478bd9Sstevel@tonic-gate {
3037c478bd9Sstevel@tonic-gate 
3047c478bd9Sstevel@tonic-gate 	if (door_dp->dd_dkinfo.dki_ctype != DKC_CDROM) {
3057c478bd9Sstevel@tonic-gate 		debug(5,
3067c478bd9Sstevel@tonic-gate 		"Invalid device type(0x%x) found for uscsi cmd.\n",
3077c478bd9Sstevel@tonic-gate 			door_dp->dd_dkinfo.dki_ctype);
3087c478bd9Sstevel@tonic-gate 		errno = EINVAL;
3097c478bd9Sstevel@tonic-gate 		return (EINVAL);
3107c478bd9Sstevel@tonic-gate 	}
3117c478bd9Sstevel@tonic-gate 	if (ucmd->uscsi_flags & FORBIDDEN_FLAGS) {
3127c478bd9Sstevel@tonic-gate 		debug(5,
3137c478bd9Sstevel@tonic-gate 		"Invalid flags(0x%x) set in uscsi cmd. cdb[0]=0x%x\n",
3147c478bd9Sstevel@tonic-gate 		ucmd->uscsi_flags,  ucmd->uscsi_cdb[0]);
3157c478bd9Sstevel@tonic-gate 		errno = EINVAL;
3167c478bd9Sstevel@tonic-gate 		return (EINVAL);
3177c478bd9Sstevel@tonic-gate 	}
3187c478bd9Sstevel@tonic-gate 	if (ucmd->uscsi_cdb[0] == SCMD_COPY ||
3197c478bd9Sstevel@tonic-gate 	    ucmd->uscsi_cdb[0] == SCMD_COPY_VERIFY ||
3207c478bd9Sstevel@tonic-gate 	    ucmd->uscsi_cdb[0] == SCMD_COMPARE ||
3217c478bd9Sstevel@tonic-gate 	    ucmd->uscsi_cdb[0] == SCMD_WRITE_BUFFER) {
3227c478bd9Sstevel@tonic-gate 		debug(5,
3237c478bd9Sstevel@tonic-gate 		"Invalid command(0x%x) found in cdb.\n",
3247c478bd9Sstevel@tonic-gate 		ucmd->uscsi_cdb[0]);
3257c478bd9Sstevel@tonic-gate 		errno = EINVAL;
3267c478bd9Sstevel@tonic-gate 		return (EINVAL);
3277c478bd9Sstevel@tonic-gate 	}
3287c478bd9Sstevel@tonic-gate 	return (0);
3297c478bd9Sstevel@tonic-gate }
3307c478bd9Sstevel@tonic-gate 
3317c478bd9Sstevel@tonic-gate static uint32_t
3327c478bd9Sstevel@tonic-gate get_sector_size(int fd)
3337c478bd9Sstevel@tonic-gate {
3347c478bd9Sstevel@tonic-gate 	uint32_t	sector_size;
3357c478bd9Sstevel@tonic-gate 	struct uscsi_cmd	ucmd;
3367c478bd9Sstevel@tonic-gate 	union scsi_cdb		cdb;
3377c478bd9Sstevel@tonic-gate 	int32_t		ret_val;
3387c478bd9Sstevel@tonic-gate 	uint32_t rc_data[2];
3397c478bd9Sstevel@tonic-gate 	char rq_data[RQ_LEN];
3407c478bd9Sstevel@tonic-gate 
3417c478bd9Sstevel@tonic-gate 	cdb.scc_cmd = SCMD_READ_CAPACITY;
3427c478bd9Sstevel@tonic-gate 	ucmd.uscsi_cdb = (caddr_t)&cdb;
3437c478bd9Sstevel@tonic-gate 	ucmd.uscsi_cdblen = CDB_GROUP1;
3447c478bd9Sstevel@tonic-gate 	ucmd.uscsi_bufaddr = (caddr_t)&rc_data;
3457c478bd9Sstevel@tonic-gate 	ucmd.uscsi_buflen = sizeof (rc_data);
3467c478bd9Sstevel@tonic-gate 	ucmd.uscsi_timeout = 120; /* If 0, HBA hangs forever */
3477c478bd9Sstevel@tonic-gate 	ucmd.uscsi_rqlen = RQ_LEN;
3487c478bd9Sstevel@tonic-gate 	ucmd.uscsi_rqbuf = rq_data;
3497c478bd9Sstevel@tonic-gate 
3507c478bd9Sstevel@tonic-gate 	ret_val = do_uscsi_cmd(fd,
3517c478bd9Sstevel@tonic-gate 		&ucmd, USCSI_READ|USCSI_RQENABLE);
3527c478bd9Sstevel@tonic-gate 	if (ret_val || ucmd.uscsi_status) {
3537c478bd9Sstevel@tonic-gate 		debug(5, "Read capacity : %d - %d errno = %d\n",
3547c478bd9Sstevel@tonic-gate 			ret_val, ucmd.uscsi_status, errno);
3557c478bd9Sstevel@tonic-gate 		sector_size = 512;
3567c478bd9Sstevel@tonic-gate 	} else {
3577c478bd9Sstevel@tonic-gate 		sector_size = ntohl(rc_data[1]);
3587c478bd9Sstevel@tonic-gate 	}
3597c478bd9Sstevel@tonic-gate 	debug(5, "sector size = 0x%x(%d)\n",
3607c478bd9Sstevel@tonic-gate 		sector_size, sector_size);
3617c478bd9Sstevel@tonic-gate 	return (sector_size);
3627c478bd9Sstevel@tonic-gate }
3637c478bd9Sstevel@tonic-gate 
3647c478bd9Sstevel@tonic-gate static char *
3657c478bd9Sstevel@tonic-gate xlate_state(int32_t state)
3667c478bd9Sstevel@tonic-gate {
3677c478bd9Sstevel@tonic-gate 	switch (state) {
3687c478bd9Sstevel@tonic-gate 
3697c478bd9Sstevel@tonic-gate 	case SM_WRITE_PROTECT_DISABLE:
3707c478bd9Sstevel@tonic-gate 		return ("PROTECTION_DISABLED");
3717c478bd9Sstevel@tonic-gate 	case SM_WRITE_PROTECT_PASSWD:
3727c478bd9Sstevel@tonic-gate 		return ("WRITE_PROTECT_PASSWD");
3737c478bd9Sstevel@tonic-gate 	case SM_WRITE_PROTECT_NOPASSWD:
3747c478bd9Sstevel@tonic-gate 		return ("WRITE_PROTECT_NOPASSWD");
3757c478bd9Sstevel@tonic-gate 	case SM_READ_WRITE_PROTECT:
3767c478bd9Sstevel@tonic-gate 		return ("READ_WRITE_PROTECT");
3777c478bd9Sstevel@tonic-gate 	case SM_TEMP_UNLOCK_MODE:
3787c478bd9Sstevel@tonic-gate 		return ("PROTECTION DISABLED");
3797c478bd9Sstevel@tonic-gate 	default:
3807c478bd9Sstevel@tonic-gate 		return ("UNKNOWN_STATE");
3817c478bd9Sstevel@tonic-gate 	}
3827c478bd9Sstevel@tonic-gate }
3837c478bd9Sstevel@tonic-gate 
3847c478bd9Sstevel@tonic-gate static char *
3857c478bd9Sstevel@tonic-gate xlate_cnum(smedia_callnumber_t cnum)
3867c478bd9Sstevel@tonic-gate {
3877c478bd9Sstevel@tonic-gate 	switch (cnum) {
3887c478bd9Sstevel@tonic-gate 
3897c478bd9Sstevel@tonic-gate 	case SMEDIA_CNUM_OPEN_FD:
3907c478bd9Sstevel@tonic-gate 		return ("SMEDIA_CNUM_OPEN_FD");
3917c478bd9Sstevel@tonic-gate 	case SMEDIA_CNUM_GET_DEVICE_INFO:
3927c478bd9Sstevel@tonic-gate 		return ("SMEDIA_CNUM_GET_DEVICE_INFO");
3937c478bd9Sstevel@tonic-gate 	case SMEDIA_CNUM_GET_MEDIUM_PROPERTY:
3947c478bd9Sstevel@tonic-gate 		return ("SMEDIA_CNUM_GET_MEDIUM_PROPERTY");
3957c478bd9Sstevel@tonic-gate 	case SMEDIA_CNUM_GET_PROTECTION_STATUS:
3967c478bd9Sstevel@tonic-gate 		return ("SMEDIA_CNUM_GET_PROTECTION_STATUS");
3977c478bd9Sstevel@tonic-gate 	case SMEDIA_CNUM_SET_PROTECTION_STATUS:
3987c478bd9Sstevel@tonic-gate 		return ("SMEDIA_CNUM_SET_PROTECTION_STATUS");
3997c478bd9Sstevel@tonic-gate 	case SMEDIA_CNUM_RAW_READ:
4007c478bd9Sstevel@tonic-gate 		return ("SMEDIA_CNUM_RAW_READ");
4017c478bd9Sstevel@tonic-gate 	case SMEDIA_CNUM_RAW_WRITE:
4027c478bd9Sstevel@tonic-gate 		return (" SMEDIA_CNUM_RAW_WRITE");
4037c478bd9Sstevel@tonic-gate 	case SMEDIA_CNUM_FORMAT:
4047c478bd9Sstevel@tonic-gate 		return ("SMEDIA_CNUM_FORMAT");
4057c478bd9Sstevel@tonic-gate 	case SMEDIA_CNUM_CHECK_FORMAT_STATUS:
4067c478bd9Sstevel@tonic-gate 		return ("SMEDIA_CNUM_CHECK_FORMAT_STATUS");
4077c478bd9Sstevel@tonic-gate 	case SMEDIA_CNUM_EJECT:
4087c478bd9Sstevel@tonic-gate 		return ("SMEDIA_CNUM_EJECT");
4097c478bd9Sstevel@tonic-gate 	case SMEDIA_CNUM_REASSIGN_BLOCK:
4107c478bd9Sstevel@tonic-gate 		return ("SMEDIA_CNUM_REASSIGN_BLOCK");
4117c478bd9Sstevel@tonic-gate 	case SMEDIA_CNUM_SET_SHFD:
4127c478bd9Sstevel@tonic-gate 		return ("SMEDIA_CNUM_SET_SHFD");
4137c478bd9Sstevel@tonic-gate 	case SMEDIA_CNUM_PING:
4147c478bd9Sstevel@tonic-gate 		return ("SMEDIA_CNUM_PING");
4157c478bd9Sstevel@tonic-gate 	case SMEDIA_CNUM_USCSI_CMD:
4167c478bd9Sstevel@tonic-gate 		return ("SMEDIA_CNUM_USCSI_CMD");
4177c478bd9Sstevel@tonic-gate 	default:
4187c478bd9Sstevel@tonic-gate 		return ("UNKNOWN_CNUM");
4197c478bd9Sstevel@tonic-gate 	}
4207c478bd9Sstevel@tonic-gate }
4217c478bd9Sstevel@tonic-gate 
4227c478bd9Sstevel@tonic-gate /*ARGSUSED*/
4237c478bd9Sstevel@tonic-gate smserver_info *
4247c478bd9Sstevel@tonic-gate smserverproc_get_serverinfo_1(void *argp, CLIENT *clnt)
4257c478bd9Sstevel@tonic-gate {
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) {
4397c478bd9Sstevel@tonic-gate 		debug(1,
4407c478bd9Sstevel@tonic-gate "init_server did not do the job. 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
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
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
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
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) {
5327c478bd9Sstevel@tonic-gate 		debug(5, "inquiry failed: %d - %d errno = %d\n",
5337c478bd9Sstevel@tonic-gate 			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
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
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
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
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 
9757c478bd9Sstevel@tonic-gate static int32_t
9767c478bd9Sstevel@tonic-gate scsi_media_status(int32_t fd)
9777c478bd9Sstevel@tonic-gate {
9787c478bd9Sstevel@tonic-gate 	struct mode_header modeh;
9797c478bd9Sstevel@tonic-gate 	struct uscsi_cmd ucmd;
9807c478bd9Sstevel@tonic-gate 	union scsi_cdb  cdb;
9817c478bd9Sstevel@tonic-gate 	int32_t	ret_val;
9827c478bd9Sstevel@tonic-gate 	int32_t cur_status;
9837c478bd9Sstevel@tonic-gate 	char rq_data[RQ_LEN];
9847c478bd9Sstevel@tonic-gate 
9857c478bd9Sstevel@tonic-gate 	debug(10, "SCSI MEDIA STATUS CALLED \n");
9867c478bd9Sstevel@tonic-gate 
9877c478bd9Sstevel@tonic-gate 	(void) memset((void *) &modeh, 0, sizeof (modeh));
9887c478bd9Sstevel@tonic-gate 	(void) memset((void *) &ucmd, 0, sizeof (ucmd));
9897c478bd9Sstevel@tonic-gate 	(void) memset((void *) &cdb, 0, sizeof (union scsi_cdb));
9907c478bd9Sstevel@tonic-gate 	cdb.scc_cmd = SCMD_MODE_SENSE;
9917c478bd9Sstevel@tonic-gate 	FORMG0COUNT(&cdb, sizeof (modeh));
9927c478bd9Sstevel@tonic-gate 	ucmd.uscsi_cdb = (caddr_t)&cdb;
9937c478bd9Sstevel@tonic-gate 	ucmd.uscsi_cdblen = CDB_GROUP0;
9947c478bd9Sstevel@tonic-gate 	ucmd.uscsi_bufaddr = (caddr_t)&modeh;
9957c478bd9Sstevel@tonic-gate 	ucmd.uscsi_buflen = sizeof (modeh);
9967c478bd9Sstevel@tonic-gate 	ucmd.uscsi_timeout = 120;	/* If 0, HBA hangs forever */
9977c478bd9Sstevel@tonic-gate 	ucmd.uscsi_rqlen = RQ_LEN;
9987c478bd9Sstevel@tonic-gate 	ucmd.uscsi_rqbuf = rq_data;
9997c478bd9Sstevel@tonic-gate 	ret_val = do_uscsi_cmd(fd, &ucmd, USCSI_READ|USCSI_RQENABLE);
10007c478bd9Sstevel@tonic-gate 	if (ret_val || ucmd.uscsi_status) {
10017c478bd9Sstevel@tonic-gate 		debug(5, "Modesense failed: %d - %d errno = %d\n",
10027c478bd9Sstevel@tonic-gate 			ret_val, ucmd.uscsi_status, errno);
10037c478bd9Sstevel@tonic-gate 		return (-1);
10047c478bd9Sstevel@tonic-gate 	}
10057c478bd9Sstevel@tonic-gate 
10067c478bd9Sstevel@tonic-gate 
10077c478bd9Sstevel@tonic-gate 	if (modeh.device_specific & W_E_MASK) {
10087c478bd9Sstevel@tonic-gate 		cur_status = SM_WRITE_PROTECT_NOPASSWD;
10097c478bd9Sstevel@tonic-gate 	} else {
10107c478bd9Sstevel@tonic-gate 		cur_status = SM_WRITE_PROTECT_DISABLE;
10117c478bd9Sstevel@tonic-gate 	}
10127c478bd9Sstevel@tonic-gate 	debug(5, "cur status %d\n", cur_status);
10137c478bd9Sstevel@tonic-gate 
10147c478bd9Sstevel@tonic-gate 	return (cur_status);
10157c478bd9Sstevel@tonic-gate }
10167c478bd9Sstevel@tonic-gate 
10177c478bd9Sstevel@tonic-gate static int32_t
10187c478bd9Sstevel@tonic-gate scsi_zip_media_status(int32_t fd)
10197c478bd9Sstevel@tonic-gate {
10207c478bd9Sstevel@tonic-gate 	struct uscsi_cmd ucmd;
10217c478bd9Sstevel@tonic-gate 	uchar_t cdb[12];
10227c478bd9Sstevel@tonic-gate 	int32_t	status;
10237c478bd9Sstevel@tonic-gate 	int32_t mode;
10247c478bd9Sstevel@tonic-gate 	uchar_t data[64];
10257c478bd9Sstevel@tonic-gate 	char rq_data[RQ_LEN];
10267c478bd9Sstevel@tonic-gate 
10277c478bd9Sstevel@tonic-gate 	debug(10, "Getting media status\n");
10287c478bd9Sstevel@tonic-gate 
10297c478bd9Sstevel@tonic-gate 	(void) memset((void *)&ucmd, 0, sizeof (ucmd));
10307c478bd9Sstevel@tonic-gate 	(void) memset((void *)&cdb, 0, sizeof (cdb));
10317c478bd9Sstevel@tonic-gate 
10327c478bd9Sstevel@tonic-gate 	cdb[0] = IOMEGA_NONSENSE_CMD;
10337c478bd9Sstevel@tonic-gate 	cdb[2] = CARTRIDGE_STATUS_PAGE;
10347c478bd9Sstevel@tonic-gate 	cdb[4] = ND_LENGTH;
10357c478bd9Sstevel@tonic-gate 	ucmd.uscsi_cdb = (caddr_t)&cdb;
10367c478bd9Sstevel@tonic-gate 	ucmd.uscsi_cdblen = CDB_GROUP0;
10377c478bd9Sstevel@tonic-gate 	ucmd.uscsi_bufaddr = (caddr_t)data;
10387c478bd9Sstevel@tonic-gate 	ucmd.uscsi_buflen = 64;
10397c478bd9Sstevel@tonic-gate 	ucmd.uscsi_timeout = 120;	/* If 0, HBA hangs forever */
10407c478bd9Sstevel@tonic-gate 	ucmd.uscsi_rqlen = RQ_LEN;
10417c478bd9Sstevel@tonic-gate 	ucmd.uscsi_rqbuf = rq_data;
10427c478bd9Sstevel@tonic-gate 	status = do_uscsi_cmd(fd, &ucmd, USCSI_READ|USCSI_RQENABLE);
10437c478bd9Sstevel@tonic-gate 	if (status || ucmd.uscsi_status) {
10447c478bd9Sstevel@tonic-gate 		debug(5,
10457c478bd9Sstevel@tonic-gate 		"Catridge protect operation failed: %d - %d errno = %d\n",
10467c478bd9Sstevel@tonic-gate 			status, ucmd.uscsi_status, errno);
10477c478bd9Sstevel@tonic-gate 		return (-1);
10487c478bd9Sstevel@tonic-gate 	}
10497c478bd9Sstevel@tonic-gate 
10507c478bd9Sstevel@tonic-gate 	if (data[DISK_STATUS_OFFSET + NON_SENSE_HDR_LEN] == 4) {
10517c478bd9Sstevel@tonic-gate 		debug(1, "Disk not present. \n");
10527c478bd9Sstevel@tonic-gate 		return (-1);
10537c478bd9Sstevel@tonic-gate 	}
10547c478bd9Sstevel@tonic-gate 	mode = data[PROTECT_MODE_OFFSET + NON_SENSE_HDR_LEN] & 0xF;
10557c478bd9Sstevel@tonic-gate 
10567c478bd9Sstevel@tonic-gate 	debug(5, "MODE %x\n", mode);
10577c478bd9Sstevel@tonic-gate 
10587c478bd9Sstevel@tonic-gate 	debug(5, "Mode = %d\n", mode);
10597c478bd9Sstevel@tonic-gate 	switch (mode) {
10607c478bd9Sstevel@tonic-gate 		case UNLOCK_MODE:
10617c478bd9Sstevel@tonic-gate 			status = SM_WRITE_PROTECT_DISABLE;
10627c478bd9Sstevel@tonic-gate 			break;
10637c478bd9Sstevel@tonic-gate 		case WRITE_PROTECT_MODE:
10647c478bd9Sstevel@tonic-gate 			status = SM_WRITE_PROTECT_NOPASSWD;
10657c478bd9Sstevel@tonic-gate 			break;
10667c478bd9Sstevel@tonic-gate 		case PASSWD_WRITE_PROTECT_MODE:
10677c478bd9Sstevel@tonic-gate 			status = SM_WRITE_PROTECT_PASSWD;
10687c478bd9Sstevel@tonic-gate 			break;
10697c478bd9Sstevel@tonic-gate 		case READ_WRITE_PROTECT_MODE:
10707c478bd9Sstevel@tonic-gate 			status = SM_READ_WRITE_PROTECT;
10717c478bd9Sstevel@tonic-gate 			break;
10727c478bd9Sstevel@tonic-gate 		default :
10737c478bd9Sstevel@tonic-gate 			if (mode & TEMP_UNLOCK_MODE)
10747c478bd9Sstevel@tonic-gate 				status = SM_TEMP_UNLOCK_MODE;
10757c478bd9Sstevel@tonic-gate 			else
10767c478bd9Sstevel@tonic-gate 				status = SM_STATUS_UNKNOWN;
10777c478bd9Sstevel@tonic-gate 			break;
10787c478bd9Sstevel@tonic-gate 	}
10797c478bd9Sstevel@tonic-gate 
10807c478bd9Sstevel@tonic-gate 	debug(5, "status %d \n", status);
10817c478bd9Sstevel@tonic-gate 	return (status);
10827c478bd9Sstevel@tonic-gate }
10837c478bd9Sstevel@tonic-gate 
10847c478bd9Sstevel@tonic-gate int32_t
10857c478bd9Sstevel@tonic-gate scsi_reassign_block(int32_t fd, diskaddr_t block)
10867c478bd9Sstevel@tonic-gate {
10877c478bd9Sstevel@tonic-gate 	uchar_t data[8];
10887c478bd9Sstevel@tonic-gate 	struct uscsi_cmd ucmd;
10897c478bd9Sstevel@tonic-gate 	char cdb[12];
10907c478bd9Sstevel@tonic-gate 	int32_t	ret_val;
10917c478bd9Sstevel@tonic-gate 	char rq_data[RQ_LEN];
10927c478bd9Sstevel@tonic-gate 
10937c478bd9Sstevel@tonic-gate 	debug(5, "SCSI REASSIGN CALLED block = %lld\n", block);
10947c478bd9Sstevel@tonic-gate 
10957c478bd9Sstevel@tonic-gate 	(void) memset((void *) &data, 0, sizeof (data));
10967c478bd9Sstevel@tonic-gate 	(void) memset((void *) &ucmd, 0, sizeof (ucmd));
10977c478bd9Sstevel@tonic-gate 	(void) memset((void *) &cdb, 0, sizeof (cdb));
10987c478bd9Sstevel@tonic-gate 	cdb[0] = SCMD_REASSIGN_BLOCK;
10997c478bd9Sstevel@tonic-gate 	data[3] = 4;
11007c478bd9Sstevel@tonic-gate 	data[4] = ((block & 0xFF000000) >> 24);
11017c478bd9Sstevel@tonic-gate 	data[5] = ((block & 0xFF0000) >> 16);
11027c478bd9Sstevel@tonic-gate 	data[6] = ((block & 0xFF00) >> 8);
11037c478bd9Sstevel@tonic-gate 	data[7] = block & 0xFF;
11047c478bd9Sstevel@tonic-gate 
11057c478bd9Sstevel@tonic-gate 	ucmd.uscsi_cdb = (caddr_t)&cdb;
11067c478bd9Sstevel@tonic-gate 	ucmd.uscsi_cdblen = CDB_GROUP0;
11077c478bd9Sstevel@tonic-gate 	ucmd.uscsi_bufaddr = (caddr_t)data;
11087c478bd9Sstevel@tonic-gate 	ucmd.uscsi_buflen = sizeof (data);
11097c478bd9Sstevel@tonic-gate 	ucmd.uscsi_timeout = 120;	/* If 0, HBA hangs forever */
11107c478bd9Sstevel@tonic-gate 	ucmd.uscsi_rqlen = RQ_LEN;
11117c478bd9Sstevel@tonic-gate 	ucmd.uscsi_rqbuf = rq_data;
11127c478bd9Sstevel@tonic-gate 	ret_val = do_uscsi_cmd(fd, &ucmd, USCSI_WRITE|USCSI_RQENABLE);
11137c478bd9Sstevel@tonic-gate 	if (ret_val || ucmd.uscsi_status) {
11147c478bd9Sstevel@tonic-gate 		debug(5, "Reassign block failed: %d - %d errno = %d\n",
11157c478bd9Sstevel@tonic-gate 			ret_val, ucmd.uscsi_status, errno);
11167c478bd9Sstevel@tonic-gate 		return (-1);
11177c478bd9Sstevel@tonic-gate 	}
11187c478bd9Sstevel@tonic-gate 
11197c478bd9Sstevel@tonic-gate 	return (0);
11207c478bd9Sstevel@tonic-gate }
11217c478bd9Sstevel@tonic-gate 
11227c478bd9Sstevel@tonic-gate int32_t
11237c478bd9Sstevel@tonic-gate get_mode_page(int32_t fd, uchar_t pc, uchar_t page_code,
11247c478bd9Sstevel@tonic-gate 				uchar_t *md_data, uchar_t data_len)
11257c478bd9Sstevel@tonic-gate {
11267c478bd9Sstevel@tonic-gate 	struct uscsi_cmd ucmd;
11277c478bd9Sstevel@tonic-gate 	uchar_t cdb[12];
11287c478bd9Sstevel@tonic-gate 	int32_t	ret_val;
11297c478bd9Sstevel@tonic-gate 	char rq_data[RQ_LEN];
11307c478bd9Sstevel@tonic-gate 
11317c478bd9Sstevel@tonic-gate 	debug(10, "GET MODE PAGE CALLED \n");
11327c478bd9Sstevel@tonic-gate 
11337c478bd9Sstevel@tonic-gate 	(void) memset((void *) md_data, 0, sizeof (data_len));
11347c478bd9Sstevel@tonic-gate 	(void) memset((void *) &ucmd, 0, sizeof (ucmd));
11357c478bd9Sstevel@tonic-gate 	(void) memset((void *) &cdb, 0, sizeof (cdb));
11367c478bd9Sstevel@tonic-gate 	cdb[0] = SCMD_MODE_SENSE;
11377c478bd9Sstevel@tonic-gate 	cdb[2] = (pc << 6) | page_code;
11387c478bd9Sstevel@tonic-gate 	cdb[4] = data_len;
11397c478bd9Sstevel@tonic-gate 
11407c478bd9Sstevel@tonic-gate 
11417c478bd9Sstevel@tonic-gate 	ucmd.uscsi_cdb = (caddr_t)&cdb;
11427c478bd9Sstevel@tonic-gate 	ucmd.uscsi_cdblen = CDB_GROUP0;
11437c478bd9Sstevel@tonic-gate 	ucmd.uscsi_bufaddr = (caddr_t)md_data;
11447c478bd9Sstevel@tonic-gate 	ucmd.uscsi_buflen = data_len;
11457c478bd9Sstevel@tonic-gate 	ucmd.uscsi_timeout = 120;	/* If 0, HBA hangs forever */
11467c478bd9Sstevel@tonic-gate 	ucmd.uscsi_rqlen = RQ_LEN;
11477c478bd9Sstevel@tonic-gate 	ucmd.uscsi_rqbuf = rq_data;
11487c478bd9Sstevel@tonic-gate 	ret_val = do_uscsi_cmd(fd, &ucmd, USCSI_READ|USCSI_RQENABLE);
11497c478bd9Sstevel@tonic-gate 	if (ret_val || ucmd.uscsi_status) {
11507c478bd9Sstevel@tonic-gate 		debug(5, "Modesense failed: %d - %d errno = %d\n",
11517c478bd9Sstevel@tonic-gate 			ret_val, ucmd.uscsi_status, errno);
11527c478bd9Sstevel@tonic-gate 		return (-2);
11537c478bd9Sstevel@tonic-gate 	}
11547c478bd9Sstevel@tonic-gate 
11557c478bd9Sstevel@tonic-gate 	return (0);
11567c478bd9Sstevel@tonic-gate }
11577c478bd9Sstevel@tonic-gate 
11587c478bd9Sstevel@tonic-gate static int32_t
11597c478bd9Sstevel@tonic-gate scsi_zip_write_protect(int32_t fd, smwp_state_t *wp)
11607c478bd9Sstevel@tonic-gate {
11617c478bd9Sstevel@tonic-gate 	struct uscsi_cmd ucmd;
11627c478bd9Sstevel@tonic-gate 	struct scsi_inquiry inq;
11637c478bd9Sstevel@tonic-gate 	uchar_t cdb[12];
11647c478bd9Sstevel@tonic-gate 	int32_t	status;
11657c478bd9Sstevel@tonic-gate 	int32_t new_mode;
11667c478bd9Sstevel@tonic-gate 	char rq_data[RQ_LEN];
11677c478bd9Sstevel@tonic-gate 	int32_t wa_bit;
11687c478bd9Sstevel@tonic-gate 	char *tmp_passwd = NULL;
11697c478bd9Sstevel@tonic-gate 
11707c478bd9Sstevel@tonic-gate 	debug(10, "SCSI ZIP WRITE PROTECT CALLED \n");
11717c478bd9Sstevel@tonic-gate 
11727c478bd9Sstevel@tonic-gate 	/*
11737c478bd9Sstevel@tonic-gate 	 * Do an inquiry and try to figure out if it an
11747c478bd9Sstevel@tonic-gate 	 * ATAPI or SCSI device.
11757c478bd9Sstevel@tonic-gate 	 */
11767c478bd9Sstevel@tonic-gate 
11777c478bd9Sstevel@tonic-gate 	(void) memset((void *) &inq, 0, sizeof (inq));
11787c478bd9Sstevel@tonic-gate 	(void) memset((void *) &ucmd, 0, sizeof (ucmd));
11797c478bd9Sstevel@tonic-gate 	(void) memset((void *) &cdb, 0, sizeof (cdb));
11807c478bd9Sstevel@tonic-gate 	(void) memset((void *) &rq_data, 0, sizeof (rq_data));
11817c478bd9Sstevel@tonic-gate 	cdb[0] = SCMD_INQUIRY;
11827c478bd9Sstevel@tonic-gate 	cdb[4] = sizeof (inq);
11837c478bd9Sstevel@tonic-gate 	ucmd.uscsi_cdb = (caddr_t)&cdb;
11847c478bd9Sstevel@tonic-gate 	ucmd.uscsi_cdblen = CDB_GROUP0;
11857c478bd9Sstevel@tonic-gate 	ucmd.uscsi_bufaddr = (caddr_t)&inq;
11867c478bd9Sstevel@tonic-gate 	ucmd.uscsi_buflen = sizeof (inq);
11877c478bd9Sstevel@tonic-gate 	ucmd.uscsi_timeout = 120;	/* If 0, HBA hangs forever */
11887c478bd9Sstevel@tonic-gate 	ucmd.uscsi_rqlen = RQ_LEN;
11897c478bd9Sstevel@tonic-gate 	ucmd.uscsi_rqbuf = rq_data;
11907c478bd9Sstevel@tonic-gate 	status = do_uscsi_cmd(fd, &ucmd, USCSI_READ|USCSI_RQENABLE);
11917c478bd9Sstevel@tonic-gate 	if (status || ucmd.uscsi_status) {
11927c478bd9Sstevel@tonic-gate 		debug(5, "inquiry failed: %d - %d errno = %d\n",
11937c478bd9Sstevel@tonic-gate 			status, ucmd.uscsi_status, errno);
11947c478bd9Sstevel@tonic-gate 		return (-1);
11957c478bd9Sstevel@tonic-gate 	}
11967c478bd9Sstevel@tonic-gate 
11977c478bd9Sstevel@tonic-gate 	if (inq.inq_ansi > 0) {
11987c478bd9Sstevel@tonic-gate 		wa_bit = 0;
11997c478bd9Sstevel@tonic-gate 		debug(5, "SCSI device\n");
12007c478bd9Sstevel@tonic-gate 	} else {
12017c478bd9Sstevel@tonic-gate 		wa_bit = 1;
12027c478bd9Sstevel@tonic-gate 		debug(5, "ATAPI device\n");
12037c478bd9Sstevel@tonic-gate 	}
12047c478bd9Sstevel@tonic-gate 
12057c478bd9Sstevel@tonic-gate 	switch (wp->sm_new_state) {
12067c478bd9Sstevel@tonic-gate 		case SM_WRITE_PROTECT_DISABLE :
12077c478bd9Sstevel@tonic-gate 			new_mode = 0x0;
12087c478bd9Sstevel@tonic-gate 			break;
12097c478bd9Sstevel@tonic-gate 		case SM_WRITE_PROTECT_NOPASSWD :
12107c478bd9Sstevel@tonic-gate 			new_mode = 0x2;
12117c478bd9Sstevel@tonic-gate 			break;
12127c478bd9Sstevel@tonic-gate 		case SM_WRITE_PROTECT_PASSWD :
12137c478bd9Sstevel@tonic-gate 			new_mode = 0x3;
12147c478bd9Sstevel@tonic-gate 			break;
12157c478bd9Sstevel@tonic-gate 		case SM_READ_WRITE_PROTECT :
12167c478bd9Sstevel@tonic-gate 			new_mode = 0x5;
12177c478bd9Sstevel@tonic-gate 			break;
12187c478bd9Sstevel@tonic-gate 		case SM_TEMP_UNLOCK_MODE :
12197c478bd9Sstevel@tonic-gate 			new_mode = 0x8;
12207c478bd9Sstevel@tonic-gate 			break;
12217c478bd9Sstevel@tonic-gate 		default :
12227c478bd9Sstevel@tonic-gate 			debug(1, "Invalid mode 0x%x specified\n",
12237c478bd9Sstevel@tonic-gate 			wp->sm_new_state);
12247c478bd9Sstevel@tonic-gate 			errno = ENOTSUP;
12257c478bd9Sstevel@tonic-gate 			return (-1);
12267c478bd9Sstevel@tonic-gate 	}
12277c478bd9Sstevel@tonic-gate 
12287c478bd9Sstevel@tonic-gate 
12297c478bd9Sstevel@tonic-gate 	(void) memset((void *)&ucmd, 0, sizeof (ucmd));
12307c478bd9Sstevel@tonic-gate 	(void) memset((void *)&cdb, 0, sizeof (cdb));
12317c478bd9Sstevel@tonic-gate 	(void) memset((void *) &rq_data, 0, sizeof (rq_data));
12327c478bd9Sstevel@tonic-gate 	cdb[0] = IOMEGA_CATRIDGE_PROTECT;
12337c478bd9Sstevel@tonic-gate 	cdb[1] |= new_mode;
12347c478bd9Sstevel@tonic-gate 	if (wa_bit)
12357c478bd9Sstevel@tonic-gate 		cdb[1] |= WA_BIT;
12367c478bd9Sstevel@tonic-gate 	cdb[4] = wp->sm_passwd_len;
12377c478bd9Sstevel@tonic-gate 	ucmd.uscsi_cdb = (caddr_t)&cdb;
12387c478bd9Sstevel@tonic-gate 	ucmd.uscsi_cdblen = CDB_GROUP0;
12397c478bd9Sstevel@tonic-gate 	if (wa_bit && (wp->sm_passwd_len & 1)) {
12407c478bd9Sstevel@tonic-gate 		/*
12417c478bd9Sstevel@tonic-gate 		 * Oops, ATAPI device with an odd length passwd!
12427c478bd9Sstevel@tonic-gate 		 * Allocate a buffer to hold one extra byte.
12437c478bd9Sstevel@tonic-gate 		 */
12447c478bd9Sstevel@tonic-gate 		debug(5, "Odd len passwd for ATAPI device!\n");
12457c478bd9Sstevel@tonic-gate 		errno = 0;
12467c478bd9Sstevel@tonic-gate 		tmp_passwd = (char *)malloc(wp->sm_passwd_len+1);
12477c478bd9Sstevel@tonic-gate 		if (tmp_passwd == NULL) {
12487c478bd9Sstevel@tonic-gate 			if (errno == 0)
12497c478bd9Sstevel@tonic-gate 				errno = ENOMEM;
12507c478bd9Sstevel@tonic-gate 			return (-1);
12517c478bd9Sstevel@tonic-gate 		}
12527c478bd9Sstevel@tonic-gate 		(void) memset(tmp_passwd, 0, wp->sm_passwd_len+1);
12537c478bd9Sstevel@tonic-gate 		(void) memcpy(tmp_passwd, wp->sm_passwd, wp->sm_passwd_len);
12547c478bd9Sstevel@tonic-gate 		ucmd.uscsi_bufaddr = (caddr_t)tmp_passwd;
12557c478bd9Sstevel@tonic-gate 		ucmd.uscsi_buflen = wp->sm_passwd_len+1;
12567c478bd9Sstevel@tonic-gate 	} else {
12577c478bd9Sstevel@tonic-gate 		ucmd.uscsi_bufaddr = (caddr_t)wp->sm_passwd;
12587c478bd9Sstevel@tonic-gate 		ucmd.uscsi_buflen = wp->sm_passwd_len;
12597c478bd9Sstevel@tonic-gate 	}
12607c478bd9Sstevel@tonic-gate 	ucmd.uscsi_timeout = 120;	/* If 0, HBA hangs forever */
12617c478bd9Sstevel@tonic-gate 	ucmd.uscsi_rqlen = RQ_LEN;
12627c478bd9Sstevel@tonic-gate 	ucmd.uscsi_rqbuf = rq_data;
12637c478bd9Sstevel@tonic-gate 	status = do_uscsi_cmd(fd, &ucmd, USCSI_WRITE|USCSI_RQENABLE);
12647c478bd9Sstevel@tonic-gate 	if (tmp_passwd != NULL) {
12657c478bd9Sstevel@tonic-gate 		free(tmp_passwd);
12667c478bd9Sstevel@tonic-gate 	}
12677c478bd9Sstevel@tonic-gate 	if (status || ucmd.uscsi_status) {
12687c478bd9Sstevel@tonic-gate 		debug(5,
12697c478bd9Sstevel@tonic-gate 	"Catridge protect operation failed: status = %d - %d errno = %d\n",
12707c478bd9Sstevel@tonic-gate 			status, ucmd.uscsi_status, errno);
12717c478bd9Sstevel@tonic-gate 		    if ((rq_data[2] & 0xF) == KEY_ILLEGAL_REQUEST) {
12727c478bd9Sstevel@tonic-gate 			if (rq_data[12] == 0x26) {
12737c478bd9Sstevel@tonic-gate 				/* Wrong passwd */
12747c478bd9Sstevel@tonic-gate 				debug(5,
12757c478bd9Sstevel@tonic-gate "Protection Request with wrong passwd. errno is being set to EACCES.\n");
12767c478bd9Sstevel@tonic-gate 				errno = EACCES;
12777c478bd9Sstevel@tonic-gate 			}
12787c478bd9Sstevel@tonic-gate 		}
12797c478bd9Sstevel@tonic-gate 		return (-1);
12807c478bd9Sstevel@tonic-gate 	}
12817c478bd9Sstevel@tonic-gate 
12827c478bd9Sstevel@tonic-gate 	return (0);
12837c478bd9Sstevel@tonic-gate }
12847c478bd9Sstevel@tonic-gate 
12857c478bd9Sstevel@tonic-gate /*ARGSUSED*/
12867c478bd9Sstevel@tonic-gate static int32_t
12877c478bd9Sstevel@tonic-gate scsi_write_protect(int32_t fd, smwp_state_t *wp)
12887c478bd9Sstevel@tonic-gate {
12897c478bd9Sstevel@tonic-gate 	errno = ENOTSUP;
12907c478bd9Sstevel@tonic-gate 	return (-1);
12917c478bd9Sstevel@tonic-gate }
12927c478bd9Sstevel@tonic-gate 
12937c478bd9Sstevel@tonic-gate static void *
12947c478bd9Sstevel@tonic-gate my_server_thread(void *arg)
12957c478bd9Sstevel@tonic-gate {
12967c478bd9Sstevel@tonic-gate 	door_data_t	*door_dp;
12977c478bd9Sstevel@tonic-gate 	struct	sigaction act;
12987c478bd9Sstevel@tonic-gate 	int	i, oldtype;
12997c478bd9Sstevel@tonic-gate 
13007c478bd9Sstevel@tonic-gate 	door_dp = (door_data_t *)arg;
13017c478bd9Sstevel@tonic-gate 
13027c478bd9Sstevel@tonic-gate 	if (door_dp == NULL) {
13037c478bd9Sstevel@tonic-gate 		fatal("my_server_thread[%d]: argument is NULL!!\n",
13047c478bd9Sstevel@tonic-gate 			pthread_self());
13057c478bd9Sstevel@tonic-gate 		exit(-1);
13067c478bd9Sstevel@tonic-gate 	}
13077c478bd9Sstevel@tonic-gate 	/* Wait for door to be created */
13087c478bd9Sstevel@tonic-gate 
13097c478bd9Sstevel@tonic-gate 	(void) mutex_lock(&door_dp->dd_lock);
13107c478bd9Sstevel@tonic-gate 
13117c478bd9Sstevel@tonic-gate 	if (door_dp->dd_desc[0].d_data.d_desc.d_descriptor == -1)
13127c478bd9Sstevel@tonic-gate 		(void) cond_wait(&door_dp->dd_cv, &door_dp->dd_lock);
13137c478bd9Sstevel@tonic-gate 	(void) mutex_unlock(&door_dp->dd_lock);
13147c478bd9Sstevel@tonic-gate 
13157c478bd9Sstevel@tonic-gate 	for (i = 0; i < N_BADSIGS; i++) {
13167c478bd9Sstevel@tonic-gate 		act.sa_sigaction = server_badsig_handler;
13177c478bd9Sstevel@tonic-gate 		(void) sigemptyset(&act.sa_mask);
13187c478bd9Sstevel@tonic-gate 		act.sa_flags = SA_SIGINFO;
13197c478bd9Sstevel@tonic-gate 		if (sigaction(badsigs[i], &act, NULL) == -1)
13207c478bd9Sstevel@tonic-gate 			warning(gettext(SIGACT_FAILED), strsignal(badsigs[i]),
13217c478bd9Sstevel@tonic-gate 				strerror(errno));
13227c478bd9Sstevel@tonic-gate 	}
13237c478bd9Sstevel@tonic-gate 	if (sigemptyset(&door_dp->dd_newset) != 0)
13247c478bd9Sstevel@tonic-gate 		warning(gettext("sigemptyset failed. errno = %d\n"),
13257c478bd9Sstevel@tonic-gate 			errno);
13267c478bd9Sstevel@tonic-gate 	if (pthread_sigmask(SIG_BLOCK, &door_dp->dd_newset, NULL) != 0)
13277c478bd9Sstevel@tonic-gate 		warning(gettext("pthread_sigmask failed. errno = %d\n"),
13287c478bd9Sstevel@tonic-gate 			errno);
13297c478bd9Sstevel@tonic-gate 
13307c478bd9Sstevel@tonic-gate 	/* Bind thread with pool associated with this door */
13317c478bd9Sstevel@tonic-gate 
13327c478bd9Sstevel@tonic-gate 	if (door_bind(door_dp->dd_desc[0].d_data.d_desc.d_descriptor) < 0) {
13337c478bd9Sstevel@tonic-gate 		fatal("door_bind");
13347c478bd9Sstevel@tonic-gate 		exit(-1);
13357c478bd9Sstevel@tonic-gate 	}
13367c478bd9Sstevel@tonic-gate 	debug(5, "thread 0x%x bound to the door %d.\n", pthread_self(),
13377c478bd9Sstevel@tonic-gate 		door_dp->dd_desc[0].d_data.d_desc.d_descriptor);
13387c478bd9Sstevel@tonic-gate 	/*
13397c478bd9Sstevel@tonic-gate 	 * We ENABLE thread cancellation as default.
13407c478bd9Sstevel@tonic-gate 	 * We will disable it whenever it is unsafe for thread to be cancelled.
13417c478bd9Sstevel@tonic-gate 	 * For example if we are going to be holding locks, we will disable
13427c478bd9Sstevel@tonic-gate 	 * thread cancellation.
13437c478bd9Sstevel@tonic-gate 	 */
13447c478bd9Sstevel@tonic-gate 	if (pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL) != 0)
13457c478bd9Sstevel@tonic-gate 		warning(gettext("pthread_setcancelstate failed. errno = %d\n"),
13467c478bd9Sstevel@tonic-gate 			errno);
13477c478bd9Sstevel@tonic-gate 	/*
13487c478bd9Sstevel@tonic-gate 	 * Receipt of pthread_cancel should cause  immediate cancellation.
13497c478bd9Sstevel@tonic-gate 	 */
13507c478bd9Sstevel@tonic-gate 	if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldtype) != 0)
13517c478bd9Sstevel@tonic-gate 		warning(gettext("pthread_setcanceltype failed. errno = %d\n"),
13527c478bd9Sstevel@tonic-gate 			errno);
13537c478bd9Sstevel@tonic-gate 	/*
13547c478bd9Sstevel@tonic-gate 	 * Inform the main thread that bind is complete.
13557c478bd9Sstevel@tonic-gate 	 */
13567c478bd9Sstevel@tonic-gate 	(void) cond_signal(&door_dp->dd_cv_bind);
13577c478bd9Sstevel@tonic-gate 	(void) door_return(NULL, 0, NULL, 0);
13587c478bd9Sstevel@tonic-gate 	warning(gettext("Exiting my_server_thread[%d]\n"), pthread_self());
13597c478bd9Sstevel@tonic-gate 	return (NULL);
13607c478bd9Sstevel@tonic-gate }
13617c478bd9Sstevel@tonic-gate 
13627c478bd9Sstevel@tonic-gate static void
13637c478bd9Sstevel@tonic-gate cleanup(door_data_t	*door_dp)
13647c478bd9Sstevel@tonic-gate {
13657c478bd9Sstevel@tonic-gate 
13667c478bd9Sstevel@tonic-gate 	debug(5, "cleanup running for thread %d\n", door_dp->dd_thread);
13677c478bd9Sstevel@tonic-gate 	if (door_dp->dd_desc[1].d_data.d_desc.d_descriptor >= 0)
13687c478bd9Sstevel@tonic-gate 	    if (close(door_dp->dd_desc[1].d_data.d_desc.d_descriptor) < 0) {
13697c478bd9Sstevel@tonic-gate 		warning(gettext(
13707c478bd9Sstevel@tonic-gate 		"cleanup:close death door : door id = 0x%x, errno =%d"),
13717c478bd9Sstevel@tonic-gate 			door_dp->dd_desc[1].d_data.d_desc.d_descriptor,
13727c478bd9Sstevel@tonic-gate 			errno);
13737c478bd9Sstevel@tonic-gate 	}
13747c478bd9Sstevel@tonic-gate 	if (door_dp->dd_buffd != -1) {
13757c478bd9Sstevel@tonic-gate 		(void) munmap(door_dp->dd_buf, door_dp->dd_buf_len);
13767c478bd9Sstevel@tonic-gate 		(void) close(door_dp->dd_buffd);
13777c478bd9Sstevel@tonic-gate 		door_dp->dd_buf = NULL;
13787c478bd9Sstevel@tonic-gate 		door_dp->dd_buf_len = 0;
13797c478bd9Sstevel@tonic-gate 	}
13807c478bd9Sstevel@tonic-gate 
13817c478bd9Sstevel@tonic-gate 	/* close the device */
13827c478bd9Sstevel@tonic-gate 	if (door_dp->dd_fd >= 0)
13837c478bd9Sstevel@tonic-gate 	    if (close(door_dp->dd_fd) < 0) {
13847c478bd9Sstevel@tonic-gate 		warning(gettext("cleanup:close fd failed. errno = %d\n"),
13857c478bd9Sstevel@tonic-gate 			errno);
13867c478bd9Sstevel@tonic-gate 	}
13877c478bd9Sstevel@tonic-gate 	if (door_dp->dd_thread != 0)
13887c478bd9Sstevel@tonic-gate 	    if (pthread_cancel(door_dp->dd_thread) != 0)
13897c478bd9Sstevel@tonic-gate 		warning(gettext("pthread_cancel failed. errno = %d\n"),
13907c478bd9Sstevel@tonic-gate 			errno);
13917c478bd9Sstevel@tonic-gate 	free(door_dp);
13927c478bd9Sstevel@tonic-gate 	debug(5, "Exiting cleanup\n");
13937c478bd9Sstevel@tonic-gate }
13947c478bd9Sstevel@tonic-gate 
13957c478bd9Sstevel@tonic-gate static void
13967c478bd9Sstevel@tonic-gate my_create(door_info_t *dip)
13977c478bd9Sstevel@tonic-gate {
13987c478bd9Sstevel@tonic-gate 	door_data_t	*door_dp;
13997c478bd9Sstevel@tonic-gate 	pthread_t	tid;
14007c478bd9Sstevel@tonic-gate 	pthread_attr_t	attr;
14017c478bd9Sstevel@tonic-gate 	int		ret_val;
14027c478bd9Sstevel@tonic-gate 
14037c478bd9Sstevel@tonic-gate 	if (dip == NULL) {
14047c478bd9Sstevel@tonic-gate 		return;
14057c478bd9Sstevel@tonic-gate 	}
1406*360e6f5eSmathue 	door_dp = (door_data_t *)(uintptr_t)dip->di_data;
14077c478bd9Sstevel@tonic-gate 
14087c478bd9Sstevel@tonic-gate 	debug(10, "entering my_create\n");
14097c478bd9Sstevel@tonic-gate 
14107c478bd9Sstevel@tonic-gate 	/* create one thread for this door */
14117c478bd9Sstevel@tonic-gate 
14127c478bd9Sstevel@tonic-gate 	(void) mutex_lock(&door_dp->dd_threadlock);
14137c478bd9Sstevel@tonic-gate 
14147c478bd9Sstevel@tonic-gate 	if (door_dp->dd_thread != 0) {
14157c478bd9Sstevel@tonic-gate 		debug(8, "Exiting my_create without creating thread.\n");
14167c478bd9Sstevel@tonic-gate 		(void) mutex_unlock(&door_dp->dd_threadlock);
14177c478bd9Sstevel@tonic-gate 		return;
14187c478bd9Sstevel@tonic-gate 	}
14197c478bd9Sstevel@tonic-gate 
14207c478bd9Sstevel@tonic-gate 	(void) pthread_attr_init(&attr);
14217c478bd9Sstevel@tonic-gate 	if (pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM) != 0)
14227c478bd9Sstevel@tonic-gate 		warning(gettext(
14237c478bd9Sstevel@tonic-gate 		"pthread_attr_setscope failed. errno = %d\n"),
14247c478bd9Sstevel@tonic-gate 			errno);
14257c478bd9Sstevel@tonic-gate 	if (pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED) != 0)
14267c478bd9Sstevel@tonic-gate 		warning(gettext(
14277c478bd9Sstevel@tonic-gate 		"pthread_attr_setdetachstate failed. errno = %d\n"),
14287c478bd9Sstevel@tonic-gate 			errno);
14297c478bd9Sstevel@tonic-gate 	ret_val = pthread_create(&tid, &attr, my_server_thread,
1430*360e6f5eSmathue 		(void *)(uintptr_t)(dip->di_data));
14317c478bd9Sstevel@tonic-gate 
14327c478bd9Sstevel@tonic-gate 	if (ret_val != 0) {
14337c478bd9Sstevel@tonic-gate 		warning(gettext(
14347c478bd9Sstevel@tonic-gate 			"my_create[%d]:pthread_create failed. errno = %d\n"),
14357c478bd9Sstevel@tonic-gate 				pthread_self(), errno);
14367c478bd9Sstevel@tonic-gate 		(void) mutex_unlock(&door_dp->dd_threadlock);
14377c478bd9Sstevel@tonic-gate 		(void) pthread_attr_destroy(&attr);
14387c478bd9Sstevel@tonic-gate 		return;
14397c478bd9Sstevel@tonic-gate 	}
14407c478bd9Sstevel@tonic-gate 	(void) pthread_attr_destroy(&attr);
14417c478bd9Sstevel@tonic-gate 	door_dp->dd_thread = tid;
14427c478bd9Sstevel@tonic-gate 	debug(5, "my_server_thread[%d] created.\n", tid);
14437c478bd9Sstevel@tonic-gate 
14447c478bd9Sstevel@tonic-gate 	(void) mutex_unlock(&door_dp->dd_threadlock);
14457c478bd9Sstevel@tonic-gate 	debug(5,
14467c478bd9Sstevel@tonic-gate 		"Exiting my_create[%d] after creating a thread.\n",
14477c478bd9Sstevel@tonic-gate 		pthread_self());
14487c478bd9Sstevel@tonic-gate 
14497c478bd9Sstevel@tonic-gate }
14507c478bd9Sstevel@tonic-gate 
14517c478bd9Sstevel@tonic-gate static void
14527c478bd9Sstevel@tonic-gate door_ret_err(smedia_reterror_t *reterror, int32_t err)
14537c478bd9Sstevel@tonic-gate {
14547c478bd9Sstevel@tonic-gate 	reterror->cnum = SMEDIA_CNUM_ERROR;
14557c478bd9Sstevel@tonic-gate 	reterror->errnum = err;
14567c478bd9Sstevel@tonic-gate 	(void) door_return((char *)reterror, sizeof (smedia_reterror_t), 0, 0);
14577c478bd9Sstevel@tonic-gate }
14587c478bd9Sstevel@tonic-gate 
14597c478bd9Sstevel@tonic-gate static void
14607c478bd9Sstevel@tonic-gate my_door_return(char *data_ptr, size_t data_size,
14617c478bd9Sstevel@tonic-gate 	door_desc_t *desc_ptr, uint_t num_desc)
14627c478bd9Sstevel@tonic-gate {
14637c478bd9Sstevel@tonic-gate 	(void) door_return(data_ptr, data_size, desc_ptr, num_desc);
14647c478bd9Sstevel@tonic-gate }
14657c478bd9Sstevel@tonic-gate 
14667c478bd9Sstevel@tonic-gate static int32_t
14677c478bd9Sstevel@tonic-gate raw_read(door_data_t *door_dp, smedia_services_t *req)
14687c478bd9Sstevel@tonic-gate {
14697c478bd9Sstevel@tonic-gate 	struct uscsi_cmd	ucmd;
14707c478bd9Sstevel@tonic-gate 	union scsi_cdb		cdb;
14717c478bd9Sstevel@tonic-gate 	int32_t			ret_val;
14727c478bd9Sstevel@tonic-gate 	int32_t			num_sectors, sector_size;
14737c478bd9Sstevel@tonic-gate 	int32_t			rc_data[2];
14747c478bd9Sstevel@tonic-gate 	char			rq_data[RQ_LEN];
14757c478bd9Sstevel@tonic-gate 
14767c478bd9Sstevel@tonic-gate 	(void) memset((void *) &rc_data, 0, sizeof (rc_data));
14777c478bd9Sstevel@tonic-gate 	(void) memset((void *) &ucmd, 0, sizeof (ucmd));
14787c478bd9Sstevel@tonic-gate 	(void) memset((void *) &cdb, 0, sizeof (union scsi_cdb));
14797c478bd9Sstevel@tonic-gate 
14807c478bd9Sstevel@tonic-gate 	if (door_dp->dd_sector_size == 0) {
14817c478bd9Sstevel@tonic-gate 		sector_size = get_sector_size(door_dp->dd_fd);
14827c478bd9Sstevel@tonic-gate 		door_dp->dd_sector_size = sector_size;
14837c478bd9Sstevel@tonic-gate 	} else sector_size = door_dp->dd_sector_size;
14847c478bd9Sstevel@tonic-gate 
14857c478bd9Sstevel@tonic-gate 	if ((req->reqraw_read.nbytes > door_dp->dd_buf_len) ||
14867c478bd9Sstevel@tonic-gate 		(door_dp->dd_buf == NULL)) {
14877c478bd9Sstevel@tonic-gate 		errno = EINVAL;
14887c478bd9Sstevel@tonic-gate 		return (-1);
14897c478bd9Sstevel@tonic-gate 	}
14907c478bd9Sstevel@tonic-gate 	if ((!req->reqraw_read.nbytes) ||
14917c478bd9Sstevel@tonic-gate 		(req->reqraw_read.nbytes % sector_size)) {
14927c478bd9Sstevel@tonic-gate 		errno = EINVAL;
14937c478bd9Sstevel@tonic-gate 		return (-1);
14947c478bd9Sstevel@tonic-gate 	}
14957c478bd9Sstevel@tonic-gate 
14967c478bd9Sstevel@tonic-gate 	(void) memset((void *) &cdb, 0, sizeof (cdb));
14977c478bd9Sstevel@tonic-gate 	num_sectors = (uint32_t)req->reqraw_read.nbytes/sector_size;
14987c478bd9Sstevel@tonic-gate 
14997c478bd9Sstevel@tonic-gate 	cdb.scc_cmd = SCMD_READ_G1;
15007c478bd9Sstevel@tonic-gate 	FORMG1ADDR(&cdb, (uint32_t)req->reqraw_read.blockno);
15017c478bd9Sstevel@tonic-gate 	FORMG1COUNT(&cdb, num_sectors);
15027c478bd9Sstevel@tonic-gate 
15037c478bd9Sstevel@tonic-gate 	ucmd.uscsi_cdb = (caddr_t)&cdb;
15047c478bd9Sstevel@tonic-gate 	ucmd.uscsi_cdblen = CDB_GROUP1;
15057c478bd9Sstevel@tonic-gate 	ucmd.uscsi_bufaddr = (caddr_t)door_dp->dd_buf;
15067c478bd9Sstevel@tonic-gate 	ucmd.uscsi_buflen = (uint32_t)req->reqraw_read.nbytes;
15077c478bd9Sstevel@tonic-gate 	ucmd.uscsi_timeout = 120;	/* If 0, HBA hangs forever */
15087c478bd9Sstevel@tonic-gate 	ucmd.uscsi_rqlen = RQ_LEN;
15097c478bd9Sstevel@tonic-gate 	ucmd.uscsi_rqbuf = rq_data;
15107c478bd9Sstevel@tonic-gate 	ret_val = do_uscsi_cmd(door_dp->dd_fd,
15117c478bd9Sstevel@tonic-gate 		&ucmd, USCSI_READ|USCSI_RQENABLE);
15127c478bd9Sstevel@tonic-gate 	if (ret_val || ucmd.uscsi_status) {
15137c478bd9Sstevel@tonic-gate 		debug(5, "read failed: %d - %d errno = %d\n",
15147c478bd9Sstevel@tonic-gate 			ret_val, ucmd.uscsi_status, errno);
15157c478bd9Sstevel@tonic-gate 		debug(5, "buflen = 0x%x resid = 0x%x sector size = %d\n",
15167c478bd9Sstevel@tonic-gate 			ucmd.uscsi_buflen, ucmd.uscsi_resid, sector_size);
15177c478bd9Sstevel@tonic-gate 		debug(5, "cdb addr: %x %x %x %x \n", cdb.g1_addr3,
15187c478bd9Sstevel@tonic-gate 			cdb.g1_addr2, cdb.g1_addr1, cdb.g1_addr0);
15197c478bd9Sstevel@tonic-gate 		debug(5, "cdb count: %x %x\n", cdb.g1_count1,
15207c478bd9Sstevel@tonic-gate 			cdb.g1_count0);
15217c478bd9Sstevel@tonic-gate 		return (-1);
15227c478bd9Sstevel@tonic-gate 	}
15237c478bd9Sstevel@tonic-gate 	ret_val = ucmd.uscsi_buflen - ucmd.uscsi_resid;
15247c478bd9Sstevel@tonic-gate 	return (ret_val);
15257c478bd9Sstevel@tonic-gate }
15267c478bd9Sstevel@tonic-gate 
15277c478bd9Sstevel@tonic-gate static int32_t
15287c478bd9Sstevel@tonic-gate raw_write(door_data_t *door_dp, smedia_services_t *req)
15297c478bd9Sstevel@tonic-gate {
15307c478bd9Sstevel@tonic-gate 	struct uscsi_cmd	ucmd;
15317c478bd9Sstevel@tonic-gate 	union scsi_cdb		cdb;
15327c478bd9Sstevel@tonic-gate 	int32_t			ret_val;
15337c478bd9Sstevel@tonic-gate 	int32_t			num_sectors, sector_size;
15347c478bd9Sstevel@tonic-gate 	int32_t			rc_data[2];
15357c478bd9Sstevel@tonic-gate 	char			rq_data[RQ_LEN];
15367c478bd9Sstevel@tonic-gate 
15377c478bd9Sstevel@tonic-gate 	(void) memset((void *) &rc_data, 0, sizeof (rc_data));
15387c478bd9Sstevel@tonic-gate 	(void) memset((void *) &ucmd, 0, sizeof (ucmd));
15397c478bd9Sstevel@tonic-gate 	(void) memset((void *) &cdb, 0, sizeof (union scsi_cdb));
15407c478bd9Sstevel@tonic-gate 
15417c478bd9Sstevel@tonic-gate 	if (door_dp->dd_sector_size == 0) {
15427c478bd9Sstevel@tonic-gate 		sector_size = get_sector_size(door_dp->dd_fd);
15437c478bd9Sstevel@tonic-gate 		door_dp->dd_sector_size = sector_size;
15447c478bd9Sstevel@tonic-gate 	} else sector_size = door_dp->dd_sector_size;
15457c478bd9Sstevel@tonic-gate 
15467c478bd9Sstevel@tonic-gate 
15477c478bd9Sstevel@tonic-gate 	if ((req->reqraw_write.nbytes > door_dp->dd_buf_len) ||
15487c478bd9Sstevel@tonic-gate 		(door_dp->dd_buf == NULL)) {
15497c478bd9Sstevel@tonic-gate 		errno = EINVAL;
15507c478bd9Sstevel@tonic-gate 		return (-1);
15517c478bd9Sstevel@tonic-gate 	}
15527c478bd9Sstevel@tonic-gate 	if ((req->reqraw_write.nbytes % sector_size)) {
15537c478bd9Sstevel@tonic-gate 		errno = EINVAL;
15547c478bd9Sstevel@tonic-gate 		return (-1);
15557c478bd9Sstevel@tonic-gate 	}
15567c478bd9Sstevel@tonic-gate 
15577c478bd9Sstevel@tonic-gate 	(void) memset((void *) &cdb, 0, sizeof (cdb));
15587c478bd9Sstevel@tonic-gate 	num_sectors = (uint32_t)req->reqraw_write.nbytes/sector_size;
15597c478bd9Sstevel@tonic-gate 
15607c478bd9Sstevel@tonic-gate 	cdb.scc_cmd = SCMD_WRITE_G1;
15617c478bd9Sstevel@tonic-gate 	FORMG1ADDR(&cdb, (uint32_t)req->reqraw_write.blockno);
15627c478bd9Sstevel@tonic-gate 	FORMG1COUNT(&cdb, num_sectors);
15637c478bd9Sstevel@tonic-gate 
15647c478bd9Sstevel@tonic-gate 	ucmd.uscsi_cdb = (caddr_t)&cdb;
15657c478bd9Sstevel@tonic-gate 	ucmd.uscsi_cdblen = CDB_GROUP1;
15667c478bd9Sstevel@tonic-gate 	ucmd.uscsi_bufaddr = (caddr_t)door_dp->dd_buf;
15677c478bd9Sstevel@tonic-gate 	ucmd.uscsi_buflen = (uint32_t)req->reqraw_write.nbytes;
15687c478bd9Sstevel@tonic-gate 	ucmd.uscsi_timeout = 120;	/* If 0, HBA hangs forever */
15697c478bd9Sstevel@tonic-gate 	ucmd.uscsi_rqlen = RQ_LEN;
15707c478bd9Sstevel@tonic-gate 	ucmd.uscsi_rqbuf = rq_data;
15717c478bd9Sstevel@tonic-gate 	ret_val = do_uscsi_cmd(door_dp->dd_fd,
15727c478bd9Sstevel@tonic-gate 		&ucmd, USCSI_WRITE|USCSI_RQENABLE);
15737c478bd9Sstevel@tonic-gate 	if (ret_val || ucmd.uscsi_status) {
15747c478bd9Sstevel@tonic-gate 		debug(5, "write failed: %d - %d errno = %d\n",
15757c478bd9Sstevel@tonic-gate 			ret_val, ucmd.uscsi_status, errno);
15767c478bd9Sstevel@tonic-gate 		debug(5, "buflen = 0x%x resid = 0x%x sector size = %d\n",
15777c478bd9Sstevel@tonic-gate 			ucmd.uscsi_buflen, ucmd.uscsi_resid, sector_size);
15787c478bd9Sstevel@tonic-gate 		debug(5, "cdb addr: %x %x %x %x \n", cdb.g1_addr3,
15797c478bd9Sstevel@tonic-gate 			cdb.g1_addr2, cdb.g1_addr1, cdb.g1_addr0);
15807c478bd9Sstevel@tonic-gate 		debug(5, "cdb count: %x %x\n", cdb.g1_count1,
15817c478bd9Sstevel@tonic-gate 			cdb.g1_count0);
15827c478bd9Sstevel@tonic-gate 		return (-1);
15837c478bd9Sstevel@tonic-gate 	}
15847c478bd9Sstevel@tonic-gate 	ret_val = ucmd.uscsi_buflen - ucmd.uscsi_resid;
15857c478bd9Sstevel@tonic-gate 	return (ret_val);
15867c478bd9Sstevel@tonic-gate }
15877c478bd9Sstevel@tonic-gate 
15887c478bd9Sstevel@tonic-gate static int32_t
15897c478bd9Sstevel@tonic-gate set_protection_status(door_data_t *door_dp, smedia_services_t *req)
15907c478bd9Sstevel@tonic-gate {
15917c478bd9Sstevel@tonic-gate 	int32_t			ret_val, saved_errno, status;
15927c478bd9Sstevel@tonic-gate 	struct scsi_inquiry	inq;
15937c478bd9Sstevel@tonic-gate 	char			vid[9];
15947c478bd9Sstevel@tonic-gate 	char			pid[17];
15957c478bd9Sstevel@tonic-gate 	struct passwd		*pwd;
15967c478bd9Sstevel@tonic-gate 	char			uname[MAXUGNAME + 1];
15977c478bd9Sstevel@tonic-gate 	char			*new_state, *old_state;
15987c478bd9Sstevel@tonic-gate 
15997c478bd9Sstevel@tonic-gate 	/*
16007c478bd9Sstevel@tonic-gate 	 * Read the current protection state before modifiying.
16017c478bd9Sstevel@tonic-gate 	 * Needed for audit purposes.
16027c478bd9Sstevel@tonic-gate 	 */
16037c478bd9Sstevel@tonic-gate 	switch (get_device_type_scsi(door_dp->dd_fd, &inq)) {
16047c478bd9Sstevel@tonic-gate 	case SCSI_IOMEGA:
16057c478bd9Sstevel@tonic-gate 		status = scsi_zip_media_status(door_dp->dd_fd);
16067c478bd9Sstevel@tonic-gate 		ret_val = scsi_zip_write_protect(door_dp->dd_fd,
16077c478bd9Sstevel@tonic-gate 			&req->reqset_protection_status.prot_state);
16087c478bd9Sstevel@tonic-gate 		break;
16097c478bd9Sstevel@tonic-gate 	case SCSI_FLOPPY:
16107c478bd9Sstevel@tonic-gate 		info("Formatting floppy");
16117c478bd9Sstevel@tonic-gate 		status = scsi_floppy_media_status(door_dp->dd_fd);
16127c478bd9Sstevel@tonic-gate 		ret_val = scsi_floppy_write_protect(door_dp->dd_fd,
16137c478bd9Sstevel@tonic-gate 			&req->reqset_protection_status.prot_state);
16147c478bd9Sstevel@tonic-gate 		break;
16157c478bd9Sstevel@tonic-gate 	case SCSI_GENERIC:
16167c478bd9Sstevel@tonic-gate 		status = scsi_media_status(door_dp->dd_fd);
16177c478bd9Sstevel@tonic-gate 		ret_val = scsi_write_protect(door_dp->dd_fd,
16187c478bd9Sstevel@tonic-gate 			&req->reqset_protection_status.prot_state);
16197c478bd9Sstevel@tonic-gate 		break;
16207c478bd9Sstevel@tonic-gate 	}
16217c478bd9Sstevel@tonic-gate 
16227c478bd9Sstevel@tonic-gate 	saved_errno = errno;
16237c478bd9Sstevel@tonic-gate 	new_state = xlate_state(
16247c478bd9Sstevel@tonic-gate 	    req->reqset_protection_status.prot_state.sm_new_state);
16257c478bd9Sstevel@tonic-gate 	old_state = xlate_state(status);
16267c478bd9Sstevel@tonic-gate 
16277c478bd9Sstevel@tonic-gate 	if (can_audit()) {
16287c478bd9Sstevel@tonic-gate 		(void) audit_save_me(door_dp);
16297c478bd9Sstevel@tonic-gate 		door_dp->audit_text[0] = 0;
16307c478bd9Sstevel@tonic-gate 		door_dp->audit_text1[0] = 0;
16317c478bd9Sstevel@tonic-gate 		door_dp->audit_event = AUE_smserverd;
16327c478bd9Sstevel@tonic-gate 	}
16337c478bd9Sstevel@tonic-gate 	(void) strlcpy(vid, inq.inq_vid, sizeof (vid));
16347c478bd9Sstevel@tonic-gate 	(void) strlcpy(pid, inq.inq_pid, sizeof (pid));
16357c478bd9Sstevel@tonic-gate 	if (ret_val < 0) {
16367c478bd9Sstevel@tonic-gate 	    if (errno == EACCES) {
16377c478bd9Sstevel@tonic-gate 		pwd = getpwuid(door_dp->dd_cred.dc_ruid);
16387c478bd9Sstevel@tonic-gate 		if (pwd != NULL) {
16397c478bd9Sstevel@tonic-gate 			(void) strlcpy(uname,
16407c478bd9Sstevel@tonic-gate 				pwd->pw_name, MAXUGNAME);
16417c478bd9Sstevel@tonic-gate 		} else uname[0] = 0;
16427c478bd9Sstevel@tonic-gate 
16437c478bd9Sstevel@tonic-gate 		if (can_audit()) {
16447c478bd9Sstevel@tonic-gate 			(void) snprintf(door_dp->audit_text,
16457c478bd9Sstevel@tonic-gate 				sizeof (door_dp->audit_text),
16467c478bd9Sstevel@tonic-gate 				dgettext(TEXT_DOMAIN, "from %s to %s"),
16477c478bd9Sstevel@tonic-gate 				old_state, new_state);
16487c478bd9Sstevel@tonic-gate 
16497c478bd9Sstevel@tonic-gate 			(void) snprintf(door_dp->audit_text1,
16507c478bd9Sstevel@tonic-gate 				sizeof (door_dp->audit_text1),
16517c478bd9Sstevel@tonic-gate 				"%s %s (%d,%d)", vid, pid,
16527c478bd9Sstevel@tonic-gate 				(int)major(door_dp->dd_stat.st_rdev),
16537c478bd9Sstevel@tonic-gate 				(int)minor(door_dp->dd_stat.st_rdev));
16547c478bd9Sstevel@tonic-gate 
16557c478bd9Sstevel@tonic-gate 			door_dp->audit_sorf = 1;
16567c478bd9Sstevel@tonic-gate 			if (audit_audit(door_dp) == -1)
16577c478bd9Sstevel@tonic-gate 			    warning("Error in writing audit info\n");
16587c478bd9Sstevel@tonic-gate 		}
16597c478bd9Sstevel@tonic-gate 	    } /* errno == EACCES */
16607c478bd9Sstevel@tonic-gate 	    errno = saved_errno;
16617c478bd9Sstevel@tonic-gate 	    return (-1);
16627c478bd9Sstevel@tonic-gate 	}
16637c478bd9Sstevel@tonic-gate 	if (can_audit()) {
16647c478bd9Sstevel@tonic-gate 		(void) snprintf(door_dp->audit_text,
16657c478bd9Sstevel@tonic-gate 			sizeof (door_dp->audit_text),
16667c478bd9Sstevel@tonic-gate 			dgettext(TEXT_DOMAIN, "from %s to %s"),
16677c478bd9Sstevel@tonic-gate 			old_state, new_state);
16687c478bd9Sstevel@tonic-gate 
16697c478bd9Sstevel@tonic-gate 		(void) snprintf(door_dp->audit_text1,
16707c478bd9Sstevel@tonic-gate 			sizeof (door_dp->audit_text1),
16717c478bd9Sstevel@tonic-gate 			"%s %s (%d,%d)", vid, pid,
16727c478bd9Sstevel@tonic-gate 			(int)major(door_dp->dd_stat.st_rdev),
16737c478bd9Sstevel@tonic-gate 			(int)minor(door_dp->dd_stat.st_rdev));
16747c478bd9Sstevel@tonic-gate 
16757c478bd9Sstevel@tonic-gate 		door_dp->audit_sorf = 0;
16767c478bd9Sstevel@tonic-gate 		if (audit_audit(door_dp) == -1)
16777c478bd9Sstevel@tonic-gate 		    warning("Error in writing audit info\n");
16787c478bd9Sstevel@tonic-gate 	}
16797c478bd9Sstevel@tonic-gate 	errno = saved_errno;
16807c478bd9Sstevel@tonic-gate 	return (0);
16817c478bd9Sstevel@tonic-gate }
16827c478bd9Sstevel@tonic-gate 
16837c478bd9Sstevel@tonic-gate static int32_t
16847c478bd9Sstevel@tonic-gate set_shfd(door_data_t	*door_dp, int32_t fd, smedia_services_t *req)
16857c478bd9Sstevel@tonic-gate {
16867c478bd9Sstevel@tonic-gate 	void	*fbuf;
16877c478bd9Sstevel@tonic-gate 	int32_t	ret_val;
16887c478bd9Sstevel@tonic-gate 
16897c478bd9Sstevel@tonic-gate 	if ((door_dp->dd_buffd != -1) &&
16907c478bd9Sstevel@tonic-gate 		(door_dp->dd_buf != NULL)) {
16917c478bd9Sstevel@tonic-gate 			ret_val = munmap(door_dp->dd_buf,
16927c478bd9Sstevel@tonic-gate 				door_dp->dd_buf_len);
16937c478bd9Sstevel@tonic-gate 			if (ret_val == -1)
16947c478bd9Sstevel@tonic-gate 				warning(gettext(
16957c478bd9Sstevel@tonic-gate 					"munmap failed. errno=%d\n"),
16967c478bd9Sstevel@tonic-gate 						errno);
16977c478bd9Sstevel@tonic-gate 			(void) close(door_dp->dd_buffd);
16987c478bd9Sstevel@tonic-gate 			door_dp->dd_buffd = -1;
16997c478bd9Sstevel@tonic-gate 			door_dp->dd_buf = 0;
17007c478bd9Sstevel@tonic-gate 			door_dp->dd_buf_len = 0;
17017c478bd9Sstevel@tonic-gate 	}
17027c478bd9Sstevel@tonic-gate 	fbuf = mmap(0, req->reqset_shfd.fdbuf_len,
17037c478bd9Sstevel@tonic-gate 		PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
17047c478bd9Sstevel@tonic-gate 	if (fbuf == (char *)-1) {
17057c478bd9Sstevel@tonic-gate 		debug(5, "mmap failed. errno=%d\n", errno);
17067c478bd9Sstevel@tonic-gate 		return (-1);
17077c478bd9Sstevel@tonic-gate 	}
17087c478bd9Sstevel@tonic-gate 	door_dp->dd_buffd = fd;
17097c478bd9Sstevel@tonic-gate 	door_dp->dd_buf = fbuf;
17107c478bd9Sstevel@tonic-gate 	door_dp->dd_buf_len = req->reqset_shfd.fdbuf_len;
17117c478bd9Sstevel@tonic-gate 	return (0);
17127c478bd9Sstevel@tonic-gate }
17137c478bd9Sstevel@tonic-gate 
17147c478bd9Sstevel@tonic-gate static int32_t
17157c478bd9Sstevel@tonic-gate reassign_block(door_data_t *door_dp, smedia_services_t *req)
17167c478bd9Sstevel@tonic-gate {
17177c478bd9Sstevel@tonic-gate 	struct uscsi_cmd	ucmd;
17187c478bd9Sstevel@tonic-gate 	union scsi_cdb		cdb;
17197c478bd9Sstevel@tonic-gate 	int32_t			ret_val;
17207c478bd9Sstevel@tonic-gate 	int32_t			sector_size;
17217c478bd9Sstevel@tonic-gate 	char			*read_buf;
17227c478bd9Sstevel@tonic-gate 	uchar_t			mode_data[MD_LEN];
17237c478bd9Sstevel@tonic-gate 
17247c478bd9Sstevel@tonic-gate 	if (get_mode_page(door_dp->dd_fd, 0, 1,
17257c478bd9Sstevel@tonic-gate 		mode_data, MD_LEN) < 0) {
17267c478bd9Sstevel@tonic-gate 		debug(5, "Mode sense failed\n");
17277c478bd9Sstevel@tonic-gate 		ret_val =  scsi_reassign_block(door_dp->dd_fd,
17287c478bd9Sstevel@tonic-gate 			req->reqreassign_block.blockno);
17297c478bd9Sstevel@tonic-gate 		if (ret_val != 0)
17307c478bd9Sstevel@tonic-gate 			return (-1);
17317c478bd9Sstevel@tonic-gate 		return (0);
17327c478bd9Sstevel@tonic-gate 	}
17337c478bd9Sstevel@tonic-gate 
17347c478bd9Sstevel@tonic-gate 	/*
17357c478bd9Sstevel@tonic-gate 	 * No need to check if enough data is returned for
17367c478bd9Sstevel@tonic-gate 	 * AWRE bit or not.
17377c478bd9Sstevel@tonic-gate 	 * It will be 0 otherwise which needs to reassign the block.
17387c478bd9Sstevel@tonic-gate 	 */
17397c478bd9Sstevel@tonic-gate 	if (!(mode_data[AWRE_OFFSET] & AWRE)) {
17407c478bd9Sstevel@tonic-gate 		debug(5, "AWRE bit not set\n");
17417c478bd9Sstevel@tonic-gate 		ret_val =  scsi_reassign_block(door_dp->dd_fd,
17427c478bd9Sstevel@tonic-gate 			req->reqreassign_block.blockno);
17437c478bd9Sstevel@tonic-gate 		if (ret_val != 0)
17447c478bd9Sstevel@tonic-gate 			return (-1);
17457c478bd9Sstevel@tonic-gate 		return (0);
17467c478bd9Sstevel@tonic-gate 	}
17477c478bd9Sstevel@tonic-gate 	sector_size = (mode_data[BLOCK_LEN_OFFSET] << 16) |
17487c478bd9Sstevel@tonic-gate 		(mode_data[BLOCK_LEN_OFFSET + 1] << 8) |
17497c478bd9Sstevel@tonic-gate 		mode_data[BLOCK_LEN_OFFSET + 2];
17507c478bd9Sstevel@tonic-gate 
17517c478bd9Sstevel@tonic-gate 	debug(5, "REASSIGN BLOCK: sec size = 0x%x\n", sector_size);
17527c478bd9Sstevel@tonic-gate 	read_buf = (char *)malloc(sector_size);
17537c478bd9Sstevel@tonic-gate 	if (read_buf == NULL) {
17547c478bd9Sstevel@tonic-gate 		/* Alloc failed. Atleast reassign the block */
17557c478bd9Sstevel@tonic-gate 		ret_val =  scsi_reassign_block(door_dp->dd_fd,
17567c478bd9Sstevel@tonic-gate 			req->reqreassign_block.blockno);
17577c478bd9Sstevel@tonic-gate 		if (ret_val != 0)
17587c478bd9Sstevel@tonic-gate 			return (-1);
17597c478bd9Sstevel@tonic-gate 		return (0);
17607c478bd9Sstevel@tonic-gate 	}
17617c478bd9Sstevel@tonic-gate 
17627c478bd9Sstevel@tonic-gate 	(void) memset(read_buf, 0, sector_size);
17637c478bd9Sstevel@tonic-gate 	/* Read the sector */
17647c478bd9Sstevel@tonic-gate 	debug(5, "Reading the block %d\n",
17657c478bd9Sstevel@tonic-gate 		(uint32_t)req->reqreassign_block.blockno);
17667c478bd9Sstevel@tonic-gate 
17677c478bd9Sstevel@tonic-gate 	(void) memset((void *) &ucmd, 0, sizeof (ucmd));
17687c478bd9Sstevel@tonic-gate 	(void) memset((void *) &cdb, 0, sizeof (union scsi_cdb));
17697c478bd9Sstevel@tonic-gate 
17707c478bd9Sstevel@tonic-gate 	cdb.scc_cmd = SCMD_READ_G1;
17717c478bd9Sstevel@tonic-gate 	FORMG1ADDR(&cdb, req->reqreassign_block.blockno);
17727c478bd9Sstevel@tonic-gate 	FORMG1COUNT(&cdb, 1);	/* One block */
17737c478bd9Sstevel@tonic-gate 
17747c478bd9Sstevel@tonic-gate 	ucmd.uscsi_cdb = (caddr_t)&cdb;
17757c478bd9Sstevel@tonic-gate 	ucmd.uscsi_cdblen = CDB_GROUP1;
17767c478bd9Sstevel@tonic-gate 	ucmd.uscsi_bufaddr = (caddr_t)read_buf;
17777c478bd9Sstevel@tonic-gate 	ucmd.uscsi_buflen = sector_size;
17787c478bd9Sstevel@tonic-gate 	ucmd.uscsi_timeout = 120;	/* If 0, HBA hangs forever */
17797c478bd9Sstevel@tonic-gate 	(void) do_uscsi_cmd(door_dp->dd_fd, &ucmd, USCSI_READ);
17807c478bd9Sstevel@tonic-gate 
17817c478bd9Sstevel@tonic-gate 	/* Write the data back */
17827c478bd9Sstevel@tonic-gate 
17837c478bd9Sstevel@tonic-gate 	debug(5, "Writing the block %d\n",
17847c478bd9Sstevel@tonic-gate 		(uint32_t)req->reqreassign_block.blockno);
17857c478bd9Sstevel@tonic-gate 	(void) memset((void *) &ucmd, 0, sizeof (ucmd));
17867c478bd9Sstevel@tonic-gate 	(void) memset((void *) &cdb, 0, sizeof (cdb));
17877c478bd9Sstevel@tonic-gate 
17887c478bd9Sstevel@tonic-gate 	cdb.scc_cmd = SCMD_WRITE_G1;
17897c478bd9Sstevel@tonic-gate 	FORMG1ADDR(&cdb, req->reqreassign_block.blockno);
17907c478bd9Sstevel@tonic-gate 	FORMG1COUNT(&cdb, 1);	/* One block */
17917c478bd9Sstevel@tonic-gate 
17927c478bd9Sstevel@tonic-gate 	ucmd.uscsi_cdb = (caddr_t)&cdb;
17937c478bd9Sstevel@tonic-gate 	ucmd.uscsi_cdblen = CDB_GROUP1;
17947c478bd9Sstevel@tonic-gate 	ucmd.uscsi_bufaddr = (caddr_t)read_buf;
17957c478bd9Sstevel@tonic-gate 	ucmd.uscsi_buflen = sector_size;
17967c478bd9Sstevel@tonic-gate 	ucmd.uscsi_timeout = 120;	/* If 0, HBA hangs forever */
17977c478bd9Sstevel@tonic-gate 	ret_val = do_uscsi_cmd(door_dp->dd_fd, &ucmd, USCSI_WRITE);
17987c478bd9Sstevel@tonic-gate 	free(read_buf);
17997c478bd9Sstevel@tonic-gate 	if (ret_val || ucmd.uscsi_status) {
18007c478bd9Sstevel@tonic-gate 		debug(5, "Reassign failed: %d - %d errno = %d\n",
18017c478bd9Sstevel@tonic-gate 			ret_val, ucmd.uscsi_status, errno);
18027c478bd9Sstevel@tonic-gate 		ret_val = scsi_reassign_block(door_dp->dd_fd,
18037c478bd9Sstevel@tonic-gate 			req->reqreassign_block.blockno);
18047c478bd9Sstevel@tonic-gate 		if (ret_val != 0)
18057c478bd9Sstevel@tonic-gate 			return (-1);
18067c478bd9Sstevel@tonic-gate 		return (0);
18077c478bd9Sstevel@tonic-gate 	}
18087c478bd9Sstevel@tonic-gate 
18097c478bd9Sstevel@tonic-gate 	return (0);
18107c478bd9Sstevel@tonic-gate }
18117c478bd9Sstevel@tonic-gate 
18127c478bd9Sstevel@tonic-gate static void
18137c478bd9Sstevel@tonic-gate close_door_descs(door_desc_t *dp, uint_t ndesc)
18147c478bd9Sstevel@tonic-gate {
18157c478bd9Sstevel@tonic-gate 	while (ndesc > 0) {
18167c478bd9Sstevel@tonic-gate 		int fd = dp->d_data.d_desc.d_descriptor;
18177c478bd9Sstevel@tonic-gate 		if (dp->d_attributes & DOOR_DESCRIPTOR)
18187c478bd9Sstevel@tonic-gate 			(void) close(fd);
18197c478bd9Sstevel@tonic-gate 		dp++;
18207c478bd9Sstevel@tonic-gate 		ndesc--;
18217c478bd9Sstevel@tonic-gate 	}
18227c478bd9Sstevel@tonic-gate }
18237c478bd9Sstevel@tonic-gate 
18247c478bd9Sstevel@tonic-gate static void
18257c478bd9Sstevel@tonic-gate client_server(void *cookie, char *argp, size_t arg_size,
18267c478bd9Sstevel@tonic-gate     door_desc_t *dp, uint_t ndesc)
18277c478bd9Sstevel@tonic-gate {
18287c478bd9Sstevel@tonic-gate 	smedia_services_t	*req;
18297c478bd9Sstevel@tonic-gate 	smedia_services_t	rmsvc;
18307c478bd9Sstevel@tonic-gate 	smedia_reterror_t	reterror;
18317c478bd9Sstevel@tonic-gate 	smedia_retraw_read_t	retraw_read;
18327c478bd9Sstevel@tonic-gate 	struct scsi_inquiry	inq;
18337c478bd9Sstevel@tonic-gate 	struct dk_minfo		media_info;
18347c478bd9Sstevel@tonic-gate 	struct dk_geom		dkgeom;
18357c478bd9Sstevel@tonic-gate 	int32_t			status;
18367c478bd9Sstevel@tonic-gate 	uchar_t			data[18];
18377c478bd9Sstevel@tonic-gate 	int32_t			completed = 0;
18387c478bd9Sstevel@tonic-gate 	door_data_t		*door_dp;
18397c478bd9Sstevel@tonic-gate 	size_t			retbuf_size;
18407c478bd9Sstevel@tonic-gate 	struct uscsi_cmd	ucmd;
18417c478bd9Sstevel@tonic-gate 	union scsi_cdb		cdb;
18427c478bd9Sstevel@tonic-gate 	int32_t			ret_val, err;
18437c478bd9Sstevel@tonic-gate 	char			rq_data[RQ_LEN];
18447c478bd9Sstevel@tonic-gate 	uint_t			expected_descs;
18457c478bd9Sstevel@tonic-gate 	struct vtoc		vtoc;
18467c478bd9Sstevel@tonic-gate 
18477c478bd9Sstevel@tonic-gate 	door_dp = (door_data_t *)cookie;
18487c478bd9Sstevel@tonic-gate 	req = (smedia_services_t *)((void *)argp);
18497c478bd9Sstevel@tonic-gate 
18507c478bd9Sstevel@tonic-gate 	debug(10, "Entering client server...\n");
18517c478bd9Sstevel@tonic-gate 
18527c478bd9Sstevel@tonic-gate 	if (argp == DOOR_UNREF_DATA) {
18537c478bd9Sstevel@tonic-gate 		debug(5, "client_server[%d]...DOOR_UNREF_DATA\n",
18547c478bd9Sstevel@tonic-gate 			pthread_self());
18557c478bd9Sstevel@tonic-gate 		debug(5, "Client has exited. Cleaning up resources\n");
18567c478bd9Sstevel@tonic-gate 		(void) mutex_lock(&svcstate_lock);
18577c478bd9Sstevel@tonic-gate 		svccount--;
18587c478bd9Sstevel@tonic-gate 		(void) mutex_unlock(&svcstate_lock);
18597c478bd9Sstevel@tonic-gate 		cleanup(door_dp);
18607c478bd9Sstevel@tonic-gate 		(void) door_return(NULL, 0, NULL, 0);
18617c478bd9Sstevel@tonic-gate 	}
18627c478bd9Sstevel@tonic-gate 	/*
18637c478bd9Sstevel@tonic-gate 	 * we disable thread cancellation while holding locks.
18647c478bd9Sstevel@tonic-gate 	 */
18657c478bd9Sstevel@tonic-gate 	if (pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL) != 0)
18667c478bd9Sstevel@tonic-gate 		warning(gettext("pthread_setcancelstate failed. errno = %d\n"),
18677c478bd9Sstevel@tonic-gate 			errno);
18687c478bd9Sstevel@tonic-gate 	(void) mutex_lock(&svcstate_lock);
18697c478bd9Sstevel@tonic-gate 	svcstate = _SERVED;
18707c478bd9Sstevel@tonic-gate 	(void) mutex_unlock(&svcstate_lock);
18717c478bd9Sstevel@tonic-gate 	if (pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL) != 0)
18727c478bd9Sstevel@tonic-gate 		warning(gettext("pthread_setcancelstate failed. errno = %d\n"),
18737c478bd9Sstevel@tonic-gate 			errno);
18747c478bd9Sstevel@tonic-gate 
18757c478bd9Sstevel@tonic-gate 	rmsvc.in.cnum = req->in.cnum;
18767c478bd9Sstevel@tonic-gate 	debug(5, "client_server[%d]...req = %s\n", pthread_self(),
18777c478bd9Sstevel@tonic-gate 		xlate_cnum(req->in.cnum));
18787c478bd9Sstevel@tonic-gate 
18797c478bd9Sstevel@tonic-gate 	/*
18807c478bd9Sstevel@tonic-gate 	 * Our caller may have passed more descriptors than we expected.
18817c478bd9Sstevel@tonic-gate 	 * If so, we silently close (and ignore) them.
18827c478bd9Sstevel@tonic-gate 	 */
18837c478bd9Sstevel@tonic-gate 	if (req->in.cnum == SMEDIA_CNUM_SET_SHFD)
18847c478bd9Sstevel@tonic-gate 		expected_descs = 1;
18857c478bd9Sstevel@tonic-gate 	else
18867c478bd9Sstevel@tonic-gate 		expected_descs = 0;
18877c478bd9Sstevel@tonic-gate 
18887c478bd9Sstevel@tonic-gate 	if (ndesc > expected_descs)
18897c478bd9Sstevel@tonic-gate 		close_door_descs(dp + expected_descs, ndesc - expected_descs);
18907c478bd9Sstevel@tonic-gate 
18917c478bd9Sstevel@tonic-gate 	switch (req->in.cnum) {
18927c478bd9Sstevel@tonic-gate 
18937c478bd9Sstevel@tonic-gate 	default:
18947c478bd9Sstevel@tonic-gate 		debug(5, "unknown command %d\n", req->in.cnum);
18957c478bd9Sstevel@tonic-gate 		door_ret_err(&reterror, ENOTSUP);
18967c478bd9Sstevel@tonic-gate 		break;
18977c478bd9Sstevel@tonic-gate 
18987c478bd9Sstevel@tonic-gate 	case	SMEDIA_CNUM_SET_SHFD:
18997c478bd9Sstevel@tonic-gate 		if (ndesc == 0)
19007c478bd9Sstevel@tonic-gate 			door_ret_err(&reterror, EINVAL);
19017c478bd9Sstevel@tonic-gate 		/*
19027c478bd9Sstevel@tonic-gate 		 * If an 0ld mapping exists destroy it before creaing
19037c478bd9Sstevel@tonic-gate 		 * a new map.
19047c478bd9Sstevel@tonic-gate 		 */
19057c478bd9Sstevel@tonic-gate 		ret_val =
19067c478bd9Sstevel@tonic-gate 			set_shfd(door_dp, dp->d_data.d_desc.d_descriptor, req);
19077c478bd9Sstevel@tonic-gate 		if (ret_val == 0) {
19087c478bd9Sstevel@tonic-gate 			reterror.cnum = SMEDIA_CNUM_SET_SHFD;
19097c478bd9Sstevel@tonic-gate 			reterror.errnum = 0;
19107c478bd9Sstevel@tonic-gate 			my_door_return((char *)&reterror,
19117c478bd9Sstevel@tonic-gate 				sizeof (smedia_reterror_t), 0, 0);
19127c478bd9Sstevel@tonic-gate 		} else {
19137c478bd9Sstevel@tonic-gate 			(void) close(dp->d_data.d_desc.d_descriptor);
19147c478bd9Sstevel@tonic-gate 			door_ret_err(&reterror, errno);
19157c478bd9Sstevel@tonic-gate 		}
19167c478bd9Sstevel@tonic-gate 
19177c478bd9Sstevel@tonic-gate 		break;
19187c478bd9Sstevel@tonic-gate 
19197c478bd9Sstevel@tonic-gate 	case	SMEDIA_CNUM_RAW_READ:
19207c478bd9Sstevel@tonic-gate 		debug(10, " arg size = %d blk num=0x%x nbytes = 0x%x \n",
19217c478bd9Sstevel@tonic-gate 			(int)arg_size,
19227c478bd9Sstevel@tonic-gate 			(uint32_t)req->reqraw_read.blockno,
19237c478bd9Sstevel@tonic-gate 			req->reqraw_read.nbytes);
19247c478bd9Sstevel@tonic-gate 		retbuf_size = sizeof (smedia_retraw_read_t);
19257c478bd9Sstevel@tonic-gate 		if (req->reqraw_read.nbytes == 0) {
19267c478bd9Sstevel@tonic-gate 			/* Nothing to write */
19277c478bd9Sstevel@tonic-gate 			rmsvc.retraw_write.nbytes = 0;
19287c478bd9Sstevel@tonic-gate 			my_door_return((char *)&rmsvc,
19297c478bd9Sstevel@tonic-gate 				sizeof (smedia_retraw_write_t), 0, 0);
19307c478bd9Sstevel@tonic-gate 		}
19317c478bd9Sstevel@tonic-gate 		retraw_read.cnum = SMEDIA_CNUM_RAW_READ;
19327c478bd9Sstevel@tonic-gate 		ret_val = raw_read(door_dp, req);
19337c478bd9Sstevel@tonic-gate 		if (ret_val == -1) {
19347c478bd9Sstevel@tonic-gate 			door_ret_err(&reterror, errno);
19357c478bd9Sstevel@tonic-gate 		}
19367c478bd9Sstevel@tonic-gate 		retraw_read.nbytes = ret_val;
19377c478bd9Sstevel@tonic-gate 		my_door_return((char *)&retraw_read, retbuf_size, 0, 0);
19387c478bd9Sstevel@tonic-gate 		break;
19397c478bd9Sstevel@tonic-gate 
19407c478bd9Sstevel@tonic-gate 	case	SMEDIA_CNUM_USCSI_CMD:
19417c478bd9Sstevel@tonic-gate 		retbuf_size = sizeof (smedia_retuscsi_cmd_t);
19427c478bd9Sstevel@tonic-gate 		rmsvc.retuscsi_cmd.cnum = SMEDIA_CNUM_USCSI_CMD;
19437c478bd9Sstevel@tonic-gate 		ucmd.uscsi_flags = req->requscsi_cmd.uscsi_flags;
19447c478bd9Sstevel@tonic-gate 		ucmd.uscsi_cdb = (caddr_t)&req->requscsi_cmd.uscsi_cdb;
19457c478bd9Sstevel@tonic-gate 		ucmd.uscsi_cdblen = req->requscsi_cmd.uscsi_cdblen;
19467c478bd9Sstevel@tonic-gate 		ucmd.uscsi_bufaddr = (caddr_t)door_dp->dd_buf;
19477c478bd9Sstevel@tonic-gate 		ucmd.uscsi_buflen = req->requscsi_cmd.uscsi_buflen;
19487c478bd9Sstevel@tonic-gate 		ucmd.uscsi_timeout = req->requscsi_cmd.uscsi_timeout;
19497c478bd9Sstevel@tonic-gate 		ucmd.uscsi_rqlen = req->requscsi_cmd.uscsi_rqlen;
19507c478bd9Sstevel@tonic-gate 		ucmd.uscsi_rqbuf = (caddr_t)&rmsvc.retuscsi_cmd.uscsi_rqbuf;
19517c478bd9Sstevel@tonic-gate 		debug(5,
19527c478bd9Sstevel@tonic-gate 		"USCSI CMD 0x%x requested.\n",
19537c478bd9Sstevel@tonic-gate 		    req->requscsi_cmd.uscsi_cdb[0]);
19547c478bd9Sstevel@tonic-gate 		/*
19557c478bd9Sstevel@tonic-gate 		 * Check the device type and invalid flags specified.
19567c478bd9Sstevel@tonic-gate 		 * We permit operations only on CDROM devices types.
19577c478bd9Sstevel@tonic-gate 		 */
19587c478bd9Sstevel@tonic-gate 		errno = invalid_uscsi_operation(door_dp,
19597c478bd9Sstevel@tonic-gate 				&ucmd);
19607c478bd9Sstevel@tonic-gate 		if (errno) {
19617c478bd9Sstevel@tonic-gate 			door_ret_err(&reterror, errno);
19627c478bd9Sstevel@tonic-gate 		}
19637c478bd9Sstevel@tonic-gate 
19647c478bd9Sstevel@tonic-gate 		if ((req->requscsi_cmd.uscsi_buflen) &&
19657c478bd9Sstevel@tonic-gate 		    ((req->requscsi_cmd.uscsi_buflen > door_dp->dd_buf_len) ||
19667c478bd9Sstevel@tonic-gate 		    (door_dp->dd_buf == NULL))) {
19677c478bd9Sstevel@tonic-gate 			debug(5,
19687c478bd9Sstevel@tonic-gate 	"uscsi_cmd failed: uscsi_buflen=0x%x dd_buf_len=0x%x dd_buf=0x%p\n",
19697c478bd9Sstevel@tonic-gate 				req->requscsi_cmd.uscsi_buflen,
19707c478bd9Sstevel@tonic-gate 				door_dp->dd_buf_len,
19717c478bd9Sstevel@tonic-gate 				door_dp->dd_buf);
19727c478bd9Sstevel@tonic-gate 			errno = EINVAL;
19737c478bd9Sstevel@tonic-gate 			door_ret_err(&reterror, errno);
19747c478bd9Sstevel@tonic-gate 		}
19757c478bd9Sstevel@tonic-gate 		ret_val = do_uscsi_cmd(door_dp->dd_fd,
19767c478bd9Sstevel@tonic-gate 			&ucmd, req->requscsi_cmd.uscsi_flags);
19777c478bd9Sstevel@tonic-gate 		rmsvc.retuscsi_cmd.uscsi_status = ucmd.uscsi_status;
19787c478bd9Sstevel@tonic-gate 		rmsvc.retuscsi_cmd.uscsi_resid = ucmd.uscsi_resid;
19797c478bd9Sstevel@tonic-gate 		rmsvc.retuscsi_cmd.uscsi_rqstatus = ucmd.uscsi_rqstatus;
19807c478bd9Sstevel@tonic-gate 		rmsvc.retuscsi_cmd.uscsi_rqresid = ucmd.uscsi_rqresid;
19817c478bd9Sstevel@tonic-gate 		rmsvc.retuscsi_cmd.uscsi_retval = ret_val;
19827c478bd9Sstevel@tonic-gate 		rmsvc.retuscsi_cmd.uscsi_errno = errno;
19837c478bd9Sstevel@tonic-gate 		if (ret_val || ucmd.uscsi_status) {
19847c478bd9Sstevel@tonic-gate 			debug(5, "uscsi_cmd failed: %d - %d errno = %d\n",
19857c478bd9Sstevel@tonic-gate 				ret_val, ucmd.uscsi_status, errno);
19867c478bd9Sstevel@tonic-gate 		}
19877c478bd9Sstevel@tonic-gate 		my_door_return((char *)&rmsvc, retbuf_size, 0, 0);
19887c478bd9Sstevel@tonic-gate 		break;
19897c478bd9Sstevel@tonic-gate 
19907c478bd9Sstevel@tonic-gate 	case SMEDIA_CNUM_RAW_WRITE:
19917c478bd9Sstevel@tonic-gate 		if (req->reqraw_write.nbytes == 0) {
19927c478bd9Sstevel@tonic-gate 			/* Nothing to write */
19937c478bd9Sstevel@tonic-gate 			rmsvc.retraw_write.nbytes = 0;
19947c478bd9Sstevel@tonic-gate 			my_door_return((char *)&rmsvc,
19957c478bd9Sstevel@tonic-gate 				sizeof (smedia_retraw_write_t), 0, 0);
19967c478bd9Sstevel@tonic-gate 		}
19977c478bd9Sstevel@tonic-gate 		ret_val = raw_write(door_dp, req);
19987c478bd9Sstevel@tonic-gate 		if (ret_val == -1)
19997c478bd9Sstevel@tonic-gate 			door_ret_err(&reterror, errno);
20007c478bd9Sstevel@tonic-gate 		rmsvc.retraw_write.nbytes = ret_val;
20017c478bd9Sstevel@tonic-gate 		my_door_return((char *)&rmsvc, sizeof (smedia_retraw_write_t),
20027c478bd9Sstevel@tonic-gate 			0, 0);
20037c478bd9Sstevel@tonic-gate 		break;
20047c478bd9Sstevel@tonic-gate 
20057c478bd9Sstevel@tonic-gate 	case SMEDIA_CNUM_GET_DEVICE_INFO:
20067c478bd9Sstevel@tonic-gate 
20077c478bd9Sstevel@tonic-gate 		(void) memset((void *) &inq, 0, sizeof (inq));
20087c478bd9Sstevel@tonic-gate 		(void) memset((void *) &ucmd, 0, sizeof (ucmd));
20097c478bd9Sstevel@tonic-gate 		(void) memset((void *) &cdb, 0, sizeof (union scsi_cdb));
20107c478bd9Sstevel@tonic-gate 		cdb.scc_cmd = SCMD_INQUIRY;
20117c478bd9Sstevel@tonic-gate 		FORMG0COUNT(&cdb, sizeof (inq));
20127c478bd9Sstevel@tonic-gate 		ucmd.uscsi_cdb = (caddr_t)&cdb;
20137c478bd9Sstevel@tonic-gate 		ucmd.uscsi_cdblen = CDB_GROUP0;
20147c478bd9Sstevel@tonic-gate 		ucmd.uscsi_bufaddr = (caddr_t)&inq;
20157c478bd9Sstevel@tonic-gate 		ucmd.uscsi_buflen = sizeof (inq);
20167c478bd9Sstevel@tonic-gate 		ucmd.uscsi_timeout = 120;	/* If 0, HBA hangs forever */
20177c478bd9Sstevel@tonic-gate 		ucmd.uscsi_rqlen = RQ_LEN;
20187c478bd9Sstevel@tonic-gate 		ucmd.uscsi_rqbuf = rq_data;
20197c478bd9Sstevel@tonic-gate 		ret_val = do_uscsi_cmd(door_dp->dd_fd,
20207c478bd9Sstevel@tonic-gate 			&ucmd, USCSI_READ|USCSI_RQENABLE);
20217c478bd9Sstevel@tonic-gate 		if (ret_val || ucmd.uscsi_status) {
20227c478bd9Sstevel@tonic-gate 			debug(5, "inquiry failed: %d - %d errno = %d\n",
20237c478bd9Sstevel@tonic-gate 				ret_val, ucmd.uscsi_status, errno);
20247c478bd9Sstevel@tonic-gate 			door_ret_err(&reterror, errno);
20257c478bd9Sstevel@tonic-gate 		}
20267c478bd9Sstevel@tonic-gate 
20277c478bd9Sstevel@tonic-gate 		debug(5, "%s\n", inq.inq_vid);
20287c478bd9Sstevel@tonic-gate 		debug(5, "%s\n", rmsvc.retget_device_info.sm_vendor_name);
20297c478bd9Sstevel@tonic-gate 
20307c478bd9Sstevel@tonic-gate 		(void) strlcpy(rmsvc.retget_device_info.sm_vendor_name,
20317c478bd9Sstevel@tonic-gate 			inq.inq_vid, 8);
20327c478bd9Sstevel@tonic-gate 		rmsvc.retget_device_info.sm_vendor_name[8] = 0;
20337c478bd9Sstevel@tonic-gate 		(void) strlcpy(rmsvc.retget_device_info.sm_product_name,
20347c478bd9Sstevel@tonic-gate 			inq.inq_pid, 16);
20357c478bd9Sstevel@tonic-gate 		rmsvc.retget_device_info.sm_product_name[16] = 0;
20367c478bd9Sstevel@tonic-gate 		(void) strlcpy(rmsvc.retget_device_info.sm_firmware_version,
20377c478bd9Sstevel@tonic-gate 			inq.inq_revision, 4);
20387c478bd9Sstevel@tonic-gate 		rmsvc.retget_device_info.sm_firmware_version[4] = ' ';
20397c478bd9Sstevel@tonic-gate 		(void) strlcpy(
20407c478bd9Sstevel@tonic-gate 			&rmsvc.retget_device_info.sm_firmware_version[5],
20417c478bd9Sstevel@tonic-gate 				inq.inq_serial, 12);
20427c478bd9Sstevel@tonic-gate 		rmsvc.retget_device_info.sm_product_name[17] = 0;
20437c478bd9Sstevel@tonic-gate 
20447c478bd9Sstevel@tonic-gate 		rmsvc.retget_device_info.sm_interface_type = IF_SCSI;
20457c478bd9Sstevel@tonic-gate 
20467c478bd9Sstevel@tonic-gate 		debug(5,
20477c478bd9Sstevel@tonic-gate 	"Vendor name = %s\n", rmsvc.retget_device_info.sm_vendor_name);
20487c478bd9Sstevel@tonic-gate 		debug(5,
20497c478bd9Sstevel@tonic-gate 	"product name = %s\n", rmsvc.retget_device_info.sm_product_name);
20507c478bd9Sstevel@tonic-gate 		debug(5,
20517c478bd9Sstevel@tonic-gate "Firmware revision = %s\n", rmsvc.retget_device_info.sm_firmware_version);
20527c478bd9Sstevel@tonic-gate 		my_door_return((char *)&rmsvc.retget_device_info,
20537c478bd9Sstevel@tonic-gate 			sizeof (smedia_retget_device_info_t), 0, 0);
20547c478bd9Sstevel@tonic-gate 
20557c478bd9Sstevel@tonic-gate 		break;
20567c478bd9Sstevel@tonic-gate 
20577c478bd9Sstevel@tonic-gate 	case	SMEDIA_CNUM_GET_MEDIUM_PROPERTY:
20587c478bd9Sstevel@tonic-gate 
20597c478bd9Sstevel@tonic-gate 		(void) memset((void *)&rmsvc.retget_medium_property.smprop,
20607c478bd9Sstevel@tonic-gate 			0, sizeof (smmedium_prop_t));
20617c478bd9Sstevel@tonic-gate 
20627c478bd9Sstevel@tonic-gate 		ret_val = ioctl(door_dp->dd_fd, DKIOCGMEDIAINFO, &media_info);
20637c478bd9Sstevel@tonic-gate 
20647c478bd9Sstevel@tonic-gate 		if (ret_val < 0) {
20657c478bd9Sstevel@tonic-gate 			uint32_t capacity;
20667c478bd9Sstevel@tonic-gate 			uint32_t blocksize;
20677c478bd9Sstevel@tonic-gate 			/*
20687c478bd9Sstevel@tonic-gate 			 * Devices may fail DKIOCGMEDIAINFO if an unformed
20697c478bd9Sstevel@tonic-gate 			 * media is inserted. We can get the capacity
20707c478bd9Sstevel@tonic-gate 			 * information from the SCMD_READ_FORMAT_CAP command.
20717c478bd9Sstevel@tonic-gate 			 */
20727c478bd9Sstevel@tonic-gate 
20737c478bd9Sstevel@tonic-gate 			debug(5, "DKIOCGMEDIAINFO failed");
20747c478bd9Sstevel@tonic-gate 
20757c478bd9Sstevel@tonic-gate 			debug(5, "using SCMD_READ_FORMAT_CAP");
20767c478bd9Sstevel@tonic-gate 			ret_val = get_media_capacity(door_dp->dd_fd,
20777c478bd9Sstevel@tonic-gate 			    &capacity, &blocksize);
20787c478bd9Sstevel@tonic-gate 
20797c478bd9Sstevel@tonic-gate 			if (ret_val >= 0) {
20807c478bd9Sstevel@tonic-gate 				media_info.dki_lbsize =	blocksize;
20817c478bd9Sstevel@tonic-gate 				media_info.dki_capacity = capacity;
20827c478bd9Sstevel@tonic-gate 			} else {
20837c478bd9Sstevel@tonic-gate 				debug(5, "SCMD_READ_FORMAT_CAP failed");
20847c478bd9Sstevel@tonic-gate 				door_ret_err(&reterror, errno);
20857c478bd9Sstevel@tonic-gate 			}
20867c478bd9Sstevel@tonic-gate 
20877c478bd9Sstevel@tonic-gate 		}
20887c478bd9Sstevel@tonic-gate 		rmsvc.retget_medium_property.smprop.sm_blocksize =
20897c478bd9Sstevel@tonic-gate 		    media_info.dki_lbsize;
20907c478bd9Sstevel@tonic-gate 		rmsvc.retget_medium_property.smprop.sm_capacity =
20917c478bd9Sstevel@tonic-gate 		    media_info.dki_capacity;
20927c478bd9Sstevel@tonic-gate 
20937c478bd9Sstevel@tonic-gate 		rmsvc.retget_medium_property.smprop.sm_media_type =
20947c478bd9Sstevel@tonic-gate 		    media_info.dki_media_type;
20957c478bd9Sstevel@tonic-gate 		/*
20967c478bd9Sstevel@tonic-gate 		 * These devices show as SCSI devices but we need to treat it
20977c478bd9Sstevel@tonic-gate 		 * differently. so we need a seperate class.
20987c478bd9Sstevel@tonic-gate 		 */
20997c478bd9Sstevel@tonic-gate 		if (get_device_type_scsi(door_dp->dd_fd, &inq) == SCSI_FLOPPY) {
21007c478bd9Sstevel@tonic-gate 			rmsvc.retget_medium_property.smprop.sm_media_type =
21017c478bd9Sstevel@tonic-gate 			    SM_SCSI_FLOPPY;
21027c478bd9Sstevel@tonic-gate 		}
21037c478bd9Sstevel@tonic-gate 
21047c478bd9Sstevel@tonic-gate 		/* Check for EFI type because DKIOCGGEOM does not support EFI */
21057c478bd9Sstevel@tonic-gate 		ret_val = ioctl(door_dp->dd_fd, DKIOCGVTOC, &vtoc);
21067c478bd9Sstevel@tonic-gate 		if (!((ret_val < 0) && (errno == ENOTSUP))) {
21077c478bd9Sstevel@tonic-gate 			ret_val = ioctl(door_dp->dd_fd, DKIOCGGEOM, &dkgeom);
21087c478bd9Sstevel@tonic-gate 			if (ret_val < 0)  {
21097c478bd9Sstevel@tonic-gate 				/*
21107c478bd9Sstevel@tonic-gate 				 * DKIOCGGEOM may fail for unformed floppies.
21117c478bd9Sstevel@tonic-gate 				 * We need to generate the appropriate geometry
21127c478bd9Sstevel@tonic-gate 				 * information.
21137c478bd9Sstevel@tonic-gate 				 */
21147c478bd9Sstevel@tonic-gate 				if (rmsvc.retget_medium_property.smprop.
21157c478bd9Sstevel@tonic-gate 				    sm_media_type == SM_SCSI_FLOPPY) {
21167c478bd9Sstevel@tonic-gate 					ret_val = get_floppy_geom(
21177c478bd9Sstevel@tonic-gate 					    door_dp->dd_fd,
21187c478bd9Sstevel@tonic-gate 					    media_info.dki_capacity, &dkgeom);
21197c478bd9Sstevel@tonic-gate 
21207c478bd9Sstevel@tonic-gate 					if (ret_val < 0) {
21217c478bd9Sstevel@tonic-gate 						debug(5, "Cannot determine "
21227c478bd9Sstevel@tonic-gate 						    "media size");
21237c478bd9Sstevel@tonic-gate 						door_ret_err(&reterror, errno);
21247c478bd9Sstevel@tonic-gate 					}
21257c478bd9Sstevel@tonic-gate 				} else {
21267c478bd9Sstevel@tonic-gate #ifdef sparc
21277c478bd9Sstevel@tonic-gate 					debug(5, "DKIOCGGEOM ioctl failed");
21287c478bd9Sstevel@tonic-gate 					door_ret_err(&reterror, errno);
21297c478bd9Sstevel@tonic-gate #else /* !sparc */
21307c478bd9Sstevel@tonic-gate 					/*
21317c478bd9Sstevel@tonic-gate 					 * Try getting Physical geometry on x86.
21327c478bd9Sstevel@tonic-gate 					 */
21337c478bd9Sstevel@tonic-gate 					ret_val = ioctl(door_dp->dd_fd,
21347c478bd9Sstevel@tonic-gate 					    DKIOCG_PHYGEOM, &dkgeom);
21357c478bd9Sstevel@tonic-gate 					if (ret_val < 0) {
21367c478bd9Sstevel@tonic-gate 						debug(5, "DKIOCG_PHYGEOM "
21377c478bd9Sstevel@tonic-gate 						    "ioctl failed");
21387c478bd9Sstevel@tonic-gate 						door_ret_err(&reterror, errno);
21397c478bd9Sstevel@tonic-gate 					}
21407c478bd9Sstevel@tonic-gate #endif /* sparc */
21417c478bd9Sstevel@tonic-gate 				}
21427c478bd9Sstevel@tonic-gate 			}
21437c478bd9Sstevel@tonic-gate 
21447c478bd9Sstevel@tonic-gate 
21457c478bd9Sstevel@tonic-gate 			/*
21467c478bd9Sstevel@tonic-gate 			 * Some faked geometry may not have pcyl filled in so
21477c478bd9Sstevel@tonic-gate 			 * later calculations using this field will be
21487c478bd9Sstevel@tonic-gate 			 * incorrect.  We will substitute it with the number of
21497c478bd9Sstevel@tonic-gate 			 * available cylinders.
21507c478bd9Sstevel@tonic-gate 			 */
21517c478bd9Sstevel@tonic-gate 			if (dkgeom.dkg_pcyl == 0)
21527c478bd9Sstevel@tonic-gate 				rmsvc.retget_medium_property.smprop.sm_pcyl =
21537c478bd9Sstevel@tonic-gate 				    dkgeom.dkg_ncyl;
21547c478bd9Sstevel@tonic-gate 			else
21557c478bd9Sstevel@tonic-gate 				rmsvc.retget_medium_property.smprop.sm_pcyl =
21567c478bd9Sstevel@tonic-gate 				    dkgeom.dkg_pcyl;
21577c478bd9Sstevel@tonic-gate 
21587c478bd9Sstevel@tonic-gate 			rmsvc.retget_medium_property.smprop.sm_nhead =
21597c478bd9Sstevel@tonic-gate 			    dkgeom.dkg_nhead;
21607c478bd9Sstevel@tonic-gate 			rmsvc.retget_medium_property.smprop.sm_nsect =
21617c478bd9Sstevel@tonic-gate 			    dkgeom.dkg_nsect;
21627c478bd9Sstevel@tonic-gate 		}
21637c478bd9Sstevel@tonic-gate 
21647c478bd9Sstevel@tonic-gate 		debug(1, "properties are: lbasize = %d, cap = %llu",
21657c478bd9Sstevel@tonic-gate 		    media_info.dki_lbsize, media_info.dki_capacity);
21667c478bd9Sstevel@tonic-gate 
21677c478bd9Sstevel@tonic-gate 		my_door_return((char *)&rmsvc.retget_medium_property,
21687c478bd9Sstevel@tonic-gate 			sizeof (smedia_retget_medium_property_t), 0, 0);
21697c478bd9Sstevel@tonic-gate 		break;
21707c478bd9Sstevel@tonic-gate 
21717c478bd9Sstevel@tonic-gate 	case	SMEDIA_CNUM_GET_PROTECTION_STATUS:
21727c478bd9Sstevel@tonic-gate 		switch (get_device_type_scsi(door_dp->dd_fd, &inq)) {
21737c478bd9Sstevel@tonic-gate 		case SCSI_FLOPPY:
21747c478bd9Sstevel@tonic-gate 			status = scsi_floppy_media_status(door_dp->dd_fd);
21757c478bd9Sstevel@tonic-gate 			break;
21767c478bd9Sstevel@tonic-gate 		case SCSI_IOMEGA:
21777c478bd9Sstevel@tonic-gate 			status = scsi_zip_media_status(door_dp->dd_fd);
21787c478bd9Sstevel@tonic-gate 			break;
21797c478bd9Sstevel@tonic-gate 		case SCSI_GENERIC:
21807c478bd9Sstevel@tonic-gate 			status = scsi_media_status(door_dp->dd_fd);
21817c478bd9Sstevel@tonic-gate 			break;
21827c478bd9Sstevel@tonic-gate 		default:
21837c478bd9Sstevel@tonic-gate 			door_ret_err(&reterror, errno);
21847c478bd9Sstevel@tonic-gate 		}
21857c478bd9Sstevel@tonic-gate 		if (status < 0)
21867c478bd9Sstevel@tonic-gate 			door_ret_err(&reterror, errno);
21877c478bd9Sstevel@tonic-gate 
21887c478bd9Sstevel@tonic-gate 		rmsvc.retget_protection_status.prot_state.sm_new_state  =
21897c478bd9Sstevel@tonic-gate 			status;
21907c478bd9Sstevel@tonic-gate 
21917c478bd9Sstevel@tonic-gate 		my_door_return((char *)&rmsvc.retget_protection_status,
21927c478bd9Sstevel@tonic-gate 			sizeof (smedia_retget_protection_status_t), 0, 0);
21937c478bd9Sstevel@tonic-gate 		break;
21947c478bd9Sstevel@tonic-gate 
21957c478bd9Sstevel@tonic-gate 	case	SMEDIA_CNUM_SET_PROTECTION_STATUS:
21967c478bd9Sstevel@tonic-gate 
21977c478bd9Sstevel@tonic-gate 		ret_val = set_protection_status(door_dp, req);
21987c478bd9Sstevel@tonic-gate 		if (ret_val == -1)
21997c478bd9Sstevel@tonic-gate 			door_ret_err(&reterror, errno);
22007c478bd9Sstevel@tonic-gate 		else
22017c478bd9Sstevel@tonic-gate 			my_door_return((char *)&rmsvc.retset_protection_status,
22027c478bd9Sstevel@tonic-gate 				sizeof (smedia_retset_protection_status_t),
22037c478bd9Sstevel@tonic-gate 				0, 0);
22047c478bd9Sstevel@tonic-gate 		break;
22057c478bd9Sstevel@tonic-gate 
22067c478bd9Sstevel@tonic-gate 	case SMEDIA_CNUM_FORMAT:
22077c478bd9Sstevel@tonic-gate 		switch (get_device_type_scsi(door_dp->dd_fd, &inq)) {
22087c478bd9Sstevel@tonic-gate 		case SCSI_FLOPPY:
22097c478bd9Sstevel@tonic-gate 			info("formatting floppy");
22107c478bd9Sstevel@tonic-gate 			err = scsi_floppy_format(door_dp->dd_fd,
22117c478bd9Sstevel@tonic-gate 				req->reqformat.flavor, req->reqformat.mode);
22127c478bd9Sstevel@tonic-gate 
22137c478bd9Sstevel@tonic-gate 			break;
22147c478bd9Sstevel@tonic-gate 		case SCSI_IOMEGA:
22157c478bd9Sstevel@tonic-gate 			err = scsi_zip_format(door_dp->dd_fd,
22167c478bd9Sstevel@tonic-gate 				req->reqformat.flavor, req->reqformat.mode);
22177c478bd9Sstevel@tonic-gate 			break;
22187c478bd9Sstevel@tonic-gate 		case SCSI_GENERIC:
22197c478bd9Sstevel@tonic-gate 			err = scsi_format(door_dp->dd_fd,
22207c478bd9Sstevel@tonic-gate 				req->reqformat.flavor, req->reqformat.mode);
22217c478bd9Sstevel@tonic-gate 			break;
22227c478bd9Sstevel@tonic-gate 		default:
22237c478bd9Sstevel@tonic-gate 			door_ret_err(&reterror, ENOTSUP);
22247c478bd9Sstevel@tonic-gate 		}
22257c478bd9Sstevel@tonic-gate 
22267c478bd9Sstevel@tonic-gate 		if (err)
22277c478bd9Sstevel@tonic-gate 			door_ret_err(&reterror, errno);
22287c478bd9Sstevel@tonic-gate 		my_door_return((char *)&rmsvc.retformat,
22297c478bd9Sstevel@tonic-gate 			sizeof (smedia_retformat_t), 0, 0);
22307c478bd9Sstevel@tonic-gate 
22317c478bd9Sstevel@tonic-gate 		break;
22327c478bd9Sstevel@tonic-gate 
22337c478bd9Sstevel@tonic-gate 	case SMEDIA_CNUM_CHECK_FORMAT_STATUS:
22347c478bd9Sstevel@tonic-gate 
22357c478bd9Sstevel@tonic-gate 		(void) memset((void *) &cdb, 0, sizeof (union scsi_cdb));
22367c478bd9Sstevel@tonic-gate 		(void) memset((void *) &ucmd, 0, sizeof (ucmd));
22377c478bd9Sstevel@tonic-gate 		(void) memset((void *) &data, 0, sizeof (data));
22387c478bd9Sstevel@tonic-gate 		cdb.scc_cmd = SCMD_REQUEST_SENSE;
22397c478bd9Sstevel@tonic-gate 		cdb.g0_count0 = sizeof (data);
22407c478bd9Sstevel@tonic-gate 		ucmd.uscsi_cdb = (caddr_t)&cdb;
22417c478bd9Sstevel@tonic-gate 		ucmd.uscsi_cdblen = CDB_GROUP0;
22427c478bd9Sstevel@tonic-gate 		ucmd.uscsi_bufaddr = (caddr_t)&data;
22437c478bd9Sstevel@tonic-gate 		ucmd.uscsi_buflen = sizeof (data);
22447c478bd9Sstevel@tonic-gate 		ucmd.uscsi_timeout = 120;	/* If 0, HBA hangs forever */
22457c478bd9Sstevel@tonic-gate 		ucmd.uscsi_rqlen = RQ_LEN;
22467c478bd9Sstevel@tonic-gate 		ucmd.uscsi_rqbuf = rq_data;
22477c478bd9Sstevel@tonic-gate 		ret_val = do_uscsi_cmd(door_dp->dd_fd,
22487c478bd9Sstevel@tonic-gate 			&ucmd, USCSI_READ|USCSI_RQENABLE);
22497c478bd9Sstevel@tonic-gate 		if (ret_val || ucmd.uscsi_status) {
22507c478bd9Sstevel@tonic-gate 			debug(5, "Request sense failed: %d - %d errno = %d\n",
22517c478bd9Sstevel@tonic-gate 				ret_val, ucmd.uscsi_status, errno);
22527c478bd9Sstevel@tonic-gate 			door_ret_err(&reterror, errno);
22537c478bd9Sstevel@tonic-gate 		}
22547c478bd9Sstevel@tonic-gate 
22557c478bd9Sstevel@tonic-gate 		if ((data[0] & 0x7F) == DEFERRED_ERROR) {
22567c478bd9Sstevel@tonic-gate 		/* Deffered error. The format must have failed */
22577c478bd9Sstevel@tonic-gate 			debug(5, "format failed!\n");
22587c478bd9Sstevel@tonic-gate 			door_ret_err(&reterror, EIO);
22597c478bd9Sstevel@tonic-gate 		}
22607c478bd9Sstevel@tonic-gate 
22617c478bd9Sstevel@tonic-gate 		if (data[SKSV_OFFSET] & SKSV_FIELD) {
22627c478bd9Sstevel@tonic-gate 			completed =
22637c478bd9Sstevel@tonic-gate 				(data[FORMAT_PROGRESS_INDICATOR_OFFSET_0] << 8)
22647c478bd9Sstevel@tonic-gate 				| data[FORMAT_PROGRESS_INDICATOR_OFFSET_1];
22657c478bd9Sstevel@tonic-gate 			completed = (completed*100/65536);
22667c478bd9Sstevel@tonic-gate 		} else {
22677c478bd9Sstevel@tonic-gate 			completed = (100);
22687c478bd9Sstevel@tonic-gate 		}
22697c478bd9Sstevel@tonic-gate 		rmsvc.retcheck_format_status.percent_complete = completed;
22707c478bd9Sstevel@tonic-gate 		my_door_return((char *)&rmsvc.retcheck_format_status,
22717c478bd9Sstevel@tonic-gate 			sizeof (smedia_retcheck_format_status_t), 0, 0);
22727c478bd9Sstevel@tonic-gate 		break;
22737c478bd9Sstevel@tonic-gate 
22747c478bd9Sstevel@tonic-gate 	case SMEDIA_CNUM_REASSIGN_BLOCK:
22757c478bd9Sstevel@tonic-gate 
22767c478bd9Sstevel@tonic-gate 		ret_val = reassign_block(door_dp, req);
22777c478bd9Sstevel@tonic-gate 		if (ret_val == -1)
22787c478bd9Sstevel@tonic-gate 			door_ret_err(&reterror, errno);
22797c478bd9Sstevel@tonic-gate 		my_door_return((char *)&rmsvc.retreassign_block,
22807c478bd9Sstevel@tonic-gate 			sizeof (smedia_retreassign_block_t), 0, 0);
22817c478bd9Sstevel@tonic-gate 		break;
22827c478bd9Sstevel@tonic-gate 
22837c478bd9Sstevel@tonic-gate 	}	/* end of switch */
22847c478bd9Sstevel@tonic-gate 
22857c478bd9Sstevel@tonic-gate 	debug(10, "Exiting client server...\n");
22867c478bd9Sstevel@tonic-gate 
22877c478bd9Sstevel@tonic-gate 
22887c478bd9Sstevel@tonic-gate 	my_door_return((char *)&reterror, sizeof (smedia_reterror_t), 0, 0);
22897c478bd9Sstevel@tonic-gate }
22907c478bd9Sstevel@tonic-gate 
22917c478bd9Sstevel@tonic-gate /*ARGSUSED*/
22927c478bd9Sstevel@tonic-gate static void
22937c478bd9Sstevel@tonic-gate main_server(void *server_data, char *argp, size_t arg_size,
22947c478bd9Sstevel@tonic-gate     door_desc_t *dp, uint_t ndesc)
22957c478bd9Sstevel@tonic-gate {
22967c478bd9Sstevel@tonic-gate 	smedia_services_t	*req;
22977c478bd9Sstevel@tonic-gate 	door_cred_t	door_credentials;
22987c478bd9Sstevel@tonic-gate 	int		ret_val;
22997c478bd9Sstevel@tonic-gate 	door_data_t	*ddata;
23007c478bd9Sstevel@tonic-gate 	smedia_reterror_t	reterror;
23017c478bd9Sstevel@tonic-gate 	smedia_reterror_t	retok;
23027c478bd9Sstevel@tonic-gate 	struct	stat	stat;
23037c478bd9Sstevel@tonic-gate 	door_desc_t	*didpp;
23047c478bd9Sstevel@tonic-gate 	struct dk_cinfo dkinfo;
23057c478bd9Sstevel@tonic-gate 	uint_t		expected_descs;
23067c478bd9Sstevel@tonic-gate 
23077c478bd9Sstevel@tonic-gate 	debug(10, "Entering main server[%d].\n", pthread_self());
23087c478bd9Sstevel@tonic-gate 
23097c478bd9Sstevel@tonic-gate 	didpp = dp;
23107c478bd9Sstevel@tonic-gate 	(void) mutex_lock(&svcstate_lock);
23117c478bd9Sstevel@tonic-gate 	svcstate = _SERVED;
23127c478bd9Sstevel@tonic-gate 	(void) mutex_unlock(&svcstate_lock);
23137c478bd9Sstevel@tonic-gate 
23147c478bd9Sstevel@tonic-gate 	reterror.cnum = SMEDIA_CNUM_ERROR;
23157c478bd9Sstevel@tonic-gate 	reterror.errnum = SMEDIA_FAILURE;
23167c478bd9Sstevel@tonic-gate 	if (argp == NULL) {
23177c478bd9Sstevel@tonic-gate 		debug(5, "argp is NULL\n");
23187c478bd9Sstevel@tonic-gate 		if (ndesc > 0)
23197c478bd9Sstevel@tonic-gate 			close_door_descs(dp, ndesc);
23207c478bd9Sstevel@tonic-gate 		my_door_return((char *)&reterror,
23217c478bd9Sstevel@tonic-gate 		    sizeof (smedia_reterror_t), 0, 0);
23227c478bd9Sstevel@tonic-gate 	}
23237c478bd9Sstevel@tonic-gate 
23247c478bd9Sstevel@tonic-gate 	req = (smedia_services_t *)((void *)argp);
23257c478bd9Sstevel@tonic-gate 	retok.cnum = req->in.cnum;
23267c478bd9Sstevel@tonic-gate 	retok.errnum = 0;
23277c478bd9Sstevel@tonic-gate 
23287c478bd9Sstevel@tonic-gate 	debug(5, "req = %s arg_size = 0x%x \n",
23297c478bd9Sstevel@tonic-gate 		xlate_cnum(req->reqopen.cnum), arg_size);
23307c478bd9Sstevel@tonic-gate 
23317c478bd9Sstevel@tonic-gate 	/*
23327c478bd9Sstevel@tonic-gate 	 * Our caller may have passed more descriptors than we expected.
23337c478bd9Sstevel@tonic-gate 	 * If so, we silently close (and ignore) them.
23347c478bd9Sstevel@tonic-gate 	 */
23357c478bd9Sstevel@tonic-gate 	if (req->in.cnum == SMEDIA_CNUM_OPEN_FD)
23367c478bd9Sstevel@tonic-gate 		expected_descs = 1;
23377c478bd9Sstevel@tonic-gate 	else
23387c478bd9Sstevel@tonic-gate 		expected_descs = 0;
23397c478bd9Sstevel@tonic-gate 
23407c478bd9Sstevel@tonic-gate 	if (ndesc > expected_descs)
23417c478bd9Sstevel@tonic-gate 		close_door_descs(dp + expected_descs, ndesc - expected_descs);
23427c478bd9Sstevel@tonic-gate 
23437c478bd9Sstevel@tonic-gate 	switch (req->in.cnum) {
23447c478bd9Sstevel@tonic-gate 
23457c478bd9Sstevel@tonic-gate 	default:
23467c478bd9Sstevel@tonic-gate 		debug(5, "unkmown command 0x%x\n", req->reqopen.cnum);
23477c478bd9Sstevel@tonic-gate 		break;
23487c478bd9Sstevel@tonic-gate 
23497c478bd9Sstevel@tonic-gate 	case	SMEDIA_CNUM_PING:
23507c478bd9Sstevel@tonic-gate 		/*
23517c478bd9Sstevel@tonic-gate 		 * This service is to indicate that server is up and
23527c478bd9Sstevel@tonic-gate 		 * running. It is usually called from another instance of
23537c478bd9Sstevel@tonic-gate 		 * server that is started.
23547c478bd9Sstevel@tonic-gate 		 */
23557c478bd9Sstevel@tonic-gate 
23567c478bd9Sstevel@tonic-gate 		reterror.cnum = SMEDIA_CNUM_PING;
23577c478bd9Sstevel@tonic-gate 		reterror.errnum = 0;
23587c478bd9Sstevel@tonic-gate 		my_door_return((char *)&reterror,
23597c478bd9Sstevel@tonic-gate 			sizeof (smedia_reterror_t), 0, 0);
23607c478bd9Sstevel@tonic-gate 		break;
23617c478bd9Sstevel@tonic-gate 
23627c478bd9Sstevel@tonic-gate 
23637c478bd9Sstevel@tonic-gate 	case	SMEDIA_CNUM_OPEN_FD:
23647c478bd9Sstevel@tonic-gate 
23657c478bd9Sstevel@tonic-gate 		debug(5, "ndesc = %d\n", ndesc);
23667c478bd9Sstevel@tonic-gate 		if (ndesc == 0) {
23677c478bd9Sstevel@tonic-gate 			my_door_return((char *)&reterror,
23687c478bd9Sstevel@tonic-gate 				sizeof (smedia_reterror_t), 0, 0);
23697c478bd9Sstevel@tonic-gate 		}
23707c478bd9Sstevel@tonic-gate 		debug(5, "Checking descriptor 1\n");
23717c478bd9Sstevel@tonic-gate 		if (fstat(didpp->d_data.d_desc.d_descriptor, &stat) < 0) {
23727c478bd9Sstevel@tonic-gate 			warning(gettext(
23737c478bd9Sstevel@tonic-gate 			"main_server:fstat failed. errno = %d\n"),
23747c478bd9Sstevel@tonic-gate 				errno);
23757c478bd9Sstevel@tonic-gate 			(void) close(didpp->d_data.d_desc.d_descriptor);
23767c478bd9Sstevel@tonic-gate 			my_door_return((char *)&reterror,
23777c478bd9Sstevel@tonic-gate 				sizeof (smedia_reterror_t), 0, 0);
23787c478bd9Sstevel@tonic-gate 		}
23797c478bd9Sstevel@tonic-gate 		debug(5, "descriptor = %d st_mode = 0x%lx\n",
23807c478bd9Sstevel@tonic-gate 			didpp->d_data.d_desc.d_descriptor,
23817c478bd9Sstevel@tonic-gate 			stat.st_mode);
23827c478bd9Sstevel@tonic-gate 
23837c478bd9Sstevel@tonic-gate 		/* Obtain the credentials of the user */
23847c478bd9Sstevel@tonic-gate 		ret_val = door_cred(&door_credentials);
23857c478bd9Sstevel@tonic-gate 		if (ret_val < 0) {
23867c478bd9Sstevel@tonic-gate 			warning(gettext(
23877c478bd9Sstevel@tonic-gate 			"main_server:door_cred failed. errno = %d\n"),
23887c478bd9Sstevel@tonic-gate 				errno);
23897c478bd9Sstevel@tonic-gate 			(void) close(didpp->d_data.d_desc.d_descriptor);
23907c478bd9Sstevel@tonic-gate 			my_door_return((char *)&reterror,
23917c478bd9Sstevel@tonic-gate 				sizeof (smedia_reterror_t), 0, 0);
23927c478bd9Sstevel@tonic-gate 		}
23937c478bd9Sstevel@tonic-gate 		if (ioctl(didpp->d_data.d_desc.d_descriptor, DKIOCINFO,
23947c478bd9Sstevel@tonic-gate 			&dkinfo) == -1) {
23957c478bd9Sstevel@tonic-gate 			warning(gettext(
23967c478bd9Sstevel@tonic-gate 			"main_server:DKIOCINFO failed. errno = %d\n"),
23977c478bd9Sstevel@tonic-gate 				errno);
23987c478bd9Sstevel@tonic-gate 			(void) close(didpp->d_data.d_desc.d_descriptor);
23997c478bd9Sstevel@tonic-gate 			my_door_return((char *)&reterror,
24007c478bd9Sstevel@tonic-gate 				sizeof (smedia_reterror_t), 0, 0);
24017c478bd9Sstevel@tonic-gate 		}
24027c478bd9Sstevel@tonic-gate 
24037c478bd9Sstevel@tonic-gate 		/*
24047c478bd9Sstevel@tonic-gate 		 * create a separate thread to handle IO calls to this device.
24057c478bd9Sstevel@tonic-gate 		 */
24067c478bd9Sstevel@tonic-gate 		ddata = (door_data_t *)calloc(1, sizeof (door_data_t));
24077c478bd9Sstevel@tonic-gate 		if (ddata == NULL) {
24087c478bd9Sstevel@tonic-gate 			warning(gettext(
24097c478bd9Sstevel@tonic-gate 			"main_server:calloc failed. errno = %d\n"),
24107c478bd9Sstevel@tonic-gate 				errno);
24117c478bd9Sstevel@tonic-gate 			(void) close(didpp->d_data.d_desc.d_descriptor);
24127c478bd9Sstevel@tonic-gate 			my_door_return((char *)&reterror,
24137c478bd9Sstevel@tonic-gate 				sizeof (smedia_reterror_t), 0, 0);
24147c478bd9Sstevel@tonic-gate 		}
24157c478bd9Sstevel@tonic-gate 		ddata->dd_stat = stat;
24167c478bd9Sstevel@tonic-gate 		ddata->dd_cred = door_credentials;
24177c478bd9Sstevel@tonic-gate 		ddata->dd_fd = didpp->d_data.d_desc.d_descriptor;
24187c478bd9Sstevel@tonic-gate 		ddata->dd_buf = NULL;
24197c478bd9Sstevel@tonic-gate 		ddata->dd_buf_len = 0;
24207c478bd9Sstevel@tonic-gate 		ddata->dd_buffd = -1;
24217c478bd9Sstevel@tonic-gate 		ddata->dd_sector_size = 0;
24227c478bd9Sstevel@tonic-gate 		ddata->dd_dkinfo = dkinfo;
24237c478bd9Sstevel@tonic-gate 		debug(5, "ddata = %p \n", (void *)ddata);
24247c478bd9Sstevel@tonic-gate 
24257c478bd9Sstevel@tonic-gate 		(void) door_server_create(my_create);
24267c478bd9Sstevel@tonic-gate 		debug(5, "door_server_create called.\n");
24277c478bd9Sstevel@tonic-gate 
24287c478bd9Sstevel@tonic-gate 		(void) mutex_lock(&ddata->dd_lock);
24297c478bd9Sstevel@tonic-gate 
24307c478bd9Sstevel@tonic-gate 		ddata->dd_desc[0].d_data.d_desc.d_descriptor = door_create(
24317c478bd9Sstevel@tonic-gate 		    client_server, (void *)ddata, DOOR_PRIVATE);
24327c478bd9Sstevel@tonic-gate 		if (ddata->dd_desc[0].d_data.d_desc.d_descriptor < 0) {
24337c478bd9Sstevel@tonic-gate 			warning(gettext(
24347c478bd9Sstevel@tonic-gate 			"main_server:client door_create failed. errno = %d\n"),
24357c478bd9Sstevel@tonic-gate 				errno);
24367c478bd9Sstevel@tonic-gate 			free(ddata);
24377c478bd9Sstevel@tonic-gate 			(void) close(didpp->d_data.d_desc.d_descriptor);
24387c478bd9Sstevel@tonic-gate 		}
24397c478bd9Sstevel@tonic-gate 		ddata->dd_desc[1].d_data.d_desc.d_descriptor =
24407c478bd9Sstevel@tonic-gate 		    door_create(client_server, (void *)ddata, DOOR_UNREF);
24417c478bd9Sstevel@tonic-gate 		if (ddata->dd_desc[1].d_data.d_desc.d_descriptor < 0) {
24427c478bd9Sstevel@tonic-gate 			warning(gettext(
24437c478bd9Sstevel@tonic-gate 			"main_server:death door_create failed. errno = %d\n"),
24447c478bd9Sstevel@tonic-gate 				errno);
24457c478bd9Sstevel@tonic-gate 			(void) close(
24467c478bd9Sstevel@tonic-gate 				ddata->dd_desc[0].d_data.d_desc.d_descriptor);
24477c478bd9Sstevel@tonic-gate 			free(ddata);
24487c478bd9Sstevel@tonic-gate 			(void) close(didpp->d_data.d_desc.d_descriptor);
24497c478bd9Sstevel@tonic-gate 		}
24507c478bd9Sstevel@tonic-gate 		debug(5,
24517c478bd9Sstevel@tonic-gate 		"Client door server 0x%0x and death door 0x%x created.\n",
24527c478bd9Sstevel@tonic-gate 			ddata->dd_desc[0].d_data.d_desc.d_descriptor,
24537c478bd9Sstevel@tonic-gate 			ddata->dd_desc[1].d_data.d_desc.d_descriptor);
24547c478bd9Sstevel@tonic-gate 		ddata->dd_desc[0].d_attributes = (DOOR_DESCRIPTOR|DOOR_RELEASE);
24557c478bd9Sstevel@tonic-gate 		ddata->dd_desc[1].d_attributes = (DOOR_DESCRIPTOR);
24567c478bd9Sstevel@tonic-gate 
24577c478bd9Sstevel@tonic-gate 		audit_init(ddata);
24587c478bd9Sstevel@tonic-gate 
24597c478bd9Sstevel@tonic-gate 		(void) cond_signal(&ddata->dd_cv);
24607c478bd9Sstevel@tonic-gate 		(void) cond_wait(&ddata->dd_cv_bind, &ddata->dd_lock);
24617c478bd9Sstevel@tonic-gate 		(void) mutex_unlock(&ddata->dd_lock);
24627c478bd9Sstevel@tonic-gate 		debug(5, "retok.cnum = 0x%x\n", retok.cnum);
24637c478bd9Sstevel@tonic-gate 
24647c478bd9Sstevel@tonic-gate 		(void) mutex_lock(&svcstate_lock);
24657c478bd9Sstevel@tonic-gate 		svccount++;
24667c478bd9Sstevel@tonic-gate 		(void) mutex_unlock(&svcstate_lock);
24677c478bd9Sstevel@tonic-gate 		my_door_return((char *)&retok, sizeof (smedia_reterror_t),
24687c478bd9Sstevel@tonic-gate 			&ddata->dd_desc[0], 2);
24697c478bd9Sstevel@tonic-gate 
24707c478bd9Sstevel@tonic-gate 		break;
24717c478bd9Sstevel@tonic-gate 	}
24727c478bd9Sstevel@tonic-gate 
24737c478bd9Sstevel@tonic-gate 	debug(10, "exiting main server. \n");
24747c478bd9Sstevel@tonic-gate 	my_door_return((char *)&reterror, sizeof (smedia_reterror_t), 0, 0);
24757c478bd9Sstevel@tonic-gate }
24767c478bd9Sstevel@tonic-gate 
24777c478bd9Sstevel@tonic-gate /* ARGSUSED */
24787c478bd9Sstevel@tonic-gate static void
24797c478bd9Sstevel@tonic-gate term_handler(int sig, siginfo_t *siginfo, void *sigctx)
24807c478bd9Sstevel@tonic-gate {
24817c478bd9Sstevel@tonic-gate 	warning(gettext("thread[%d]: Received signal %d. Ignoring it.\n"),
24827c478bd9Sstevel@tonic-gate 		pthread_self(),
24837c478bd9Sstevel@tonic-gate 		sig);
24847c478bd9Sstevel@tonic-gate }
24857c478bd9Sstevel@tonic-gate 
24867c478bd9Sstevel@tonic-gate /* ARGSUSED */
24877c478bd9Sstevel@tonic-gate static void
24887c478bd9Sstevel@tonic-gate hup_handler(int sig, siginfo_t *siginfo, void *sigctx)
24897c478bd9Sstevel@tonic-gate {
24907c478bd9Sstevel@tonic-gate 	warning(gettext("thread[%d]: Received signal %d. Ignoring it.\n"),
24917c478bd9Sstevel@tonic-gate 		pthread_self(),
24927c478bd9Sstevel@tonic-gate 		sig);
24937c478bd9Sstevel@tonic-gate }
24947c478bd9Sstevel@tonic-gate 
24957c478bd9Sstevel@tonic-gate /*ARGSUSED*/
24967c478bd9Sstevel@tonic-gate static void
24977c478bd9Sstevel@tonic-gate sig_handler(int sig, siginfo_t *siginfo, void *sigctx)
24987c478bd9Sstevel@tonic-gate {
24997c478bd9Sstevel@tonic-gate 	warning(gettext("thread[%d]: Received signal %d. Ignoring it.\n"),
25007c478bd9Sstevel@tonic-gate 		pthread_self(),
25017c478bd9Sstevel@tonic-gate 		sig);
25027c478bd9Sstevel@tonic-gate }
25037c478bd9Sstevel@tonic-gate 
25047c478bd9Sstevel@tonic-gate /*ARGSUSED*/
25057c478bd9Sstevel@tonic-gate static void
25067c478bd9Sstevel@tonic-gate badsig_handler(int sig, siginfo_t *siginfo, void *sigctx)
25077c478bd9Sstevel@tonic-gate {
25087c478bd9Sstevel@tonic-gate 
25097c478bd9Sstevel@tonic-gate 	fatal(BADSIG_MSG, pthread_self(), sig, siginfo->si_addr,
25107c478bd9Sstevel@tonic-gate 		siginfo->si_trapno,
25117c478bd9Sstevel@tonic-gate 		siginfo->si_pc);
25127c478bd9Sstevel@tonic-gate }
25137c478bd9Sstevel@tonic-gate 
25147c478bd9Sstevel@tonic-gate /*ARGSUSED*/
25157c478bd9Sstevel@tonic-gate void *
25167c478bd9Sstevel@tonic-gate init_server(void *argp)
25177c478bd9Sstevel@tonic-gate {
25187c478bd9Sstevel@tonic-gate 	int	i, fd;
25197c478bd9Sstevel@tonic-gate 	struct	sigaction	act;
25207c478bd9Sstevel@tonic-gate 	struct	rlimit		rlim;
25217c478bd9Sstevel@tonic-gate 
25227c478bd9Sstevel@tonic-gate 	debug(10, "init_server  running\n");
25237c478bd9Sstevel@tonic-gate 
25247c478bd9Sstevel@tonic-gate 	(void) setlocale(LC_ALL, "");
25257c478bd9Sstevel@tonic-gate #if !defined(TEXT_DOMAIN)
25267c478bd9Sstevel@tonic-gate #define	TEXT_DOMAIN "SYS_TEST"
25277c478bd9Sstevel@tonic-gate #endif
25287c478bd9Sstevel@tonic-gate 	(void) textdomain(TEXT_DOMAIN);
25297c478bd9Sstevel@tonic-gate 
25307c478bd9Sstevel@tonic-gate 
25317c478bd9Sstevel@tonic-gate 	if (geteuid() != 0) fatal("Must be root to execute smserverd\n");
25327c478bd9Sstevel@tonic-gate 
25337c478bd9Sstevel@tonic-gate 
25347c478bd9Sstevel@tonic-gate 	/*
25357c478bd9Sstevel@tonic-gate 	 * setup signal handlers.
25367c478bd9Sstevel@tonic-gate 	 */
25377c478bd9Sstevel@tonic-gate 
25387c478bd9Sstevel@tonic-gate 	for (i = 0; i < N_BADSIGS; i++) {
25397c478bd9Sstevel@tonic-gate 		act.sa_sigaction = badsig_handler;
25407c478bd9Sstevel@tonic-gate 		(void) sigemptyset(&act.sa_mask);
25417c478bd9Sstevel@tonic-gate 		act.sa_flags = SA_SIGINFO;
25427c478bd9Sstevel@tonic-gate 		if (sigaction(badsigs[i], &act, NULL) == -1)
25437c478bd9Sstevel@tonic-gate 			warning(gettext(SIGACT_FAILED), strsignal(badsigs[i]),
25447c478bd9Sstevel@tonic-gate 				strerror(errno));
25457c478bd9Sstevel@tonic-gate 	}
25467c478bd9Sstevel@tonic-gate 
25477c478bd9Sstevel@tonic-gate 	/*
25487c478bd9Sstevel@tonic-gate 	 * Ignore SIGHUP until all the initialization is done.
25497c478bd9Sstevel@tonic-gate 	 */
25507c478bd9Sstevel@tonic-gate 	act.sa_handler = SIG_IGN;
25517c478bd9Sstevel@tonic-gate 	(void) sigemptyset(&act.sa_mask);
25527c478bd9Sstevel@tonic-gate 	act.sa_flags = 0;
25537c478bd9Sstevel@tonic-gate 	if (sigaction(SIGHUP, &act, NULL) == -1)
25547c478bd9Sstevel@tonic-gate 		warning(gettext(SIGACT_FAILED), strsignal(SIGHUP),
25557c478bd9Sstevel@tonic-gate 			strerror(errno));
25567c478bd9Sstevel@tonic-gate 	/*
25577c478bd9Sstevel@tonic-gate 	 * Increase file descriptor limit to the most it can possibly
25587c478bd9Sstevel@tonic-gate 	 * be.
25597c478bd9Sstevel@tonic-gate 	 */
25607c478bd9Sstevel@tonic-gate 	if (getrlimit(RLIMIT_NOFILE, &rlim) < 0) {
25617c478bd9Sstevel@tonic-gate 		warning(gettext("getrlimit for fd's failed; %m\n"));
25627c478bd9Sstevel@tonic-gate 	}
25637c478bd9Sstevel@tonic-gate 
25647c478bd9Sstevel@tonic-gate 	rlim.rlim_cur = rlim.rlim_max;
25657c478bd9Sstevel@tonic-gate 
25667c478bd9Sstevel@tonic-gate 	if (setrlimit(RLIMIT_NOFILE, &rlim) < 0) {
25677c478bd9Sstevel@tonic-gate 		warning(gettext("setrlimit for fd's failed; %m\n"));
25687c478bd9Sstevel@tonic-gate 	}
25697c478bd9Sstevel@tonic-gate 
25707c478bd9Sstevel@tonic-gate 	server_door = door_create(main_server, (void *)&server_data, 0);
25717c478bd9Sstevel@tonic-gate 	if (server_door == -1) {
25727c478bd9Sstevel@tonic-gate 		debug(1, "main door_create");
25737c478bd9Sstevel@tonic-gate 		exit(1);
25747c478bd9Sstevel@tonic-gate 	}
25757c478bd9Sstevel@tonic-gate 
25767c478bd9Sstevel@tonic-gate 	(void) unlink(smedia_service);
25777c478bd9Sstevel@tonic-gate 	fd = open(smedia_service, O_RDWR|O_CREAT|O_EXCL, 0644);
25787c478bd9Sstevel@tonic-gate 	if (fd < 0) {
25797c478bd9Sstevel@tonic-gate 		debug(5, "could not open %s.\n", smedia_service);
25807c478bd9Sstevel@tonic-gate 		exit(1);
25817c478bd9Sstevel@tonic-gate 	}
25827c478bd9Sstevel@tonic-gate 	(void) close(fd);
25837c478bd9Sstevel@tonic-gate 	server_fd = fattach(server_door, smedia_service);
25847c478bd9Sstevel@tonic-gate 	if (server_fd == -1) {
25857c478bd9Sstevel@tonic-gate 		debug(1, "main fattach");
25867c478bd9Sstevel@tonic-gate 		exit(1);
25877c478bd9Sstevel@tonic-gate 	}
25887c478bd9Sstevel@tonic-gate 	server_data.sd_door = server_door;
25897c478bd9Sstevel@tonic-gate 	server_data.sd_fd = server_fd;
25907c478bd9Sstevel@tonic-gate 
25917c478bd9Sstevel@tonic-gate 	/*
25927c478bd9Sstevel@tonic-gate 	 * setup signal handlers for post-init
25937c478bd9Sstevel@tonic-gate 	 */
25947c478bd9Sstevel@tonic-gate 
25957c478bd9Sstevel@tonic-gate 	act.sa_sigaction = hup_handler;
25967c478bd9Sstevel@tonic-gate 	(void) sigemptyset(&act.sa_mask);
25977c478bd9Sstevel@tonic-gate 	act.sa_flags = SA_SIGINFO;
25987c478bd9Sstevel@tonic-gate 	if (sigaction(SIGHUP, &act, NULL) == -1)
25997c478bd9Sstevel@tonic-gate 		warning(gettext(SIGACT_FAILED), strsignal(SIGHUP),
26007c478bd9Sstevel@tonic-gate 		    strerror(errno));
26017c478bd9Sstevel@tonic-gate 
26027c478bd9Sstevel@tonic-gate 	act.sa_sigaction = term_handler;
26037c478bd9Sstevel@tonic-gate 	(void) sigemptyset(&act.sa_mask);
26047c478bd9Sstevel@tonic-gate 	act.sa_flags = SA_SIGINFO;
26057c478bd9Sstevel@tonic-gate 	if (sigaction(SIGTERM, &act, NULL) == -1)
26067c478bd9Sstevel@tonic-gate 		warning(gettext(SIGACT_FAILED), strsignal(SIGTERM),
26077c478bd9Sstevel@tonic-gate 		    strerror(errno));
26087c478bd9Sstevel@tonic-gate 
26097c478bd9Sstevel@tonic-gate 	act.sa_sigaction = sig_handler;
26107c478bd9Sstevel@tonic-gate 	(void) sigemptyset(&act.sa_mask);
26117c478bd9Sstevel@tonic-gate 	act.sa_flags = SA_SIGINFO;
26127c478bd9Sstevel@tonic-gate 	if (sigaction(SIGINT, &act, NULL) == -1)
26137c478bd9Sstevel@tonic-gate 		warning(gettext(SIGACT_FAILED), strsignal(SIGHUP),
26147c478bd9Sstevel@tonic-gate 		    strerror(errno));
26157c478bd9Sstevel@tonic-gate 
26167c478bd9Sstevel@tonic-gate 	act.sa_sigaction = sig_handler;
26177c478bd9Sstevel@tonic-gate 	(void) sigemptyset(&act.sa_mask);
26187c478bd9Sstevel@tonic-gate 	act.sa_flags = SA_SIGINFO;
26197c478bd9Sstevel@tonic-gate 	if (sigaction(SIGQUIT, &act, NULL) == -1)
26207c478bd9Sstevel@tonic-gate 		warning(gettext(SIGACT_FAILED), strsignal(SIGHUP),
26217c478bd9Sstevel@tonic-gate 		    strerror(errno));
26227c478bd9Sstevel@tonic-gate 	debug(10, "init_server completed successfully\n");
26237c478bd9Sstevel@tonic-gate 
26247c478bd9Sstevel@tonic-gate 	server_data.sd_init_state = INIT_DONE;
26257c478bd9Sstevel@tonic-gate 	return (NULL);
26267c478bd9Sstevel@tonic-gate }
26277c478bd9Sstevel@tonic-gate 
26287c478bd9Sstevel@tonic-gate static int
26297c478bd9Sstevel@tonic-gate server_exists()
26307c478bd9Sstevel@tonic-gate {
26317c478bd9Sstevel@tonic-gate 	door_arg_t		darg;
26327c478bd9Sstevel@tonic-gate 	smedia_reqping_t	req_ping;
26337c478bd9Sstevel@tonic-gate 	smedia_retping_t	*ret_ping;
26347c478bd9Sstevel@tonic-gate 	int			doorh;
26357c478bd9Sstevel@tonic-gate 	door_info_t		dinfo;
26367c478bd9Sstevel@tonic-gate 	char    rbuf[sizeof (smedia_services_t) + sizeof (door_desc_t)];
26377c478bd9Sstevel@tonic-gate 
26387c478bd9Sstevel@tonic-gate 	doorh = open(smedia_service, O_RDONLY);
26397c478bd9Sstevel@tonic-gate 	if (doorh < 0)
26407c478bd9Sstevel@tonic-gate 		return (0);
26417c478bd9Sstevel@tonic-gate 	if (door_info(doorh, &dinfo) < 0) {
26427c478bd9Sstevel@tonic-gate 		(void) close(doorh);
26437c478bd9Sstevel@tonic-gate 		return (0);
26447c478bd9Sstevel@tonic-gate 	}
26457c478bd9Sstevel@tonic-gate 
26467c478bd9Sstevel@tonic-gate 	if (dinfo.di_attributes & DOOR_REVOKED) {
26477c478bd9Sstevel@tonic-gate 		(void) close(doorh);
26487c478bd9Sstevel@tonic-gate 		return (0);
26497c478bd9Sstevel@tonic-gate 	}
26507c478bd9Sstevel@tonic-gate 
26517c478bd9Sstevel@tonic-gate 	req_ping.cnum = SMEDIA_CNUM_PING;
26527c478bd9Sstevel@tonic-gate 
26537c478bd9Sstevel@tonic-gate 	darg.data_ptr = (char *)&req_ping;
26547c478bd9Sstevel@tonic-gate 	darg.data_size = sizeof (smedia_reqping_t);
26557c478bd9Sstevel@tonic-gate 	darg.desc_ptr = NULL;
26567c478bd9Sstevel@tonic-gate 	darg.desc_num = 0;
26577c478bd9Sstevel@tonic-gate 	darg.rbuf = rbuf;
26587c478bd9Sstevel@tonic-gate 	darg.rsize = sizeof (rbuf);
26597c478bd9Sstevel@tonic-gate 
26607c478bd9Sstevel@tonic-gate 	if (door_call(doorh, &darg) < 0) {
26617c478bd9Sstevel@tonic-gate 		(void) close(doorh);
26627c478bd9Sstevel@tonic-gate 		return (0);
26637c478bd9Sstevel@tonic-gate 	}
26647c478bd9Sstevel@tonic-gate 	ret_ping = (smedia_retping_t *)((void *)darg.data_ptr);
26657c478bd9Sstevel@tonic-gate 	if (ret_ping->cnum != SMEDIA_CNUM_PING) {
26667c478bd9Sstevel@tonic-gate 		(void) close(doorh);
26677c478bd9Sstevel@tonic-gate 		return (0);
26687c478bd9Sstevel@tonic-gate 	}
26697c478bd9Sstevel@tonic-gate 
26707c478bd9Sstevel@tonic-gate 	(void) close(doorh);
26717c478bd9Sstevel@tonic-gate 	return (1);
26727c478bd9Sstevel@tonic-gate }
26737c478bd9Sstevel@tonic-gate 
26747c478bd9Sstevel@tonic-gate static int
26757c478bd9Sstevel@tonic-gate get_run_level()
26767c478bd9Sstevel@tonic-gate {
26777c478bd9Sstevel@tonic-gate 	int	run_level;
26787c478bd9Sstevel@tonic-gate 	struct utmpx	*utmpp;
26797c478bd9Sstevel@tonic-gate 
26807c478bd9Sstevel@tonic-gate 	setutxent();
26817c478bd9Sstevel@tonic-gate 	while ((utmpp = getutxent()) != NULL) {
26827c478bd9Sstevel@tonic-gate 		if (utmpp->ut_type == RUN_LVL) {
26837c478bd9Sstevel@tonic-gate 			run_level = atoi(
26847c478bd9Sstevel@tonic-gate 				&utmpp->ut_line[strlen("run-level ")]);
26857c478bd9Sstevel@tonic-gate 		}
26867c478bd9Sstevel@tonic-gate 	}
26877c478bd9Sstevel@tonic-gate 	return (run_level);
26887c478bd9Sstevel@tonic-gate }
26897c478bd9Sstevel@tonic-gate 
26907c478bd9Sstevel@tonic-gate /*ARGSUSED*/
26917c478bd9Sstevel@tonic-gate static void *
26927c478bd9Sstevel@tonic-gate closedown(void *arg)
26937c478bd9Sstevel@tonic-gate {
26947c478bd9Sstevel@tonic-gate 
26957c478bd9Sstevel@tonic-gate 	int	current_run_level;
26967c478bd9Sstevel@tonic-gate 
26977c478bd9Sstevel@tonic-gate 	/*CONSTCOND*/
26987c478bd9Sstevel@tonic-gate #ifndef lint
26997c478bd9Sstevel@tonic-gate 	while (1) {
27007c478bd9Sstevel@tonic-gate #endif
27017c478bd9Sstevel@tonic-gate 		(void) sleep(SVC_CLOSEDOWN/2);
27027c478bd9Sstevel@tonic-gate 
27037c478bd9Sstevel@tonic-gate 		/*
27047c478bd9Sstevel@tonic-gate 		 * If the server was started at init level 1
27057c478bd9Sstevel@tonic-gate 		 * and the current init level is 1 then
27067c478bd9Sstevel@tonic-gate 		 * do not exit from server. This server will run
27077c478bd9Sstevel@tonic-gate 		 * until it is explicitly stopped by the user.
27087c478bd9Sstevel@tonic-gate 		 */
27097c478bd9Sstevel@tonic-gate 		if (svcstart_level == 1) {
27107c478bd9Sstevel@tonic-gate 			current_run_level = get_run_level();
27117c478bd9Sstevel@tonic-gate 			if (current_run_level == 1)
27127c478bd9Sstevel@tonic-gate #ifndef lint
27137c478bd9Sstevel@tonic-gate 				continue;
27147c478bd9Sstevel@tonic-gate #else
27157c478bd9Sstevel@tonic-gate 				return (NULL);
27167c478bd9Sstevel@tonic-gate #endif
27177c478bd9Sstevel@tonic-gate 			/*
27187c478bd9Sstevel@tonic-gate 			 * who ever started the server at level 1 has
27197c478bd9Sstevel@tonic-gate 			 * forgotten to stop the server. we will kill ourself.
27207c478bd9Sstevel@tonic-gate 			 */
27217c478bd9Sstevel@tonic-gate 			debug(5,
27227c478bd9Sstevel@tonic-gate 			"Terminating the server started at init level 1\n");
27237c478bd9Sstevel@tonic-gate 			exit(0);
27247c478bd9Sstevel@tonic-gate 		}
27257c478bd9Sstevel@tonic-gate 
27267c478bd9Sstevel@tonic-gate 		if (mutex_trylock(&svcstate_lock) != 0)
27277c478bd9Sstevel@tonic-gate #ifndef lint
27287c478bd9Sstevel@tonic-gate 			continue;
27297c478bd9Sstevel@tonic-gate #else
27307c478bd9Sstevel@tonic-gate 			return (NULL);
27317c478bd9Sstevel@tonic-gate #endif
27327c478bd9Sstevel@tonic-gate 
27337c478bd9Sstevel@tonic-gate 		if (svcstate == _IDLE && svccount == 0) {
27347c478bd9Sstevel@tonic-gate 			int size;
27357c478bd9Sstevel@tonic-gate 			int i, openfd = 0;
27367c478bd9Sstevel@tonic-gate 
27377c478bd9Sstevel@tonic-gate 			size = svc_max_pollfd;
27387c478bd9Sstevel@tonic-gate 			for (i = 0; i < size && openfd < 2; i++)
27397c478bd9Sstevel@tonic-gate 				if (svc_pollfd[i].fd >= 0)
27407c478bd9Sstevel@tonic-gate 					openfd++;
27417c478bd9Sstevel@tonic-gate 			if (openfd <= 1) {
27427c478bd9Sstevel@tonic-gate 				debug(5,
27437c478bd9Sstevel@tonic-gate 				"Exiting the server from closedown routine.\n");
27447c478bd9Sstevel@tonic-gate 				exit(0);
27457c478bd9Sstevel@tonic-gate 			}
27467c478bd9Sstevel@tonic-gate 		} else
27477c478bd9Sstevel@tonic-gate 			svcstate = _IDLE;
27487c478bd9Sstevel@tonic-gate 
27497c478bd9Sstevel@tonic-gate 		(void) mutex_unlock(&svcstate_lock);
27507c478bd9Sstevel@tonic-gate #ifndef lint
27517c478bd9Sstevel@tonic-gate 	}
27527c478bd9Sstevel@tonic-gate #else
27537c478bd9Sstevel@tonic-gate 	return (NULL);
27547c478bd9Sstevel@tonic-gate #endif
27557c478bd9Sstevel@tonic-gate 
27567c478bd9Sstevel@tonic-gate }
27577c478bd9Sstevel@tonic-gate 
27587c478bd9Sstevel@tonic-gate static void
27597c478bd9Sstevel@tonic-gate usage()
27607c478bd9Sstevel@tonic-gate {
27617c478bd9Sstevel@tonic-gate 	warning(gettext("usage: %s [-L loglevel] level of debug information\n"),
27627c478bd9Sstevel@tonic-gate 		prog_name);
27637c478bd9Sstevel@tonic-gate }
27647c478bd9Sstevel@tonic-gate 
27657c478bd9Sstevel@tonic-gate 
27667c478bd9Sstevel@tonic-gate /*ARGSUSED*/
2767*360e6f5eSmathue int
27687c478bd9Sstevel@tonic-gate main(int argc, char **argv)
27697c478bd9Sstevel@tonic-gate {
27707c478bd9Sstevel@tonic-gate 	int c;
27717c478bd9Sstevel@tonic-gate 	pthread_attr_t	attr;
27727c478bd9Sstevel@tonic-gate 
27737c478bd9Sstevel@tonic-gate 	(void) setlocale(LC_ALL, "");
27747c478bd9Sstevel@tonic-gate #if !defined(TEXT_DOMAIN)
27757c478bd9Sstevel@tonic-gate #define	TEXT_DOMAIN "SYS_TEST"
27767c478bd9Sstevel@tonic-gate #endif
27777c478bd9Sstevel@tonic-gate 	(void) textdomain(TEXT_DOMAIN);
27787c478bd9Sstevel@tonic-gate 
27797c478bd9Sstevel@tonic-gate 	prog_name = argv[0];
27807c478bd9Sstevel@tonic-gate 
27817c478bd9Sstevel@tonic-gate 	(void) sigset(SIGPIPE, SIG_IGN);
27827c478bd9Sstevel@tonic-gate 
27837c478bd9Sstevel@tonic-gate 	while ((c = getopt(argc, argv, "L:")) != -1) {
27847c478bd9Sstevel@tonic-gate 		switch (c) {
27857c478bd9Sstevel@tonic-gate 		case 'L':
27867c478bd9Sstevel@tonic-gate 			debug_level = atoi((char *)optarg);
27877c478bd9Sstevel@tonic-gate 			break;
27887c478bd9Sstevel@tonic-gate 		default:
27897c478bd9Sstevel@tonic-gate 			usage();
27907c478bd9Sstevel@tonic-gate 			break;
27917c478bd9Sstevel@tonic-gate 		}
27927c478bd9Sstevel@tonic-gate 	}
27937c478bd9Sstevel@tonic-gate 
27947c478bd9Sstevel@tonic-gate 	/*
27957c478bd9Sstevel@tonic-gate 	 * If stdin looks like a TLI endpoint, we assume
27967c478bd9Sstevel@tonic-gate 	 * that we were started by a port monitor. If
27977c478bd9Sstevel@tonic-gate 	 * t_getstate fails with TBADF, this is not a
27987c478bd9Sstevel@tonic-gate 	 * TLI endpoint.
27997c478bd9Sstevel@tonic-gate 	 */
28007c478bd9Sstevel@tonic-gate 	if (t_getstate(0) != -1 || t_errno != TBADF) {
28017c478bd9Sstevel@tonic-gate 		char *netid;
28027c478bd9Sstevel@tonic-gate 		struct netconfig *nconf = NULL;
28037c478bd9Sstevel@tonic-gate 		SVCXPRT *transp;
28047c478bd9Sstevel@tonic-gate 		int pmclose;
28057c478bd9Sstevel@tonic-gate 
28067c478bd9Sstevel@tonic-gate 		openlog(prog_name, LOG_PID, LOG_DAEMON);
28077c478bd9Sstevel@tonic-gate 
28087c478bd9Sstevel@tonic-gate 		debug(1, gettext("server started by port monitor.\n"));
28097c478bd9Sstevel@tonic-gate 		if ((netid = getenv("NLSPROVIDER")) == NULL) {
28107c478bd9Sstevel@tonic-gate 		/* started from inetd */
28117c478bd9Sstevel@tonic-gate 			pmclose = 1;
28127c478bd9Sstevel@tonic-gate 		} else {
28137c478bd9Sstevel@tonic-gate 			if ((nconf = getnetconfigent(netid)) == NULL)
28147c478bd9Sstevel@tonic-gate 				syslog(LOG_ERR, gettext(
28157c478bd9Sstevel@tonic-gate 					"cannot get transport info"));
28167c478bd9Sstevel@tonic-gate 
28177c478bd9Sstevel@tonic-gate 			pmclose = (t_getstate(0) != T_DATAXFER);
28187c478bd9Sstevel@tonic-gate 		}
28197c478bd9Sstevel@tonic-gate 		if ((transp = svc_tli_create(0, nconf, NULL, 0, 0)) == NULL) {
28207c478bd9Sstevel@tonic-gate 			syslog(LOG_ERR, gettext("cannot create server handle"));
28217c478bd9Sstevel@tonic-gate 			exit(1);
28227c478bd9Sstevel@tonic-gate 		}
28237c478bd9Sstevel@tonic-gate 		if (nconf)
28247c478bd9Sstevel@tonic-gate 			freenetconfigent(nconf);
28257c478bd9Sstevel@tonic-gate 		if (!svc_reg(transp, SMSERVERPROG, SMSERVERVERS,
28267c478bd9Sstevel@tonic-gate 			smserverprog_1, 0)) {
28277c478bd9Sstevel@tonic-gate 			syslog(LOG_ERR, gettext(
28287c478bd9Sstevel@tonic-gate 			"unable to register (SMSERVERPROG, SMSERVERVERS)."));
28297c478bd9Sstevel@tonic-gate 			exit(1);
28307c478bd9Sstevel@tonic-gate 		}
28317c478bd9Sstevel@tonic-gate 		svcstart_level = get_run_level();
28327c478bd9Sstevel@tonic-gate 		if (pmclose) {
28337c478bd9Sstevel@tonic-gate 			(void) pthread_attr_init(&attr);
28347c478bd9Sstevel@tonic-gate 			(void) pthread_attr_setscope(&attr,
28357c478bd9Sstevel@tonic-gate 				PTHREAD_SCOPE_SYSTEM | PTHREAD_CREATE_DETACHED);
28367c478bd9Sstevel@tonic-gate 			if (pthread_create(NULL, &attr, closedown, NULL) != 0) {
28377c478bd9Sstevel@tonic-gate 				syslog(LOG_ERR, gettext(
28387c478bd9Sstevel@tonic-gate 					"cannot create closedown thread"));
28397c478bd9Sstevel@tonic-gate 				exit(1);
28407c478bd9Sstevel@tonic-gate 			}
28417c478bd9Sstevel@tonic-gate 			(void) pthread_attr_destroy(&attr);
28427c478bd9Sstevel@tonic-gate 		}
28437c478bd9Sstevel@tonic-gate 		svc_run();
28447c478bd9Sstevel@tonic-gate 		exit(1);
28457c478bd9Sstevel@tonic-gate 		/* NOTREACHED */
28467c478bd9Sstevel@tonic-gate 	} else {
28477c478bd9Sstevel@tonic-gate 		/*
28487c478bd9Sstevel@tonic-gate 		 * Started by library or manually.
28497c478bd9Sstevel@tonic-gate 		 */
28507c478bd9Sstevel@tonic-gate 		/*
28517c478bd9Sstevel@tonic-gate 		 * Check to see if the server is already running.
28527c478bd9Sstevel@tonic-gate 		 * There is no need to log messages in the syslog file
28537c478bd9Sstevel@tonic-gate 		 * because server will get launched each time libsmedia
28547c478bd9Sstevel@tonic-gate 		 * library calls are made at init 1 level.
28557c478bd9Sstevel@tonic-gate 		 * We ensure that only one copy will run.
28567c478bd9Sstevel@tonic-gate 		 */
28577c478bd9Sstevel@tonic-gate 		debug(1, gettext("server started manually.\n"));
28587c478bd9Sstevel@tonic-gate 		if (server_exists()) {
28597c478bd9Sstevel@tonic-gate 			exit(0);
28607c478bd9Sstevel@tonic-gate 		}
28617c478bd9Sstevel@tonic-gate 		svcstart_level = get_run_level();
28627c478bd9Sstevel@tonic-gate 		(void) pthread_attr_init(&attr);
28637c478bd9Sstevel@tonic-gate 		(void) pthread_attr_setscope(&attr,
28647c478bd9Sstevel@tonic-gate 			PTHREAD_SCOPE_SYSTEM | PTHREAD_CREATE_DETACHED);
28657c478bd9Sstevel@tonic-gate 		if (pthread_create(NULL, &attr, closedown, NULL) != 0) {
28667c478bd9Sstevel@tonic-gate 			syslog(LOG_ERR, gettext(
28677c478bd9Sstevel@tonic-gate 				"cannot create closedown thread"));
28687c478bd9Sstevel@tonic-gate 			exit(1);
28697c478bd9Sstevel@tonic-gate 		}
28707c478bd9Sstevel@tonic-gate 		(void) pthread_attr_destroy(&attr);
28717c478bd9Sstevel@tonic-gate 		(void) init_server(NULL);
28727c478bd9Sstevel@tonic-gate 		for (;;) (void) pause();
28737c478bd9Sstevel@tonic-gate 	}
2874*360e6f5eSmathue 	return (0);
28757c478bd9Sstevel@tonic-gate }
28767c478bd9Sstevel@tonic-gate 
28777c478bd9Sstevel@tonic-gate 
28787c478bd9Sstevel@tonic-gate /*ARGSUSED*/
28797c478bd9Sstevel@tonic-gate static int32_t
28807c478bd9Sstevel@tonic-gate scsi_floppy_write_protect(int32_t fd, smwp_state_t *wp)
28817c478bd9Sstevel@tonic-gate {
28827c478bd9Sstevel@tonic-gate 	debug(5, "Invalid mode\n");
28837c478bd9Sstevel@tonic-gate 	errno = ENOTSUP;
28847c478bd9Sstevel@tonic-gate 
28857c478bd9Sstevel@tonic-gate 	return (-1);
28867c478bd9Sstevel@tonic-gate }
28877c478bd9Sstevel@tonic-gate 
28887c478bd9Sstevel@tonic-gate /*
28897c478bd9Sstevel@tonic-gate  * Generate standard geometry information for SCSI floppy devices. And
28907c478bd9Sstevel@tonic-gate  * register the geometry with the SCSI driver. This will expand as more
28917c478bd9Sstevel@tonic-gate  * formats are added.
28927c478bd9Sstevel@tonic-gate  */
28937c478bd9Sstevel@tonic-gate 
28947c478bd9Sstevel@tonic-gate /*ARGSUSED*/
28957c478bd9Sstevel@tonic-gate static int32_t
28967c478bd9Sstevel@tonic-gate get_floppy_geom(int32_t fd, uint32_t capacity, struct dk_geom *dkgeom)
28977c478bd9Sstevel@tonic-gate {
28987c478bd9Sstevel@tonic-gate 
28997c478bd9Sstevel@tonic-gate 
29007c478bd9Sstevel@tonic-gate 	debug(5, "get_floppy_geom: capacity = 0x%x\n", capacity);
29017c478bd9Sstevel@tonic-gate 
29027c478bd9Sstevel@tonic-gate 	switch (capacity) {
29037c478bd9Sstevel@tonic-gate 
29047c478bd9Sstevel@tonic-gate 		case 0x5A0:
29057c478bd9Sstevel@tonic-gate 			/* Double Density 720K */
29067c478bd9Sstevel@tonic-gate 			dkgeom->dkg_pcyl = 80;
29077c478bd9Sstevel@tonic-gate 			dkgeom->dkg_ncyl = 80;
29087c478bd9Sstevel@tonic-gate 			dkgeom->dkg_nhead = 2;
29097c478bd9Sstevel@tonic-gate 			dkgeom->dkg_nsect = 9;
29107c478bd9Sstevel@tonic-gate 			break;
29117c478bd9Sstevel@tonic-gate 		case 0x4D0:
29127c478bd9Sstevel@tonic-gate 			/* High Density 1.25MB */
29137c478bd9Sstevel@tonic-gate 			dkgeom->dkg_pcyl = 77;
29147c478bd9Sstevel@tonic-gate 			dkgeom->dkg_ncyl = 77;
29157c478bd9Sstevel@tonic-gate 			dkgeom->dkg_nhead = 2;
29167c478bd9Sstevel@tonic-gate 			dkgeom->dkg_nsect = 9;
29177c478bd9Sstevel@tonic-gate 			break;
29187c478bd9Sstevel@tonic-gate 		case 0xB40:
29197c478bd9Sstevel@tonic-gate 			/* High Density 1.44MB */
29207c478bd9Sstevel@tonic-gate 
29217c478bd9Sstevel@tonic-gate 			dkgeom->dkg_pcyl = 80;
29227c478bd9Sstevel@tonic-gate 			dkgeom->dkg_ncyl = 80;
29237c478bd9Sstevel@tonic-gate 			dkgeom->dkg_nhead = 2;
29247c478bd9Sstevel@tonic-gate 			dkgeom->dkg_nsect = 18;
29257c478bd9Sstevel@tonic-gate 			break;
29267c478bd9Sstevel@tonic-gate 		case 0x3C300:
29277c478bd9Sstevel@tonic-gate 			/* Ultra High density ls-120 120MB */
29287c478bd9Sstevel@tonic-gate 			dkgeom->dkg_pcyl = 963;
29297c478bd9Sstevel@tonic-gate 			dkgeom->dkg_ncyl = 963;
29307c478bd9Sstevel@tonic-gate 			dkgeom->dkg_nhead = 8;
29317c478bd9Sstevel@tonic-gate 			dkgeom->dkg_nsect = 32;
29327c478bd9Sstevel@tonic-gate 			break;
29337c478bd9Sstevel@tonic-gate 		default:
29347c478bd9Sstevel@tonic-gate 			debug(5, "unknown capacity type %d\n", capacity);
29357c478bd9Sstevel@tonic-gate 			return (-1);
29367c478bd9Sstevel@tonic-gate 
29377c478bd9Sstevel@tonic-gate 	}
29387c478bd9Sstevel@tonic-gate 	debug(5, "get_floppy_geom: setting cyl = %d, nsect = %d, head = %d",
29397c478bd9Sstevel@tonic-gate 		dkgeom->dkg_pcyl, dkgeom->dkg_nhead, dkgeom->dkg_nsect);
29407c478bd9Sstevel@tonic-gate 	return (0);
29417c478bd9Sstevel@tonic-gate 
29427c478bd9Sstevel@tonic-gate }
29437c478bd9Sstevel@tonic-gate /* ARGSUSED */
29447c478bd9Sstevel@tonic-gate int32_t
29457c478bd9Sstevel@tonic-gate scsi_floppy_format(int32_t fd, uint_t flavor, uint_t mode)
29467c478bd9Sstevel@tonic-gate {
29477c478bd9Sstevel@tonic-gate 	struct uscsi_cmd ucmd;
29487c478bd9Sstevel@tonic-gate 	uchar_t		cdb[12];
29497c478bd9Sstevel@tonic-gate 	int32_t		ret_val;
29507c478bd9Sstevel@tonic-gate 	uint32_t	capacity, blocksize;
29517c478bd9Sstevel@tonic-gate 	uchar_t		data[12];
29527c478bd9Sstevel@tonic-gate 	char 		rq_data[RQ_LEN];
29537c478bd9Sstevel@tonic-gate 	int		i;
29547c478bd9Sstevel@tonic-gate 	struct dk_geom	dkgeom;
29557c478bd9Sstevel@tonic-gate 
29567c478bd9Sstevel@tonic-gate 	debug(5, "scsi_floppy_format:\n");
29577c478bd9Sstevel@tonic-gate 
29587c478bd9Sstevel@tonic-gate 	if ((mode != SM_FORMAT_IMMEDIATE) && (mode != SM_FORMAT_BLOCKED)) {
29597c478bd9Sstevel@tonic-gate 		errno = ENOTSUP;
29607c478bd9Sstevel@tonic-gate 
29617c478bd9Sstevel@tonic-gate 		return (-1);
29627c478bd9Sstevel@tonic-gate 	}
29637c478bd9Sstevel@tonic-gate 
29647c478bd9Sstevel@tonic-gate 	switch (flavor) {
29657c478bd9Sstevel@tonic-gate 		case SM_FORMAT_QUICK :
29667c478bd9Sstevel@tonic-gate 			debug(1, "Format not supported\n");
29677c478bd9Sstevel@tonic-gate 			errno = ENOTSUP;
29687c478bd9Sstevel@tonic-gate 			return (-1);
29697c478bd9Sstevel@tonic-gate 		case SM_FORMAT_FORCE :
29707c478bd9Sstevel@tonic-gate 			break;
29717c478bd9Sstevel@tonic-gate 		case SM_FORMAT_LONG :
29727c478bd9Sstevel@tonic-gate 			break;
29737c478bd9Sstevel@tonic-gate 
29747c478bd9Sstevel@tonic-gate 		default :
29757c478bd9Sstevel@tonic-gate 			debug(1, "Format option not specified!!\n");
29767c478bd9Sstevel@tonic-gate 			errno = ENOTSUP;
29777c478bd9Sstevel@tonic-gate 			return (-1);
29787c478bd9Sstevel@tonic-gate 	}
29797c478bd9Sstevel@tonic-gate 
29807c478bd9Sstevel@tonic-gate 	ret_val = get_media_capacity(fd, &capacity, &blocksize);
29817c478bd9Sstevel@tonic-gate 
29827c478bd9Sstevel@tonic-gate 	if (capacity >= 0x3C300) {
29837c478bd9Sstevel@tonic-gate 		/*
29847c478bd9Sstevel@tonic-gate 		 * It's an LS-120 media, it does not support track
29857c478bd9Sstevel@tonic-gate 		 * formatting.
29867c478bd9Sstevel@tonic-gate 		 */
29877c478bd9Sstevel@tonic-gate 		return (scsi_ls120_format(fd, flavor, capacity, blocksize));
29887c478bd9Sstevel@tonic-gate 	}
29897c478bd9Sstevel@tonic-gate 
29907c478bd9Sstevel@tonic-gate 	ret_val = get_floppy_geom(fd, capacity, &dkgeom);
29917c478bd9Sstevel@tonic-gate 		if (ret_val) {
29927c478bd9Sstevel@tonic-gate 			errno = ENOTSUP;
29937c478bd9Sstevel@tonic-gate 			return (-1);
29947c478bd9Sstevel@tonic-gate 		}
29957c478bd9Sstevel@tonic-gate 
29967c478bd9Sstevel@tonic-gate 	(void) memset((void *)&data, 0, sizeof (data));
29977c478bd9Sstevel@tonic-gate 	(void) memset((void *)&ucmd, 0, sizeof (ucmd));
29987c478bd9Sstevel@tonic-gate 	(void) memset((void *)&cdb, 0, sizeof (cdb));
29997c478bd9Sstevel@tonic-gate 
30007c478bd9Sstevel@tonic-gate 	/* retrieve size discriptor of inserted media */
30017c478bd9Sstevel@tonic-gate 	cdb[0] = SCMD_FORMAT;	/* format */
30027c478bd9Sstevel@tonic-gate 
30037c478bd9Sstevel@tonic-gate 	/*
30047c478bd9Sstevel@tonic-gate 	 * Defect list sent by initiator is a complete list of defects.
30057c478bd9Sstevel@tonic-gate 	 */
30067c478bd9Sstevel@tonic-gate 
30077c478bd9Sstevel@tonic-gate 	cdb[1] = (FMTDATA | 0x7);
30087c478bd9Sstevel@tonic-gate 
30097c478bd9Sstevel@tonic-gate 	cdb[8] = 0xC;   /* parameter list length */
30107c478bd9Sstevel@tonic-gate 	data[3] = 0x8;	/* should be always 8 */
30117c478bd9Sstevel@tonic-gate 
30127c478bd9Sstevel@tonic-gate 	data[4] = (uchar_t)(capacity >> 24);
30137c478bd9Sstevel@tonic-gate 	data[5] = (uchar_t)(capacity >> 16);
30147c478bd9Sstevel@tonic-gate 	data[6] = (uchar_t)(capacity >> 8);
30157c478bd9Sstevel@tonic-gate 	data[7] = (uchar_t)capacity;
30167c478bd9Sstevel@tonic-gate 
30177c478bd9Sstevel@tonic-gate 	data[9] = (uchar_t)(blocksize >> 16);
30187c478bd9Sstevel@tonic-gate 	data[10] = (uchar_t)(blocksize >> 8);
30197c478bd9Sstevel@tonic-gate 	data[11] = (uchar_t)blocksize;
30207c478bd9Sstevel@tonic-gate 
30217c478bd9Sstevel@tonic-gate 	ucmd.uscsi_cdb = (caddr_t)&cdb;
30227c478bd9Sstevel@tonic-gate 	ucmd.uscsi_cdblen = CDB_GROUP5;
30237c478bd9Sstevel@tonic-gate 	ucmd.uscsi_bufaddr = (caddr_t)data;
30247c478bd9Sstevel@tonic-gate 	ucmd.uscsi_buflen = sizeof (data);
30257c478bd9Sstevel@tonic-gate 	ucmd.uscsi_timeout = 0x15;
30267c478bd9Sstevel@tonic-gate 	ucmd.uscsi_rqlen = RQ_LEN;
30277c478bd9Sstevel@tonic-gate 	ucmd.uscsi_rqbuf = rq_data;
30287c478bd9Sstevel@tonic-gate 
30297c478bd9Sstevel@tonic-gate 	debug(5, "cdb: %x %x %x ... %x", cdb[0], cdb[1], cdb[2], cdb[8]);
30307c478bd9Sstevel@tonic-gate 	debug(5, "data: %x %x %x %x\n", data[0], data[1], data[2], data[3]);
30317c478bd9Sstevel@tonic-gate 	debug(5, "    : %x %x %x %x\n", data[4], data[5], data[6], data[7]);
30327c478bd9Sstevel@tonic-gate 	debug(5, "    : %x %x %x %x\n", data[8], data[9], data[10], data[11]);
30337c478bd9Sstevel@tonic-gate 
30347c478bd9Sstevel@tonic-gate 	for (i = 0; i < dkgeom.dkg_pcyl; i++) {	/* number of tracks */
30357c478bd9Sstevel@tonic-gate 		data[1] = (0xb0 | FOV);
30367c478bd9Sstevel@tonic-gate 		cdb[2] = i;
30377c478bd9Sstevel@tonic-gate 
30387c478bd9Sstevel@tonic-gate 		(void) fflush(stdout);
30397c478bd9Sstevel@tonic-gate 		ret_val = do_uscsi_cmd(fd, &ucmd, USCSI_WRITE|USCSI_RQENABLE);
30407c478bd9Sstevel@tonic-gate 		info("format side 0 returned : 0x%x\n", ret_val);
30417c478bd9Sstevel@tonic-gate 
30427c478bd9Sstevel@tonic-gate 		if (ret_val || ucmd.uscsi_status) {
30437c478bd9Sstevel@tonic-gate 			debug(5, "Retrieving media info failed: %d - %d\n",
30447c478bd9Sstevel@tonic-gate 			    ret_val, ucmd.uscsi_status);
30457c478bd9Sstevel@tonic-gate 			if ((rq_data[2] == KEY_DATA_PROTECT) &&
30467c478bd9Sstevel@tonic-gate 			    (rq_data[12] == 0x30) && (rq_data[13] == 0)) {
30477c478bd9Sstevel@tonic-gate 				debug(5, "Invalid command for media\n");
30487c478bd9Sstevel@tonic-gate 				errno = EINVAL;
30497c478bd9Sstevel@tonic-gate 			}
30507c478bd9Sstevel@tonic-gate 
30517c478bd9Sstevel@tonic-gate 			if ((rq_data[2] == KEY_NOT_READY) &&
30527c478bd9Sstevel@tonic-gate 			    (rq_data[12] == 0x30)) {
30537c478bd9Sstevel@tonic-gate 				debug(5, "Incompatible media.\n");
30547c478bd9Sstevel@tonic-gate 				errno = EINVAL;
30557c478bd9Sstevel@tonic-gate 			}
30567c478bd9Sstevel@tonic-gate 
30577c478bd9Sstevel@tonic-gate 			return (-1);
30587c478bd9Sstevel@tonic-gate 		}
30597c478bd9Sstevel@tonic-gate 		data[1] = (0xb0 | FOV) + 1;
30607c478bd9Sstevel@tonic-gate 		ret_val = do_uscsi_cmd(fd, &ucmd, USCSI_WRITE|USCSI_RQENABLE);
30617c478bd9Sstevel@tonic-gate 		info("format side 1 returned : 0x%x\n", ret_val);
30627c478bd9Sstevel@tonic-gate 
30637c478bd9Sstevel@tonic-gate 		if (ret_val || ucmd.uscsi_status) {
30647c478bd9Sstevel@tonic-gate 			debug(5, "Retrieving media info failed: %d - %d\n",
30657c478bd9Sstevel@tonic-gate 			    ret_val, ucmd.uscsi_status);
30667c478bd9Sstevel@tonic-gate 			if ((rq_data[2] == KEY_DATA_PROTECT) &&
30677c478bd9Sstevel@tonic-gate 			    (rq_data[12] == 0x30) && (rq_data[13] == 0)) {
30687c478bd9Sstevel@tonic-gate 				(void) info("Invalid command for media\n");
30697c478bd9Sstevel@tonic-gate 				errno = EINVAL;
30707c478bd9Sstevel@tonic-gate 			}
30717c478bd9Sstevel@tonic-gate 
30727c478bd9Sstevel@tonic-gate 			if ((rq_data[2] == KEY_NOT_READY) &&
30737c478bd9Sstevel@tonic-gate 			    (rq_data[12] == 0x30)) {
30747c478bd9Sstevel@tonic-gate 				debug(5, "Incompatible media.\n");
30757c478bd9Sstevel@tonic-gate 				errno = EINVAL;
30767c478bd9Sstevel@tonic-gate 			}
30777c478bd9Sstevel@tonic-gate 
30787c478bd9Sstevel@tonic-gate 			return (-1);
30797c478bd9Sstevel@tonic-gate 		}
30807c478bd9Sstevel@tonic-gate 	}
30817c478bd9Sstevel@tonic-gate 
30827c478bd9Sstevel@tonic-gate 	debug(5, "formatting done!");
30837c478bd9Sstevel@tonic-gate 	return (0);
30847c478bd9Sstevel@tonic-gate }
30857c478bd9Sstevel@tonic-gate 
30867c478bd9Sstevel@tonic-gate 
30877c478bd9Sstevel@tonic-gate /* ARGSUSED */
30887c478bd9Sstevel@tonic-gate int32_t
30897c478bd9Sstevel@tonic-gate scsi_floppy_media_status(int32_t fd)
30907c478bd9Sstevel@tonic-gate {
30917c478bd9Sstevel@tonic-gate 	struct mode_header_g1 modeh;
30927c478bd9Sstevel@tonic-gate 	struct uscsi_cmd ucmd;
30937c478bd9Sstevel@tonic-gate 	uchar_t cdb[10];
30947c478bd9Sstevel@tonic-gate 	int32_t ret_val;
30957c478bd9Sstevel@tonic-gate 	int32_t cur_status;
30967c478bd9Sstevel@tonic-gate 	char rq_data[RQ_LEN];
30977c478bd9Sstevel@tonic-gate 
30987c478bd9Sstevel@tonic-gate 	debug(5, "SCSI MEDIA STATUS CALLED \n");
30997c478bd9Sstevel@tonic-gate 
31007c478bd9Sstevel@tonic-gate 	(void) memset((void *) &modeh, 0, sizeof (modeh));
31017c478bd9Sstevel@tonic-gate 	(void) memset((void *) &ucmd, 0, sizeof (ucmd));
31027c478bd9Sstevel@tonic-gate 	(void) memset(cdb, 0, sizeof (cdb));
31037c478bd9Sstevel@tonic-gate 	/*
31047c478bd9Sstevel@tonic-gate 	 * issue 10 byte mode sense (0x5A)
31057c478bd9Sstevel@tonic-gate 	 */
31067c478bd9Sstevel@tonic-gate 	cdb[0] = SCMD_MODE_SENSE_G1;
31077c478bd9Sstevel@tonic-gate 	cdb[7] = sizeof (modeh) >> 8;
31087c478bd9Sstevel@tonic-gate 	cdb[8] = sizeof (modeh) & 0xff;
31097c478bd9Sstevel@tonic-gate 
31107c478bd9Sstevel@tonic-gate 	ucmd.uscsi_cdb = (caddr_t)cdb;
31117c478bd9Sstevel@tonic-gate 	ucmd.uscsi_cdblen = CDB_GROUP1;
31127c478bd9Sstevel@tonic-gate 	ucmd.uscsi_bufaddr = (caddr_t)&modeh;
31137c478bd9Sstevel@tonic-gate 	ucmd.uscsi_buflen = sizeof (modeh);
31147c478bd9Sstevel@tonic-gate 	ucmd.uscsi_timeout = 120;	/* If 0, HBA hangs forever */
31157c478bd9Sstevel@tonic-gate 	ucmd.uscsi_rqlen = RQ_LEN;
31167c478bd9Sstevel@tonic-gate 	ucmd.uscsi_rqbuf = rq_data;
31177c478bd9Sstevel@tonic-gate 	ret_val = do_uscsi_cmd(fd, &ucmd, USCSI_READ|USCSI_RQENABLE);
31187c478bd9Sstevel@tonic-gate 	if (ret_val || ucmd.uscsi_status) {
31197c478bd9Sstevel@tonic-gate 		/*
31207c478bd9Sstevel@tonic-gate 		 * UFI devices may not respond to the 0 mode page.
31217c478bd9Sstevel@tonic-gate 		 * retry with the error recovery page(0x01)
31227c478bd9Sstevel@tonic-gate 		 */
31237c478bd9Sstevel@tonic-gate 		if (ucmd.uscsi_status & STATUS_CHECK) {
31247c478bd9Sstevel@tonic-gate 			cdb[2] = 0x1;	/* page code */
31257c478bd9Sstevel@tonic-gate 			ret_val = do_uscsi_cmd(fd, &ucmd,
31267c478bd9Sstevel@tonic-gate 					USCSI_READ|USCSI_RQENABLE);
31277c478bd9Sstevel@tonic-gate 		}
31287c478bd9Sstevel@tonic-gate 		if (ret_val || ucmd.uscsi_status) {
31297c478bd9Sstevel@tonic-gate 			debug(1, "Modesense failed: %d - %d\n",
31307c478bd9Sstevel@tonic-gate 				ret_val, ucmd.uscsi_status);
31317c478bd9Sstevel@tonic-gate 			return (-1);
31327c478bd9Sstevel@tonic-gate 		}
31337c478bd9Sstevel@tonic-gate 	}
31347c478bd9Sstevel@tonic-gate 	debug(5, "Modesense succeeded: 0x%x\n", modeh.device_specific);
31357c478bd9Sstevel@tonic-gate 
31367c478bd9Sstevel@tonic-gate 	if (modeh.device_specific & 0x80) {
31377c478bd9Sstevel@tonic-gate 		cur_status = SM_WRITE_PROTECT_NOPASSWD;
31387c478bd9Sstevel@tonic-gate 	} else {
31397c478bd9Sstevel@tonic-gate 		cur_status = SM_WRITE_PROTECT_DISABLE;
31407c478bd9Sstevel@tonic-gate 	}
31417c478bd9Sstevel@tonic-gate 	return (cur_status);
31427c478bd9Sstevel@tonic-gate }
3143