xref: /titanic_44/usr/src/cmd/smserverd/smediad.c (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * CDDL HEADER START
3*7c478bd9Sstevel@tonic-gate  *
4*7c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*7c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*7c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*7c478bd9Sstevel@tonic-gate  * with the License.
8*7c478bd9Sstevel@tonic-gate  *
9*7c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*7c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*7c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*7c478bd9Sstevel@tonic-gate  * and limitations under the License.
13*7c478bd9Sstevel@tonic-gate  *
14*7c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*7c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*7c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*7c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*7c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*7c478bd9Sstevel@tonic-gate  *
20*7c478bd9Sstevel@tonic-gate  * CDDL HEADER END
21*7c478bd9Sstevel@tonic-gate  */
22*7c478bd9Sstevel@tonic-gate /*
23*7c478bd9Sstevel@tonic-gate  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24*7c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
25*7c478bd9Sstevel@tonic-gate  */
26*7c478bd9Sstevel@tonic-gate 
27*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*7c478bd9Sstevel@tonic-gate 
29*7c478bd9Sstevel@tonic-gate #include <stdio.h>
30*7c478bd9Sstevel@tonic-gate #include <errno.h>
31*7c478bd9Sstevel@tonic-gate #include <ctype.h>
32*7c478bd9Sstevel@tonic-gate #include <syslog.h>
33*7c478bd9Sstevel@tonic-gate #include <signal.h>
34*7c478bd9Sstevel@tonic-gate #include <limits.h>
35*7c478bd9Sstevel@tonic-gate #include <unistd.h>
36*7c478bd9Sstevel@tonic-gate #include <sys/types.h>
37*7c478bd9Sstevel@tonic-gate #include <sys/mman.h>
38*7c478bd9Sstevel@tonic-gate #include <stdlib.h>
39*7c478bd9Sstevel@tonic-gate #include <sys/stat.h>
40*7c478bd9Sstevel@tonic-gate #include <sys/mkdev.h>
41*7c478bd9Sstevel@tonic-gate #include <fcntl.h>
42*7c478bd9Sstevel@tonic-gate #include <sys/scsi/scsi.h>
43*7c478bd9Sstevel@tonic-gate #include <sys/scsi/generic/commands.h>
44*7c478bd9Sstevel@tonic-gate #include <string.h>
45*7c478bd9Sstevel@tonic-gate #include <door.h>
46*7c478bd9Sstevel@tonic-gate #include <pwd.h>
47*7c478bd9Sstevel@tonic-gate #include <thread.h>
48*7c478bd9Sstevel@tonic-gate #include <synch.h>
49*7c478bd9Sstevel@tonic-gate #include <pthread.h>
50*7c478bd9Sstevel@tonic-gate #include <locale.h>
51*7c478bd9Sstevel@tonic-gate #include <sys/resource.h>
52*7c478bd9Sstevel@tonic-gate #include <netconfig.h>
53*7c478bd9Sstevel@tonic-gate #include <sys/smedia.h>
54*7c478bd9Sstevel@tonic-gate #include "smserver.h"
55*7c478bd9Sstevel@tonic-gate #include <rpc/rpc.h>
56*7c478bd9Sstevel@tonic-gate #include "smed.h"
57*7c478bd9Sstevel@tonic-gate #include "myaudit.h"
58*7c478bd9Sstevel@tonic-gate #include <bsm/libbsm.h>
59*7c478bd9Sstevel@tonic-gate #include <bsm/audit_uevents.h>
60*7c478bd9Sstevel@tonic-gate #include <utmpx.h>
61*7c478bd9Sstevel@tonic-gate 
62*7c478bd9Sstevel@tonic-gate 
63*7c478bd9Sstevel@tonic-gate /*
64*7c478bd9Sstevel@tonic-gate  * The comments below would help in understanding what is being attempted
65*7c478bd9Sstevel@tonic-gate  * in the server.
66*7c478bd9Sstevel@tonic-gate  *
67*7c478bd9Sstevel@tonic-gate  * The server can be started either by inetd or by the client directly.
68*7c478bd9Sstevel@tonic-gate  * Normally the server is started by inetd when the client invokes the
69*7c478bd9Sstevel@tonic-gate  * appropriate libsmedia library call(smedia_get_handle).
70*7c478bd9Sstevel@tonic-gate  * However since the inetd runs only at init level 2 and above a mechanism
71*7c478bd9Sstevel@tonic-gate  * is provided for the server to be started if an attempt is made to use
72*7c478bd9Sstevel@tonic-gate  * the libsmedia calls in maintenence mode(init level 1).
73*7c478bd9Sstevel@tonic-gate  * The main() routine determines how the server was invoked and takes
74*7c478bd9Sstevel@tonic-gate  * the necessary action.
75*7c478bd9Sstevel@tonic-gate  * When started by inetd it registers itself as an RPC program.
76*7c478bd9Sstevel@tonic-gate  * The server also implements a mechanism by which it removes itself
77*7c478bd9Sstevel@tonic-gate  * after a period of inactivity. The period of inactivity is specified
78*7c478bd9Sstevel@tonic-gate  * by SVC_CLOSEDOWN which is set at 180 secs.
79*7c478bd9Sstevel@tonic-gate  * The logic of detecting inactivity is as follows:
80*7c478bd9Sstevel@tonic-gate  *
81*7c478bd9Sstevel@tonic-gate  * Two variables svcstate and svccount are used to determine if the server
82*7c478bd9Sstevel@tonic-gate  * is IDLE.
83*7c478bd9Sstevel@tonic-gate  * The svcstate is set to 1(_SERVED) when ever the server does any operation
84*7c478bd9Sstevel@tonic-gate  * on behalf of the client.
85*7c478bd9Sstevel@tonic-gate  * The svccount indicates the number of active clients who have established
86*7c478bd9Sstevel@tonic-gate  * a connection with the server. A connection is established when the
87*7c478bd9Sstevel@tonic-gate  * libsmedia call smedia_get_handle() succeeds.
88*7c478bd9Sstevel@tonic-gate  * The connection is broken when the client calls smedia_free_handle() OR
89*7c478bd9Sstevel@tonic-gate  * exits.
90*7c478bd9Sstevel@tonic-gate  * A thread called closedown is started up when server is started.
91*7c478bd9Sstevel@tonic-gate  * This thread runs periodically and monitors both svcstate and svccount.
92*7c478bd9Sstevel@tonic-gate  * If svcstate is IDLE and svccount is 0 then server exits.
93*7c478bd9Sstevel@tonic-gate  * The svcstate is set to IDLE by the closedown thread. It is set to _SERVED
94*7c478bd9Sstevel@tonic-gate  * by server. It is possible for the state to be _SERVED and the svccount
95*7c478bd9Sstevel@tonic-gate  * to be 0. The server could be kept busy by client calls of smedia_get_handle
96*7c478bd9Sstevel@tonic-gate  * that do not succeed. This is the reason for using both svcstate and svccount
97*7c478bd9Sstevel@tonic-gate  * to determine the true server state.
98*7c478bd9Sstevel@tonic-gate  *
99*7c478bd9Sstevel@tonic-gate  * The communication between client and server is thru door calls.
100*7c478bd9Sstevel@tonic-gate  * Below are the door descriptors available to communicate to the server.
101*7c478bd9Sstevel@tonic-gate  *
102*7c478bd9Sstevel@tonic-gate  * main_door_descriptor:
103*7c478bd9Sstevel@tonic-gate  * ---------------------
104*7c478bd9Sstevel@tonic-gate  * 	This is a predefined descriptor used by client to establish a
105*7c478bd9Sstevel@tonic-gate  * connection with the server. This descriptor is available to the client
106*7c478bd9Sstevel@tonic-gate  * as /var/adm/smedia_svc
107*7c478bd9Sstevel@tonic-gate  * The client uses the main door_descriptor to obtain a dedicated
108*7c478bd9Sstevel@tonic-gate  * client_door_descriptor for itself. The smedia_get_handle call communicates
109*7c478bd9Sstevel@tonic-gate  * to the server using the main_door_descriptor and obtains the
110*7c478bd9Sstevel@tonic-gate  * client_door_descriptor which is stored in the handle structure.
111*7c478bd9Sstevel@tonic-gate  * All other libsmedia calls use the client_door_descriptor to communicate
112*7c478bd9Sstevel@tonic-gate  * with the server.
113*7c478bd9Sstevel@tonic-gate  *
114*7c478bd9Sstevel@tonic-gate  * client_door_descriptor:
115*7c478bd9Sstevel@tonic-gate  * -----------------------
116*7c478bd9Sstevel@tonic-gate  *	This is the door descriptor that is used by the clients to
117*7c478bd9Sstevel@tonic-gate  * request server to perform the necessary tasks. This door descriptor is
118*7c478bd9Sstevel@tonic-gate  * available only to the client for whom it was created.
119*7c478bd9Sstevel@tonic-gate  *
120*7c478bd9Sstevel@tonic-gate  * death_door_descriptor:
121*7c478bd9Sstevel@tonic-gate  * ----------------------
122*7c478bd9Sstevel@tonic-gate  * 	The sole function of this door descriptor is to inform the server of
123*7c478bd9Sstevel@tonic-gate  * the untimely death of the client. This helps the server to do the necessary
124*7c478bd9Sstevel@tonic-gate  * cleanups.
125*7c478bd9Sstevel@tonic-gate  *
126*7c478bd9Sstevel@tonic-gate  * main_server()
127*7c478bd9Sstevel@tonic-gate  * -------------
128*7c478bd9Sstevel@tonic-gate  *	This is the routine associated with the main_door_descriptor.
129*7c478bd9Sstevel@tonic-gate  * This is the routine that handles the smedia_get_handle() call
130*7c478bd9Sstevel@tonic-gate  * of the client. If the door call to this routine succeeds it creates a
131*7c478bd9Sstevel@tonic-gate  * client_door_descriptor that is used by the client in subsequent library
132*7c478bd9Sstevel@tonic-gate  * calls.
133*7c478bd9Sstevel@tonic-gate  * This client_door_descriptor is passed to the client thru the door_return
134*7c478bd9Sstevel@tonic-gate  * call. This client_door_descriptor cannot be used by any other process other
135*7c478bd9Sstevel@tonic-gate  * than the client process that obtained it.
136*7c478bd9Sstevel@tonic-gate  * In addition to the client_door_descriptor a death_door_descriptor is also
137*7c478bd9Sstevel@tonic-gate  * created by the main server and passed on to the client. The client does not
138*7c478bd9Sstevel@tonic-gate  * use the death_door_descriptor at all. It is there to inform the server in
139*7c478bd9Sstevel@tonic-gate  * case the client program were to exit without calling smedia_free_handle().
140*7c478bd9Sstevel@tonic-gate  *
141*7c478bd9Sstevel@tonic-gate  * client_server()
142*7c478bd9Sstevel@tonic-gate  * ---------------
143*7c478bd9Sstevel@tonic-gate  *	This is the routine that handles the libsmedia calls of the
144*7c478bd9Sstevel@tonic-gate  * client. In the current implementation the server takes control of the
145*7c478bd9Sstevel@tonic-gate  * number of threads that handle the door calls. This is done by creating the
146*7c478bd9Sstevel@tonic-gate  * door descriptor as DOOR_PRIVATE.
147*7c478bd9Sstevel@tonic-gate  * The server runs only one thread per handle. This makes the implementation
148*7c478bd9Sstevel@tonic-gate  * simple as we do not have to use mutex to make the code MT safe.
149*7c478bd9Sstevel@tonic-gate  * The client_server thread has a data structure door_data_t associated with it.
150*7c478bd9Sstevel@tonic-gate  *
151*7c478bd9Sstevel@tonic-gate  * door_data_t
152*7c478bd9Sstevel@tonic-gate  * -----------
153*7c478bd9Sstevel@tonic-gate  * This is the data structure that is created by the main_server when it
154*7c478bd9Sstevel@tonic-gate  * creates the client_door_descriptor. The door mechanism has a way to associate
155*7c478bd9Sstevel@tonic-gate  * a cookie with the door descriptor. door_data_t is the cookie for the
156*7c478bd9Sstevel@tonic-gate  * client-door_descriptor. This cookie is passed to the server function that
157*7c478bd9Sstevel@tonic-gate  * handles the clinet_door_descriptor calls. In our case it is the client_server
158*7c478bd9Sstevel@tonic-gate  * routine.
159*7c478bd9Sstevel@tonic-gate  * The key elements of the door_data_t are the following:
160*7c478bd9Sstevel@tonic-gate  *
161*7c478bd9Sstevel@tonic-gate  *	dd_fd		file descriptor for the device.
162*7c478bd9Sstevel@tonic-gate  *	dd_buf		The shared memory buffer between client-server.
163*7c478bd9Sstevel@tonic-gate  *	dd_thread	The thread that handles the door_calls.
164*7c478bd9Sstevel@tonic-gate  *
165*7c478bd9Sstevel@tonic-gate  * signal handling:
166*7c478bd9Sstevel@tonic-gate  * ----------------
167*7c478bd9Sstevel@tonic-gate  *		The main purpose of trapping the signals is to exit gracefully
168*7c478bd9Sstevel@tonic-gate  * from the server after recording the appropriate message in the syslog.
169*7c478bd9Sstevel@tonic-gate  * This will help the administrator to determine the cause of failure of the
170*7c478bd9Sstevel@tonic-gate  * server by examining the log file.
171*7c478bd9Sstevel@tonic-gate  *
172*7c478bd9Sstevel@tonic-gate  * cleanup()
173*7c478bd9Sstevel@tonic-gate  * ---------
174*7c478bd9Sstevel@tonic-gate  *	This routine frees up all the resources allocated for the client.
175*7c478bd9Sstevel@tonic-gate  * Resources inlcude the file descriptor, shared memory, threads.
176*7c478bd9Sstevel@tonic-gate  *
177*7c478bd9Sstevel@tonic-gate  * shared memory
178*7c478bd9Sstevel@tonic-gate  * -------------
179*7c478bd9Sstevel@tonic-gate  *	In order to reduce the overheads of moving large amounts of data
180*7c478bd9Sstevel@tonic-gate  * during raw read/write operations, the server uses the mmapped data of
181*7c478bd9Sstevel@tonic-gate  * client. The smedia_raw_read, smedia_raw_write library calls mmap the
182*7c478bd9Sstevel@tonic-gate  * memory and pass on the file descriptor that maps the memory to the server.
183*7c478bd9Sstevel@tonic-gate  * The server subsequently uses this mmapped memory during the IO.
184*7c478bd9Sstevel@tonic-gate  * If the mmapped memory changes in size, the server is informed and it
185*7c478bd9Sstevel@tonic-gate  * remaps the memory to the changed size.
186*7c478bd9Sstevel@tonic-gate  */
187*7c478bd9Sstevel@tonic-gate #ifdef DEBUG
188*7c478bd9Sstevel@tonic-gate #define	DEFAULT_VERBOSE		1
189*7c478bd9Sstevel@tonic-gate #define	DEFAULT_DEBUG		1
190*7c478bd9Sstevel@tonic-gate #else
191*7c478bd9Sstevel@tonic-gate #define	DEFAULT_VERBOSE		0
192*7c478bd9Sstevel@tonic-gate #define	DEFAULT_DEBUG		0
193*7c478bd9Sstevel@tonic-gate #endif
194*7c478bd9Sstevel@tonic-gate 
195*7c478bd9Sstevel@tonic-gate #define	N_BADSIGS		(sizeof (badsigs)/sizeof (badsigs[0]))
196*7c478bd9Sstevel@tonic-gate #define	MD_LEN			30
197*7c478bd9Sstevel@tonic-gate #define	MAXUGNAME		10
198*7c478bd9Sstevel@tonic-gate #define	SVC_CLOSEDOWN 		180
199*7c478bd9Sstevel@tonic-gate 
200*7c478bd9Sstevel@tonic-gate /*
201*7c478bd9Sstevel@tonic-gate  * We will NOT be permitting the following USCI cmd options.
202*7c478bd9Sstevel@tonic-gate  *
203*7c478bd9Sstevel@tonic-gate  * RESET of target
204*7c478bd9Sstevel@tonic-gate  * RESET of  Bus.
205*7c478bd9Sstevel@tonic-gate  * Tagged commands to device
206*7c478bd9Sstevel@tonic-gate  * Explicitly setting SYNC/ASYNC mode of operations.
207*7c478bd9Sstevel@tonic-gate  * POLLED MODE of operation.
208*7c478bd9Sstevel@tonic-gate  * Explicitly setting NO DISCONNECT features.
209*7c478bd9Sstevel@tonic-gate  * use of RESERVED flags.
210*7c478bd9Sstevel@tonic-gate  */
211*7c478bd9Sstevel@tonic-gate #define	FORBIDDEN_FLAGS		(USCSI_RESET | USCSI_RESET_ALL | USCSI_RENEGOT \
212*7c478bd9Sstevel@tonic-gate 				| USCSI_ASYNC  | USCSI_SYNC | USCSI_NOINTR | \
213*7c478bd9Sstevel@tonic-gate 				USCSI_NOTAG | USCSI_NOPARITY | USCSI_NODISCON \
214*7c478bd9Sstevel@tonic-gate 				| USCSI_RESERVED)
215*7c478bd9Sstevel@tonic-gate 
216*7c478bd9Sstevel@tonic-gate /* States a server can be in wrt request */
217*7c478bd9Sstevel@tonic-gate 
218*7c478bd9Sstevel@tonic-gate #define	_IDLE 0
219*7c478bd9Sstevel@tonic-gate #define	_SERVED 1
220*7c478bd9Sstevel@tonic-gate 
221*7c478bd9Sstevel@tonic-gate static char		*prog_name;
222*7c478bd9Sstevel@tonic-gate static int svcstate = _IDLE;	/* Set when a request is serviced */
223*7c478bd9Sstevel@tonic-gate static int svccount = 0;	/* Number of requests being serviced */
224*7c478bd9Sstevel@tonic-gate static int svcstart_level = 0;	/* init level when server was started */
225*7c478bd9Sstevel@tonic-gate static mutex_t svcstate_lock;	/* lock for svcstate, svccount */
226*7c478bd9Sstevel@tonic-gate 
227*7c478bd9Sstevel@tonic-gate extern	void smserverprog_1(struct svc_req *, SVCXPRT *);
228*7c478bd9Sstevel@tonic-gate 
229*7c478bd9Sstevel@tonic-gate /*
230*7c478bd9Sstevel@tonic-gate  * Log messages
231*7c478bd9Sstevel@tonic-gate  */
232*7c478bd9Sstevel@tonic-gate #define	SIGACT_FAILED	"Failed to install signal handler for %s: %s"
233*7c478bd9Sstevel@tonic-gate #define	BADSIG_MSG	"Thread %d Caught signal %d addr=%p trapno=%d pc=%p"
234*7c478bd9Sstevel@tonic-gate 
235*7c478bd9Sstevel@tonic-gate static int	badsigs[] = {SIGSEGV, SIGBUS, SIGFPE, SIGILL};
236*7c478bd9Sstevel@tonic-gate 
237*7c478bd9Sstevel@tonic-gate /* global variables */
238*7c478bd9Sstevel@tonic-gate int		verbose		= DEFAULT_VERBOSE;
239*7c478bd9Sstevel@tonic-gate int		debug_level	= DEFAULT_DEBUG;
240*7c478bd9Sstevel@tonic-gate char		*smediad_devdir = DEFAULT_SMEDIAD_DEVDIR;
241*7c478bd9Sstevel@tonic-gate 
242*7c478bd9Sstevel@tonic-gate thread_key_t	door_key;
243*7c478bd9Sstevel@tonic-gate 
244*7c478bd9Sstevel@tonic-gate server_data_t	server_data;
245*7c478bd9Sstevel@tonic-gate 
246*7c478bd9Sstevel@tonic-gate static int	server_door, server_fd;
247*7c478bd9Sstevel@tonic-gate 
248*7c478bd9Sstevel@tonic-gate static int32_t do_uscsi_cmd(int32_t file, struct uscsi_cmd *uscsi_cmd,
249*7c478bd9Sstevel@tonic-gate 		int32_t flag);
250*7c478bd9Sstevel@tonic-gate static void client_server(void *cookie, char *argp, size_t arg_size,
251*7c478bd9Sstevel@tonic-gate 		door_desc_t *dp, uint_t ndesc);
252*7c478bd9Sstevel@tonic-gate static void cleanup(door_data_t *);
253*7c478bd9Sstevel@tonic-gate static void *init_server(void *);
254*7c478bd9Sstevel@tonic-gate static int32_t scsi_reassign_block(int32_t fd, diskaddr_t);
255*7c478bd9Sstevel@tonic-gate static int32_t get_mode_page(int32_t fd, uchar_t pc, uchar_t page_code,
256*7c478bd9Sstevel@tonic-gate 				uchar_t *md_data, uchar_t data_len);
257*7c478bd9Sstevel@tonic-gate static int32_t get_device_type(char *v_name);
258*7c478bd9Sstevel@tonic-gate static int32_t get_device_type_scsi(int32_t fd, struct scsi_inquiry *inq);
259*7c478bd9Sstevel@tonic-gate 
260*7c478bd9Sstevel@tonic-gate static int32_t scsi_format(int32_t fd, uint_t flavor, uint_t mode);
261*7c478bd9Sstevel@tonic-gate static int32_t scsi_media_status(int32_t fd);
262*7c478bd9Sstevel@tonic-gate static int32_t scsi_write_protect(int32_t fd, smwp_state_t *wp);
263*7c478bd9Sstevel@tonic-gate static int32_t scsi_floppy_media_status(int32_t fd);
264*7c478bd9Sstevel@tonic-gate static int32_t scsi_floppy_write_protect(int32_t fd, smwp_state_t *wp);
265*7c478bd9Sstevel@tonic-gate static int32_t scsi_floppy_format(int32_t, uint_t, uint_t);
266*7c478bd9Sstevel@tonic-gate static int32_t get_floppy_geom(int32_t fd, uint32_t capacity,
267*7c478bd9Sstevel@tonic-gate 			struct dk_geom *dkgeom);
268*7c478bd9Sstevel@tonic-gate static int32_t get_media_capacity(int32_t fd, uint32_t *capacity,
269*7c478bd9Sstevel@tonic-gate 			uint32_t *blocksize);
270*7c478bd9Sstevel@tonic-gate 
271*7c478bd9Sstevel@tonic-gate static int32_t scsi_ls120_format(uint_t fd, uint_t flavor, uint32_t capacity,
272*7c478bd9Sstevel@tonic-gate 			uint32_t blocksize);
273*7c478bd9Sstevel@tonic-gate 
274*7c478bd9Sstevel@tonic-gate static void * my_server_thread(void *arg);
275*7c478bd9Sstevel@tonic-gate static void my_create(door_info_t *dip);
276*7c478bd9Sstevel@tonic-gate static void term_handler(int sig, siginfo_t *siginfo, void *sigctx);
277*7c478bd9Sstevel@tonic-gate static void hup_handler(int sig, siginfo_t *siginfo, void *sigctx);
278*7c478bd9Sstevel@tonic-gate static void sig_handler(int sig, siginfo_t *siginfo, void *sigctx);
279*7c478bd9Sstevel@tonic-gate static void badsig_handler(int sig, siginfo_t *siginfo, void *sigctx);
280*7c478bd9Sstevel@tonic-gate static void server_badsig_handler(int sig, siginfo_t *siginfo, void *sigctx);
281*7c478bd9Sstevel@tonic-gate static char *xlate_state(int32_t);
282*7c478bd9Sstevel@tonic-gate static uint32_t	get_sector_size(int fd);
283*7c478bd9Sstevel@tonic-gate static int32_t raw_read(door_data_t *door_dp, smedia_services_t *req);
284*7c478bd9Sstevel@tonic-gate static int32_t raw_write(door_data_t *door_dp, smedia_services_t *req);
285*7c478bd9Sstevel@tonic-gate static int32_t reassign_block(door_data_t *door_dp, smedia_services_t *req);
286*7c478bd9Sstevel@tonic-gate static int32_t set_protection_status(door_data_t *door_dp,
287*7c478bd9Sstevel@tonic-gate 			smedia_services_t *req);
288*7c478bd9Sstevel@tonic-gate static int32_t set_shfd(door_data_t *door_dp, int32_t fd,
289*7c478bd9Sstevel@tonic-gate 			smedia_services_t *req);
290*7c478bd9Sstevel@tonic-gate 
291*7c478bd9Sstevel@tonic-gate static void door_ret_err(smedia_reterror_t *reterror, int32_t err);
292*7c478bd9Sstevel@tonic-gate static void my_door_return(char *data_ptr, size_t data_size,
293*7c478bd9Sstevel@tonic-gate 			door_desc_t *desc_ptr, uint_t num_desc);
294*7c478bd9Sstevel@tonic-gate static int32_t invalid_uscsi_operation(door_data_t *, struct uscsi_cmd *);
295*7c478bd9Sstevel@tonic-gate 
296*7c478bd9Sstevel@tonic-gate #define	W_E_MASK	0x80
297*7c478bd9Sstevel@tonic-gate 
298*7c478bd9Sstevel@tonic-gate static smserver_info server_info;
299*7c478bd9Sstevel@tonic-gate 
300*7c478bd9Sstevel@tonic-gate static int32_t
301*7c478bd9Sstevel@tonic-gate invalid_uscsi_operation(door_data_t *door_dp, struct uscsi_cmd *ucmd)
302*7c478bd9Sstevel@tonic-gate {
303*7c478bd9Sstevel@tonic-gate 
304*7c478bd9Sstevel@tonic-gate 	if (door_dp->dd_dkinfo.dki_ctype != DKC_CDROM) {
305*7c478bd9Sstevel@tonic-gate 		debug(5,
306*7c478bd9Sstevel@tonic-gate 		"Invalid device type(0x%x) found for uscsi cmd.\n",
307*7c478bd9Sstevel@tonic-gate 			door_dp->dd_dkinfo.dki_ctype);
308*7c478bd9Sstevel@tonic-gate 		errno = EINVAL;
309*7c478bd9Sstevel@tonic-gate 		return (EINVAL);
310*7c478bd9Sstevel@tonic-gate 	}
311*7c478bd9Sstevel@tonic-gate 	if (ucmd->uscsi_flags & FORBIDDEN_FLAGS) {
312*7c478bd9Sstevel@tonic-gate 		debug(5,
313*7c478bd9Sstevel@tonic-gate 		"Invalid flags(0x%x) set in uscsi cmd. cdb[0]=0x%x\n",
314*7c478bd9Sstevel@tonic-gate 		ucmd->uscsi_flags,  ucmd->uscsi_cdb[0]);
315*7c478bd9Sstevel@tonic-gate 		errno = EINVAL;
316*7c478bd9Sstevel@tonic-gate 		return (EINVAL);
317*7c478bd9Sstevel@tonic-gate 	}
318*7c478bd9Sstevel@tonic-gate 	if (ucmd->uscsi_cdb[0] == SCMD_COPY ||
319*7c478bd9Sstevel@tonic-gate 	    ucmd->uscsi_cdb[0] == SCMD_COPY_VERIFY ||
320*7c478bd9Sstevel@tonic-gate 	    ucmd->uscsi_cdb[0] == SCMD_COMPARE ||
321*7c478bd9Sstevel@tonic-gate 	    ucmd->uscsi_cdb[0] == SCMD_WRITE_BUFFER) {
322*7c478bd9Sstevel@tonic-gate 		debug(5,
323*7c478bd9Sstevel@tonic-gate 		"Invalid command(0x%x) found in cdb.\n",
324*7c478bd9Sstevel@tonic-gate 		ucmd->uscsi_cdb[0]);
325*7c478bd9Sstevel@tonic-gate 		errno = EINVAL;
326*7c478bd9Sstevel@tonic-gate 		return (EINVAL);
327*7c478bd9Sstevel@tonic-gate 	}
328*7c478bd9Sstevel@tonic-gate 	return (0);
329*7c478bd9Sstevel@tonic-gate }
330*7c478bd9Sstevel@tonic-gate 
331*7c478bd9Sstevel@tonic-gate static uint32_t
332*7c478bd9Sstevel@tonic-gate get_sector_size(int fd)
333*7c478bd9Sstevel@tonic-gate {
334*7c478bd9Sstevel@tonic-gate 	uint32_t	sector_size;
335*7c478bd9Sstevel@tonic-gate 	struct uscsi_cmd	ucmd;
336*7c478bd9Sstevel@tonic-gate 	union scsi_cdb		cdb;
337*7c478bd9Sstevel@tonic-gate 	int32_t		ret_val;
338*7c478bd9Sstevel@tonic-gate 	uint32_t rc_data[2];
339*7c478bd9Sstevel@tonic-gate 	char rq_data[RQ_LEN];
340*7c478bd9Sstevel@tonic-gate 
341*7c478bd9Sstevel@tonic-gate 	cdb.scc_cmd = SCMD_READ_CAPACITY;
342*7c478bd9Sstevel@tonic-gate 	ucmd.uscsi_cdb = (caddr_t)&cdb;
343*7c478bd9Sstevel@tonic-gate 	ucmd.uscsi_cdblen = CDB_GROUP1;
344*7c478bd9Sstevel@tonic-gate 	ucmd.uscsi_bufaddr = (caddr_t)&rc_data;
345*7c478bd9Sstevel@tonic-gate 	ucmd.uscsi_buflen = sizeof (rc_data);
346*7c478bd9Sstevel@tonic-gate 	ucmd.uscsi_timeout = 120; /* If 0, HBA hangs forever */
347*7c478bd9Sstevel@tonic-gate 	ucmd.uscsi_rqlen = RQ_LEN;
348*7c478bd9Sstevel@tonic-gate 	ucmd.uscsi_rqbuf = rq_data;
349*7c478bd9Sstevel@tonic-gate 
350*7c478bd9Sstevel@tonic-gate 	ret_val = do_uscsi_cmd(fd,
351*7c478bd9Sstevel@tonic-gate 		&ucmd, USCSI_READ|USCSI_RQENABLE);
352*7c478bd9Sstevel@tonic-gate 	if (ret_val || ucmd.uscsi_status) {
353*7c478bd9Sstevel@tonic-gate 		debug(5, "Read capacity : %d - %d errno = %d\n",
354*7c478bd9Sstevel@tonic-gate 			ret_val, ucmd.uscsi_status, errno);
355*7c478bd9Sstevel@tonic-gate 		sector_size = 512;
356*7c478bd9Sstevel@tonic-gate 	} else {
357*7c478bd9Sstevel@tonic-gate 		sector_size = ntohl(rc_data[1]);
358*7c478bd9Sstevel@tonic-gate 	}
359*7c478bd9Sstevel@tonic-gate 	debug(5, "sector size = 0x%x(%d)\n",
360*7c478bd9Sstevel@tonic-gate 		sector_size, sector_size);
361*7c478bd9Sstevel@tonic-gate 	return (sector_size);
362*7c478bd9Sstevel@tonic-gate }
363*7c478bd9Sstevel@tonic-gate 
364*7c478bd9Sstevel@tonic-gate static char *
365*7c478bd9Sstevel@tonic-gate xlate_state(int32_t state)
366*7c478bd9Sstevel@tonic-gate {
367*7c478bd9Sstevel@tonic-gate 	switch (state) {
368*7c478bd9Sstevel@tonic-gate 
369*7c478bd9Sstevel@tonic-gate 	case SM_WRITE_PROTECT_DISABLE:
370*7c478bd9Sstevel@tonic-gate 		return ("PROTECTION_DISABLED");
371*7c478bd9Sstevel@tonic-gate 	case SM_WRITE_PROTECT_PASSWD:
372*7c478bd9Sstevel@tonic-gate 		return ("WRITE_PROTECT_PASSWD");
373*7c478bd9Sstevel@tonic-gate 	case SM_WRITE_PROTECT_NOPASSWD:
374*7c478bd9Sstevel@tonic-gate 		return ("WRITE_PROTECT_NOPASSWD");
375*7c478bd9Sstevel@tonic-gate 	case SM_READ_WRITE_PROTECT:
376*7c478bd9Sstevel@tonic-gate 		return ("READ_WRITE_PROTECT");
377*7c478bd9Sstevel@tonic-gate 	case SM_TEMP_UNLOCK_MODE:
378*7c478bd9Sstevel@tonic-gate 		return ("PROTECTION DISABLED");
379*7c478bd9Sstevel@tonic-gate 	default:
380*7c478bd9Sstevel@tonic-gate 		return ("UNKNOWN_STATE");
381*7c478bd9Sstevel@tonic-gate 	}
382*7c478bd9Sstevel@tonic-gate }
383*7c478bd9Sstevel@tonic-gate 
384*7c478bd9Sstevel@tonic-gate static char *
385*7c478bd9Sstevel@tonic-gate xlate_cnum(smedia_callnumber_t cnum)
386*7c478bd9Sstevel@tonic-gate {
387*7c478bd9Sstevel@tonic-gate 	switch (cnum) {
388*7c478bd9Sstevel@tonic-gate 
389*7c478bd9Sstevel@tonic-gate 	case SMEDIA_CNUM_OPEN_FD:
390*7c478bd9Sstevel@tonic-gate 		return ("SMEDIA_CNUM_OPEN_FD");
391*7c478bd9Sstevel@tonic-gate 	case SMEDIA_CNUM_GET_DEVICE_INFO:
392*7c478bd9Sstevel@tonic-gate 		return ("SMEDIA_CNUM_GET_DEVICE_INFO");
393*7c478bd9Sstevel@tonic-gate 	case SMEDIA_CNUM_GET_MEDIUM_PROPERTY:
394*7c478bd9Sstevel@tonic-gate 		return ("SMEDIA_CNUM_GET_MEDIUM_PROPERTY");
395*7c478bd9Sstevel@tonic-gate 	case SMEDIA_CNUM_GET_PROTECTION_STATUS:
396*7c478bd9Sstevel@tonic-gate 		return ("SMEDIA_CNUM_GET_PROTECTION_STATUS");
397*7c478bd9Sstevel@tonic-gate 	case SMEDIA_CNUM_SET_PROTECTION_STATUS:
398*7c478bd9Sstevel@tonic-gate 		return ("SMEDIA_CNUM_SET_PROTECTION_STATUS");
399*7c478bd9Sstevel@tonic-gate 	case SMEDIA_CNUM_RAW_READ:
400*7c478bd9Sstevel@tonic-gate 		return ("SMEDIA_CNUM_RAW_READ");
401*7c478bd9Sstevel@tonic-gate 	case SMEDIA_CNUM_RAW_WRITE:
402*7c478bd9Sstevel@tonic-gate 		return (" SMEDIA_CNUM_RAW_WRITE");
403*7c478bd9Sstevel@tonic-gate 	case SMEDIA_CNUM_FORMAT:
404*7c478bd9Sstevel@tonic-gate 		return ("SMEDIA_CNUM_FORMAT");
405*7c478bd9Sstevel@tonic-gate 	case SMEDIA_CNUM_CHECK_FORMAT_STATUS:
406*7c478bd9Sstevel@tonic-gate 		return ("SMEDIA_CNUM_CHECK_FORMAT_STATUS");
407*7c478bd9Sstevel@tonic-gate 	case SMEDIA_CNUM_EJECT:
408*7c478bd9Sstevel@tonic-gate 		return ("SMEDIA_CNUM_EJECT");
409*7c478bd9Sstevel@tonic-gate 	case SMEDIA_CNUM_REASSIGN_BLOCK:
410*7c478bd9Sstevel@tonic-gate 		return ("SMEDIA_CNUM_REASSIGN_BLOCK");
411*7c478bd9Sstevel@tonic-gate 	case SMEDIA_CNUM_SET_SHFD:
412*7c478bd9Sstevel@tonic-gate 		return ("SMEDIA_CNUM_SET_SHFD");
413*7c478bd9Sstevel@tonic-gate 	case SMEDIA_CNUM_PING:
414*7c478bd9Sstevel@tonic-gate 		return ("SMEDIA_CNUM_PING");
415*7c478bd9Sstevel@tonic-gate 	case SMEDIA_CNUM_USCSI_CMD:
416*7c478bd9Sstevel@tonic-gate 		return ("SMEDIA_CNUM_USCSI_CMD");
417*7c478bd9Sstevel@tonic-gate 	default:
418*7c478bd9Sstevel@tonic-gate 		return ("UNKNOWN_CNUM");
419*7c478bd9Sstevel@tonic-gate 	}
420*7c478bd9Sstevel@tonic-gate }
421*7c478bd9Sstevel@tonic-gate 
422*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/
423*7c478bd9Sstevel@tonic-gate smserver_info *
424*7c478bd9Sstevel@tonic-gate smserverproc_get_serverinfo_1(void *argp, CLIENT *clnt)
425*7c478bd9Sstevel@tonic-gate {
426*7c478bd9Sstevel@tonic-gate 
427*7c478bd9Sstevel@tonic-gate 	(void) mutex_lock(&svcstate_lock);
428*7c478bd9Sstevel@tonic-gate 	svcstate = _SERVED;
429*7c478bd9Sstevel@tonic-gate 	(void) mutex_unlock(&svcstate_lock);
430*7c478bd9Sstevel@tonic-gate 	server_info.vernum = SMSERVERVERS;
431*7c478bd9Sstevel@tonic-gate 	server_info.status = 0;
432*7c478bd9Sstevel@tonic-gate 	(void) mutex_lock(&server_data.sd_init_lock);
433*7c478bd9Sstevel@tonic-gate 	if (server_data.sd_init_state == INIT_NOT_DONE) {
434*7c478bd9Sstevel@tonic-gate 		server_data.sd_init_state = INIT_IN_PROGRESS;
435*7c478bd9Sstevel@tonic-gate 		debug(5, "Initialising server\n");
436*7c478bd9Sstevel@tonic-gate 		(void) init_server(NULL);
437*7c478bd9Sstevel@tonic-gate 	}
438*7c478bd9Sstevel@tonic-gate 	if (server_data.sd_init_state != INIT_DONE) {
439*7c478bd9Sstevel@tonic-gate 		debug(1,
440*7c478bd9Sstevel@tonic-gate "init_server did not do the job. init_state=%d\n", server_data.sd_init_state);
441*7c478bd9Sstevel@tonic-gate 		server_data.sd_init_state = INIT_NOT_DONE;
442*7c478bd9Sstevel@tonic-gate 		(void) mutex_unlock(&server_data.sd_init_lock);
443*7c478bd9Sstevel@tonic-gate 		server_info.status = -1;
444*7c478bd9Sstevel@tonic-gate 		return (&server_info);
445*7c478bd9Sstevel@tonic-gate 	}
446*7c478bd9Sstevel@tonic-gate 	(void) mutex_unlock(&server_data.sd_init_lock);
447*7c478bd9Sstevel@tonic-gate 
448*7c478bd9Sstevel@tonic-gate 	debug(5, "smserverproc thread %d running....\n", pthread_self());
449*7c478bd9Sstevel@tonic-gate 	return (&server_info);
450*7c478bd9Sstevel@tonic-gate }
451*7c478bd9Sstevel@tonic-gate 
452*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/
453*7c478bd9Sstevel@tonic-gate static void
454*7c478bd9Sstevel@tonic-gate server_badsig_handler(int sig, siginfo_t *siginfo, void *sigctx)
455*7c478bd9Sstevel@tonic-gate {
456*7c478bd9Sstevel@tonic-gate 
457*7c478bd9Sstevel@tonic-gate 	fatal(gettext(BADSIG_MSG), pthread_self(), sig, siginfo->si_addr,
458*7c478bd9Sstevel@tonic-gate 		siginfo->si_trapno,
459*7c478bd9Sstevel@tonic-gate 		siginfo->si_pc);
460*7c478bd9Sstevel@tonic-gate }
461*7c478bd9Sstevel@tonic-gate 
462*7c478bd9Sstevel@tonic-gate static int32_t
463*7c478bd9Sstevel@tonic-gate do_uscsi_cmd(int32_t file, struct uscsi_cmd *uscsi_cmd, int32_t	flag)
464*7c478bd9Sstevel@tonic-gate {
465*7c478bd9Sstevel@tonic-gate 	int32_t	ret_val;
466*7c478bd9Sstevel@tonic-gate 
467*7c478bd9Sstevel@tonic-gate 	/*
468*7c478bd9Sstevel@tonic-gate 	 * Set function flags for driver.
469*7c478bd9Sstevel@tonic-gate 	 */
470*7c478bd9Sstevel@tonic-gate 	uscsi_cmd->uscsi_flags = USCSI_ISOLATE;
471*7c478bd9Sstevel@tonic-gate 
472*7c478bd9Sstevel@tonic-gate #ifdef DEBUG
473*7c478bd9Sstevel@tonic-gate 	uscsi_cmd->uscsi_flags |= USCSI_DIAGNOSE;
474*7c478bd9Sstevel@tonic-gate #else
475*7c478bd9Sstevel@tonic-gate 	uscsi_cmd->uscsi_flags |= USCSI_SILENT;
476*7c478bd9Sstevel@tonic-gate #endif /* DEBUG */
477*7c478bd9Sstevel@tonic-gate 
478*7c478bd9Sstevel@tonic-gate 	uscsi_cmd->uscsi_flags |= flag;
479*7c478bd9Sstevel@tonic-gate 
480*7c478bd9Sstevel@tonic-gate 	errno = 0;
481*7c478bd9Sstevel@tonic-gate 	ret_val = ioctl(file, USCSICMD, uscsi_cmd);
482*7c478bd9Sstevel@tonic-gate 	if (ret_val == 0 && uscsi_cmd->uscsi_status == 0) {
483*7c478bd9Sstevel@tonic-gate 		return (ret_val);
484*7c478bd9Sstevel@tonic-gate 	}
485*7c478bd9Sstevel@tonic-gate 	if (!errno)
486*7c478bd9Sstevel@tonic-gate 		errno = EIO;
487*7c478bd9Sstevel@tonic-gate 	return (-1);
488*7c478bd9Sstevel@tonic-gate }
489*7c478bd9Sstevel@tonic-gate 
490*7c478bd9Sstevel@tonic-gate static int32_t
491*7c478bd9Sstevel@tonic-gate get_device_type(char *v_name)
492*7c478bd9Sstevel@tonic-gate {
493*7c478bd9Sstevel@tonic-gate 	int32_t i;
494*7c478bd9Sstevel@tonic-gate 
495*7c478bd9Sstevel@tonic-gate 	for (i = 0; i < 8; i++) {
496*7c478bd9Sstevel@tonic-gate 		v_name[i] = toupper(v_name[i]);
497*7c478bd9Sstevel@tonic-gate 	}
498*7c478bd9Sstevel@tonic-gate 	if (strstr(v_name, "IOMEGA")) {
499*7c478bd9Sstevel@tonic-gate 		return (SCSI_IOMEGA);
500*7c478bd9Sstevel@tonic-gate 	}
501*7c478bd9Sstevel@tonic-gate 	if (strstr(v_name, "FD") ||
502*7c478bd9Sstevel@tonic-gate 	    strstr(v_name, "LS-120")) {
503*7c478bd9Sstevel@tonic-gate 		return (SCSI_FLOPPY);
504*7c478bd9Sstevel@tonic-gate 	}
505*7c478bd9Sstevel@tonic-gate 	return (SCSI_GENERIC);
506*7c478bd9Sstevel@tonic-gate 
507*7c478bd9Sstevel@tonic-gate }
508*7c478bd9Sstevel@tonic-gate 
509*7c478bd9Sstevel@tonic-gate static int32_t
510*7c478bd9Sstevel@tonic-gate get_device_type_scsi(int32_t fd, struct scsi_inquiry *inq)
511*7c478bd9Sstevel@tonic-gate {
512*7c478bd9Sstevel@tonic-gate 	int32_t dev_type;
513*7c478bd9Sstevel@tonic-gate 	struct uscsi_cmd ucmd;
514*7c478bd9Sstevel@tonic-gate 	union scsi_cdb  cdb;
515*7c478bd9Sstevel@tonic-gate 	int32_t	ret_val;
516*7c478bd9Sstevel@tonic-gate 	char rq_data[RQ_LEN];
517*7c478bd9Sstevel@tonic-gate 
518*7c478bd9Sstevel@tonic-gate 	(void) memset((void *) inq, 0, sizeof (struct scsi_inquiry));
519*7c478bd9Sstevel@tonic-gate 	(void) memset((void *) &ucmd, 0, sizeof (ucmd));
520*7c478bd9Sstevel@tonic-gate 	(void) memset((void *) &cdb, 0, sizeof (union scsi_cdb));
521*7c478bd9Sstevel@tonic-gate 	cdb.scc_cmd = SCMD_INQUIRY;
522*7c478bd9Sstevel@tonic-gate 	FORMG0COUNT(&cdb, sizeof (struct scsi_inquiry));
523*7c478bd9Sstevel@tonic-gate 	ucmd.uscsi_cdb = (caddr_t)&cdb;
524*7c478bd9Sstevel@tonic-gate 	ucmd.uscsi_cdblen = CDB_GROUP0;
525*7c478bd9Sstevel@tonic-gate 	ucmd.uscsi_bufaddr = (caddr_t)inq;
526*7c478bd9Sstevel@tonic-gate 	ucmd.uscsi_buflen = sizeof (struct scsi_inquiry);
527*7c478bd9Sstevel@tonic-gate 	ucmd.uscsi_timeout = 120;	/* If 0, HBA hangs forever */
528*7c478bd9Sstevel@tonic-gate 	ucmd.uscsi_rqlen = RQ_LEN;
529*7c478bd9Sstevel@tonic-gate 	ucmd.uscsi_rqbuf = rq_data;
530*7c478bd9Sstevel@tonic-gate 	ret_val = do_uscsi_cmd(fd, &ucmd, USCSI_READ|USCSI_RQENABLE);
531*7c478bd9Sstevel@tonic-gate 	if (ret_val || ucmd.uscsi_status) {
532*7c478bd9Sstevel@tonic-gate 		debug(5, "inquiry failed: %d - %d errno = %d\n",
533*7c478bd9Sstevel@tonic-gate 			ret_val, ucmd.uscsi_status, errno);
534*7c478bd9Sstevel@tonic-gate 		return (-1);
535*7c478bd9Sstevel@tonic-gate 	}
536*7c478bd9Sstevel@tonic-gate 
537*7c478bd9Sstevel@tonic-gate 	dev_type = get_device_type(inq->inq_vid);
538*7c478bd9Sstevel@tonic-gate 
539*7c478bd9Sstevel@tonic-gate 	debug(5, "dev_type %d\n", dev_type);
540*7c478bd9Sstevel@tonic-gate 	return (dev_type);
541*7c478bd9Sstevel@tonic-gate 
542*7c478bd9Sstevel@tonic-gate }
543*7c478bd9Sstevel@tonic-gate 
544*7c478bd9Sstevel@tonic-gate static int32_t
545*7c478bd9Sstevel@tonic-gate get_media_capacity(int32_t fd, uint32_t *capacity, uint32_t *blocksize)
546*7c478bd9Sstevel@tonic-gate {
547*7c478bd9Sstevel@tonic-gate 	struct uscsi_cmd ucmd;
548*7c478bd9Sstevel@tonic-gate 	uchar_t cdb[12];
549*7c478bd9Sstevel@tonic-gate 	int32_t ret_val;
550*7c478bd9Sstevel@tonic-gate 	uchar_t data[20];
551*7c478bd9Sstevel@tonic-gate 	char rq_data[RQ_LEN];
552*7c478bd9Sstevel@tonic-gate 
553*7c478bd9Sstevel@tonic-gate 	debug(5, "get_media_capacity:\n");
554*7c478bd9Sstevel@tonic-gate 
555*7c478bd9Sstevel@tonic-gate 	(void) memset((void *)&data, 0, sizeof (data));
556*7c478bd9Sstevel@tonic-gate 	(void) memset((void *)&ucmd, 0, sizeof (ucmd));
557*7c478bd9Sstevel@tonic-gate 	(void) memset((void *)&cdb, 0, sizeof (cdb));
558*7c478bd9Sstevel@tonic-gate 
559*7c478bd9Sstevel@tonic-gate 	/* retrieve size discriptor of inserted media */
560*7c478bd9Sstevel@tonic-gate 	cdb[0] = SCMD_READ_FORMAT_CAP;
561*7c478bd9Sstevel@tonic-gate 	cdb[8] = 0x14;  /* data size */
562*7c478bd9Sstevel@tonic-gate 
563*7c478bd9Sstevel@tonic-gate 	/* Fill in the USCSI fields */
564*7c478bd9Sstevel@tonic-gate 	ucmd.uscsi_cdb = (caddr_t)&cdb;
565*7c478bd9Sstevel@tonic-gate 	ucmd.uscsi_cdblen = CDB_GROUP5;
566*7c478bd9Sstevel@tonic-gate 	ucmd.uscsi_bufaddr = (caddr_t)data;
567*7c478bd9Sstevel@tonic-gate 	ucmd.uscsi_buflen = sizeof (data);
568*7c478bd9Sstevel@tonic-gate 	ucmd.uscsi_timeout = 120;
569*7c478bd9Sstevel@tonic-gate 	ucmd.uscsi_rqlen = RQ_LEN;
570*7c478bd9Sstevel@tonic-gate 	ucmd.uscsi_rqbuf = rq_data;
571*7c478bd9Sstevel@tonic-gate 	ret_val = do_uscsi_cmd(fd, &ucmd, USCSI_READ|USCSI_RQENABLE);
572*7c478bd9Sstevel@tonic-gate 
573*7c478bd9Sstevel@tonic-gate 	if (ret_val || ucmd.uscsi_status) {
574*7c478bd9Sstevel@tonic-gate 		debug(5, "Retrieving media info failed: %d - %d\n", ret_val,
575*7c478bd9Sstevel@tonic-gate 		    ucmd.uscsi_status);
576*7c478bd9Sstevel@tonic-gate 
577*7c478bd9Sstevel@tonic-gate 		if ((rq_data[2] == KEY_DATA_PROTECT) && (rq_data[12] == 0x30) &&
578*7c478bd9Sstevel@tonic-gate 		    (rq_data[13] == 0)) {
579*7c478bd9Sstevel@tonic-gate 			(void) debug(1, "Invalid command for media\n");
580*7c478bd9Sstevel@tonic-gate 			errno = EINVAL;
581*7c478bd9Sstevel@tonic-gate 		}
582*7c478bd9Sstevel@tonic-gate 		return (-1);
583*7c478bd9Sstevel@tonic-gate 	}
584*7c478bd9Sstevel@tonic-gate 
585*7c478bd9Sstevel@tonic-gate 	/* No media, bail out */
586*7c478bd9Sstevel@tonic-gate 	if (data[8] == 0x3) {
587*7c478bd9Sstevel@tonic-gate 		(void) debug(5, "no media in drive\n");
588*7c478bd9Sstevel@tonic-gate 		return (-1);
589*7c478bd9Sstevel@tonic-gate 	}
590*7c478bd9Sstevel@tonic-gate 
591*7c478bd9Sstevel@tonic-gate 	/*
592*7c478bd9Sstevel@tonic-gate 	 * Generate capacity and blocksize information
593*7c478bd9Sstevel@tonic-gate 	 */
594*7c478bd9Sstevel@tonic-gate 
595*7c478bd9Sstevel@tonic-gate 	*capacity =  (uint32_t)((data[4] << 24) + (data[5] << 16) +
596*7c478bd9Sstevel@tonic-gate 	    (data[6] << 8) + data[7]);
597*7c478bd9Sstevel@tonic-gate 
598*7c478bd9Sstevel@tonic-gate 	debug(1, "capacity is %x %x %x %x = %x", data[4], data[5], data[6],
599*7c478bd9Sstevel@tonic-gate 	    data[7], *capacity);
600*7c478bd9Sstevel@tonic-gate 
601*7c478bd9Sstevel@tonic-gate 	*blocksize = (uint32_t)((data[9] << 16) + (data[10] << 8) + data[11]);
602*7c478bd9Sstevel@tonic-gate 
603*7c478bd9Sstevel@tonic-gate 	return (0);
604*7c478bd9Sstevel@tonic-gate }
605*7c478bd9Sstevel@tonic-gate 
606*7c478bd9Sstevel@tonic-gate static int32_t
607*7c478bd9Sstevel@tonic-gate scsi_zip_format(int32_t fd, uint_t flavor, uint_t mode)
608*7c478bd9Sstevel@tonic-gate {
609*7c478bd9Sstevel@tonic-gate 	struct uscsi_cmd ucmd;
610*7c478bd9Sstevel@tonic-gate 	struct scsi_inquiry inq;
611*7c478bd9Sstevel@tonic-gate 	uchar_t cdb[12];
612*7c478bd9Sstevel@tonic-gate 	int32_t   ret_val;
613*7c478bd9Sstevel@tonic-gate 	uchar_t data[4];
614*7c478bd9Sstevel@tonic-gate 	uint32_t rc_data[2];
615*7c478bd9Sstevel@tonic-gate 	char rq_data[RQ_LEN];
616*7c478bd9Sstevel@tonic-gate 	uint32_t capacity;
617*7c478bd9Sstevel@tonic-gate 
618*7c478bd9Sstevel@tonic-gate 
619*7c478bd9Sstevel@tonic-gate 	if ((mode != SM_FORMAT_IMMEDIATE) &&
620*7c478bd9Sstevel@tonic-gate 		(mode != SM_FORMAT_BLOCKED)) {
621*7c478bd9Sstevel@tonic-gate 		errno = ENOTSUP;
622*7c478bd9Sstevel@tonic-gate 		return (ENOTSUP);
623*7c478bd9Sstevel@tonic-gate 	}
624*7c478bd9Sstevel@tonic-gate 	/*
625*7c478bd9Sstevel@tonic-gate 	 * Do an inquiry and try to figure out if it an
626*7c478bd9Sstevel@tonic-gate 	 * IOMEGA JAZ 2GB device.
627*7c478bd9Sstevel@tonic-gate 	 */
628*7c478bd9Sstevel@tonic-gate 
629*7c478bd9Sstevel@tonic-gate 	(void) memset((void *) &inq, 0, sizeof (inq));
630*7c478bd9Sstevel@tonic-gate 	(void) memset((void *) &ucmd, 0, sizeof (ucmd));
631*7c478bd9Sstevel@tonic-gate 	(void) memset((void *) &cdb, 0, sizeof (cdb));
632*7c478bd9Sstevel@tonic-gate 	(void) memset((void *) &rq_data, 0, sizeof (rq_data));
633*7c478bd9Sstevel@tonic-gate 	cdb[0] = SCMD_INQUIRY;
634*7c478bd9Sstevel@tonic-gate 	cdb[4] = sizeof (inq);
635*7c478bd9Sstevel@tonic-gate 	ucmd.uscsi_cdb = (caddr_t)&cdb;
636*7c478bd9Sstevel@tonic-gate 	ucmd.uscsi_cdblen = CDB_GROUP0;
637*7c478bd9Sstevel@tonic-gate 	ucmd.uscsi_bufaddr = (caddr_t)&inq;
638*7c478bd9Sstevel@tonic-gate 	ucmd.uscsi_buflen = sizeof (inq);
639*7c478bd9Sstevel@tonic-gate 	ucmd.uscsi_timeout = 120;	/* If 0, HBA hangs forever */
640*7c478bd9Sstevel@tonic-gate 	ucmd.uscsi_rqlen = RQ_LEN;
641*7c478bd9Sstevel@tonic-gate 	ucmd.uscsi_rqbuf = rq_data;
642*7c478bd9Sstevel@tonic-gate 	ret_val = do_uscsi_cmd(fd, &ucmd, USCSI_READ|USCSI_RQENABLE);
643*7c478bd9Sstevel@tonic-gate 	if (ret_val || ucmd.uscsi_status) {
644*7c478bd9Sstevel@tonic-gate 		debug(5, "inquiry failed: %d - %d errno = %d\n",
645*7c478bd9Sstevel@tonic-gate 			ret_val, ucmd.uscsi_status, errno);
646*7c478bd9Sstevel@tonic-gate 		return (ucmd.uscsi_status);
647*7c478bd9Sstevel@tonic-gate 	}
648*7c478bd9Sstevel@tonic-gate 
649*7c478bd9Sstevel@tonic-gate 	(void) memset((void *) &rc_data, 0, sizeof (rc_data));
650*7c478bd9Sstevel@tonic-gate 	(void) memset((void *) &ucmd, 0, sizeof (ucmd));
651*7c478bd9Sstevel@tonic-gate 	(void) memset((void *) &cdb, 0, sizeof (cdb));
652*7c478bd9Sstevel@tonic-gate 	cdb[0] = SCMD_READ_CAPACITY;
653*7c478bd9Sstevel@tonic-gate 	ucmd.uscsi_cdb = (caddr_t)&cdb;
654*7c478bd9Sstevel@tonic-gate 	ucmd.uscsi_cdblen = CDB_GROUP1;
655*7c478bd9Sstevel@tonic-gate 	ucmd.uscsi_bufaddr = (caddr_t)&rc_data;
656*7c478bd9Sstevel@tonic-gate 	ucmd.uscsi_buflen = sizeof (rc_data);
657*7c478bd9Sstevel@tonic-gate 	ucmd.uscsi_timeout = 120;	/* If 0, HBA hangs forever */
658*7c478bd9Sstevel@tonic-gate 
659*7c478bd9Sstevel@tonic-gate 	ret_val = do_uscsi_cmd(fd, &ucmd, USCSI_READ);
660*7c478bd9Sstevel@tonic-gate 	if (ret_val || ucmd.uscsi_status) {
661*7c478bd9Sstevel@tonic-gate 		debug(5, "Read capacity : %d - %d errno = %d\n",
662*7c478bd9Sstevel@tonic-gate 			ret_val, ucmd.uscsi_status, errno);
663*7c478bd9Sstevel@tonic-gate 		return (ucmd.uscsi_status);
664*7c478bd9Sstevel@tonic-gate 	}
665*7c478bd9Sstevel@tonic-gate 
666*7c478bd9Sstevel@tonic-gate 	capacity = ntohl(rc_data[0]);
667*7c478bd9Sstevel@tonic-gate 
668*7c478bd9Sstevel@tonic-gate 	(void) memset((void *)&data, 0, sizeof (data));
669*7c478bd9Sstevel@tonic-gate 	(void) memset((void *)&ucmd, 0, sizeof (ucmd));
670*7c478bd9Sstevel@tonic-gate 	(void) memset((void *)&cdb, 0, sizeof (cdb));
671*7c478bd9Sstevel@tonic-gate 	cdb[0] =  SCMD_FORMAT;
672*7c478bd9Sstevel@tonic-gate 	/*
673*7c478bd9Sstevel@tonic-gate 	 * Defect list sent by initiator is a complete list of defects.
674*7c478bd9Sstevel@tonic-gate 	 */
675*7c478bd9Sstevel@tonic-gate 	cdb[1] = (FMTDATA | CMPLIST);
676*7c478bd9Sstevel@tonic-gate 	/*
677*7c478bd9Sstevel@tonic-gate 	 * Target should examine the setting of the DPRY, DCRT, STPF, IP
678*7c478bd9Sstevel@tonic-gate 	 * and DSP bits.
679*7c478bd9Sstevel@tonic-gate 	 */
680*7c478bd9Sstevel@tonic-gate 	data[1] = FOV;
681*7c478bd9Sstevel@tonic-gate 
682*7c478bd9Sstevel@tonic-gate 	switch (flavor) {
683*7c478bd9Sstevel@tonic-gate 		case SM_FORMAT_QUICK :
684*7c478bd9Sstevel@tonic-gate 			/*
685*7c478bd9Sstevel@tonic-gate 			 * Target should not perform any vendor specific
686*7c478bd9Sstevel@tonic-gate 			 * medium certification process or format verification
687*7c478bd9Sstevel@tonic-gate 			 */
688*7c478bd9Sstevel@tonic-gate 			data[1] = (FOV | DCRT);
689*7c478bd9Sstevel@tonic-gate 			/*
690*7c478bd9Sstevel@tonic-gate 			 * Defect list sent is an addition to the existing
691*7c478bd9Sstevel@tonic-gate 			 * list of defects.
692*7c478bd9Sstevel@tonic-gate 			 */
693*7c478bd9Sstevel@tonic-gate 			cdb[1] =  FMTDATA;
694*7c478bd9Sstevel@tonic-gate 			break;
695*7c478bd9Sstevel@tonic-gate 		case SM_FORMAT_FORCE :
696*7c478bd9Sstevel@tonic-gate 			if (strstr(inq.inq_pid, "jaz")) {
697*7c478bd9Sstevel@tonic-gate 				debug(1,
698*7c478bd9Sstevel@tonic-gate 				"LONG Format of JAZ media not supported\n");
699*7c478bd9Sstevel@tonic-gate 				errno = ENOTSUP;
700*7c478bd9Sstevel@tonic-gate 				return (ENOTSUP);
701*7c478bd9Sstevel@tonic-gate 			}
702*7c478bd9Sstevel@tonic-gate 			/*
703*7c478bd9Sstevel@tonic-gate 			 * Formatting a write-protected or read/write
704*7c478bd9Sstevel@tonic-gate 			 * protected cartridge is allowed.
705*7c478bd9Sstevel@tonic-gate 			 * This is a vendor specific Format Option.
706*7c478bd9Sstevel@tonic-gate 			 */
707*7c478bd9Sstevel@tonic-gate 			cdb[2] = 0x20;
708*7c478bd9Sstevel@tonic-gate 			break;
709*7c478bd9Sstevel@tonic-gate 		case SM_FORMAT_LONG :
710*7c478bd9Sstevel@tonic-gate 			if (strstr(inq.inq_pid, "jaz")) {
711*7c478bd9Sstevel@tonic-gate 				debug(1,
712*7c478bd9Sstevel@tonic-gate 				"LONG Format of JAZ media not supported\n");
713*7c478bd9Sstevel@tonic-gate 				errno = ENOTSUP;
714*7c478bd9Sstevel@tonic-gate 				return (ENOTSUP);
715*7c478bd9Sstevel@tonic-gate 			}
716*7c478bd9Sstevel@tonic-gate 			/*
717*7c478bd9Sstevel@tonic-gate 			 * Defect list sent is an addition to the existing
718*7c478bd9Sstevel@tonic-gate 			 * list of defects.
719*7c478bd9Sstevel@tonic-gate 			 */
720*7c478bd9Sstevel@tonic-gate 			cdb[1] = FMTDATA;
721*7c478bd9Sstevel@tonic-gate 			break;
722*7c478bd9Sstevel@tonic-gate 		default :
723*7c478bd9Sstevel@tonic-gate 			debug(1, "Format option %d not supported!!\n",
724*7c478bd9Sstevel@tonic-gate 			flavor);
725*7c478bd9Sstevel@tonic-gate 			errno = ENOTSUP;
726*7c478bd9Sstevel@tonic-gate 			return (ENOTSUP);
727*7c478bd9Sstevel@tonic-gate 	}
728*7c478bd9Sstevel@tonic-gate 
729*7c478bd9Sstevel@tonic-gate 	if (mode == SM_FORMAT_IMMEDIATE) {
730*7c478bd9Sstevel@tonic-gate 		data[1] |= IMMED;
731*7c478bd9Sstevel@tonic-gate 		debug(5, "immediate_flag set\n");
732*7c478bd9Sstevel@tonic-gate 	}
733*7c478bd9Sstevel@tonic-gate 
734*7c478bd9Sstevel@tonic-gate 	ucmd.uscsi_cdb = (caddr_t)&cdb;
735*7c478bd9Sstevel@tonic-gate 	debug(5, "cdb: %x ", cdb[0]);
736*7c478bd9Sstevel@tonic-gate 	debug(5, "%x %x ", cdb[1], cdb[2]);
737*7c478bd9Sstevel@tonic-gate 	debug(5, "%x %x %x\n", cdb[3], cdb[4], cdb[5]);
738*7c478bd9Sstevel@tonic-gate 	debug(5, "data: %x %x %x %x\n", data[0], data[1], data[2], data[3]);
739*7c478bd9Sstevel@tonic-gate 
740*7c478bd9Sstevel@tonic-gate 	ucmd.uscsi_cdblen = CDB_GROUP0;
741*7c478bd9Sstevel@tonic-gate 	ucmd.uscsi_bufaddr = (caddr_t)data;
742*7c478bd9Sstevel@tonic-gate 	ucmd.uscsi_buflen = sizeof (data);
743*7c478bd9Sstevel@tonic-gate 	ucmd.uscsi_timeout = FORMAT_TIMEOUT(capacity);
744*7c478bd9Sstevel@tonic-gate 	ucmd.uscsi_rqlen = RQ_LEN;
745*7c478bd9Sstevel@tonic-gate 	ucmd.uscsi_rqbuf = rq_data;
746*7c478bd9Sstevel@tonic-gate 	ret_val = do_uscsi_cmd(fd, &ucmd, USCSI_WRITE|USCSI_RQENABLE);
747*7c478bd9Sstevel@tonic-gate 	if (ret_val || ucmd.uscsi_status) {
748*7c478bd9Sstevel@tonic-gate 		debug(5, "Format failed : %d - uscsi_status = %d errno = %d\n",
749*7c478bd9Sstevel@tonic-gate 			ret_val,
750*7c478bd9Sstevel@tonic-gate 			ucmd.uscsi_status, errno);
751*7c478bd9Sstevel@tonic-gate 		if ((rq_data[2] == KEY_DATA_PROTECT) ||
752*7c478bd9Sstevel@tonic-gate 			(rq_data[2] == KEY_ILLEGAL_REQUEST))
753*7c478bd9Sstevel@tonic-gate 			errno = EINVAL;
754*7c478bd9Sstevel@tonic-gate 		if ((rq_data[2] == KEY_MEDIUM_ERROR) ||
755*7c478bd9Sstevel@tonic-gate 			(rq_data[2] == KEY_HARDWARE_ERROR))
756*7c478bd9Sstevel@tonic-gate 			errno = EIO;
757*7c478bd9Sstevel@tonic-gate 		return (errno);
758*7c478bd9Sstevel@tonic-gate 	}
759*7c478bd9Sstevel@tonic-gate 
760*7c478bd9Sstevel@tonic-gate 	return (0);
761*7c478bd9Sstevel@tonic-gate }
762*7c478bd9Sstevel@tonic-gate 
763*7c478bd9Sstevel@tonic-gate static int32_t
764*7c478bd9Sstevel@tonic-gate scsi_ls120_format(uint_t fd, uint_t flavor, uint32_t capacity,
765*7c478bd9Sstevel@tonic-gate     uint32_t blocksize)
766*7c478bd9Sstevel@tonic-gate {
767*7c478bd9Sstevel@tonic-gate 	struct uscsi_cmd ucmd;
768*7c478bd9Sstevel@tonic-gate 	uchar_t cdb[12];
769*7c478bd9Sstevel@tonic-gate 	int32_t ret_val;
770*7c478bd9Sstevel@tonic-gate 	uchar_t data[12];
771*7c478bd9Sstevel@tonic-gate 	char	rq_data[RQ_LEN];
772*7c478bd9Sstevel@tonic-gate 
773*7c478bd9Sstevel@tonic-gate 	debug(5, "scsi_ls120_format:\n");
774*7c478bd9Sstevel@tonic-gate 
775*7c478bd9Sstevel@tonic-gate 	(void) memset((void *) &ucmd, 0, sizeof (ucmd));
776*7c478bd9Sstevel@tonic-gate 	(void) memset((void *) &cdb, 0, sizeof (cdb));
777*7c478bd9Sstevel@tonic-gate 	(void) memset((void *) &rq_data, 0, sizeof (rq_data));
778*7c478bd9Sstevel@tonic-gate 
779*7c478bd9Sstevel@tonic-gate 	cdb[0] = SCMD_FORMAT;
780*7c478bd9Sstevel@tonic-gate 	cdb[1] = (FMTDATA | 0x7);
781*7c478bd9Sstevel@tonic-gate 	cdb[8] = 0x0C; /* parameter list length */
782*7c478bd9Sstevel@tonic-gate 
783*7c478bd9Sstevel@tonic-gate 	data[1] = 0x80;
784*7c478bd9Sstevel@tonic-gate 	data[3] = 0x08;
785*7c478bd9Sstevel@tonic-gate 
786*7c478bd9Sstevel@tonic-gate 
787*7c478bd9Sstevel@tonic-gate 	data[4] = (capacity >> 24) & 0xff;
788*7c478bd9Sstevel@tonic-gate 	data[5] = (capacity >> 16) & 0xff;
789*7c478bd9Sstevel@tonic-gate 	data[6] = (capacity >> 8) & 0xff;
790*7c478bd9Sstevel@tonic-gate 	data[7] = capacity & 0xff;
791*7c478bd9Sstevel@tonic-gate 
792*7c478bd9Sstevel@tonic-gate 
793*7c478bd9Sstevel@tonic-gate 	data[9] =  (blocksize >> 16) & 0xff;
794*7c478bd9Sstevel@tonic-gate 	data[10] = (blocksize >> 8) & 0xff;
795*7c478bd9Sstevel@tonic-gate 	data[11] = blocksize & 0xff;
796*7c478bd9Sstevel@tonic-gate 
797*7c478bd9Sstevel@tonic-gate 	debug(5, "cdb: %x %x %x ... %x", cdb[0], cdb[1], cdb[2], cdb[8]);
798*7c478bd9Sstevel@tonic-gate 	debug(5, "data: %x %x %x %x\n", data[0], data[1], data[2], data[3]);
799*7c478bd9Sstevel@tonic-gate 	debug(5, "    : %x %x %x %x\n", data[4], data[5], data[6], data[7]);
800*7c478bd9Sstevel@tonic-gate 	debug(5, "    : %x %x %x %x\n", data[8], data[9], data[10], data[11]);
801*7c478bd9Sstevel@tonic-gate 
802*7c478bd9Sstevel@tonic-gate 	switch (flavor) {
803*7c478bd9Sstevel@tonic-gate 		case SM_FORMAT_QUICK :
804*7c478bd9Sstevel@tonic-gate 			debug(1, "Format not supported\n");
805*7c478bd9Sstevel@tonic-gate 			errno = ENOTSUP;
806*7c478bd9Sstevel@tonic-gate 			return (-1);
807*7c478bd9Sstevel@tonic-gate 		case SM_FORMAT_FORCE :
808*7c478bd9Sstevel@tonic-gate 			break;
809*7c478bd9Sstevel@tonic-gate 		case SM_FORMAT_LONG :
810*7c478bd9Sstevel@tonic-gate 			break;
811*7c478bd9Sstevel@tonic-gate 		default :
812*7c478bd9Sstevel@tonic-gate 			debug(1, "Format option not specified!!\n");
813*7c478bd9Sstevel@tonic-gate 			errno = ENOTSUP;
814*7c478bd9Sstevel@tonic-gate 			return (-1);
815*7c478bd9Sstevel@tonic-gate 	}
816*7c478bd9Sstevel@tonic-gate 
817*7c478bd9Sstevel@tonic-gate 	ucmd.uscsi_cdb = (caddr_t)&cdb;
818*7c478bd9Sstevel@tonic-gate 
819*7c478bd9Sstevel@tonic-gate 
820*7c478bd9Sstevel@tonic-gate 	ucmd.uscsi_cdblen = CDB_GROUP5;
821*7c478bd9Sstevel@tonic-gate 	ucmd.uscsi_bufaddr = (caddr_t)data;
822*7c478bd9Sstevel@tonic-gate 	ucmd.uscsi_buflen = sizeof (data);
823*7c478bd9Sstevel@tonic-gate 	ucmd.uscsi_timeout = 0x12c0;
824*7c478bd9Sstevel@tonic-gate 	ucmd.uscsi_rqlen = RQ_LEN;
825*7c478bd9Sstevel@tonic-gate 	ucmd.uscsi_rqbuf = rq_data;
826*7c478bd9Sstevel@tonic-gate 	(void) fflush(stdout);
827*7c478bd9Sstevel@tonic-gate 
828*7c478bd9Sstevel@tonic-gate 	ret_val = do_uscsi_cmd(fd, &ucmd, USCSI_WRITE|USCSI_RQENABLE);
829*7c478bd9Sstevel@tonic-gate 	if (ret_val || ucmd.uscsi_status) {
830*7c478bd9Sstevel@tonic-gate 		debug(1, "Format failed failed: %d - %d\n", ret_val,
831*7c478bd9Sstevel@tonic-gate 		    ucmd.uscsi_status);
832*7c478bd9Sstevel@tonic-gate 
833*7c478bd9Sstevel@tonic-gate 		if ((rq_data[2] == KEY_DATA_PROTECT) &&
834*7c478bd9Sstevel@tonic-gate 		    (rq_data[12] == 0x30) && (rq_data[13] == 0)) {
835*7c478bd9Sstevel@tonic-gate 
836*7c478bd9Sstevel@tonic-gate 			debug(1, "Invalid command for media\n");
837*7c478bd9Sstevel@tonic-gate 			errno = EINVAL;
838*7c478bd9Sstevel@tonic-gate 		}
839*7c478bd9Sstevel@tonic-gate 
840*7c478bd9Sstevel@tonic-gate 		if ((rq_data[2] == KEY_NOT_READY) && (rq_data[12] == 0x30)) {
841*7c478bd9Sstevel@tonic-gate 			debug(1, "Incompatible media.\n");
842*7c478bd9Sstevel@tonic-gate 			errno = EINVAL;
843*7c478bd9Sstevel@tonic-gate 		}
844*7c478bd9Sstevel@tonic-gate 
845*7c478bd9Sstevel@tonic-gate 		return (-1);
846*7c478bd9Sstevel@tonic-gate 	}
847*7c478bd9Sstevel@tonic-gate 
848*7c478bd9Sstevel@tonic-gate 	return (0);
849*7c478bd9Sstevel@tonic-gate }
850*7c478bd9Sstevel@tonic-gate 
851*7c478bd9Sstevel@tonic-gate static int32_t
852*7c478bd9Sstevel@tonic-gate scsi_format(int32_t fd, uint_t flavor, uint_t mode)
853*7c478bd9Sstevel@tonic-gate {
854*7c478bd9Sstevel@tonic-gate 	struct uscsi_cmd ucmd;
855*7c478bd9Sstevel@tonic-gate 	struct scsi_inquiry inq;
856*7c478bd9Sstevel@tonic-gate 	uchar_t cdb[12];
857*7c478bd9Sstevel@tonic-gate 	int32_t   ret_val;
858*7c478bd9Sstevel@tonic-gate 	uchar_t data[4];
859*7c478bd9Sstevel@tonic-gate 	char rq_data[RQ_LEN];
860*7c478bd9Sstevel@tonic-gate 	uint32_t rc_data[2];
861*7c478bd9Sstevel@tonic-gate 	uint32_t capacity;
862*7c478bd9Sstevel@tonic-gate 
863*7c478bd9Sstevel@tonic-gate 
864*7c478bd9Sstevel@tonic-gate 
865*7c478bd9Sstevel@tonic-gate 	if ((mode != SM_FORMAT_IMMEDIATE) &&
866*7c478bd9Sstevel@tonic-gate 		(mode != SM_FORMAT_BLOCKED)) {
867*7c478bd9Sstevel@tonic-gate 		errno = ENOTSUP;
868*7c478bd9Sstevel@tonic-gate 		return (-1);
869*7c478bd9Sstevel@tonic-gate 	}
870*7c478bd9Sstevel@tonic-gate 
871*7c478bd9Sstevel@tonic-gate 	/*
872*7c478bd9Sstevel@tonic-gate 	 * Do an inquiry and try to figure out if it an
873*7c478bd9Sstevel@tonic-gate 	 * IOMEGA JAZ 2GB device.
874*7c478bd9Sstevel@tonic-gate 	 */
875*7c478bd9Sstevel@tonic-gate 
876*7c478bd9Sstevel@tonic-gate 	(void) memset((void *) &inq, 0, sizeof (inq));
877*7c478bd9Sstevel@tonic-gate 	(void) memset((void *) &ucmd, 0, sizeof (ucmd));
878*7c478bd9Sstevel@tonic-gate 	(void) memset((void *) &cdb, 0, sizeof (cdb));
879*7c478bd9Sstevel@tonic-gate 	(void) memset((void *) &rq_data, 0, sizeof (rq_data));
880*7c478bd9Sstevel@tonic-gate 	cdb[0] = SCMD_INQUIRY;
881*7c478bd9Sstevel@tonic-gate 	cdb[4] = sizeof (inq);
882*7c478bd9Sstevel@tonic-gate 	ucmd.uscsi_cdb = (caddr_t)&cdb;
883*7c478bd9Sstevel@tonic-gate 	ucmd.uscsi_cdblen = CDB_GROUP0;
884*7c478bd9Sstevel@tonic-gate 	ucmd.uscsi_bufaddr = (caddr_t)&inq;
885*7c478bd9Sstevel@tonic-gate 	ucmd.uscsi_buflen = sizeof (inq);
886*7c478bd9Sstevel@tonic-gate 	ucmd.uscsi_timeout = 120;	/* If 0, HBA hangs forever */
887*7c478bd9Sstevel@tonic-gate 	ucmd.uscsi_rqlen = RQ_LEN;
888*7c478bd9Sstevel@tonic-gate 	ucmd.uscsi_rqbuf = rq_data;
889*7c478bd9Sstevel@tonic-gate 	ret_val = do_uscsi_cmd(fd, &ucmd, USCSI_READ|USCSI_RQENABLE);
890*7c478bd9Sstevel@tonic-gate 	if (ret_val || ucmd.uscsi_status) {
891*7c478bd9Sstevel@tonic-gate 		debug(5, "inquiry failed: %d - %d errno = %d\n",
892*7c478bd9Sstevel@tonic-gate 			ret_val, ucmd.uscsi_status, errno);
893*7c478bd9Sstevel@tonic-gate 		return (ucmd.uscsi_status);
894*7c478bd9Sstevel@tonic-gate 	}
895*7c478bd9Sstevel@tonic-gate 
896*7c478bd9Sstevel@tonic-gate 	(void) memset((void *) &rc_data, 0, sizeof (rc_data));
897*7c478bd9Sstevel@tonic-gate 	(void) memset((void *) &ucmd, 0, sizeof (ucmd));
898*7c478bd9Sstevel@tonic-gate 	(void) memset((void *) &cdb, 0, sizeof (cdb));
899*7c478bd9Sstevel@tonic-gate 	cdb[0] = SCMD_READ_CAPACITY;
900*7c478bd9Sstevel@tonic-gate 	ucmd.uscsi_cdb = (caddr_t)&cdb;
901*7c478bd9Sstevel@tonic-gate 	ucmd.uscsi_cdblen = CDB_GROUP1;
902*7c478bd9Sstevel@tonic-gate 	ucmd.uscsi_bufaddr = (caddr_t)&rc_data;
903*7c478bd9Sstevel@tonic-gate 	ucmd.uscsi_buflen = sizeof (rc_data);
904*7c478bd9Sstevel@tonic-gate 	ucmd.uscsi_timeout = 120;	/* If 0, HBA hangs forever */
905*7c478bd9Sstevel@tonic-gate 
906*7c478bd9Sstevel@tonic-gate 	ret_val = do_uscsi_cmd(fd, &ucmd, USCSI_READ);
907*7c478bd9Sstevel@tonic-gate 	if (ret_val || ucmd.uscsi_status) {
908*7c478bd9Sstevel@tonic-gate 		debug(5, "Read capacity : %d - %d errno = %d\n",
909*7c478bd9Sstevel@tonic-gate 			ret_val, ucmd.uscsi_status, errno);
910*7c478bd9Sstevel@tonic-gate 		return (ucmd.uscsi_status);
911*7c478bd9Sstevel@tonic-gate 	}
912*7c478bd9Sstevel@tonic-gate 
913*7c478bd9Sstevel@tonic-gate 	capacity = ntohl(rc_data[0]);
914*7c478bd9Sstevel@tonic-gate 
915*7c478bd9Sstevel@tonic-gate 	(void) memset((void *)&data, 0, sizeof (data));
916*7c478bd9Sstevel@tonic-gate 	(void) memset((void *)&ucmd, 0, sizeof (ucmd));
917*7c478bd9Sstevel@tonic-gate 	(void) memset((void *)&cdb, 0, sizeof (cdb));
918*7c478bd9Sstevel@tonic-gate 	cdb[0] =  SCMD_FORMAT;
919*7c478bd9Sstevel@tonic-gate 	/*
920*7c478bd9Sstevel@tonic-gate 	 * Defect list sent is an addition to the existing
921*7c478bd9Sstevel@tonic-gate 	 * list of defects.
922*7c478bd9Sstevel@tonic-gate 	 */
923*7c478bd9Sstevel@tonic-gate 	cdb[1] =  FMTDATA;
924*7c478bd9Sstevel@tonic-gate 	/*
925*7c478bd9Sstevel@tonic-gate 	 * Target should examine the setting of the DPRY, DCRT, STPF, IP
926*7c478bd9Sstevel@tonic-gate 	 * and DSP bits.
927*7c478bd9Sstevel@tonic-gate 	 */
928*7c478bd9Sstevel@tonic-gate 	data[1] = FOV;
929*7c478bd9Sstevel@tonic-gate 
930*7c478bd9Sstevel@tonic-gate 	if (mode == SM_FORMAT_IMMEDIATE) {
931*7c478bd9Sstevel@tonic-gate 		debug(5,
932*7c478bd9Sstevel@tonic-gate 	"SM_FORMAT_IMMEDIATE specified ignored. Performing a long format!\n");
933*7c478bd9Sstevel@tonic-gate 	}
934*7c478bd9Sstevel@tonic-gate 
935*7c478bd9Sstevel@tonic-gate 	switch (flavor) {
936*7c478bd9Sstevel@tonic-gate 		case SM_FORMAT_LONG :
937*7c478bd9Sstevel@tonic-gate 			if (strstr(inq.inq_pid, "jaz")) {
938*7c478bd9Sstevel@tonic-gate 				debug(1,
939*7c478bd9Sstevel@tonic-gate 				"LONG Format of JAZ media not supported\n");
940*7c478bd9Sstevel@tonic-gate 				errno = ENOTSUP;
941*7c478bd9Sstevel@tonic-gate 				return (ENOTSUP);
942*7c478bd9Sstevel@tonic-gate 			}
943*7c478bd9Sstevel@tonic-gate 			/*
944*7c478bd9Sstevel@tonic-gate 			 * Defect list sent is an addition to the existing
945*7c478bd9Sstevel@tonic-gate 			 * list of defects.
946*7c478bd9Sstevel@tonic-gate 			 */
947*7c478bd9Sstevel@tonic-gate 			cdb[1] = FMTDATA;
948*7c478bd9Sstevel@tonic-gate 			break;
949*7c478bd9Sstevel@tonic-gate 		default :
950*7c478bd9Sstevel@tonic-gate 			debug(1, "Format option %d  not supported!!\n",
951*7c478bd9Sstevel@tonic-gate 			flavor);
952*7c478bd9Sstevel@tonic-gate 			errno = ENOTSUP;
953*7c478bd9Sstevel@tonic-gate 			return (ENOTSUP);
954*7c478bd9Sstevel@tonic-gate 	}
955*7c478bd9Sstevel@tonic-gate 
956*7c478bd9Sstevel@tonic-gate 
957*7c478bd9Sstevel@tonic-gate 	ucmd.uscsi_cdb = (caddr_t)&cdb;
958*7c478bd9Sstevel@tonic-gate 	ucmd.uscsi_cdblen = CDB_GROUP0;
959*7c478bd9Sstevel@tonic-gate 	ucmd.uscsi_bufaddr = (caddr_t)data;
960*7c478bd9Sstevel@tonic-gate 	ucmd.uscsi_buflen = sizeof (data);
961*7c478bd9Sstevel@tonic-gate 	ucmd.uscsi_timeout = FORMAT_TIMEOUT(capacity);
962*7c478bd9Sstevel@tonic-gate 	ucmd.uscsi_rqlen = RQ_LEN;
963*7c478bd9Sstevel@tonic-gate 	ucmd.uscsi_rqbuf = rq_data;
964*7c478bd9Sstevel@tonic-gate 	ret_val = do_uscsi_cmd(fd, &ucmd, USCSI_WRITE|USCSI_RQENABLE);
965*7c478bd9Sstevel@tonic-gate 	if (ret_val || ucmd.uscsi_status) {
966*7c478bd9Sstevel@tonic-gate 		debug(5, "Format failed failed: %d - %d errno = %d\n",
967*7c478bd9Sstevel@tonic-gate 			ret_val, ucmd.uscsi_status, errno);
968*7c478bd9Sstevel@tonic-gate 		return (ucmd.uscsi_status);
969*7c478bd9Sstevel@tonic-gate 	}
970*7c478bd9Sstevel@tonic-gate 
971*7c478bd9Sstevel@tonic-gate 	return (0);
972*7c478bd9Sstevel@tonic-gate }
973*7c478bd9Sstevel@tonic-gate 
974*7c478bd9Sstevel@tonic-gate 
975*7c478bd9Sstevel@tonic-gate static int32_t
976*7c478bd9Sstevel@tonic-gate scsi_media_status(int32_t fd)
977*7c478bd9Sstevel@tonic-gate {
978*7c478bd9Sstevel@tonic-gate 	struct mode_header modeh;
979*7c478bd9Sstevel@tonic-gate 	struct uscsi_cmd ucmd;
980*7c478bd9Sstevel@tonic-gate 	union scsi_cdb  cdb;
981*7c478bd9Sstevel@tonic-gate 	int32_t	ret_val;
982*7c478bd9Sstevel@tonic-gate 	int32_t cur_status;
983*7c478bd9Sstevel@tonic-gate 	char rq_data[RQ_LEN];
984*7c478bd9Sstevel@tonic-gate 
985*7c478bd9Sstevel@tonic-gate 	debug(10, "SCSI MEDIA STATUS CALLED \n");
986*7c478bd9Sstevel@tonic-gate 
987*7c478bd9Sstevel@tonic-gate 	(void) memset((void *) &modeh, 0, sizeof (modeh));
988*7c478bd9Sstevel@tonic-gate 	(void) memset((void *) &ucmd, 0, sizeof (ucmd));
989*7c478bd9Sstevel@tonic-gate 	(void) memset((void *) &cdb, 0, sizeof (union scsi_cdb));
990*7c478bd9Sstevel@tonic-gate 	cdb.scc_cmd = SCMD_MODE_SENSE;
991*7c478bd9Sstevel@tonic-gate 	FORMG0COUNT(&cdb, sizeof (modeh));
992*7c478bd9Sstevel@tonic-gate 	ucmd.uscsi_cdb = (caddr_t)&cdb;
993*7c478bd9Sstevel@tonic-gate 	ucmd.uscsi_cdblen = CDB_GROUP0;
994*7c478bd9Sstevel@tonic-gate 	ucmd.uscsi_bufaddr = (caddr_t)&modeh;
995*7c478bd9Sstevel@tonic-gate 	ucmd.uscsi_buflen = sizeof (modeh);
996*7c478bd9Sstevel@tonic-gate 	ucmd.uscsi_timeout = 120;	/* If 0, HBA hangs forever */
997*7c478bd9Sstevel@tonic-gate 	ucmd.uscsi_rqlen = RQ_LEN;
998*7c478bd9Sstevel@tonic-gate 	ucmd.uscsi_rqbuf = rq_data;
999*7c478bd9Sstevel@tonic-gate 	ret_val = do_uscsi_cmd(fd, &ucmd, USCSI_READ|USCSI_RQENABLE);
1000*7c478bd9Sstevel@tonic-gate 	if (ret_val || ucmd.uscsi_status) {
1001*7c478bd9Sstevel@tonic-gate 		debug(5, "Modesense failed: %d - %d errno = %d\n",
1002*7c478bd9Sstevel@tonic-gate 			ret_val, ucmd.uscsi_status, errno);
1003*7c478bd9Sstevel@tonic-gate 		return (-1);
1004*7c478bd9Sstevel@tonic-gate 	}
1005*7c478bd9Sstevel@tonic-gate 
1006*7c478bd9Sstevel@tonic-gate 
1007*7c478bd9Sstevel@tonic-gate 	if (modeh.device_specific & W_E_MASK) {
1008*7c478bd9Sstevel@tonic-gate 		cur_status = SM_WRITE_PROTECT_NOPASSWD;
1009*7c478bd9Sstevel@tonic-gate 	} else {
1010*7c478bd9Sstevel@tonic-gate 		cur_status = SM_WRITE_PROTECT_DISABLE;
1011*7c478bd9Sstevel@tonic-gate 	}
1012*7c478bd9Sstevel@tonic-gate 	debug(5, "cur status %d\n", cur_status);
1013*7c478bd9Sstevel@tonic-gate 
1014*7c478bd9Sstevel@tonic-gate 	return (cur_status);
1015*7c478bd9Sstevel@tonic-gate }
1016*7c478bd9Sstevel@tonic-gate 
1017*7c478bd9Sstevel@tonic-gate static int32_t
1018*7c478bd9Sstevel@tonic-gate scsi_zip_media_status(int32_t fd)
1019*7c478bd9Sstevel@tonic-gate {
1020*7c478bd9Sstevel@tonic-gate 	struct uscsi_cmd ucmd;
1021*7c478bd9Sstevel@tonic-gate 	uchar_t cdb[12];
1022*7c478bd9Sstevel@tonic-gate 	int32_t	status;
1023*7c478bd9Sstevel@tonic-gate 	int32_t mode;
1024*7c478bd9Sstevel@tonic-gate 	uchar_t data[64];
1025*7c478bd9Sstevel@tonic-gate 	char rq_data[RQ_LEN];
1026*7c478bd9Sstevel@tonic-gate 
1027*7c478bd9Sstevel@tonic-gate 	debug(10, "Getting media status\n");
1028*7c478bd9Sstevel@tonic-gate 
1029*7c478bd9Sstevel@tonic-gate 	(void) memset((void *)&ucmd, 0, sizeof (ucmd));
1030*7c478bd9Sstevel@tonic-gate 	(void) memset((void *)&cdb, 0, sizeof (cdb));
1031*7c478bd9Sstevel@tonic-gate 
1032*7c478bd9Sstevel@tonic-gate 	cdb[0] = IOMEGA_NONSENSE_CMD;
1033*7c478bd9Sstevel@tonic-gate 	cdb[2] = CARTRIDGE_STATUS_PAGE;
1034*7c478bd9Sstevel@tonic-gate 	cdb[4] = ND_LENGTH;
1035*7c478bd9Sstevel@tonic-gate 	ucmd.uscsi_cdb = (caddr_t)&cdb;
1036*7c478bd9Sstevel@tonic-gate 	ucmd.uscsi_cdblen = CDB_GROUP0;
1037*7c478bd9Sstevel@tonic-gate 	ucmd.uscsi_bufaddr = (caddr_t)data;
1038*7c478bd9Sstevel@tonic-gate 	ucmd.uscsi_buflen = 64;
1039*7c478bd9Sstevel@tonic-gate 	ucmd.uscsi_timeout = 120;	/* If 0, HBA hangs forever */
1040*7c478bd9Sstevel@tonic-gate 	ucmd.uscsi_rqlen = RQ_LEN;
1041*7c478bd9Sstevel@tonic-gate 	ucmd.uscsi_rqbuf = rq_data;
1042*7c478bd9Sstevel@tonic-gate 	status = do_uscsi_cmd(fd, &ucmd, USCSI_READ|USCSI_RQENABLE);
1043*7c478bd9Sstevel@tonic-gate 	if (status || ucmd.uscsi_status) {
1044*7c478bd9Sstevel@tonic-gate 		debug(5,
1045*7c478bd9Sstevel@tonic-gate 		"Catridge protect operation failed: %d - %d errno = %d\n",
1046*7c478bd9Sstevel@tonic-gate 			status, ucmd.uscsi_status, errno);
1047*7c478bd9Sstevel@tonic-gate 		return (-1);
1048*7c478bd9Sstevel@tonic-gate 	}
1049*7c478bd9Sstevel@tonic-gate 
1050*7c478bd9Sstevel@tonic-gate 	if (data[DISK_STATUS_OFFSET + NON_SENSE_HDR_LEN] == 4) {
1051*7c478bd9Sstevel@tonic-gate 		debug(1, "Disk not present. \n");
1052*7c478bd9Sstevel@tonic-gate 		return (-1);
1053*7c478bd9Sstevel@tonic-gate 	}
1054*7c478bd9Sstevel@tonic-gate 	mode = data[PROTECT_MODE_OFFSET + NON_SENSE_HDR_LEN] & 0xF;
1055*7c478bd9Sstevel@tonic-gate 
1056*7c478bd9Sstevel@tonic-gate 	debug(5, "MODE %x\n", mode);
1057*7c478bd9Sstevel@tonic-gate 
1058*7c478bd9Sstevel@tonic-gate 	debug(5, "Mode = %d\n", mode);
1059*7c478bd9Sstevel@tonic-gate 	switch (mode) {
1060*7c478bd9Sstevel@tonic-gate 		case UNLOCK_MODE:
1061*7c478bd9Sstevel@tonic-gate 			status = SM_WRITE_PROTECT_DISABLE;
1062*7c478bd9Sstevel@tonic-gate 			break;
1063*7c478bd9Sstevel@tonic-gate 		case WRITE_PROTECT_MODE:
1064*7c478bd9Sstevel@tonic-gate 			status = SM_WRITE_PROTECT_NOPASSWD;
1065*7c478bd9Sstevel@tonic-gate 			break;
1066*7c478bd9Sstevel@tonic-gate 		case PASSWD_WRITE_PROTECT_MODE:
1067*7c478bd9Sstevel@tonic-gate 			status = SM_WRITE_PROTECT_PASSWD;
1068*7c478bd9Sstevel@tonic-gate 			break;
1069*7c478bd9Sstevel@tonic-gate 		case READ_WRITE_PROTECT_MODE:
1070*7c478bd9Sstevel@tonic-gate 			status = SM_READ_WRITE_PROTECT;
1071*7c478bd9Sstevel@tonic-gate 			break;
1072*7c478bd9Sstevel@tonic-gate 		default :
1073*7c478bd9Sstevel@tonic-gate 			if (mode & TEMP_UNLOCK_MODE)
1074*7c478bd9Sstevel@tonic-gate 				status = SM_TEMP_UNLOCK_MODE;
1075*7c478bd9Sstevel@tonic-gate 			else
1076*7c478bd9Sstevel@tonic-gate 				status = SM_STATUS_UNKNOWN;
1077*7c478bd9Sstevel@tonic-gate 			break;
1078*7c478bd9Sstevel@tonic-gate 	}
1079*7c478bd9Sstevel@tonic-gate 
1080*7c478bd9Sstevel@tonic-gate 	debug(5, "status %d \n", status);
1081*7c478bd9Sstevel@tonic-gate 	return (status);
1082*7c478bd9Sstevel@tonic-gate }
1083*7c478bd9Sstevel@tonic-gate 
1084*7c478bd9Sstevel@tonic-gate int32_t
1085*7c478bd9Sstevel@tonic-gate scsi_reassign_block(int32_t fd, diskaddr_t block)
1086*7c478bd9Sstevel@tonic-gate {
1087*7c478bd9Sstevel@tonic-gate 	uchar_t data[8];
1088*7c478bd9Sstevel@tonic-gate 	struct uscsi_cmd ucmd;
1089*7c478bd9Sstevel@tonic-gate 	char cdb[12];
1090*7c478bd9Sstevel@tonic-gate 	int32_t	ret_val;
1091*7c478bd9Sstevel@tonic-gate 	char rq_data[RQ_LEN];
1092*7c478bd9Sstevel@tonic-gate 
1093*7c478bd9Sstevel@tonic-gate 	debug(5, "SCSI REASSIGN CALLED block = %lld\n", block);
1094*7c478bd9Sstevel@tonic-gate 
1095*7c478bd9Sstevel@tonic-gate 	(void) memset((void *) &data, 0, sizeof (data));
1096*7c478bd9Sstevel@tonic-gate 	(void) memset((void *) &ucmd, 0, sizeof (ucmd));
1097*7c478bd9Sstevel@tonic-gate 	(void) memset((void *) &cdb, 0, sizeof (cdb));
1098*7c478bd9Sstevel@tonic-gate 	cdb[0] = SCMD_REASSIGN_BLOCK;
1099*7c478bd9Sstevel@tonic-gate 	data[3] = 4;
1100*7c478bd9Sstevel@tonic-gate 	data[4] = ((block & 0xFF000000) >> 24);
1101*7c478bd9Sstevel@tonic-gate 	data[5] = ((block & 0xFF0000) >> 16);
1102*7c478bd9Sstevel@tonic-gate 	data[6] = ((block & 0xFF00) >> 8);
1103*7c478bd9Sstevel@tonic-gate 	data[7] = block & 0xFF;
1104*7c478bd9Sstevel@tonic-gate 
1105*7c478bd9Sstevel@tonic-gate 	ucmd.uscsi_cdb = (caddr_t)&cdb;
1106*7c478bd9Sstevel@tonic-gate 	ucmd.uscsi_cdblen = CDB_GROUP0;
1107*7c478bd9Sstevel@tonic-gate 	ucmd.uscsi_bufaddr = (caddr_t)data;
1108*7c478bd9Sstevel@tonic-gate 	ucmd.uscsi_buflen = sizeof (data);
1109*7c478bd9Sstevel@tonic-gate 	ucmd.uscsi_timeout = 120;	/* If 0, HBA hangs forever */
1110*7c478bd9Sstevel@tonic-gate 	ucmd.uscsi_rqlen = RQ_LEN;
1111*7c478bd9Sstevel@tonic-gate 	ucmd.uscsi_rqbuf = rq_data;
1112*7c478bd9Sstevel@tonic-gate 	ret_val = do_uscsi_cmd(fd, &ucmd, USCSI_WRITE|USCSI_RQENABLE);
1113*7c478bd9Sstevel@tonic-gate 	if (ret_val || ucmd.uscsi_status) {
1114*7c478bd9Sstevel@tonic-gate 		debug(5, "Reassign block failed: %d - %d errno = %d\n",
1115*7c478bd9Sstevel@tonic-gate 			ret_val, ucmd.uscsi_status, errno);
1116*7c478bd9Sstevel@tonic-gate 		return (-1);
1117*7c478bd9Sstevel@tonic-gate 	}
1118*7c478bd9Sstevel@tonic-gate 
1119*7c478bd9Sstevel@tonic-gate 	return (0);
1120*7c478bd9Sstevel@tonic-gate }
1121*7c478bd9Sstevel@tonic-gate 
1122*7c478bd9Sstevel@tonic-gate int32_t
1123*7c478bd9Sstevel@tonic-gate get_mode_page(int32_t fd, uchar_t pc, uchar_t page_code,
1124*7c478bd9Sstevel@tonic-gate 				uchar_t *md_data, uchar_t data_len)
1125*7c478bd9Sstevel@tonic-gate {
1126*7c478bd9Sstevel@tonic-gate 	struct uscsi_cmd ucmd;
1127*7c478bd9Sstevel@tonic-gate 	uchar_t cdb[12];
1128*7c478bd9Sstevel@tonic-gate 	int32_t	ret_val;
1129*7c478bd9Sstevel@tonic-gate 	char rq_data[RQ_LEN];
1130*7c478bd9Sstevel@tonic-gate 
1131*7c478bd9Sstevel@tonic-gate 	debug(10, "GET MODE PAGE CALLED \n");
1132*7c478bd9Sstevel@tonic-gate 
1133*7c478bd9Sstevel@tonic-gate 	(void) memset((void *) md_data, 0, sizeof (data_len));
1134*7c478bd9Sstevel@tonic-gate 	(void) memset((void *) &ucmd, 0, sizeof (ucmd));
1135*7c478bd9Sstevel@tonic-gate 	(void) memset((void *) &cdb, 0, sizeof (cdb));
1136*7c478bd9Sstevel@tonic-gate 	cdb[0] = SCMD_MODE_SENSE;
1137*7c478bd9Sstevel@tonic-gate 	cdb[2] = (pc << 6) | page_code;
1138*7c478bd9Sstevel@tonic-gate 	cdb[4] = data_len;
1139*7c478bd9Sstevel@tonic-gate 
1140*7c478bd9Sstevel@tonic-gate 
1141*7c478bd9Sstevel@tonic-gate 	ucmd.uscsi_cdb = (caddr_t)&cdb;
1142*7c478bd9Sstevel@tonic-gate 	ucmd.uscsi_cdblen = CDB_GROUP0;
1143*7c478bd9Sstevel@tonic-gate 	ucmd.uscsi_bufaddr = (caddr_t)md_data;
1144*7c478bd9Sstevel@tonic-gate 	ucmd.uscsi_buflen = data_len;
1145*7c478bd9Sstevel@tonic-gate 	ucmd.uscsi_timeout = 120;	/* If 0, HBA hangs forever */
1146*7c478bd9Sstevel@tonic-gate 	ucmd.uscsi_rqlen = RQ_LEN;
1147*7c478bd9Sstevel@tonic-gate 	ucmd.uscsi_rqbuf = rq_data;
1148*7c478bd9Sstevel@tonic-gate 	ret_val = do_uscsi_cmd(fd, &ucmd, USCSI_READ|USCSI_RQENABLE);
1149*7c478bd9Sstevel@tonic-gate 	if (ret_val || ucmd.uscsi_status) {
1150*7c478bd9Sstevel@tonic-gate 		debug(5, "Modesense failed: %d - %d errno = %d\n",
1151*7c478bd9Sstevel@tonic-gate 			ret_val, ucmd.uscsi_status, errno);
1152*7c478bd9Sstevel@tonic-gate 		return (-2);
1153*7c478bd9Sstevel@tonic-gate 	}
1154*7c478bd9Sstevel@tonic-gate 
1155*7c478bd9Sstevel@tonic-gate 	return (0);
1156*7c478bd9Sstevel@tonic-gate }
1157*7c478bd9Sstevel@tonic-gate 
1158*7c478bd9Sstevel@tonic-gate static int32_t
1159*7c478bd9Sstevel@tonic-gate scsi_zip_write_protect(int32_t fd, smwp_state_t *wp)
1160*7c478bd9Sstevel@tonic-gate {
1161*7c478bd9Sstevel@tonic-gate 	struct uscsi_cmd ucmd;
1162*7c478bd9Sstevel@tonic-gate 	struct scsi_inquiry inq;
1163*7c478bd9Sstevel@tonic-gate 	uchar_t cdb[12];
1164*7c478bd9Sstevel@tonic-gate 	int32_t	status;
1165*7c478bd9Sstevel@tonic-gate 	int32_t new_mode;
1166*7c478bd9Sstevel@tonic-gate 	char rq_data[RQ_LEN];
1167*7c478bd9Sstevel@tonic-gate 	int32_t wa_bit;
1168*7c478bd9Sstevel@tonic-gate 	char *tmp_passwd = NULL;
1169*7c478bd9Sstevel@tonic-gate 
1170*7c478bd9Sstevel@tonic-gate 	debug(10, "SCSI ZIP WRITE PROTECT CALLED \n");
1171*7c478bd9Sstevel@tonic-gate 
1172*7c478bd9Sstevel@tonic-gate 	/*
1173*7c478bd9Sstevel@tonic-gate 	 * Do an inquiry and try to figure out if it an
1174*7c478bd9Sstevel@tonic-gate 	 * ATAPI or SCSI device.
1175*7c478bd9Sstevel@tonic-gate 	 */
1176*7c478bd9Sstevel@tonic-gate 
1177*7c478bd9Sstevel@tonic-gate 	(void) memset((void *) &inq, 0, sizeof (inq));
1178*7c478bd9Sstevel@tonic-gate 	(void) memset((void *) &ucmd, 0, sizeof (ucmd));
1179*7c478bd9Sstevel@tonic-gate 	(void) memset((void *) &cdb, 0, sizeof (cdb));
1180*7c478bd9Sstevel@tonic-gate 	(void) memset((void *) &rq_data, 0, sizeof (rq_data));
1181*7c478bd9Sstevel@tonic-gate 	cdb[0] = SCMD_INQUIRY;
1182*7c478bd9Sstevel@tonic-gate 	cdb[4] = sizeof (inq);
1183*7c478bd9Sstevel@tonic-gate 	ucmd.uscsi_cdb = (caddr_t)&cdb;
1184*7c478bd9Sstevel@tonic-gate 	ucmd.uscsi_cdblen = CDB_GROUP0;
1185*7c478bd9Sstevel@tonic-gate 	ucmd.uscsi_bufaddr = (caddr_t)&inq;
1186*7c478bd9Sstevel@tonic-gate 	ucmd.uscsi_buflen = sizeof (inq);
1187*7c478bd9Sstevel@tonic-gate 	ucmd.uscsi_timeout = 120;	/* If 0, HBA hangs forever */
1188*7c478bd9Sstevel@tonic-gate 	ucmd.uscsi_rqlen = RQ_LEN;
1189*7c478bd9Sstevel@tonic-gate 	ucmd.uscsi_rqbuf = rq_data;
1190*7c478bd9Sstevel@tonic-gate 	status = do_uscsi_cmd(fd, &ucmd, USCSI_READ|USCSI_RQENABLE);
1191*7c478bd9Sstevel@tonic-gate 	if (status || ucmd.uscsi_status) {
1192*7c478bd9Sstevel@tonic-gate 		debug(5, "inquiry failed: %d - %d errno = %d\n",
1193*7c478bd9Sstevel@tonic-gate 			status, ucmd.uscsi_status, errno);
1194*7c478bd9Sstevel@tonic-gate 		return (-1);
1195*7c478bd9Sstevel@tonic-gate 	}
1196*7c478bd9Sstevel@tonic-gate 
1197*7c478bd9Sstevel@tonic-gate 	if (inq.inq_ansi > 0) {
1198*7c478bd9Sstevel@tonic-gate 		wa_bit = 0;
1199*7c478bd9Sstevel@tonic-gate 		debug(5, "SCSI device\n");
1200*7c478bd9Sstevel@tonic-gate 	} else {
1201*7c478bd9Sstevel@tonic-gate 		wa_bit = 1;
1202*7c478bd9Sstevel@tonic-gate 		debug(5, "ATAPI device\n");
1203*7c478bd9Sstevel@tonic-gate 	}
1204*7c478bd9Sstevel@tonic-gate 
1205*7c478bd9Sstevel@tonic-gate 	switch (wp->sm_new_state) {
1206*7c478bd9Sstevel@tonic-gate 		case SM_WRITE_PROTECT_DISABLE :
1207*7c478bd9Sstevel@tonic-gate 			new_mode = 0x0;
1208*7c478bd9Sstevel@tonic-gate 			break;
1209*7c478bd9Sstevel@tonic-gate 		case SM_WRITE_PROTECT_NOPASSWD :
1210*7c478bd9Sstevel@tonic-gate 			new_mode = 0x2;
1211*7c478bd9Sstevel@tonic-gate 			break;
1212*7c478bd9Sstevel@tonic-gate 		case SM_WRITE_PROTECT_PASSWD :
1213*7c478bd9Sstevel@tonic-gate 			new_mode = 0x3;
1214*7c478bd9Sstevel@tonic-gate 			break;
1215*7c478bd9Sstevel@tonic-gate 		case SM_READ_WRITE_PROTECT :
1216*7c478bd9Sstevel@tonic-gate 			new_mode = 0x5;
1217*7c478bd9Sstevel@tonic-gate 			break;
1218*7c478bd9Sstevel@tonic-gate 		case SM_TEMP_UNLOCK_MODE :
1219*7c478bd9Sstevel@tonic-gate 			new_mode = 0x8;
1220*7c478bd9Sstevel@tonic-gate 			break;
1221*7c478bd9Sstevel@tonic-gate 		default :
1222*7c478bd9Sstevel@tonic-gate 			debug(1, "Invalid mode 0x%x specified\n",
1223*7c478bd9Sstevel@tonic-gate 			wp->sm_new_state);
1224*7c478bd9Sstevel@tonic-gate 			errno = ENOTSUP;
1225*7c478bd9Sstevel@tonic-gate 			return (-1);
1226*7c478bd9Sstevel@tonic-gate 	}
1227*7c478bd9Sstevel@tonic-gate 
1228*7c478bd9Sstevel@tonic-gate 
1229*7c478bd9Sstevel@tonic-gate 	(void) memset((void *)&ucmd, 0, sizeof (ucmd));
1230*7c478bd9Sstevel@tonic-gate 	(void) memset((void *)&cdb, 0, sizeof (cdb));
1231*7c478bd9Sstevel@tonic-gate 	(void) memset((void *) &rq_data, 0, sizeof (rq_data));
1232*7c478bd9Sstevel@tonic-gate 	cdb[0] = IOMEGA_CATRIDGE_PROTECT;
1233*7c478bd9Sstevel@tonic-gate 	cdb[1] |= new_mode;
1234*7c478bd9Sstevel@tonic-gate 	if (wa_bit)
1235*7c478bd9Sstevel@tonic-gate 		cdb[1] |= WA_BIT;
1236*7c478bd9Sstevel@tonic-gate 	cdb[4] = wp->sm_passwd_len;
1237*7c478bd9Sstevel@tonic-gate 	ucmd.uscsi_cdb = (caddr_t)&cdb;
1238*7c478bd9Sstevel@tonic-gate 	ucmd.uscsi_cdblen = CDB_GROUP0;
1239*7c478bd9Sstevel@tonic-gate 	if (wa_bit && (wp->sm_passwd_len & 1)) {
1240*7c478bd9Sstevel@tonic-gate 		/*
1241*7c478bd9Sstevel@tonic-gate 		 * Oops, ATAPI device with an odd length passwd!
1242*7c478bd9Sstevel@tonic-gate 		 * Allocate a buffer to hold one extra byte.
1243*7c478bd9Sstevel@tonic-gate 		 */
1244*7c478bd9Sstevel@tonic-gate 		debug(5, "Odd len passwd for ATAPI device!\n");
1245*7c478bd9Sstevel@tonic-gate 		errno = 0;
1246*7c478bd9Sstevel@tonic-gate 		tmp_passwd = (char *)malloc(wp->sm_passwd_len+1);
1247*7c478bd9Sstevel@tonic-gate 		if (tmp_passwd == NULL) {
1248*7c478bd9Sstevel@tonic-gate 			if (errno == 0)
1249*7c478bd9Sstevel@tonic-gate 				errno = ENOMEM;
1250*7c478bd9Sstevel@tonic-gate 			return (-1);
1251*7c478bd9Sstevel@tonic-gate 		}
1252*7c478bd9Sstevel@tonic-gate 		(void) memset(tmp_passwd, 0, wp->sm_passwd_len+1);
1253*7c478bd9Sstevel@tonic-gate 		(void) memcpy(tmp_passwd, wp->sm_passwd, wp->sm_passwd_len);
1254*7c478bd9Sstevel@tonic-gate 		ucmd.uscsi_bufaddr = (caddr_t)tmp_passwd;
1255*7c478bd9Sstevel@tonic-gate 		ucmd.uscsi_buflen = wp->sm_passwd_len+1;
1256*7c478bd9Sstevel@tonic-gate 	} else {
1257*7c478bd9Sstevel@tonic-gate 		ucmd.uscsi_bufaddr = (caddr_t)wp->sm_passwd;
1258*7c478bd9Sstevel@tonic-gate 		ucmd.uscsi_buflen = wp->sm_passwd_len;
1259*7c478bd9Sstevel@tonic-gate 	}
1260*7c478bd9Sstevel@tonic-gate 	ucmd.uscsi_timeout = 120;	/* If 0, HBA hangs forever */
1261*7c478bd9Sstevel@tonic-gate 	ucmd.uscsi_rqlen = RQ_LEN;
1262*7c478bd9Sstevel@tonic-gate 	ucmd.uscsi_rqbuf = rq_data;
1263*7c478bd9Sstevel@tonic-gate 	status = do_uscsi_cmd(fd, &ucmd, USCSI_WRITE|USCSI_RQENABLE);
1264*7c478bd9Sstevel@tonic-gate 	if (tmp_passwd != NULL) {
1265*7c478bd9Sstevel@tonic-gate 		free(tmp_passwd);
1266*7c478bd9Sstevel@tonic-gate 	}
1267*7c478bd9Sstevel@tonic-gate 	if (status || ucmd.uscsi_status) {
1268*7c478bd9Sstevel@tonic-gate 		debug(5,
1269*7c478bd9Sstevel@tonic-gate 	"Catridge protect operation failed: status = %d - %d errno = %d\n",
1270*7c478bd9Sstevel@tonic-gate 			status, ucmd.uscsi_status, errno);
1271*7c478bd9Sstevel@tonic-gate 		    if ((rq_data[2] & 0xF) == KEY_ILLEGAL_REQUEST) {
1272*7c478bd9Sstevel@tonic-gate 			if (rq_data[12] == 0x26) {
1273*7c478bd9Sstevel@tonic-gate 				/* Wrong passwd */
1274*7c478bd9Sstevel@tonic-gate 				debug(5,
1275*7c478bd9Sstevel@tonic-gate "Protection Request with wrong passwd. errno is being set to EACCES.\n");
1276*7c478bd9Sstevel@tonic-gate 				errno = EACCES;
1277*7c478bd9Sstevel@tonic-gate 			}
1278*7c478bd9Sstevel@tonic-gate 		}
1279*7c478bd9Sstevel@tonic-gate 		return (-1);
1280*7c478bd9Sstevel@tonic-gate 	}
1281*7c478bd9Sstevel@tonic-gate 
1282*7c478bd9Sstevel@tonic-gate 	return (0);
1283*7c478bd9Sstevel@tonic-gate }
1284*7c478bd9Sstevel@tonic-gate 
1285*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/
1286*7c478bd9Sstevel@tonic-gate static int32_t
1287*7c478bd9Sstevel@tonic-gate scsi_write_protect(int32_t fd, smwp_state_t *wp)
1288*7c478bd9Sstevel@tonic-gate {
1289*7c478bd9Sstevel@tonic-gate 	errno = ENOTSUP;
1290*7c478bd9Sstevel@tonic-gate 	return (-1);
1291*7c478bd9Sstevel@tonic-gate }
1292*7c478bd9Sstevel@tonic-gate 
1293*7c478bd9Sstevel@tonic-gate static void *
1294*7c478bd9Sstevel@tonic-gate my_server_thread(void *arg)
1295*7c478bd9Sstevel@tonic-gate {
1296*7c478bd9Sstevel@tonic-gate 	door_data_t	*door_dp;
1297*7c478bd9Sstevel@tonic-gate 	struct	sigaction act;
1298*7c478bd9Sstevel@tonic-gate 	int	i, oldtype;
1299*7c478bd9Sstevel@tonic-gate 
1300*7c478bd9Sstevel@tonic-gate 	door_dp = (door_data_t *)arg;
1301*7c478bd9Sstevel@tonic-gate 
1302*7c478bd9Sstevel@tonic-gate 	if (door_dp == NULL) {
1303*7c478bd9Sstevel@tonic-gate 		fatal("my_server_thread[%d]: argument is NULL!!\n",
1304*7c478bd9Sstevel@tonic-gate 			pthread_self());
1305*7c478bd9Sstevel@tonic-gate 		exit(-1);
1306*7c478bd9Sstevel@tonic-gate 	}
1307*7c478bd9Sstevel@tonic-gate 	/* Wait for door to be created */
1308*7c478bd9Sstevel@tonic-gate 
1309*7c478bd9Sstevel@tonic-gate 	(void) mutex_lock(&door_dp->dd_lock);
1310*7c478bd9Sstevel@tonic-gate 
1311*7c478bd9Sstevel@tonic-gate 	if (door_dp->dd_desc[0].d_data.d_desc.d_descriptor == -1)
1312*7c478bd9Sstevel@tonic-gate 		(void) cond_wait(&door_dp->dd_cv, &door_dp->dd_lock);
1313*7c478bd9Sstevel@tonic-gate 	(void) mutex_unlock(&door_dp->dd_lock);
1314*7c478bd9Sstevel@tonic-gate 
1315*7c478bd9Sstevel@tonic-gate 	for (i = 0; i < N_BADSIGS; i++) {
1316*7c478bd9Sstevel@tonic-gate 		act.sa_sigaction = server_badsig_handler;
1317*7c478bd9Sstevel@tonic-gate 		(void) sigemptyset(&act.sa_mask);
1318*7c478bd9Sstevel@tonic-gate 		act.sa_flags = SA_SIGINFO;
1319*7c478bd9Sstevel@tonic-gate 		if (sigaction(badsigs[i], &act, NULL) == -1)
1320*7c478bd9Sstevel@tonic-gate 			warning(gettext(SIGACT_FAILED), strsignal(badsigs[i]),
1321*7c478bd9Sstevel@tonic-gate 				strerror(errno));
1322*7c478bd9Sstevel@tonic-gate 	}
1323*7c478bd9Sstevel@tonic-gate 	if (sigemptyset(&door_dp->dd_newset) != 0)
1324*7c478bd9Sstevel@tonic-gate 		warning(gettext("sigemptyset failed. errno = %d\n"),
1325*7c478bd9Sstevel@tonic-gate 			errno);
1326*7c478bd9Sstevel@tonic-gate 	if (pthread_sigmask(SIG_BLOCK, &door_dp->dd_newset, NULL) != 0)
1327*7c478bd9Sstevel@tonic-gate 		warning(gettext("pthread_sigmask failed. errno = %d\n"),
1328*7c478bd9Sstevel@tonic-gate 			errno);
1329*7c478bd9Sstevel@tonic-gate 
1330*7c478bd9Sstevel@tonic-gate 	/* Bind thread with pool associated with this door */
1331*7c478bd9Sstevel@tonic-gate 
1332*7c478bd9Sstevel@tonic-gate 	if (door_bind(door_dp->dd_desc[0].d_data.d_desc.d_descriptor) < 0) {
1333*7c478bd9Sstevel@tonic-gate 		fatal("door_bind");
1334*7c478bd9Sstevel@tonic-gate 		exit(-1);
1335*7c478bd9Sstevel@tonic-gate 	}
1336*7c478bd9Sstevel@tonic-gate 	debug(5, "thread 0x%x bound to the door %d.\n", pthread_self(),
1337*7c478bd9Sstevel@tonic-gate 		door_dp->dd_desc[0].d_data.d_desc.d_descriptor);
1338*7c478bd9Sstevel@tonic-gate 	/*
1339*7c478bd9Sstevel@tonic-gate 	 * We ENABLE thread cancellation as default.
1340*7c478bd9Sstevel@tonic-gate 	 * We will disable it whenever it is unsafe for thread to be cancelled.
1341*7c478bd9Sstevel@tonic-gate 	 * For example if we are going to be holding locks, we will disable
1342*7c478bd9Sstevel@tonic-gate 	 * thread cancellation.
1343*7c478bd9Sstevel@tonic-gate 	 */
1344*7c478bd9Sstevel@tonic-gate 	if (pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL) != 0)
1345*7c478bd9Sstevel@tonic-gate 		warning(gettext("pthread_setcancelstate failed. errno = %d\n"),
1346*7c478bd9Sstevel@tonic-gate 			errno);
1347*7c478bd9Sstevel@tonic-gate 	/*
1348*7c478bd9Sstevel@tonic-gate 	 * Receipt of pthread_cancel should cause  immediate cancellation.
1349*7c478bd9Sstevel@tonic-gate 	 */
1350*7c478bd9Sstevel@tonic-gate 	if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldtype) != 0)
1351*7c478bd9Sstevel@tonic-gate 		warning(gettext("pthread_setcanceltype failed. errno = %d\n"),
1352*7c478bd9Sstevel@tonic-gate 			errno);
1353*7c478bd9Sstevel@tonic-gate 	/*
1354*7c478bd9Sstevel@tonic-gate 	 * Inform the main thread that bind is complete.
1355*7c478bd9Sstevel@tonic-gate 	 */
1356*7c478bd9Sstevel@tonic-gate 	(void) cond_signal(&door_dp->dd_cv_bind);
1357*7c478bd9Sstevel@tonic-gate 	(void) door_return(NULL, 0, NULL, 0);
1358*7c478bd9Sstevel@tonic-gate 	warning(gettext("Exiting my_server_thread[%d]\n"), pthread_self());
1359*7c478bd9Sstevel@tonic-gate 	return (NULL);
1360*7c478bd9Sstevel@tonic-gate }
1361*7c478bd9Sstevel@tonic-gate 
1362*7c478bd9Sstevel@tonic-gate static void
1363*7c478bd9Sstevel@tonic-gate cleanup(door_data_t	*door_dp)
1364*7c478bd9Sstevel@tonic-gate {
1365*7c478bd9Sstevel@tonic-gate 
1366*7c478bd9Sstevel@tonic-gate 	debug(5, "cleanup running for thread %d\n", door_dp->dd_thread);
1367*7c478bd9Sstevel@tonic-gate 	if (door_dp->dd_desc[1].d_data.d_desc.d_descriptor >= 0)
1368*7c478bd9Sstevel@tonic-gate 	    if (close(door_dp->dd_desc[1].d_data.d_desc.d_descriptor) < 0) {
1369*7c478bd9Sstevel@tonic-gate 		warning(gettext(
1370*7c478bd9Sstevel@tonic-gate 		"cleanup:close death door : door id = 0x%x, errno =%d"),
1371*7c478bd9Sstevel@tonic-gate 			door_dp->dd_desc[1].d_data.d_desc.d_descriptor,
1372*7c478bd9Sstevel@tonic-gate 			errno);
1373*7c478bd9Sstevel@tonic-gate 	}
1374*7c478bd9Sstevel@tonic-gate 	if (door_dp->dd_buffd != -1) {
1375*7c478bd9Sstevel@tonic-gate 		(void) munmap(door_dp->dd_buf, door_dp->dd_buf_len);
1376*7c478bd9Sstevel@tonic-gate 		(void) close(door_dp->dd_buffd);
1377*7c478bd9Sstevel@tonic-gate 		door_dp->dd_buf = NULL;
1378*7c478bd9Sstevel@tonic-gate 		door_dp->dd_buf_len = 0;
1379*7c478bd9Sstevel@tonic-gate 	}
1380*7c478bd9Sstevel@tonic-gate 
1381*7c478bd9Sstevel@tonic-gate 	/* close the device */
1382*7c478bd9Sstevel@tonic-gate 	if (door_dp->dd_fd >= 0)
1383*7c478bd9Sstevel@tonic-gate 	    if (close(door_dp->dd_fd) < 0) {
1384*7c478bd9Sstevel@tonic-gate 		warning(gettext("cleanup:close fd failed. errno = %d\n"),
1385*7c478bd9Sstevel@tonic-gate 			errno);
1386*7c478bd9Sstevel@tonic-gate 	}
1387*7c478bd9Sstevel@tonic-gate 	if (door_dp->dd_thread != 0)
1388*7c478bd9Sstevel@tonic-gate 	    if (pthread_cancel(door_dp->dd_thread) != 0)
1389*7c478bd9Sstevel@tonic-gate 		warning(gettext("pthread_cancel failed. errno = %d\n"),
1390*7c478bd9Sstevel@tonic-gate 			errno);
1391*7c478bd9Sstevel@tonic-gate 	free(door_dp);
1392*7c478bd9Sstevel@tonic-gate 	debug(5, "Exiting cleanup\n");
1393*7c478bd9Sstevel@tonic-gate }
1394*7c478bd9Sstevel@tonic-gate 
1395*7c478bd9Sstevel@tonic-gate static void
1396*7c478bd9Sstevel@tonic-gate my_create(door_info_t *dip)
1397*7c478bd9Sstevel@tonic-gate {
1398*7c478bd9Sstevel@tonic-gate 	door_data_t	*door_dp;
1399*7c478bd9Sstevel@tonic-gate 	pthread_t	tid;
1400*7c478bd9Sstevel@tonic-gate 	pthread_attr_t	attr;
1401*7c478bd9Sstevel@tonic-gate 	int		ret_val;
1402*7c478bd9Sstevel@tonic-gate 
1403*7c478bd9Sstevel@tonic-gate 	if (dip == NULL) {
1404*7c478bd9Sstevel@tonic-gate 		return;
1405*7c478bd9Sstevel@tonic-gate 	}
1406*7c478bd9Sstevel@tonic-gate 	door_dp = (door_data_t *)dip->di_data;
1407*7c478bd9Sstevel@tonic-gate 
1408*7c478bd9Sstevel@tonic-gate 	debug(10, "entering my_create\n");
1409*7c478bd9Sstevel@tonic-gate 
1410*7c478bd9Sstevel@tonic-gate 	/* create one thread for this door */
1411*7c478bd9Sstevel@tonic-gate 
1412*7c478bd9Sstevel@tonic-gate 	(void) mutex_lock(&door_dp->dd_threadlock);
1413*7c478bd9Sstevel@tonic-gate 
1414*7c478bd9Sstevel@tonic-gate 	if (door_dp->dd_thread != 0) {
1415*7c478bd9Sstevel@tonic-gate 		debug(8, "Exiting my_create without creating thread.\n");
1416*7c478bd9Sstevel@tonic-gate 		(void) mutex_unlock(&door_dp->dd_threadlock);
1417*7c478bd9Sstevel@tonic-gate 		return;
1418*7c478bd9Sstevel@tonic-gate 	}
1419*7c478bd9Sstevel@tonic-gate 
1420*7c478bd9Sstevel@tonic-gate 	(void) pthread_attr_init(&attr);
1421*7c478bd9Sstevel@tonic-gate 	if (pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM) != 0)
1422*7c478bd9Sstevel@tonic-gate 		warning(gettext(
1423*7c478bd9Sstevel@tonic-gate 		"pthread_attr_setscope failed. errno = %d\n"),
1424*7c478bd9Sstevel@tonic-gate 			errno);
1425*7c478bd9Sstevel@tonic-gate 	if (pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED) != 0)
1426*7c478bd9Sstevel@tonic-gate 		warning(gettext(
1427*7c478bd9Sstevel@tonic-gate 		"pthread_attr_setdetachstate failed. errno = %d\n"),
1428*7c478bd9Sstevel@tonic-gate 			errno);
1429*7c478bd9Sstevel@tonic-gate 	ret_val = pthread_create(&tid, &attr, my_server_thread,
1430*7c478bd9Sstevel@tonic-gate 		(void *)(dip->di_data));
1431*7c478bd9Sstevel@tonic-gate 
1432*7c478bd9Sstevel@tonic-gate 	if (ret_val != 0) {
1433*7c478bd9Sstevel@tonic-gate 		warning(gettext(
1434*7c478bd9Sstevel@tonic-gate 			"my_create[%d]:pthread_create failed. errno = %d\n"),
1435*7c478bd9Sstevel@tonic-gate 				pthread_self(), errno);
1436*7c478bd9Sstevel@tonic-gate 		(void) mutex_unlock(&door_dp->dd_threadlock);
1437*7c478bd9Sstevel@tonic-gate 		(void) pthread_attr_destroy(&attr);
1438*7c478bd9Sstevel@tonic-gate 		return;
1439*7c478bd9Sstevel@tonic-gate 	}
1440*7c478bd9Sstevel@tonic-gate 	(void) pthread_attr_destroy(&attr);
1441*7c478bd9Sstevel@tonic-gate 	door_dp->dd_thread = tid;
1442*7c478bd9Sstevel@tonic-gate 	debug(5, "my_server_thread[%d] created.\n", tid);
1443*7c478bd9Sstevel@tonic-gate 
1444*7c478bd9Sstevel@tonic-gate 	(void) mutex_unlock(&door_dp->dd_threadlock);
1445*7c478bd9Sstevel@tonic-gate 	debug(5,
1446*7c478bd9Sstevel@tonic-gate 		"Exiting my_create[%d] after creating a thread.\n",
1447*7c478bd9Sstevel@tonic-gate 		pthread_self());
1448*7c478bd9Sstevel@tonic-gate 
1449*7c478bd9Sstevel@tonic-gate }
1450*7c478bd9Sstevel@tonic-gate 
1451*7c478bd9Sstevel@tonic-gate static void
1452*7c478bd9Sstevel@tonic-gate door_ret_err(smedia_reterror_t *reterror, int32_t err)
1453*7c478bd9Sstevel@tonic-gate {
1454*7c478bd9Sstevel@tonic-gate 	reterror->cnum = SMEDIA_CNUM_ERROR;
1455*7c478bd9Sstevel@tonic-gate 	reterror->errnum = err;
1456*7c478bd9Sstevel@tonic-gate 	(void) door_return((char *)reterror, sizeof (smedia_reterror_t), 0, 0);
1457*7c478bd9Sstevel@tonic-gate }
1458*7c478bd9Sstevel@tonic-gate 
1459*7c478bd9Sstevel@tonic-gate static void
1460*7c478bd9Sstevel@tonic-gate my_door_return(char *data_ptr, size_t data_size,
1461*7c478bd9Sstevel@tonic-gate 	door_desc_t *desc_ptr, uint_t num_desc)
1462*7c478bd9Sstevel@tonic-gate {
1463*7c478bd9Sstevel@tonic-gate 	(void) door_return(data_ptr, data_size, desc_ptr, num_desc);
1464*7c478bd9Sstevel@tonic-gate }
1465*7c478bd9Sstevel@tonic-gate 
1466*7c478bd9Sstevel@tonic-gate static int32_t
1467*7c478bd9Sstevel@tonic-gate raw_read(door_data_t *door_dp, smedia_services_t *req)
1468*7c478bd9Sstevel@tonic-gate {
1469*7c478bd9Sstevel@tonic-gate 	struct uscsi_cmd	ucmd;
1470*7c478bd9Sstevel@tonic-gate 	union scsi_cdb		cdb;
1471*7c478bd9Sstevel@tonic-gate 	int32_t			ret_val;
1472*7c478bd9Sstevel@tonic-gate 	int32_t			num_sectors, sector_size;
1473*7c478bd9Sstevel@tonic-gate 	int32_t			rc_data[2];
1474*7c478bd9Sstevel@tonic-gate 	char			rq_data[RQ_LEN];
1475*7c478bd9Sstevel@tonic-gate 
1476*7c478bd9Sstevel@tonic-gate 	(void) memset((void *) &rc_data, 0, sizeof (rc_data));
1477*7c478bd9Sstevel@tonic-gate 	(void) memset((void *) &ucmd, 0, sizeof (ucmd));
1478*7c478bd9Sstevel@tonic-gate 	(void) memset((void *) &cdb, 0, sizeof (union scsi_cdb));
1479*7c478bd9Sstevel@tonic-gate 
1480*7c478bd9Sstevel@tonic-gate 	if (door_dp->dd_sector_size == 0) {
1481*7c478bd9Sstevel@tonic-gate 		sector_size = get_sector_size(door_dp->dd_fd);
1482*7c478bd9Sstevel@tonic-gate 		door_dp->dd_sector_size = sector_size;
1483*7c478bd9Sstevel@tonic-gate 	} else sector_size = door_dp->dd_sector_size;
1484*7c478bd9Sstevel@tonic-gate 
1485*7c478bd9Sstevel@tonic-gate 	if ((req->reqraw_read.nbytes > door_dp->dd_buf_len) ||
1486*7c478bd9Sstevel@tonic-gate 		(door_dp->dd_buf == NULL)) {
1487*7c478bd9Sstevel@tonic-gate 		errno = EINVAL;
1488*7c478bd9Sstevel@tonic-gate 		return (-1);
1489*7c478bd9Sstevel@tonic-gate 	}
1490*7c478bd9Sstevel@tonic-gate 	if ((!req->reqraw_read.nbytes) ||
1491*7c478bd9Sstevel@tonic-gate 		(req->reqraw_read.nbytes % sector_size)) {
1492*7c478bd9Sstevel@tonic-gate 		errno = EINVAL;
1493*7c478bd9Sstevel@tonic-gate 		return (-1);
1494*7c478bd9Sstevel@tonic-gate 	}
1495*7c478bd9Sstevel@tonic-gate 
1496*7c478bd9Sstevel@tonic-gate 	(void) memset((void *) &cdb, 0, sizeof (cdb));
1497*7c478bd9Sstevel@tonic-gate 	num_sectors = (uint32_t)req->reqraw_read.nbytes/sector_size;
1498*7c478bd9Sstevel@tonic-gate 
1499*7c478bd9Sstevel@tonic-gate 	cdb.scc_cmd = SCMD_READ_G1;
1500*7c478bd9Sstevel@tonic-gate 	FORMG1ADDR(&cdb, (uint32_t)req->reqraw_read.blockno);
1501*7c478bd9Sstevel@tonic-gate 	FORMG1COUNT(&cdb, num_sectors);
1502*7c478bd9Sstevel@tonic-gate 
1503*7c478bd9Sstevel@tonic-gate 	ucmd.uscsi_cdb = (caddr_t)&cdb;
1504*7c478bd9Sstevel@tonic-gate 	ucmd.uscsi_cdblen = CDB_GROUP1;
1505*7c478bd9Sstevel@tonic-gate 	ucmd.uscsi_bufaddr = (caddr_t)door_dp->dd_buf;
1506*7c478bd9Sstevel@tonic-gate 	ucmd.uscsi_buflen = (uint32_t)req->reqraw_read.nbytes;
1507*7c478bd9Sstevel@tonic-gate 	ucmd.uscsi_timeout = 120;	/* If 0, HBA hangs forever */
1508*7c478bd9Sstevel@tonic-gate 	ucmd.uscsi_rqlen = RQ_LEN;
1509*7c478bd9Sstevel@tonic-gate 	ucmd.uscsi_rqbuf = rq_data;
1510*7c478bd9Sstevel@tonic-gate 	ret_val = do_uscsi_cmd(door_dp->dd_fd,
1511*7c478bd9Sstevel@tonic-gate 		&ucmd, USCSI_READ|USCSI_RQENABLE);
1512*7c478bd9Sstevel@tonic-gate 	if (ret_val || ucmd.uscsi_status) {
1513*7c478bd9Sstevel@tonic-gate 		debug(5, "read failed: %d - %d errno = %d\n",
1514*7c478bd9Sstevel@tonic-gate 			ret_val, ucmd.uscsi_status, errno);
1515*7c478bd9Sstevel@tonic-gate 		debug(5, "buflen = 0x%x resid = 0x%x sector size = %d\n",
1516*7c478bd9Sstevel@tonic-gate 			ucmd.uscsi_buflen, ucmd.uscsi_resid, sector_size);
1517*7c478bd9Sstevel@tonic-gate 		debug(5, "cdb addr: %x %x %x %x \n", cdb.g1_addr3,
1518*7c478bd9Sstevel@tonic-gate 			cdb.g1_addr2, cdb.g1_addr1, cdb.g1_addr0);
1519*7c478bd9Sstevel@tonic-gate 		debug(5, "cdb count: %x %x\n", cdb.g1_count1,
1520*7c478bd9Sstevel@tonic-gate 			cdb.g1_count0);
1521*7c478bd9Sstevel@tonic-gate 		return (-1);
1522*7c478bd9Sstevel@tonic-gate 	}
1523*7c478bd9Sstevel@tonic-gate 	ret_val = ucmd.uscsi_buflen - ucmd.uscsi_resid;
1524*7c478bd9Sstevel@tonic-gate 	return (ret_val);
1525*7c478bd9Sstevel@tonic-gate }
1526*7c478bd9Sstevel@tonic-gate 
1527*7c478bd9Sstevel@tonic-gate static int32_t
1528*7c478bd9Sstevel@tonic-gate raw_write(door_data_t *door_dp, smedia_services_t *req)
1529*7c478bd9Sstevel@tonic-gate {
1530*7c478bd9Sstevel@tonic-gate 	struct uscsi_cmd	ucmd;
1531*7c478bd9Sstevel@tonic-gate 	union scsi_cdb		cdb;
1532*7c478bd9Sstevel@tonic-gate 	int32_t			ret_val;
1533*7c478bd9Sstevel@tonic-gate 	int32_t			num_sectors, sector_size;
1534*7c478bd9Sstevel@tonic-gate 	int32_t			rc_data[2];
1535*7c478bd9Sstevel@tonic-gate 	char			rq_data[RQ_LEN];
1536*7c478bd9Sstevel@tonic-gate 
1537*7c478bd9Sstevel@tonic-gate 	(void) memset((void *) &rc_data, 0, sizeof (rc_data));
1538*7c478bd9Sstevel@tonic-gate 	(void) memset((void *) &ucmd, 0, sizeof (ucmd));
1539*7c478bd9Sstevel@tonic-gate 	(void) memset((void *) &cdb, 0, sizeof (union scsi_cdb));
1540*7c478bd9Sstevel@tonic-gate 
1541*7c478bd9Sstevel@tonic-gate 	if (door_dp->dd_sector_size == 0) {
1542*7c478bd9Sstevel@tonic-gate 		sector_size = get_sector_size(door_dp->dd_fd);
1543*7c478bd9Sstevel@tonic-gate 		door_dp->dd_sector_size = sector_size;
1544*7c478bd9Sstevel@tonic-gate 	} else sector_size = door_dp->dd_sector_size;
1545*7c478bd9Sstevel@tonic-gate 
1546*7c478bd9Sstevel@tonic-gate 
1547*7c478bd9Sstevel@tonic-gate 	if ((req->reqraw_write.nbytes > door_dp->dd_buf_len) ||
1548*7c478bd9Sstevel@tonic-gate 		(door_dp->dd_buf == NULL)) {
1549*7c478bd9Sstevel@tonic-gate 		errno = EINVAL;
1550*7c478bd9Sstevel@tonic-gate 		return (-1);
1551*7c478bd9Sstevel@tonic-gate 	}
1552*7c478bd9Sstevel@tonic-gate 	if ((req->reqraw_write.nbytes % sector_size)) {
1553*7c478bd9Sstevel@tonic-gate 		errno = EINVAL;
1554*7c478bd9Sstevel@tonic-gate 		return (-1);
1555*7c478bd9Sstevel@tonic-gate 	}
1556*7c478bd9Sstevel@tonic-gate 
1557*7c478bd9Sstevel@tonic-gate 	(void) memset((void *) &cdb, 0, sizeof (cdb));
1558*7c478bd9Sstevel@tonic-gate 	num_sectors = (uint32_t)req->reqraw_write.nbytes/sector_size;
1559*7c478bd9Sstevel@tonic-gate 
1560*7c478bd9Sstevel@tonic-gate 	cdb.scc_cmd = SCMD_WRITE_G1;
1561*7c478bd9Sstevel@tonic-gate 	FORMG1ADDR(&cdb, (uint32_t)req->reqraw_write.blockno);
1562*7c478bd9Sstevel@tonic-gate 	FORMG1COUNT(&cdb, num_sectors);
1563*7c478bd9Sstevel@tonic-gate 
1564*7c478bd9Sstevel@tonic-gate 	ucmd.uscsi_cdb = (caddr_t)&cdb;
1565*7c478bd9Sstevel@tonic-gate 	ucmd.uscsi_cdblen = CDB_GROUP1;
1566*7c478bd9Sstevel@tonic-gate 	ucmd.uscsi_bufaddr = (caddr_t)door_dp->dd_buf;
1567*7c478bd9Sstevel@tonic-gate 	ucmd.uscsi_buflen = (uint32_t)req->reqraw_write.nbytes;
1568*7c478bd9Sstevel@tonic-gate 	ucmd.uscsi_timeout = 120;	/* If 0, HBA hangs forever */
1569*7c478bd9Sstevel@tonic-gate 	ucmd.uscsi_rqlen = RQ_LEN;
1570*7c478bd9Sstevel@tonic-gate 	ucmd.uscsi_rqbuf = rq_data;
1571*7c478bd9Sstevel@tonic-gate 	ret_val = do_uscsi_cmd(door_dp->dd_fd,
1572*7c478bd9Sstevel@tonic-gate 		&ucmd, USCSI_WRITE|USCSI_RQENABLE);
1573*7c478bd9Sstevel@tonic-gate 	if (ret_val || ucmd.uscsi_status) {
1574*7c478bd9Sstevel@tonic-gate 		debug(5, "write failed: %d - %d errno = %d\n",
1575*7c478bd9Sstevel@tonic-gate 			ret_val, ucmd.uscsi_status, errno);
1576*7c478bd9Sstevel@tonic-gate 		debug(5, "buflen = 0x%x resid = 0x%x sector size = %d\n",
1577*7c478bd9Sstevel@tonic-gate 			ucmd.uscsi_buflen, ucmd.uscsi_resid, sector_size);
1578*7c478bd9Sstevel@tonic-gate 		debug(5, "cdb addr: %x %x %x %x \n", cdb.g1_addr3,
1579*7c478bd9Sstevel@tonic-gate 			cdb.g1_addr2, cdb.g1_addr1, cdb.g1_addr0);
1580*7c478bd9Sstevel@tonic-gate 		debug(5, "cdb count: %x %x\n", cdb.g1_count1,
1581*7c478bd9Sstevel@tonic-gate 			cdb.g1_count0);
1582*7c478bd9Sstevel@tonic-gate 		return (-1);
1583*7c478bd9Sstevel@tonic-gate 	}
1584*7c478bd9Sstevel@tonic-gate 	ret_val = ucmd.uscsi_buflen - ucmd.uscsi_resid;
1585*7c478bd9Sstevel@tonic-gate 	return (ret_val);
1586*7c478bd9Sstevel@tonic-gate }
1587*7c478bd9Sstevel@tonic-gate 
1588*7c478bd9Sstevel@tonic-gate static int32_t
1589*7c478bd9Sstevel@tonic-gate set_protection_status(door_data_t *door_dp, smedia_services_t *req)
1590*7c478bd9Sstevel@tonic-gate {
1591*7c478bd9Sstevel@tonic-gate 	int32_t			ret_val, saved_errno, status;
1592*7c478bd9Sstevel@tonic-gate 	struct scsi_inquiry	inq;
1593*7c478bd9Sstevel@tonic-gate 	char			vid[9];
1594*7c478bd9Sstevel@tonic-gate 	char			pid[17];
1595*7c478bd9Sstevel@tonic-gate 	struct passwd		*pwd;
1596*7c478bd9Sstevel@tonic-gate 	char			uname[MAXUGNAME + 1];
1597*7c478bd9Sstevel@tonic-gate 	char			*new_state, *old_state;
1598*7c478bd9Sstevel@tonic-gate 
1599*7c478bd9Sstevel@tonic-gate 	/*
1600*7c478bd9Sstevel@tonic-gate 	 * Read the current protection state before modifiying.
1601*7c478bd9Sstevel@tonic-gate 	 * Needed for audit purposes.
1602*7c478bd9Sstevel@tonic-gate 	 */
1603*7c478bd9Sstevel@tonic-gate 	switch (get_device_type_scsi(door_dp->dd_fd, &inq)) {
1604*7c478bd9Sstevel@tonic-gate 	case SCSI_IOMEGA:
1605*7c478bd9Sstevel@tonic-gate 		status = scsi_zip_media_status(door_dp->dd_fd);
1606*7c478bd9Sstevel@tonic-gate 		ret_val = scsi_zip_write_protect(door_dp->dd_fd,
1607*7c478bd9Sstevel@tonic-gate 			&req->reqset_protection_status.prot_state);
1608*7c478bd9Sstevel@tonic-gate 		break;
1609*7c478bd9Sstevel@tonic-gate 	case SCSI_FLOPPY:
1610*7c478bd9Sstevel@tonic-gate 		info("Formatting floppy");
1611*7c478bd9Sstevel@tonic-gate 		status = scsi_floppy_media_status(door_dp->dd_fd);
1612*7c478bd9Sstevel@tonic-gate 		ret_val = scsi_floppy_write_protect(door_dp->dd_fd,
1613*7c478bd9Sstevel@tonic-gate 			&req->reqset_protection_status.prot_state);
1614*7c478bd9Sstevel@tonic-gate 		break;
1615*7c478bd9Sstevel@tonic-gate 	case SCSI_GENERIC:
1616*7c478bd9Sstevel@tonic-gate 		status = scsi_media_status(door_dp->dd_fd);
1617*7c478bd9Sstevel@tonic-gate 		ret_val = scsi_write_protect(door_dp->dd_fd,
1618*7c478bd9Sstevel@tonic-gate 			&req->reqset_protection_status.prot_state);
1619*7c478bd9Sstevel@tonic-gate 		break;
1620*7c478bd9Sstevel@tonic-gate 	}
1621*7c478bd9Sstevel@tonic-gate 
1622*7c478bd9Sstevel@tonic-gate 	saved_errno = errno;
1623*7c478bd9Sstevel@tonic-gate 	new_state = xlate_state(
1624*7c478bd9Sstevel@tonic-gate 	    req->reqset_protection_status.prot_state.sm_new_state);
1625*7c478bd9Sstevel@tonic-gate 	old_state = xlate_state(status);
1626*7c478bd9Sstevel@tonic-gate 
1627*7c478bd9Sstevel@tonic-gate 	if (can_audit()) {
1628*7c478bd9Sstevel@tonic-gate 		(void) audit_save_me(door_dp);
1629*7c478bd9Sstevel@tonic-gate 		door_dp->audit_text[0] = 0;
1630*7c478bd9Sstevel@tonic-gate 		door_dp->audit_text1[0] = 0;
1631*7c478bd9Sstevel@tonic-gate 		door_dp->audit_event = AUE_smserverd;
1632*7c478bd9Sstevel@tonic-gate 	}
1633*7c478bd9Sstevel@tonic-gate 	(void) strlcpy(vid, inq.inq_vid, sizeof (vid));
1634*7c478bd9Sstevel@tonic-gate 	(void) strlcpy(pid, inq.inq_pid, sizeof (pid));
1635*7c478bd9Sstevel@tonic-gate 	if (ret_val < 0) {
1636*7c478bd9Sstevel@tonic-gate 	    if (errno == EACCES) {
1637*7c478bd9Sstevel@tonic-gate 		pwd = getpwuid(door_dp->dd_cred.dc_ruid);
1638*7c478bd9Sstevel@tonic-gate 		if (pwd != NULL) {
1639*7c478bd9Sstevel@tonic-gate 			(void) strlcpy(uname,
1640*7c478bd9Sstevel@tonic-gate 				pwd->pw_name, MAXUGNAME);
1641*7c478bd9Sstevel@tonic-gate 		} else uname[0] = 0;
1642*7c478bd9Sstevel@tonic-gate 
1643*7c478bd9Sstevel@tonic-gate 		if (can_audit()) {
1644*7c478bd9Sstevel@tonic-gate 			(void) snprintf(door_dp->audit_text,
1645*7c478bd9Sstevel@tonic-gate 				sizeof (door_dp->audit_text),
1646*7c478bd9Sstevel@tonic-gate 				dgettext(TEXT_DOMAIN, "from %s to %s"),
1647*7c478bd9Sstevel@tonic-gate 				old_state, new_state);
1648*7c478bd9Sstevel@tonic-gate 
1649*7c478bd9Sstevel@tonic-gate 			(void) snprintf(door_dp->audit_text1,
1650*7c478bd9Sstevel@tonic-gate 				sizeof (door_dp->audit_text1),
1651*7c478bd9Sstevel@tonic-gate 				"%s %s (%d,%d)", vid, pid,
1652*7c478bd9Sstevel@tonic-gate 				(int)major(door_dp->dd_stat.st_rdev),
1653*7c478bd9Sstevel@tonic-gate 				(int)minor(door_dp->dd_stat.st_rdev));
1654*7c478bd9Sstevel@tonic-gate 
1655*7c478bd9Sstevel@tonic-gate 			door_dp->audit_sorf = 1;
1656*7c478bd9Sstevel@tonic-gate 			if (audit_audit(door_dp) == -1)
1657*7c478bd9Sstevel@tonic-gate 			    warning("Error in writing audit info\n");
1658*7c478bd9Sstevel@tonic-gate 		}
1659*7c478bd9Sstevel@tonic-gate 	    } /* errno == EACCES */
1660*7c478bd9Sstevel@tonic-gate 	    errno = saved_errno;
1661*7c478bd9Sstevel@tonic-gate 	    return (-1);
1662*7c478bd9Sstevel@tonic-gate 	}
1663*7c478bd9Sstevel@tonic-gate 	if (can_audit()) {
1664*7c478bd9Sstevel@tonic-gate 		(void) snprintf(door_dp->audit_text,
1665*7c478bd9Sstevel@tonic-gate 			sizeof (door_dp->audit_text),
1666*7c478bd9Sstevel@tonic-gate 			dgettext(TEXT_DOMAIN, "from %s to %s"),
1667*7c478bd9Sstevel@tonic-gate 			old_state, new_state);
1668*7c478bd9Sstevel@tonic-gate 
1669*7c478bd9Sstevel@tonic-gate 		(void) snprintf(door_dp->audit_text1,
1670*7c478bd9Sstevel@tonic-gate 			sizeof (door_dp->audit_text1),
1671*7c478bd9Sstevel@tonic-gate 			"%s %s (%d,%d)", vid, pid,
1672*7c478bd9Sstevel@tonic-gate 			(int)major(door_dp->dd_stat.st_rdev),
1673*7c478bd9Sstevel@tonic-gate 			(int)minor(door_dp->dd_stat.st_rdev));
1674*7c478bd9Sstevel@tonic-gate 
1675*7c478bd9Sstevel@tonic-gate 		door_dp->audit_sorf = 0;
1676*7c478bd9Sstevel@tonic-gate 		if (audit_audit(door_dp) == -1)
1677*7c478bd9Sstevel@tonic-gate 		    warning("Error in writing audit info\n");
1678*7c478bd9Sstevel@tonic-gate 	}
1679*7c478bd9Sstevel@tonic-gate 	errno = saved_errno;
1680*7c478bd9Sstevel@tonic-gate 	return (0);
1681*7c478bd9Sstevel@tonic-gate }
1682*7c478bd9Sstevel@tonic-gate 
1683*7c478bd9Sstevel@tonic-gate static int32_t
1684*7c478bd9Sstevel@tonic-gate set_shfd(door_data_t	*door_dp, int32_t fd, smedia_services_t *req)
1685*7c478bd9Sstevel@tonic-gate {
1686*7c478bd9Sstevel@tonic-gate 	void	*fbuf;
1687*7c478bd9Sstevel@tonic-gate 	int32_t	ret_val;
1688*7c478bd9Sstevel@tonic-gate 
1689*7c478bd9Sstevel@tonic-gate 	if ((door_dp->dd_buffd != -1) &&
1690*7c478bd9Sstevel@tonic-gate 		(door_dp->dd_buf != NULL)) {
1691*7c478bd9Sstevel@tonic-gate 			ret_val = munmap(door_dp->dd_buf,
1692*7c478bd9Sstevel@tonic-gate 				door_dp->dd_buf_len);
1693*7c478bd9Sstevel@tonic-gate 			if (ret_val == -1)
1694*7c478bd9Sstevel@tonic-gate 				warning(gettext(
1695*7c478bd9Sstevel@tonic-gate 					"munmap failed. errno=%d\n"),
1696*7c478bd9Sstevel@tonic-gate 						errno);
1697*7c478bd9Sstevel@tonic-gate 			(void) close(door_dp->dd_buffd);
1698*7c478bd9Sstevel@tonic-gate 			door_dp->dd_buffd = -1;
1699*7c478bd9Sstevel@tonic-gate 			door_dp->dd_buf = 0;
1700*7c478bd9Sstevel@tonic-gate 			door_dp->dd_buf_len = 0;
1701*7c478bd9Sstevel@tonic-gate 	}
1702*7c478bd9Sstevel@tonic-gate 	fbuf = mmap(0, req->reqset_shfd.fdbuf_len,
1703*7c478bd9Sstevel@tonic-gate 		PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
1704*7c478bd9Sstevel@tonic-gate 	if (fbuf == (char *)-1) {
1705*7c478bd9Sstevel@tonic-gate 		debug(5, "mmap failed. errno=%d\n", errno);
1706*7c478bd9Sstevel@tonic-gate 		return (-1);
1707*7c478bd9Sstevel@tonic-gate 	}
1708*7c478bd9Sstevel@tonic-gate 	door_dp->dd_buffd = fd;
1709*7c478bd9Sstevel@tonic-gate 	door_dp->dd_buf = fbuf;
1710*7c478bd9Sstevel@tonic-gate 	door_dp->dd_buf_len = req->reqset_shfd.fdbuf_len;
1711*7c478bd9Sstevel@tonic-gate 	return (0);
1712*7c478bd9Sstevel@tonic-gate }
1713*7c478bd9Sstevel@tonic-gate 
1714*7c478bd9Sstevel@tonic-gate static int32_t
1715*7c478bd9Sstevel@tonic-gate reassign_block(door_data_t *door_dp, smedia_services_t *req)
1716*7c478bd9Sstevel@tonic-gate {
1717*7c478bd9Sstevel@tonic-gate 	struct uscsi_cmd	ucmd;
1718*7c478bd9Sstevel@tonic-gate 	union scsi_cdb		cdb;
1719*7c478bd9Sstevel@tonic-gate 	int32_t			ret_val;
1720*7c478bd9Sstevel@tonic-gate 	int32_t			sector_size;
1721*7c478bd9Sstevel@tonic-gate 	char			*read_buf;
1722*7c478bd9Sstevel@tonic-gate 	uchar_t			mode_data[MD_LEN];
1723*7c478bd9Sstevel@tonic-gate 
1724*7c478bd9Sstevel@tonic-gate 	if (get_mode_page(door_dp->dd_fd, 0, 1,
1725*7c478bd9Sstevel@tonic-gate 		mode_data, MD_LEN) < 0) {
1726*7c478bd9Sstevel@tonic-gate 		debug(5, "Mode sense failed\n");
1727*7c478bd9Sstevel@tonic-gate 		ret_val =  scsi_reassign_block(door_dp->dd_fd,
1728*7c478bd9Sstevel@tonic-gate 			req->reqreassign_block.blockno);
1729*7c478bd9Sstevel@tonic-gate 		if (ret_val != 0)
1730*7c478bd9Sstevel@tonic-gate 			return (-1);
1731*7c478bd9Sstevel@tonic-gate 		return (0);
1732*7c478bd9Sstevel@tonic-gate 	}
1733*7c478bd9Sstevel@tonic-gate 
1734*7c478bd9Sstevel@tonic-gate 	/*
1735*7c478bd9Sstevel@tonic-gate 	 * No need to check if enough data is returned for
1736*7c478bd9Sstevel@tonic-gate 	 * AWRE bit or not.
1737*7c478bd9Sstevel@tonic-gate 	 * It will be 0 otherwise which needs to reassign the block.
1738*7c478bd9Sstevel@tonic-gate 	 */
1739*7c478bd9Sstevel@tonic-gate 	if (!(mode_data[AWRE_OFFSET] & AWRE)) {
1740*7c478bd9Sstevel@tonic-gate 		debug(5, "AWRE bit not set\n");
1741*7c478bd9Sstevel@tonic-gate 		ret_val =  scsi_reassign_block(door_dp->dd_fd,
1742*7c478bd9Sstevel@tonic-gate 			req->reqreassign_block.blockno);
1743*7c478bd9Sstevel@tonic-gate 		if (ret_val != 0)
1744*7c478bd9Sstevel@tonic-gate 			return (-1);
1745*7c478bd9Sstevel@tonic-gate 		return (0);
1746*7c478bd9Sstevel@tonic-gate 	}
1747*7c478bd9Sstevel@tonic-gate 	sector_size = (mode_data[BLOCK_LEN_OFFSET] << 16) |
1748*7c478bd9Sstevel@tonic-gate 		(mode_data[BLOCK_LEN_OFFSET + 1] << 8) |
1749*7c478bd9Sstevel@tonic-gate 		mode_data[BLOCK_LEN_OFFSET + 2];
1750*7c478bd9Sstevel@tonic-gate 
1751*7c478bd9Sstevel@tonic-gate 	debug(5, "REASSIGN BLOCK: sec size = 0x%x\n", sector_size);
1752*7c478bd9Sstevel@tonic-gate 	read_buf = (char *)malloc(sector_size);
1753*7c478bd9Sstevel@tonic-gate 	if (read_buf == NULL) {
1754*7c478bd9Sstevel@tonic-gate 		/* Alloc failed. Atleast reassign the block */
1755*7c478bd9Sstevel@tonic-gate 		ret_val =  scsi_reassign_block(door_dp->dd_fd,
1756*7c478bd9Sstevel@tonic-gate 			req->reqreassign_block.blockno);
1757*7c478bd9Sstevel@tonic-gate 		if (ret_val != 0)
1758*7c478bd9Sstevel@tonic-gate 			return (-1);
1759*7c478bd9Sstevel@tonic-gate 		return (0);
1760*7c478bd9Sstevel@tonic-gate 	}
1761*7c478bd9Sstevel@tonic-gate 
1762*7c478bd9Sstevel@tonic-gate 	(void) memset(read_buf, 0, sector_size);
1763*7c478bd9Sstevel@tonic-gate 	/* Read the sector */
1764*7c478bd9Sstevel@tonic-gate 	debug(5, "Reading the block %d\n",
1765*7c478bd9Sstevel@tonic-gate 		(uint32_t)req->reqreassign_block.blockno);
1766*7c478bd9Sstevel@tonic-gate 
1767*7c478bd9Sstevel@tonic-gate 	(void) memset((void *) &ucmd, 0, sizeof (ucmd));
1768*7c478bd9Sstevel@tonic-gate 	(void) memset((void *) &cdb, 0, sizeof (union scsi_cdb));
1769*7c478bd9Sstevel@tonic-gate 
1770*7c478bd9Sstevel@tonic-gate 	cdb.scc_cmd = SCMD_READ_G1;
1771*7c478bd9Sstevel@tonic-gate 	FORMG1ADDR(&cdb, req->reqreassign_block.blockno);
1772*7c478bd9Sstevel@tonic-gate 	FORMG1COUNT(&cdb, 1);	/* One block */
1773*7c478bd9Sstevel@tonic-gate 
1774*7c478bd9Sstevel@tonic-gate 	ucmd.uscsi_cdb = (caddr_t)&cdb;
1775*7c478bd9Sstevel@tonic-gate 	ucmd.uscsi_cdblen = CDB_GROUP1;
1776*7c478bd9Sstevel@tonic-gate 	ucmd.uscsi_bufaddr = (caddr_t)read_buf;
1777*7c478bd9Sstevel@tonic-gate 	ucmd.uscsi_buflen = sector_size;
1778*7c478bd9Sstevel@tonic-gate 	ucmd.uscsi_timeout = 120;	/* If 0, HBA hangs forever */
1779*7c478bd9Sstevel@tonic-gate 	(void) do_uscsi_cmd(door_dp->dd_fd, &ucmd, USCSI_READ);
1780*7c478bd9Sstevel@tonic-gate 
1781*7c478bd9Sstevel@tonic-gate 	/* Write the data back */
1782*7c478bd9Sstevel@tonic-gate 
1783*7c478bd9Sstevel@tonic-gate 	debug(5, "Writing the block %d\n",
1784*7c478bd9Sstevel@tonic-gate 		(uint32_t)req->reqreassign_block.blockno);
1785*7c478bd9Sstevel@tonic-gate 	(void) memset((void *) &ucmd, 0, sizeof (ucmd));
1786*7c478bd9Sstevel@tonic-gate 	(void) memset((void *) &cdb, 0, sizeof (cdb));
1787*7c478bd9Sstevel@tonic-gate 
1788*7c478bd9Sstevel@tonic-gate 	cdb.scc_cmd = SCMD_WRITE_G1;
1789*7c478bd9Sstevel@tonic-gate 	FORMG1ADDR(&cdb, req->reqreassign_block.blockno);
1790*7c478bd9Sstevel@tonic-gate 	FORMG1COUNT(&cdb, 1);	/* One block */
1791*7c478bd9Sstevel@tonic-gate 
1792*7c478bd9Sstevel@tonic-gate 	ucmd.uscsi_cdb = (caddr_t)&cdb;
1793*7c478bd9Sstevel@tonic-gate 	ucmd.uscsi_cdblen = CDB_GROUP1;
1794*7c478bd9Sstevel@tonic-gate 	ucmd.uscsi_bufaddr = (caddr_t)read_buf;
1795*7c478bd9Sstevel@tonic-gate 	ucmd.uscsi_buflen = sector_size;
1796*7c478bd9Sstevel@tonic-gate 	ucmd.uscsi_timeout = 120;	/* If 0, HBA hangs forever */
1797*7c478bd9Sstevel@tonic-gate 	ret_val = do_uscsi_cmd(door_dp->dd_fd, &ucmd, USCSI_WRITE);
1798*7c478bd9Sstevel@tonic-gate 	free(read_buf);
1799*7c478bd9Sstevel@tonic-gate 	if (ret_val || ucmd.uscsi_status) {
1800*7c478bd9Sstevel@tonic-gate 		debug(5, "Reassign failed: %d - %d errno = %d\n",
1801*7c478bd9Sstevel@tonic-gate 			ret_val, ucmd.uscsi_status, errno);
1802*7c478bd9Sstevel@tonic-gate 		ret_val = scsi_reassign_block(door_dp->dd_fd,
1803*7c478bd9Sstevel@tonic-gate 			req->reqreassign_block.blockno);
1804*7c478bd9Sstevel@tonic-gate 		if (ret_val != 0)
1805*7c478bd9Sstevel@tonic-gate 			return (-1);
1806*7c478bd9Sstevel@tonic-gate 		return (0);
1807*7c478bd9Sstevel@tonic-gate 	}
1808*7c478bd9Sstevel@tonic-gate 
1809*7c478bd9Sstevel@tonic-gate 	return (0);
1810*7c478bd9Sstevel@tonic-gate }
1811*7c478bd9Sstevel@tonic-gate 
1812*7c478bd9Sstevel@tonic-gate static void
1813*7c478bd9Sstevel@tonic-gate close_door_descs(door_desc_t *dp, uint_t ndesc)
1814*7c478bd9Sstevel@tonic-gate {
1815*7c478bd9Sstevel@tonic-gate 	while (ndesc > 0) {
1816*7c478bd9Sstevel@tonic-gate 		int fd = dp->d_data.d_desc.d_descriptor;
1817*7c478bd9Sstevel@tonic-gate 		if (dp->d_attributes & DOOR_DESCRIPTOR)
1818*7c478bd9Sstevel@tonic-gate 			(void) close(fd);
1819*7c478bd9Sstevel@tonic-gate 		dp++;
1820*7c478bd9Sstevel@tonic-gate 		ndesc--;
1821*7c478bd9Sstevel@tonic-gate 	}
1822*7c478bd9Sstevel@tonic-gate }
1823*7c478bd9Sstevel@tonic-gate 
1824*7c478bd9Sstevel@tonic-gate static void
1825*7c478bd9Sstevel@tonic-gate client_server(void *cookie, char *argp, size_t arg_size,
1826*7c478bd9Sstevel@tonic-gate     door_desc_t *dp, uint_t ndesc)
1827*7c478bd9Sstevel@tonic-gate {
1828*7c478bd9Sstevel@tonic-gate 	smedia_services_t	*req;
1829*7c478bd9Sstevel@tonic-gate 	smedia_services_t	rmsvc;
1830*7c478bd9Sstevel@tonic-gate 	smedia_reterror_t	reterror;
1831*7c478bd9Sstevel@tonic-gate 	smedia_retraw_read_t	retraw_read;
1832*7c478bd9Sstevel@tonic-gate 	struct scsi_inquiry	inq;
1833*7c478bd9Sstevel@tonic-gate 	struct dk_minfo		media_info;
1834*7c478bd9Sstevel@tonic-gate 	struct dk_geom		dkgeom;
1835*7c478bd9Sstevel@tonic-gate 	int32_t			status;
1836*7c478bd9Sstevel@tonic-gate 	uchar_t			data[18];
1837*7c478bd9Sstevel@tonic-gate 	int32_t			completed = 0;
1838*7c478bd9Sstevel@tonic-gate 	door_data_t		*door_dp;
1839*7c478bd9Sstevel@tonic-gate 	size_t			retbuf_size;
1840*7c478bd9Sstevel@tonic-gate 	struct uscsi_cmd	ucmd;
1841*7c478bd9Sstevel@tonic-gate 	union scsi_cdb		cdb;
1842*7c478bd9Sstevel@tonic-gate 	int32_t			ret_val, err;
1843*7c478bd9Sstevel@tonic-gate 	char			rq_data[RQ_LEN];
1844*7c478bd9Sstevel@tonic-gate 	uint_t			expected_descs;
1845*7c478bd9Sstevel@tonic-gate 	struct vtoc		vtoc;
1846*7c478bd9Sstevel@tonic-gate 
1847*7c478bd9Sstevel@tonic-gate 	door_dp = (door_data_t *)cookie;
1848*7c478bd9Sstevel@tonic-gate 	req = (smedia_services_t *)((void *)argp);
1849*7c478bd9Sstevel@tonic-gate 
1850*7c478bd9Sstevel@tonic-gate 	debug(10, "Entering client server...\n");
1851*7c478bd9Sstevel@tonic-gate 
1852*7c478bd9Sstevel@tonic-gate 	if (argp == DOOR_UNREF_DATA) {
1853*7c478bd9Sstevel@tonic-gate 		debug(5, "client_server[%d]...DOOR_UNREF_DATA\n",
1854*7c478bd9Sstevel@tonic-gate 			pthread_self());
1855*7c478bd9Sstevel@tonic-gate 		debug(5, "Client has exited. Cleaning up resources\n");
1856*7c478bd9Sstevel@tonic-gate 		(void) mutex_lock(&svcstate_lock);
1857*7c478bd9Sstevel@tonic-gate 		svccount--;
1858*7c478bd9Sstevel@tonic-gate 		(void) mutex_unlock(&svcstate_lock);
1859*7c478bd9Sstevel@tonic-gate 		cleanup(door_dp);
1860*7c478bd9Sstevel@tonic-gate 		(void) door_return(NULL, 0, NULL, 0);
1861*7c478bd9Sstevel@tonic-gate 	}
1862*7c478bd9Sstevel@tonic-gate 	/*
1863*7c478bd9Sstevel@tonic-gate 	 * we disable thread cancellation while holding locks.
1864*7c478bd9Sstevel@tonic-gate 	 */
1865*7c478bd9Sstevel@tonic-gate 	if (pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL) != 0)
1866*7c478bd9Sstevel@tonic-gate 		warning(gettext("pthread_setcancelstate failed. errno = %d\n"),
1867*7c478bd9Sstevel@tonic-gate 			errno);
1868*7c478bd9Sstevel@tonic-gate 	(void) mutex_lock(&svcstate_lock);
1869*7c478bd9Sstevel@tonic-gate 	svcstate = _SERVED;
1870*7c478bd9Sstevel@tonic-gate 	(void) mutex_unlock(&svcstate_lock);
1871*7c478bd9Sstevel@tonic-gate 	if (pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL) != 0)
1872*7c478bd9Sstevel@tonic-gate 		warning(gettext("pthread_setcancelstate failed. errno = %d\n"),
1873*7c478bd9Sstevel@tonic-gate 			errno);
1874*7c478bd9Sstevel@tonic-gate 
1875*7c478bd9Sstevel@tonic-gate 	rmsvc.in.cnum = req->in.cnum;
1876*7c478bd9Sstevel@tonic-gate 	debug(5, "client_server[%d]...req = %s\n", pthread_self(),
1877*7c478bd9Sstevel@tonic-gate 		xlate_cnum(req->in.cnum));
1878*7c478bd9Sstevel@tonic-gate 
1879*7c478bd9Sstevel@tonic-gate 	/*
1880*7c478bd9Sstevel@tonic-gate 	 * Our caller may have passed more descriptors than we expected.
1881*7c478bd9Sstevel@tonic-gate 	 * If so, we silently close (and ignore) them.
1882*7c478bd9Sstevel@tonic-gate 	 */
1883*7c478bd9Sstevel@tonic-gate 	if (req->in.cnum == SMEDIA_CNUM_SET_SHFD)
1884*7c478bd9Sstevel@tonic-gate 		expected_descs = 1;
1885*7c478bd9Sstevel@tonic-gate 	else
1886*7c478bd9Sstevel@tonic-gate 		expected_descs = 0;
1887*7c478bd9Sstevel@tonic-gate 
1888*7c478bd9Sstevel@tonic-gate 	if (ndesc > expected_descs)
1889*7c478bd9Sstevel@tonic-gate 		close_door_descs(dp + expected_descs, ndesc - expected_descs);
1890*7c478bd9Sstevel@tonic-gate 
1891*7c478bd9Sstevel@tonic-gate 	switch (req->in.cnum) {
1892*7c478bd9Sstevel@tonic-gate 
1893*7c478bd9Sstevel@tonic-gate 	default:
1894*7c478bd9Sstevel@tonic-gate 		debug(5, "unknown command %d\n", req->in.cnum);
1895*7c478bd9Sstevel@tonic-gate 		door_ret_err(&reterror, ENOTSUP);
1896*7c478bd9Sstevel@tonic-gate 		break;
1897*7c478bd9Sstevel@tonic-gate 
1898*7c478bd9Sstevel@tonic-gate 	case	SMEDIA_CNUM_SET_SHFD:
1899*7c478bd9Sstevel@tonic-gate 		if (ndesc == 0)
1900*7c478bd9Sstevel@tonic-gate 			door_ret_err(&reterror, EINVAL);
1901*7c478bd9Sstevel@tonic-gate 		/*
1902*7c478bd9Sstevel@tonic-gate 		 * If an 0ld mapping exists destroy it before creaing
1903*7c478bd9Sstevel@tonic-gate 		 * a new map.
1904*7c478bd9Sstevel@tonic-gate 		 */
1905*7c478bd9Sstevel@tonic-gate 		ret_val =
1906*7c478bd9Sstevel@tonic-gate 			set_shfd(door_dp, dp->d_data.d_desc.d_descriptor, req);
1907*7c478bd9Sstevel@tonic-gate 		if (ret_val == 0) {
1908*7c478bd9Sstevel@tonic-gate 			reterror.cnum = SMEDIA_CNUM_SET_SHFD;
1909*7c478bd9Sstevel@tonic-gate 			reterror.errnum = 0;
1910*7c478bd9Sstevel@tonic-gate 			my_door_return((char *)&reterror,
1911*7c478bd9Sstevel@tonic-gate 				sizeof (smedia_reterror_t), 0, 0);
1912*7c478bd9Sstevel@tonic-gate 		} else {
1913*7c478bd9Sstevel@tonic-gate 			(void) close(dp->d_data.d_desc.d_descriptor);
1914*7c478bd9Sstevel@tonic-gate 			door_ret_err(&reterror, errno);
1915*7c478bd9Sstevel@tonic-gate 		}
1916*7c478bd9Sstevel@tonic-gate 
1917*7c478bd9Sstevel@tonic-gate 		break;
1918*7c478bd9Sstevel@tonic-gate 
1919*7c478bd9Sstevel@tonic-gate 	case	SMEDIA_CNUM_RAW_READ:
1920*7c478bd9Sstevel@tonic-gate 		debug(10, " arg size = %d blk num=0x%x nbytes = 0x%x \n",
1921*7c478bd9Sstevel@tonic-gate 			(int)arg_size,
1922*7c478bd9Sstevel@tonic-gate 			(uint32_t)req->reqraw_read.blockno,
1923*7c478bd9Sstevel@tonic-gate 			req->reqraw_read.nbytes);
1924*7c478bd9Sstevel@tonic-gate 		retbuf_size = sizeof (smedia_retraw_read_t);
1925*7c478bd9Sstevel@tonic-gate 		if (req->reqraw_read.nbytes == 0) {
1926*7c478bd9Sstevel@tonic-gate 			/* Nothing to write */
1927*7c478bd9Sstevel@tonic-gate 			rmsvc.retraw_write.nbytes = 0;
1928*7c478bd9Sstevel@tonic-gate 			my_door_return((char *)&rmsvc,
1929*7c478bd9Sstevel@tonic-gate 				sizeof (smedia_retraw_write_t), 0, 0);
1930*7c478bd9Sstevel@tonic-gate 		}
1931*7c478bd9Sstevel@tonic-gate 		retraw_read.cnum = SMEDIA_CNUM_RAW_READ;
1932*7c478bd9Sstevel@tonic-gate 		ret_val = raw_read(door_dp, req);
1933*7c478bd9Sstevel@tonic-gate 		if (ret_val == -1) {
1934*7c478bd9Sstevel@tonic-gate 			door_ret_err(&reterror, errno);
1935*7c478bd9Sstevel@tonic-gate 		}
1936*7c478bd9Sstevel@tonic-gate 		retraw_read.nbytes = ret_val;
1937*7c478bd9Sstevel@tonic-gate 		my_door_return((char *)&retraw_read, retbuf_size, 0, 0);
1938*7c478bd9Sstevel@tonic-gate 		break;
1939*7c478bd9Sstevel@tonic-gate 
1940*7c478bd9Sstevel@tonic-gate 	case	SMEDIA_CNUM_USCSI_CMD:
1941*7c478bd9Sstevel@tonic-gate 		retbuf_size = sizeof (smedia_retuscsi_cmd_t);
1942*7c478bd9Sstevel@tonic-gate 		rmsvc.retuscsi_cmd.cnum = SMEDIA_CNUM_USCSI_CMD;
1943*7c478bd9Sstevel@tonic-gate 		ucmd.uscsi_flags = req->requscsi_cmd.uscsi_flags;
1944*7c478bd9Sstevel@tonic-gate 		ucmd.uscsi_cdb = (caddr_t)&req->requscsi_cmd.uscsi_cdb;
1945*7c478bd9Sstevel@tonic-gate 		ucmd.uscsi_cdblen = req->requscsi_cmd.uscsi_cdblen;
1946*7c478bd9Sstevel@tonic-gate 		ucmd.uscsi_bufaddr = (caddr_t)door_dp->dd_buf;
1947*7c478bd9Sstevel@tonic-gate 		ucmd.uscsi_buflen = req->requscsi_cmd.uscsi_buflen;
1948*7c478bd9Sstevel@tonic-gate 		ucmd.uscsi_timeout = req->requscsi_cmd.uscsi_timeout;
1949*7c478bd9Sstevel@tonic-gate 		ucmd.uscsi_rqlen = req->requscsi_cmd.uscsi_rqlen;
1950*7c478bd9Sstevel@tonic-gate 		ucmd.uscsi_rqbuf = (caddr_t)&rmsvc.retuscsi_cmd.uscsi_rqbuf;
1951*7c478bd9Sstevel@tonic-gate 		debug(5,
1952*7c478bd9Sstevel@tonic-gate 		"USCSI CMD 0x%x requested.\n",
1953*7c478bd9Sstevel@tonic-gate 		    req->requscsi_cmd.uscsi_cdb[0]);
1954*7c478bd9Sstevel@tonic-gate 		/*
1955*7c478bd9Sstevel@tonic-gate 		 * Check the device type and invalid flags specified.
1956*7c478bd9Sstevel@tonic-gate 		 * We permit operations only on CDROM devices types.
1957*7c478bd9Sstevel@tonic-gate 		 */
1958*7c478bd9Sstevel@tonic-gate 		errno = invalid_uscsi_operation(door_dp,
1959*7c478bd9Sstevel@tonic-gate 				&ucmd);
1960*7c478bd9Sstevel@tonic-gate 		if (errno) {
1961*7c478bd9Sstevel@tonic-gate 			door_ret_err(&reterror, errno);
1962*7c478bd9Sstevel@tonic-gate 		}
1963*7c478bd9Sstevel@tonic-gate 
1964*7c478bd9Sstevel@tonic-gate 		if ((req->requscsi_cmd.uscsi_buflen) &&
1965*7c478bd9Sstevel@tonic-gate 		    ((req->requscsi_cmd.uscsi_buflen > door_dp->dd_buf_len) ||
1966*7c478bd9Sstevel@tonic-gate 		    (door_dp->dd_buf == NULL))) {
1967*7c478bd9Sstevel@tonic-gate 			debug(5,
1968*7c478bd9Sstevel@tonic-gate 	"uscsi_cmd failed: uscsi_buflen=0x%x dd_buf_len=0x%x dd_buf=0x%p\n",
1969*7c478bd9Sstevel@tonic-gate 				req->requscsi_cmd.uscsi_buflen,
1970*7c478bd9Sstevel@tonic-gate 				door_dp->dd_buf_len,
1971*7c478bd9Sstevel@tonic-gate 				door_dp->dd_buf);
1972*7c478bd9Sstevel@tonic-gate 			errno = EINVAL;
1973*7c478bd9Sstevel@tonic-gate 			door_ret_err(&reterror, errno);
1974*7c478bd9Sstevel@tonic-gate 		}
1975*7c478bd9Sstevel@tonic-gate 		ret_val = do_uscsi_cmd(door_dp->dd_fd,
1976*7c478bd9Sstevel@tonic-gate 			&ucmd, req->requscsi_cmd.uscsi_flags);
1977*7c478bd9Sstevel@tonic-gate 		rmsvc.retuscsi_cmd.uscsi_status = ucmd.uscsi_status;
1978*7c478bd9Sstevel@tonic-gate 		rmsvc.retuscsi_cmd.uscsi_resid = ucmd.uscsi_resid;
1979*7c478bd9Sstevel@tonic-gate 		rmsvc.retuscsi_cmd.uscsi_rqstatus = ucmd.uscsi_rqstatus;
1980*7c478bd9Sstevel@tonic-gate 		rmsvc.retuscsi_cmd.uscsi_rqresid = ucmd.uscsi_rqresid;
1981*7c478bd9Sstevel@tonic-gate 		rmsvc.retuscsi_cmd.uscsi_retval = ret_val;
1982*7c478bd9Sstevel@tonic-gate 		rmsvc.retuscsi_cmd.uscsi_errno = errno;
1983*7c478bd9Sstevel@tonic-gate 		if (ret_val || ucmd.uscsi_status) {
1984*7c478bd9Sstevel@tonic-gate 			debug(5, "uscsi_cmd failed: %d - %d errno = %d\n",
1985*7c478bd9Sstevel@tonic-gate 				ret_val, ucmd.uscsi_status, errno);
1986*7c478bd9Sstevel@tonic-gate 		}
1987*7c478bd9Sstevel@tonic-gate 		my_door_return((char *)&rmsvc, retbuf_size, 0, 0);
1988*7c478bd9Sstevel@tonic-gate 		break;
1989*7c478bd9Sstevel@tonic-gate 
1990*7c478bd9Sstevel@tonic-gate 	case SMEDIA_CNUM_RAW_WRITE:
1991*7c478bd9Sstevel@tonic-gate 		if (req->reqraw_write.nbytes == 0) {
1992*7c478bd9Sstevel@tonic-gate 			/* Nothing to write */
1993*7c478bd9Sstevel@tonic-gate 			rmsvc.retraw_write.nbytes = 0;
1994*7c478bd9Sstevel@tonic-gate 			my_door_return((char *)&rmsvc,
1995*7c478bd9Sstevel@tonic-gate 				sizeof (smedia_retraw_write_t), 0, 0);
1996*7c478bd9Sstevel@tonic-gate 		}
1997*7c478bd9Sstevel@tonic-gate 		ret_val = raw_write(door_dp, req);
1998*7c478bd9Sstevel@tonic-gate 		if (ret_val == -1)
1999*7c478bd9Sstevel@tonic-gate 			door_ret_err(&reterror, errno);
2000*7c478bd9Sstevel@tonic-gate 		rmsvc.retraw_write.nbytes = ret_val;
2001*7c478bd9Sstevel@tonic-gate 		my_door_return((char *)&rmsvc, sizeof (smedia_retraw_write_t),
2002*7c478bd9Sstevel@tonic-gate 			0, 0);
2003*7c478bd9Sstevel@tonic-gate 		break;
2004*7c478bd9Sstevel@tonic-gate 
2005*7c478bd9Sstevel@tonic-gate 	case SMEDIA_CNUM_GET_DEVICE_INFO:
2006*7c478bd9Sstevel@tonic-gate 
2007*7c478bd9Sstevel@tonic-gate 		(void) memset((void *) &inq, 0, sizeof (inq));
2008*7c478bd9Sstevel@tonic-gate 		(void) memset((void *) &ucmd, 0, sizeof (ucmd));
2009*7c478bd9Sstevel@tonic-gate 		(void) memset((void *) &cdb, 0, sizeof (union scsi_cdb));
2010*7c478bd9Sstevel@tonic-gate 		cdb.scc_cmd = SCMD_INQUIRY;
2011*7c478bd9Sstevel@tonic-gate 		FORMG0COUNT(&cdb, sizeof (inq));
2012*7c478bd9Sstevel@tonic-gate 		ucmd.uscsi_cdb = (caddr_t)&cdb;
2013*7c478bd9Sstevel@tonic-gate 		ucmd.uscsi_cdblen = CDB_GROUP0;
2014*7c478bd9Sstevel@tonic-gate 		ucmd.uscsi_bufaddr = (caddr_t)&inq;
2015*7c478bd9Sstevel@tonic-gate 		ucmd.uscsi_buflen = sizeof (inq);
2016*7c478bd9Sstevel@tonic-gate 		ucmd.uscsi_timeout = 120;	/* If 0, HBA hangs forever */
2017*7c478bd9Sstevel@tonic-gate 		ucmd.uscsi_rqlen = RQ_LEN;
2018*7c478bd9Sstevel@tonic-gate 		ucmd.uscsi_rqbuf = rq_data;
2019*7c478bd9Sstevel@tonic-gate 		ret_val = do_uscsi_cmd(door_dp->dd_fd,
2020*7c478bd9Sstevel@tonic-gate 			&ucmd, USCSI_READ|USCSI_RQENABLE);
2021*7c478bd9Sstevel@tonic-gate 		if (ret_val || ucmd.uscsi_status) {
2022*7c478bd9Sstevel@tonic-gate 			debug(5, "inquiry failed: %d - %d errno = %d\n",
2023*7c478bd9Sstevel@tonic-gate 				ret_val, ucmd.uscsi_status, errno);
2024*7c478bd9Sstevel@tonic-gate 			door_ret_err(&reterror, errno);
2025*7c478bd9Sstevel@tonic-gate 		}
2026*7c478bd9Sstevel@tonic-gate 
2027*7c478bd9Sstevel@tonic-gate 		debug(5, "%s\n", inq.inq_vid);
2028*7c478bd9Sstevel@tonic-gate 		debug(5, "%s\n", rmsvc.retget_device_info.sm_vendor_name);
2029*7c478bd9Sstevel@tonic-gate 
2030*7c478bd9Sstevel@tonic-gate 		(void) strlcpy(rmsvc.retget_device_info.sm_vendor_name,
2031*7c478bd9Sstevel@tonic-gate 			inq.inq_vid, 8);
2032*7c478bd9Sstevel@tonic-gate 		rmsvc.retget_device_info.sm_vendor_name[8] = 0;
2033*7c478bd9Sstevel@tonic-gate 		(void) strlcpy(rmsvc.retget_device_info.sm_product_name,
2034*7c478bd9Sstevel@tonic-gate 			inq.inq_pid, 16);
2035*7c478bd9Sstevel@tonic-gate 		rmsvc.retget_device_info.sm_product_name[16] = 0;
2036*7c478bd9Sstevel@tonic-gate 		(void) strlcpy(rmsvc.retget_device_info.sm_firmware_version,
2037*7c478bd9Sstevel@tonic-gate 			inq.inq_revision, 4);
2038*7c478bd9Sstevel@tonic-gate 		rmsvc.retget_device_info.sm_firmware_version[4] = ' ';
2039*7c478bd9Sstevel@tonic-gate 		(void) strlcpy(
2040*7c478bd9Sstevel@tonic-gate 			&rmsvc.retget_device_info.sm_firmware_version[5],
2041*7c478bd9Sstevel@tonic-gate 				inq.inq_serial, 12);
2042*7c478bd9Sstevel@tonic-gate 		rmsvc.retget_device_info.sm_product_name[17] = 0;
2043*7c478bd9Sstevel@tonic-gate 
2044*7c478bd9Sstevel@tonic-gate 		rmsvc.retget_device_info.sm_interface_type = IF_SCSI;
2045*7c478bd9Sstevel@tonic-gate 
2046*7c478bd9Sstevel@tonic-gate 		debug(5,
2047*7c478bd9Sstevel@tonic-gate 	"Vendor name = %s\n", rmsvc.retget_device_info.sm_vendor_name);
2048*7c478bd9Sstevel@tonic-gate 		debug(5,
2049*7c478bd9Sstevel@tonic-gate 	"product name = %s\n", rmsvc.retget_device_info.sm_product_name);
2050*7c478bd9Sstevel@tonic-gate 		debug(5,
2051*7c478bd9Sstevel@tonic-gate "Firmware revision = %s\n", rmsvc.retget_device_info.sm_firmware_version);
2052*7c478bd9Sstevel@tonic-gate 		my_door_return((char *)&rmsvc.retget_device_info,
2053*7c478bd9Sstevel@tonic-gate 			sizeof (smedia_retget_device_info_t), 0, 0);
2054*7c478bd9Sstevel@tonic-gate 
2055*7c478bd9Sstevel@tonic-gate 		break;
2056*7c478bd9Sstevel@tonic-gate 
2057*7c478bd9Sstevel@tonic-gate 	case	SMEDIA_CNUM_GET_MEDIUM_PROPERTY:
2058*7c478bd9Sstevel@tonic-gate 
2059*7c478bd9Sstevel@tonic-gate 		(void) memset((void *)&rmsvc.retget_medium_property.smprop,
2060*7c478bd9Sstevel@tonic-gate 			0, sizeof (smmedium_prop_t));
2061*7c478bd9Sstevel@tonic-gate 
2062*7c478bd9Sstevel@tonic-gate 		ret_val = ioctl(door_dp->dd_fd, DKIOCGMEDIAINFO, &media_info);
2063*7c478bd9Sstevel@tonic-gate 
2064*7c478bd9Sstevel@tonic-gate 		if (ret_val < 0) {
2065*7c478bd9Sstevel@tonic-gate 			uint32_t capacity;
2066*7c478bd9Sstevel@tonic-gate 			uint32_t blocksize;
2067*7c478bd9Sstevel@tonic-gate 			/*
2068*7c478bd9Sstevel@tonic-gate 			 * Devices may fail DKIOCGMEDIAINFO if an unformed
2069*7c478bd9Sstevel@tonic-gate 			 * media is inserted. We can get the capacity
2070*7c478bd9Sstevel@tonic-gate 			 * information from the SCMD_READ_FORMAT_CAP command.
2071*7c478bd9Sstevel@tonic-gate 			 */
2072*7c478bd9Sstevel@tonic-gate 
2073*7c478bd9Sstevel@tonic-gate 			debug(5, "DKIOCGMEDIAINFO failed");
2074*7c478bd9Sstevel@tonic-gate 
2075*7c478bd9Sstevel@tonic-gate 			debug(5, "using SCMD_READ_FORMAT_CAP");
2076*7c478bd9Sstevel@tonic-gate 			ret_val = get_media_capacity(door_dp->dd_fd,
2077*7c478bd9Sstevel@tonic-gate 			    &capacity, &blocksize);
2078*7c478bd9Sstevel@tonic-gate 
2079*7c478bd9Sstevel@tonic-gate 			if (ret_val >= 0) {
2080*7c478bd9Sstevel@tonic-gate 				media_info.dki_lbsize =	blocksize;
2081*7c478bd9Sstevel@tonic-gate 				media_info.dki_capacity = capacity;
2082*7c478bd9Sstevel@tonic-gate 			} else {
2083*7c478bd9Sstevel@tonic-gate 				debug(5, "SCMD_READ_FORMAT_CAP failed");
2084*7c478bd9Sstevel@tonic-gate 				door_ret_err(&reterror, errno);
2085*7c478bd9Sstevel@tonic-gate 			}
2086*7c478bd9Sstevel@tonic-gate 
2087*7c478bd9Sstevel@tonic-gate 		}
2088*7c478bd9Sstevel@tonic-gate 		rmsvc.retget_medium_property.smprop.sm_blocksize =
2089*7c478bd9Sstevel@tonic-gate 		    media_info.dki_lbsize;
2090*7c478bd9Sstevel@tonic-gate 		rmsvc.retget_medium_property.smprop.sm_capacity =
2091*7c478bd9Sstevel@tonic-gate 		    media_info.dki_capacity;
2092*7c478bd9Sstevel@tonic-gate 
2093*7c478bd9Sstevel@tonic-gate 		rmsvc.retget_medium_property.smprop.sm_media_type =
2094*7c478bd9Sstevel@tonic-gate 		    media_info.dki_media_type;
2095*7c478bd9Sstevel@tonic-gate 		/*
2096*7c478bd9Sstevel@tonic-gate 		 * These devices show as SCSI devices but we need to treat it
2097*7c478bd9Sstevel@tonic-gate 		 * differently. so we need a seperate class.
2098*7c478bd9Sstevel@tonic-gate 		 */
2099*7c478bd9Sstevel@tonic-gate 		if (get_device_type_scsi(door_dp->dd_fd, &inq) == SCSI_FLOPPY) {
2100*7c478bd9Sstevel@tonic-gate 			rmsvc.retget_medium_property.smprop.sm_media_type =
2101*7c478bd9Sstevel@tonic-gate 			    SM_SCSI_FLOPPY;
2102*7c478bd9Sstevel@tonic-gate 		}
2103*7c478bd9Sstevel@tonic-gate 
2104*7c478bd9Sstevel@tonic-gate 		/* Check for EFI type because DKIOCGGEOM does not support EFI */
2105*7c478bd9Sstevel@tonic-gate 		ret_val = ioctl(door_dp->dd_fd, DKIOCGVTOC, &vtoc);
2106*7c478bd9Sstevel@tonic-gate 		if (!((ret_val < 0) && (errno == ENOTSUP))) {
2107*7c478bd9Sstevel@tonic-gate 			ret_val = ioctl(door_dp->dd_fd, DKIOCGGEOM, &dkgeom);
2108*7c478bd9Sstevel@tonic-gate 			if (ret_val < 0)  {
2109*7c478bd9Sstevel@tonic-gate 				/*
2110*7c478bd9Sstevel@tonic-gate 				 * DKIOCGGEOM may fail for unformed floppies.
2111*7c478bd9Sstevel@tonic-gate 				 * We need to generate the appropriate geometry
2112*7c478bd9Sstevel@tonic-gate 				 * information.
2113*7c478bd9Sstevel@tonic-gate 				 */
2114*7c478bd9Sstevel@tonic-gate 				if (rmsvc.retget_medium_property.smprop.
2115*7c478bd9Sstevel@tonic-gate 				    sm_media_type == SM_SCSI_FLOPPY) {
2116*7c478bd9Sstevel@tonic-gate 					ret_val = get_floppy_geom(
2117*7c478bd9Sstevel@tonic-gate 					    door_dp->dd_fd,
2118*7c478bd9Sstevel@tonic-gate 					    media_info.dki_capacity, &dkgeom);
2119*7c478bd9Sstevel@tonic-gate 
2120*7c478bd9Sstevel@tonic-gate 					if (ret_val < 0) {
2121*7c478bd9Sstevel@tonic-gate 						debug(5, "Cannot determine "
2122*7c478bd9Sstevel@tonic-gate 						    "media size");
2123*7c478bd9Sstevel@tonic-gate 						door_ret_err(&reterror, errno);
2124*7c478bd9Sstevel@tonic-gate 					}
2125*7c478bd9Sstevel@tonic-gate 				} else {
2126*7c478bd9Sstevel@tonic-gate #ifdef sparc
2127*7c478bd9Sstevel@tonic-gate 					debug(5, "DKIOCGGEOM ioctl failed");
2128*7c478bd9Sstevel@tonic-gate 					door_ret_err(&reterror, errno);
2129*7c478bd9Sstevel@tonic-gate #else /* !sparc */
2130*7c478bd9Sstevel@tonic-gate 					/*
2131*7c478bd9Sstevel@tonic-gate 					 * Try getting Physical geometry on x86.
2132*7c478bd9Sstevel@tonic-gate 					 */
2133*7c478bd9Sstevel@tonic-gate 					ret_val = ioctl(door_dp->dd_fd,
2134*7c478bd9Sstevel@tonic-gate 					    DKIOCG_PHYGEOM, &dkgeom);
2135*7c478bd9Sstevel@tonic-gate 					if (ret_val < 0) {
2136*7c478bd9Sstevel@tonic-gate 						debug(5, "DKIOCG_PHYGEOM "
2137*7c478bd9Sstevel@tonic-gate 						    "ioctl failed");
2138*7c478bd9Sstevel@tonic-gate 						door_ret_err(&reterror, errno);
2139*7c478bd9Sstevel@tonic-gate 					}
2140*7c478bd9Sstevel@tonic-gate #endif /* sparc */
2141*7c478bd9Sstevel@tonic-gate 				}
2142*7c478bd9Sstevel@tonic-gate 			}
2143*7c478bd9Sstevel@tonic-gate 
2144*7c478bd9Sstevel@tonic-gate 
2145*7c478bd9Sstevel@tonic-gate 			/*
2146*7c478bd9Sstevel@tonic-gate 			 * Some faked geometry may not have pcyl filled in so
2147*7c478bd9Sstevel@tonic-gate 			 * later calculations using this field will be
2148*7c478bd9Sstevel@tonic-gate 			 * incorrect.  We will substitute it with the number of
2149*7c478bd9Sstevel@tonic-gate 			 * available cylinders.
2150*7c478bd9Sstevel@tonic-gate 			 */
2151*7c478bd9Sstevel@tonic-gate 			if (dkgeom.dkg_pcyl == 0)
2152*7c478bd9Sstevel@tonic-gate 				rmsvc.retget_medium_property.smprop.sm_pcyl =
2153*7c478bd9Sstevel@tonic-gate 				    dkgeom.dkg_ncyl;
2154*7c478bd9Sstevel@tonic-gate 			else
2155*7c478bd9Sstevel@tonic-gate 				rmsvc.retget_medium_property.smprop.sm_pcyl =
2156*7c478bd9Sstevel@tonic-gate 				    dkgeom.dkg_pcyl;
2157*7c478bd9Sstevel@tonic-gate 
2158*7c478bd9Sstevel@tonic-gate 			rmsvc.retget_medium_property.smprop.sm_nhead =
2159*7c478bd9Sstevel@tonic-gate 			    dkgeom.dkg_nhead;
2160*7c478bd9Sstevel@tonic-gate 			rmsvc.retget_medium_property.smprop.sm_nsect =
2161*7c478bd9Sstevel@tonic-gate 			    dkgeom.dkg_nsect;
2162*7c478bd9Sstevel@tonic-gate 		}
2163*7c478bd9Sstevel@tonic-gate 
2164*7c478bd9Sstevel@tonic-gate 		debug(1, "properties are: lbasize = %d, cap = %llu",
2165*7c478bd9Sstevel@tonic-gate 		    media_info.dki_lbsize, media_info.dki_capacity);
2166*7c478bd9Sstevel@tonic-gate 
2167*7c478bd9Sstevel@tonic-gate 		my_door_return((char *)&rmsvc.retget_medium_property,
2168*7c478bd9Sstevel@tonic-gate 			sizeof (smedia_retget_medium_property_t), 0, 0);
2169*7c478bd9Sstevel@tonic-gate 		break;
2170*7c478bd9Sstevel@tonic-gate 
2171*7c478bd9Sstevel@tonic-gate 	case	SMEDIA_CNUM_GET_PROTECTION_STATUS:
2172*7c478bd9Sstevel@tonic-gate 		switch (get_device_type_scsi(door_dp->dd_fd, &inq)) {
2173*7c478bd9Sstevel@tonic-gate 		case SCSI_FLOPPY:
2174*7c478bd9Sstevel@tonic-gate 			status = scsi_floppy_media_status(door_dp->dd_fd);
2175*7c478bd9Sstevel@tonic-gate 			break;
2176*7c478bd9Sstevel@tonic-gate 		case SCSI_IOMEGA:
2177*7c478bd9Sstevel@tonic-gate 			status = scsi_zip_media_status(door_dp->dd_fd);
2178*7c478bd9Sstevel@tonic-gate 			break;
2179*7c478bd9Sstevel@tonic-gate 		case SCSI_GENERIC:
2180*7c478bd9Sstevel@tonic-gate 			status = scsi_media_status(door_dp->dd_fd);
2181*7c478bd9Sstevel@tonic-gate 			break;
2182*7c478bd9Sstevel@tonic-gate 		default:
2183*7c478bd9Sstevel@tonic-gate 			door_ret_err(&reterror, errno);
2184*7c478bd9Sstevel@tonic-gate 		}
2185*7c478bd9Sstevel@tonic-gate 		if (status < 0)
2186*7c478bd9Sstevel@tonic-gate 			door_ret_err(&reterror, errno);
2187*7c478bd9Sstevel@tonic-gate 
2188*7c478bd9Sstevel@tonic-gate 		rmsvc.retget_protection_status.prot_state.sm_new_state  =
2189*7c478bd9Sstevel@tonic-gate 			status;
2190*7c478bd9Sstevel@tonic-gate 
2191*7c478bd9Sstevel@tonic-gate 		my_door_return((char *)&rmsvc.retget_protection_status,
2192*7c478bd9Sstevel@tonic-gate 			sizeof (smedia_retget_protection_status_t), 0, 0);
2193*7c478bd9Sstevel@tonic-gate 		break;
2194*7c478bd9Sstevel@tonic-gate 
2195*7c478bd9Sstevel@tonic-gate 	case	SMEDIA_CNUM_SET_PROTECTION_STATUS:
2196*7c478bd9Sstevel@tonic-gate 
2197*7c478bd9Sstevel@tonic-gate 		ret_val = set_protection_status(door_dp, req);
2198*7c478bd9Sstevel@tonic-gate 		if (ret_val == -1)
2199*7c478bd9Sstevel@tonic-gate 			door_ret_err(&reterror, errno);
2200*7c478bd9Sstevel@tonic-gate 		else
2201*7c478bd9Sstevel@tonic-gate 			my_door_return((char *)&rmsvc.retset_protection_status,
2202*7c478bd9Sstevel@tonic-gate 				sizeof (smedia_retset_protection_status_t),
2203*7c478bd9Sstevel@tonic-gate 				0, 0);
2204*7c478bd9Sstevel@tonic-gate 		break;
2205*7c478bd9Sstevel@tonic-gate 
2206*7c478bd9Sstevel@tonic-gate 	case SMEDIA_CNUM_FORMAT:
2207*7c478bd9Sstevel@tonic-gate 		switch (get_device_type_scsi(door_dp->dd_fd, &inq)) {
2208*7c478bd9Sstevel@tonic-gate 		case SCSI_FLOPPY:
2209*7c478bd9Sstevel@tonic-gate 			info("formatting floppy");
2210*7c478bd9Sstevel@tonic-gate 			err = scsi_floppy_format(door_dp->dd_fd,
2211*7c478bd9Sstevel@tonic-gate 				req->reqformat.flavor, req->reqformat.mode);
2212*7c478bd9Sstevel@tonic-gate 
2213*7c478bd9Sstevel@tonic-gate 			break;
2214*7c478bd9Sstevel@tonic-gate 		case SCSI_IOMEGA:
2215*7c478bd9Sstevel@tonic-gate 			err = scsi_zip_format(door_dp->dd_fd,
2216*7c478bd9Sstevel@tonic-gate 				req->reqformat.flavor, req->reqformat.mode);
2217*7c478bd9Sstevel@tonic-gate 			break;
2218*7c478bd9Sstevel@tonic-gate 		case SCSI_GENERIC:
2219*7c478bd9Sstevel@tonic-gate 			err = scsi_format(door_dp->dd_fd,
2220*7c478bd9Sstevel@tonic-gate 				req->reqformat.flavor, req->reqformat.mode);
2221*7c478bd9Sstevel@tonic-gate 			break;
2222*7c478bd9Sstevel@tonic-gate 		default:
2223*7c478bd9Sstevel@tonic-gate 			door_ret_err(&reterror, ENOTSUP);
2224*7c478bd9Sstevel@tonic-gate 		}
2225*7c478bd9Sstevel@tonic-gate 
2226*7c478bd9Sstevel@tonic-gate 		if (err)
2227*7c478bd9Sstevel@tonic-gate 			door_ret_err(&reterror, errno);
2228*7c478bd9Sstevel@tonic-gate 		my_door_return((char *)&rmsvc.retformat,
2229*7c478bd9Sstevel@tonic-gate 			sizeof (smedia_retformat_t), 0, 0);
2230*7c478bd9Sstevel@tonic-gate 
2231*7c478bd9Sstevel@tonic-gate 		break;
2232*7c478bd9Sstevel@tonic-gate 
2233*7c478bd9Sstevel@tonic-gate 	case SMEDIA_CNUM_CHECK_FORMAT_STATUS:
2234*7c478bd9Sstevel@tonic-gate 
2235*7c478bd9Sstevel@tonic-gate 		(void) memset((void *) &cdb, 0, sizeof (union scsi_cdb));
2236*7c478bd9Sstevel@tonic-gate 		(void) memset((void *) &ucmd, 0, sizeof (ucmd));
2237*7c478bd9Sstevel@tonic-gate 		(void) memset((void *) &data, 0, sizeof (data));
2238*7c478bd9Sstevel@tonic-gate 		cdb.scc_cmd = SCMD_REQUEST_SENSE;
2239*7c478bd9Sstevel@tonic-gate 		cdb.g0_count0 = sizeof (data);
2240*7c478bd9Sstevel@tonic-gate 		ucmd.uscsi_cdb = (caddr_t)&cdb;
2241*7c478bd9Sstevel@tonic-gate 		ucmd.uscsi_cdblen = CDB_GROUP0;
2242*7c478bd9Sstevel@tonic-gate 		ucmd.uscsi_bufaddr = (caddr_t)&data;
2243*7c478bd9Sstevel@tonic-gate 		ucmd.uscsi_buflen = sizeof (data);
2244*7c478bd9Sstevel@tonic-gate 		ucmd.uscsi_timeout = 120;	/* If 0, HBA hangs forever */
2245*7c478bd9Sstevel@tonic-gate 		ucmd.uscsi_rqlen = RQ_LEN;
2246*7c478bd9Sstevel@tonic-gate 		ucmd.uscsi_rqbuf = rq_data;
2247*7c478bd9Sstevel@tonic-gate 		ret_val = do_uscsi_cmd(door_dp->dd_fd,
2248*7c478bd9Sstevel@tonic-gate 			&ucmd, USCSI_READ|USCSI_RQENABLE);
2249*7c478bd9Sstevel@tonic-gate 		if (ret_val || ucmd.uscsi_status) {
2250*7c478bd9Sstevel@tonic-gate 			debug(5, "Request sense failed: %d - %d errno = %d\n",
2251*7c478bd9Sstevel@tonic-gate 				ret_val, ucmd.uscsi_status, errno);
2252*7c478bd9Sstevel@tonic-gate 			door_ret_err(&reterror, errno);
2253*7c478bd9Sstevel@tonic-gate 		}
2254*7c478bd9Sstevel@tonic-gate 
2255*7c478bd9Sstevel@tonic-gate 		if ((data[0] & 0x7F) == DEFERRED_ERROR) {
2256*7c478bd9Sstevel@tonic-gate 		/* Deffered error. The format must have failed */
2257*7c478bd9Sstevel@tonic-gate 			debug(5, "format failed!\n");
2258*7c478bd9Sstevel@tonic-gate 			door_ret_err(&reterror, EIO);
2259*7c478bd9Sstevel@tonic-gate 		}
2260*7c478bd9Sstevel@tonic-gate 
2261*7c478bd9Sstevel@tonic-gate 		if (data[SKSV_OFFSET] & SKSV_FIELD) {
2262*7c478bd9Sstevel@tonic-gate 			completed =
2263*7c478bd9Sstevel@tonic-gate 				(data[FORMAT_PROGRESS_INDICATOR_OFFSET_0] << 8)
2264*7c478bd9Sstevel@tonic-gate 				| data[FORMAT_PROGRESS_INDICATOR_OFFSET_1];
2265*7c478bd9Sstevel@tonic-gate 			completed = (completed*100/65536);
2266*7c478bd9Sstevel@tonic-gate 		} else {
2267*7c478bd9Sstevel@tonic-gate 			completed = (100);
2268*7c478bd9Sstevel@tonic-gate 		}
2269*7c478bd9Sstevel@tonic-gate 		rmsvc.retcheck_format_status.percent_complete = completed;
2270*7c478bd9Sstevel@tonic-gate 		my_door_return((char *)&rmsvc.retcheck_format_status,
2271*7c478bd9Sstevel@tonic-gate 			sizeof (smedia_retcheck_format_status_t), 0, 0);
2272*7c478bd9Sstevel@tonic-gate 		break;
2273*7c478bd9Sstevel@tonic-gate 
2274*7c478bd9Sstevel@tonic-gate 	case SMEDIA_CNUM_REASSIGN_BLOCK:
2275*7c478bd9Sstevel@tonic-gate 
2276*7c478bd9Sstevel@tonic-gate 		ret_val = reassign_block(door_dp, req);
2277*7c478bd9Sstevel@tonic-gate 		if (ret_val == -1)
2278*7c478bd9Sstevel@tonic-gate 			door_ret_err(&reterror, errno);
2279*7c478bd9Sstevel@tonic-gate 		my_door_return((char *)&rmsvc.retreassign_block,
2280*7c478bd9Sstevel@tonic-gate 			sizeof (smedia_retreassign_block_t), 0, 0);
2281*7c478bd9Sstevel@tonic-gate 		break;
2282*7c478bd9Sstevel@tonic-gate 
2283*7c478bd9Sstevel@tonic-gate 	}	/* end of switch */
2284*7c478bd9Sstevel@tonic-gate 
2285*7c478bd9Sstevel@tonic-gate 	debug(10, "Exiting client server...\n");
2286*7c478bd9Sstevel@tonic-gate 
2287*7c478bd9Sstevel@tonic-gate 
2288*7c478bd9Sstevel@tonic-gate 	my_door_return((char *)&reterror, sizeof (smedia_reterror_t), 0, 0);
2289*7c478bd9Sstevel@tonic-gate }
2290*7c478bd9Sstevel@tonic-gate 
2291*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/
2292*7c478bd9Sstevel@tonic-gate static void
2293*7c478bd9Sstevel@tonic-gate main_server(void *server_data, char *argp, size_t arg_size,
2294*7c478bd9Sstevel@tonic-gate     door_desc_t *dp, uint_t ndesc)
2295*7c478bd9Sstevel@tonic-gate {
2296*7c478bd9Sstevel@tonic-gate 	smedia_services_t	*req;
2297*7c478bd9Sstevel@tonic-gate 	door_cred_t	door_credentials;
2298*7c478bd9Sstevel@tonic-gate 	int		ret_val;
2299*7c478bd9Sstevel@tonic-gate 	door_data_t	*ddata;
2300*7c478bd9Sstevel@tonic-gate 	smedia_reterror_t	reterror;
2301*7c478bd9Sstevel@tonic-gate 	smedia_reterror_t	retok;
2302*7c478bd9Sstevel@tonic-gate 	struct	stat	stat;
2303*7c478bd9Sstevel@tonic-gate 	door_desc_t	*didpp;
2304*7c478bd9Sstevel@tonic-gate 	struct dk_cinfo dkinfo;
2305*7c478bd9Sstevel@tonic-gate 	uint_t		expected_descs;
2306*7c478bd9Sstevel@tonic-gate 
2307*7c478bd9Sstevel@tonic-gate 	debug(10, "Entering main server[%d].\n", pthread_self());
2308*7c478bd9Sstevel@tonic-gate 
2309*7c478bd9Sstevel@tonic-gate 	didpp = dp;
2310*7c478bd9Sstevel@tonic-gate 	(void) mutex_lock(&svcstate_lock);
2311*7c478bd9Sstevel@tonic-gate 	svcstate = _SERVED;
2312*7c478bd9Sstevel@tonic-gate 	(void) mutex_unlock(&svcstate_lock);
2313*7c478bd9Sstevel@tonic-gate 
2314*7c478bd9Sstevel@tonic-gate 	reterror.cnum = SMEDIA_CNUM_ERROR;
2315*7c478bd9Sstevel@tonic-gate 	reterror.errnum = SMEDIA_FAILURE;
2316*7c478bd9Sstevel@tonic-gate 	if (argp == NULL) {
2317*7c478bd9Sstevel@tonic-gate 		debug(5, "argp is NULL\n");
2318*7c478bd9Sstevel@tonic-gate 		if (ndesc > 0)
2319*7c478bd9Sstevel@tonic-gate 			close_door_descs(dp, ndesc);
2320*7c478bd9Sstevel@tonic-gate 		my_door_return((char *)&reterror,
2321*7c478bd9Sstevel@tonic-gate 		    sizeof (smedia_reterror_t), 0, 0);
2322*7c478bd9Sstevel@tonic-gate 	}
2323*7c478bd9Sstevel@tonic-gate 
2324*7c478bd9Sstevel@tonic-gate 	req = (smedia_services_t *)((void *)argp);
2325*7c478bd9Sstevel@tonic-gate 	retok.cnum = req->in.cnum;
2326*7c478bd9Sstevel@tonic-gate 	retok.errnum = 0;
2327*7c478bd9Sstevel@tonic-gate 
2328*7c478bd9Sstevel@tonic-gate 	debug(5, "req = %s arg_size = 0x%x \n",
2329*7c478bd9Sstevel@tonic-gate 		xlate_cnum(req->reqopen.cnum), arg_size);
2330*7c478bd9Sstevel@tonic-gate 
2331*7c478bd9Sstevel@tonic-gate 	/*
2332*7c478bd9Sstevel@tonic-gate 	 * Our caller may have passed more descriptors than we expected.
2333*7c478bd9Sstevel@tonic-gate 	 * If so, we silently close (and ignore) them.
2334*7c478bd9Sstevel@tonic-gate 	 */
2335*7c478bd9Sstevel@tonic-gate 	if (req->in.cnum == SMEDIA_CNUM_OPEN_FD)
2336*7c478bd9Sstevel@tonic-gate 		expected_descs = 1;
2337*7c478bd9Sstevel@tonic-gate 	else
2338*7c478bd9Sstevel@tonic-gate 		expected_descs = 0;
2339*7c478bd9Sstevel@tonic-gate 
2340*7c478bd9Sstevel@tonic-gate 	if (ndesc > expected_descs)
2341*7c478bd9Sstevel@tonic-gate 		close_door_descs(dp + expected_descs, ndesc - expected_descs);
2342*7c478bd9Sstevel@tonic-gate 
2343*7c478bd9Sstevel@tonic-gate 	switch (req->in.cnum) {
2344*7c478bd9Sstevel@tonic-gate 
2345*7c478bd9Sstevel@tonic-gate 	default:
2346*7c478bd9Sstevel@tonic-gate 		debug(5, "unkmown command 0x%x\n", req->reqopen.cnum);
2347*7c478bd9Sstevel@tonic-gate 		break;
2348*7c478bd9Sstevel@tonic-gate 
2349*7c478bd9Sstevel@tonic-gate 	case	SMEDIA_CNUM_PING:
2350*7c478bd9Sstevel@tonic-gate 		/*
2351*7c478bd9Sstevel@tonic-gate 		 * This service is to indicate that server is up and
2352*7c478bd9Sstevel@tonic-gate 		 * running. It is usually called from another instance of
2353*7c478bd9Sstevel@tonic-gate 		 * server that is started.
2354*7c478bd9Sstevel@tonic-gate 		 */
2355*7c478bd9Sstevel@tonic-gate 
2356*7c478bd9Sstevel@tonic-gate 		reterror.cnum = SMEDIA_CNUM_PING;
2357*7c478bd9Sstevel@tonic-gate 		reterror.errnum = 0;
2358*7c478bd9Sstevel@tonic-gate 		my_door_return((char *)&reterror,
2359*7c478bd9Sstevel@tonic-gate 			sizeof (smedia_reterror_t), 0, 0);
2360*7c478bd9Sstevel@tonic-gate 		break;
2361*7c478bd9Sstevel@tonic-gate 
2362*7c478bd9Sstevel@tonic-gate 
2363*7c478bd9Sstevel@tonic-gate 	case	SMEDIA_CNUM_OPEN_FD:
2364*7c478bd9Sstevel@tonic-gate 
2365*7c478bd9Sstevel@tonic-gate 		debug(5, "ndesc = %d\n", ndesc);
2366*7c478bd9Sstevel@tonic-gate 		if (ndesc == 0) {
2367*7c478bd9Sstevel@tonic-gate 			my_door_return((char *)&reterror,
2368*7c478bd9Sstevel@tonic-gate 				sizeof (smedia_reterror_t), 0, 0);
2369*7c478bd9Sstevel@tonic-gate 		}
2370*7c478bd9Sstevel@tonic-gate 		debug(5, "Checking descriptor 1\n");
2371*7c478bd9Sstevel@tonic-gate 		if (fstat(didpp->d_data.d_desc.d_descriptor, &stat) < 0) {
2372*7c478bd9Sstevel@tonic-gate 			warning(gettext(
2373*7c478bd9Sstevel@tonic-gate 			"main_server:fstat failed. errno = %d\n"),
2374*7c478bd9Sstevel@tonic-gate 				errno);
2375*7c478bd9Sstevel@tonic-gate 			(void) close(didpp->d_data.d_desc.d_descriptor);
2376*7c478bd9Sstevel@tonic-gate 			my_door_return((char *)&reterror,
2377*7c478bd9Sstevel@tonic-gate 				sizeof (smedia_reterror_t), 0, 0);
2378*7c478bd9Sstevel@tonic-gate 		}
2379*7c478bd9Sstevel@tonic-gate 		debug(5, "descriptor = %d st_mode = 0x%lx\n",
2380*7c478bd9Sstevel@tonic-gate 			didpp->d_data.d_desc.d_descriptor,
2381*7c478bd9Sstevel@tonic-gate 			stat.st_mode);
2382*7c478bd9Sstevel@tonic-gate 
2383*7c478bd9Sstevel@tonic-gate 		/* Obtain the credentials of the user */
2384*7c478bd9Sstevel@tonic-gate 		ret_val = door_cred(&door_credentials);
2385*7c478bd9Sstevel@tonic-gate 		if (ret_val < 0) {
2386*7c478bd9Sstevel@tonic-gate 			warning(gettext(
2387*7c478bd9Sstevel@tonic-gate 			"main_server:door_cred failed. errno = %d\n"),
2388*7c478bd9Sstevel@tonic-gate 				errno);
2389*7c478bd9Sstevel@tonic-gate 			(void) close(didpp->d_data.d_desc.d_descriptor);
2390*7c478bd9Sstevel@tonic-gate 			my_door_return((char *)&reterror,
2391*7c478bd9Sstevel@tonic-gate 				sizeof (smedia_reterror_t), 0, 0);
2392*7c478bd9Sstevel@tonic-gate 		}
2393*7c478bd9Sstevel@tonic-gate 		if (ioctl(didpp->d_data.d_desc.d_descriptor, DKIOCINFO,
2394*7c478bd9Sstevel@tonic-gate 			&dkinfo) == -1) {
2395*7c478bd9Sstevel@tonic-gate 			warning(gettext(
2396*7c478bd9Sstevel@tonic-gate 			"main_server:DKIOCINFO failed. errno = %d\n"),
2397*7c478bd9Sstevel@tonic-gate 				errno);
2398*7c478bd9Sstevel@tonic-gate 			(void) close(didpp->d_data.d_desc.d_descriptor);
2399*7c478bd9Sstevel@tonic-gate 			my_door_return((char *)&reterror,
2400*7c478bd9Sstevel@tonic-gate 				sizeof (smedia_reterror_t), 0, 0);
2401*7c478bd9Sstevel@tonic-gate 		}
2402*7c478bd9Sstevel@tonic-gate 
2403*7c478bd9Sstevel@tonic-gate 		/*
2404*7c478bd9Sstevel@tonic-gate 		 * create a separate thread to handle IO calls to this device.
2405*7c478bd9Sstevel@tonic-gate 		 */
2406*7c478bd9Sstevel@tonic-gate 		ddata = (door_data_t *)calloc(1, sizeof (door_data_t));
2407*7c478bd9Sstevel@tonic-gate 		if (ddata == NULL) {
2408*7c478bd9Sstevel@tonic-gate 			warning(gettext(
2409*7c478bd9Sstevel@tonic-gate 			"main_server:calloc failed. errno = %d\n"),
2410*7c478bd9Sstevel@tonic-gate 				errno);
2411*7c478bd9Sstevel@tonic-gate 			(void) close(didpp->d_data.d_desc.d_descriptor);
2412*7c478bd9Sstevel@tonic-gate 			my_door_return((char *)&reterror,
2413*7c478bd9Sstevel@tonic-gate 				sizeof (smedia_reterror_t), 0, 0);
2414*7c478bd9Sstevel@tonic-gate 		}
2415*7c478bd9Sstevel@tonic-gate 		ddata->dd_stat = stat;
2416*7c478bd9Sstevel@tonic-gate 		ddata->dd_cred = door_credentials;
2417*7c478bd9Sstevel@tonic-gate 		ddata->dd_fd = didpp->d_data.d_desc.d_descriptor;
2418*7c478bd9Sstevel@tonic-gate 		ddata->dd_buf = NULL;
2419*7c478bd9Sstevel@tonic-gate 		ddata->dd_buf_len = 0;
2420*7c478bd9Sstevel@tonic-gate 		ddata->dd_buffd = -1;
2421*7c478bd9Sstevel@tonic-gate 		ddata->dd_sector_size = 0;
2422*7c478bd9Sstevel@tonic-gate 		ddata->dd_dkinfo = dkinfo;
2423*7c478bd9Sstevel@tonic-gate 		debug(5, "ddata = %p \n", (void *)ddata);
2424*7c478bd9Sstevel@tonic-gate 
2425*7c478bd9Sstevel@tonic-gate 		(void) door_server_create(my_create);
2426*7c478bd9Sstevel@tonic-gate 		debug(5, "door_server_create called.\n");
2427*7c478bd9Sstevel@tonic-gate 
2428*7c478bd9Sstevel@tonic-gate 		(void) mutex_lock(&ddata->dd_lock);
2429*7c478bd9Sstevel@tonic-gate 
2430*7c478bd9Sstevel@tonic-gate 		ddata->dd_desc[0].d_data.d_desc.d_descriptor = door_create(
2431*7c478bd9Sstevel@tonic-gate 		    client_server, (void *)ddata, DOOR_PRIVATE);
2432*7c478bd9Sstevel@tonic-gate 		if (ddata->dd_desc[0].d_data.d_desc.d_descriptor < 0) {
2433*7c478bd9Sstevel@tonic-gate 			warning(gettext(
2434*7c478bd9Sstevel@tonic-gate 			"main_server:client door_create failed. errno = %d\n"),
2435*7c478bd9Sstevel@tonic-gate 				errno);
2436*7c478bd9Sstevel@tonic-gate 			free(ddata);
2437*7c478bd9Sstevel@tonic-gate 			(void) close(didpp->d_data.d_desc.d_descriptor);
2438*7c478bd9Sstevel@tonic-gate 		}
2439*7c478bd9Sstevel@tonic-gate 		ddata->dd_desc[1].d_data.d_desc.d_descriptor =
2440*7c478bd9Sstevel@tonic-gate 		    door_create(client_server, (void *)ddata, DOOR_UNREF);
2441*7c478bd9Sstevel@tonic-gate 		if (ddata->dd_desc[1].d_data.d_desc.d_descriptor < 0) {
2442*7c478bd9Sstevel@tonic-gate 			warning(gettext(
2443*7c478bd9Sstevel@tonic-gate 			"main_server:death door_create failed. errno = %d\n"),
2444*7c478bd9Sstevel@tonic-gate 				errno);
2445*7c478bd9Sstevel@tonic-gate 			(void) close(
2446*7c478bd9Sstevel@tonic-gate 				ddata->dd_desc[0].d_data.d_desc.d_descriptor);
2447*7c478bd9Sstevel@tonic-gate 			free(ddata);
2448*7c478bd9Sstevel@tonic-gate 			(void) close(didpp->d_data.d_desc.d_descriptor);
2449*7c478bd9Sstevel@tonic-gate 		}
2450*7c478bd9Sstevel@tonic-gate 		debug(5,
2451*7c478bd9Sstevel@tonic-gate 		"Client door server 0x%0x and death door 0x%x created.\n",
2452*7c478bd9Sstevel@tonic-gate 			ddata->dd_desc[0].d_data.d_desc.d_descriptor,
2453*7c478bd9Sstevel@tonic-gate 			ddata->dd_desc[1].d_data.d_desc.d_descriptor);
2454*7c478bd9Sstevel@tonic-gate 		ddata->dd_desc[0].d_attributes = (DOOR_DESCRIPTOR|DOOR_RELEASE);
2455*7c478bd9Sstevel@tonic-gate 		ddata->dd_desc[1].d_attributes = (DOOR_DESCRIPTOR);
2456*7c478bd9Sstevel@tonic-gate 
2457*7c478bd9Sstevel@tonic-gate 		audit_init(ddata);
2458*7c478bd9Sstevel@tonic-gate 
2459*7c478bd9Sstevel@tonic-gate 		(void) cond_signal(&ddata->dd_cv);
2460*7c478bd9Sstevel@tonic-gate 		(void) cond_wait(&ddata->dd_cv_bind, &ddata->dd_lock);
2461*7c478bd9Sstevel@tonic-gate 		(void) mutex_unlock(&ddata->dd_lock);
2462*7c478bd9Sstevel@tonic-gate 		debug(5, "retok.cnum = 0x%x\n", retok.cnum);
2463*7c478bd9Sstevel@tonic-gate 
2464*7c478bd9Sstevel@tonic-gate 		(void) mutex_lock(&svcstate_lock);
2465*7c478bd9Sstevel@tonic-gate 		svccount++;
2466*7c478bd9Sstevel@tonic-gate 		(void) mutex_unlock(&svcstate_lock);
2467*7c478bd9Sstevel@tonic-gate 		my_door_return((char *)&retok, sizeof (smedia_reterror_t),
2468*7c478bd9Sstevel@tonic-gate 			&ddata->dd_desc[0], 2);
2469*7c478bd9Sstevel@tonic-gate 
2470*7c478bd9Sstevel@tonic-gate 		break;
2471*7c478bd9Sstevel@tonic-gate 	}
2472*7c478bd9Sstevel@tonic-gate 
2473*7c478bd9Sstevel@tonic-gate 	debug(10, "exiting main server. \n");
2474*7c478bd9Sstevel@tonic-gate 	my_door_return((char *)&reterror, sizeof (smedia_reterror_t), 0, 0);
2475*7c478bd9Sstevel@tonic-gate }
2476*7c478bd9Sstevel@tonic-gate 
2477*7c478bd9Sstevel@tonic-gate /* ARGSUSED */
2478*7c478bd9Sstevel@tonic-gate static void
2479*7c478bd9Sstevel@tonic-gate term_handler(int sig, siginfo_t *siginfo, void *sigctx)
2480*7c478bd9Sstevel@tonic-gate {
2481*7c478bd9Sstevel@tonic-gate 	warning(gettext("thread[%d]: Received signal %d. Ignoring it.\n"),
2482*7c478bd9Sstevel@tonic-gate 		pthread_self(),
2483*7c478bd9Sstevel@tonic-gate 		sig);
2484*7c478bd9Sstevel@tonic-gate }
2485*7c478bd9Sstevel@tonic-gate 
2486*7c478bd9Sstevel@tonic-gate /* ARGSUSED */
2487*7c478bd9Sstevel@tonic-gate static void
2488*7c478bd9Sstevel@tonic-gate hup_handler(int sig, siginfo_t *siginfo, void *sigctx)
2489*7c478bd9Sstevel@tonic-gate {
2490*7c478bd9Sstevel@tonic-gate 	warning(gettext("thread[%d]: Received signal %d. Ignoring it.\n"),
2491*7c478bd9Sstevel@tonic-gate 		pthread_self(),
2492*7c478bd9Sstevel@tonic-gate 		sig);
2493*7c478bd9Sstevel@tonic-gate }
2494*7c478bd9Sstevel@tonic-gate 
2495*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/
2496*7c478bd9Sstevel@tonic-gate static void
2497*7c478bd9Sstevel@tonic-gate sig_handler(int sig, siginfo_t *siginfo, void *sigctx)
2498*7c478bd9Sstevel@tonic-gate {
2499*7c478bd9Sstevel@tonic-gate 	warning(gettext("thread[%d]: Received signal %d. Ignoring it.\n"),
2500*7c478bd9Sstevel@tonic-gate 		pthread_self(),
2501*7c478bd9Sstevel@tonic-gate 		sig);
2502*7c478bd9Sstevel@tonic-gate }
2503*7c478bd9Sstevel@tonic-gate 
2504*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/
2505*7c478bd9Sstevel@tonic-gate static void
2506*7c478bd9Sstevel@tonic-gate badsig_handler(int sig, siginfo_t *siginfo, void *sigctx)
2507*7c478bd9Sstevel@tonic-gate {
2508*7c478bd9Sstevel@tonic-gate 
2509*7c478bd9Sstevel@tonic-gate 	fatal(BADSIG_MSG, pthread_self(), sig, siginfo->si_addr,
2510*7c478bd9Sstevel@tonic-gate 		siginfo->si_trapno,
2511*7c478bd9Sstevel@tonic-gate 		siginfo->si_pc);
2512*7c478bd9Sstevel@tonic-gate }
2513*7c478bd9Sstevel@tonic-gate 
2514*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/
2515*7c478bd9Sstevel@tonic-gate void *
2516*7c478bd9Sstevel@tonic-gate init_server(void *argp)
2517*7c478bd9Sstevel@tonic-gate {
2518*7c478bd9Sstevel@tonic-gate 	int	i, fd;
2519*7c478bd9Sstevel@tonic-gate 	struct	sigaction	act;
2520*7c478bd9Sstevel@tonic-gate 	struct	rlimit		rlim;
2521*7c478bd9Sstevel@tonic-gate 
2522*7c478bd9Sstevel@tonic-gate 	debug(10, "init_server  running\n");
2523*7c478bd9Sstevel@tonic-gate 
2524*7c478bd9Sstevel@tonic-gate 	(void) setlocale(LC_ALL, "");
2525*7c478bd9Sstevel@tonic-gate #if !defined(TEXT_DOMAIN)
2526*7c478bd9Sstevel@tonic-gate #define	TEXT_DOMAIN "SYS_TEST"
2527*7c478bd9Sstevel@tonic-gate #endif
2528*7c478bd9Sstevel@tonic-gate 	(void) textdomain(TEXT_DOMAIN);
2529*7c478bd9Sstevel@tonic-gate 
2530*7c478bd9Sstevel@tonic-gate 
2531*7c478bd9Sstevel@tonic-gate 	if (geteuid() != 0) fatal("Must be root to execute smserverd\n");
2532*7c478bd9Sstevel@tonic-gate 
2533*7c478bd9Sstevel@tonic-gate 
2534*7c478bd9Sstevel@tonic-gate 	/*
2535*7c478bd9Sstevel@tonic-gate 	 * setup signal handlers.
2536*7c478bd9Sstevel@tonic-gate 	 */
2537*7c478bd9Sstevel@tonic-gate 
2538*7c478bd9Sstevel@tonic-gate 	for (i = 0; i < N_BADSIGS; i++) {
2539*7c478bd9Sstevel@tonic-gate 		act.sa_sigaction = badsig_handler;
2540*7c478bd9Sstevel@tonic-gate 		(void) sigemptyset(&act.sa_mask);
2541*7c478bd9Sstevel@tonic-gate 		act.sa_flags = SA_SIGINFO;
2542*7c478bd9Sstevel@tonic-gate 		if (sigaction(badsigs[i], &act, NULL) == -1)
2543*7c478bd9Sstevel@tonic-gate 			warning(gettext(SIGACT_FAILED), strsignal(badsigs[i]),
2544*7c478bd9Sstevel@tonic-gate 				strerror(errno));
2545*7c478bd9Sstevel@tonic-gate 	}
2546*7c478bd9Sstevel@tonic-gate 
2547*7c478bd9Sstevel@tonic-gate 	/*
2548*7c478bd9Sstevel@tonic-gate 	 * Ignore SIGHUP until all the initialization is done.
2549*7c478bd9Sstevel@tonic-gate 	 */
2550*7c478bd9Sstevel@tonic-gate 	act.sa_handler = SIG_IGN;
2551*7c478bd9Sstevel@tonic-gate 	(void) sigemptyset(&act.sa_mask);
2552*7c478bd9Sstevel@tonic-gate 	act.sa_flags = 0;
2553*7c478bd9Sstevel@tonic-gate 	if (sigaction(SIGHUP, &act, NULL) == -1)
2554*7c478bd9Sstevel@tonic-gate 		warning(gettext(SIGACT_FAILED), strsignal(SIGHUP),
2555*7c478bd9Sstevel@tonic-gate 			strerror(errno));
2556*7c478bd9Sstevel@tonic-gate 	/*
2557*7c478bd9Sstevel@tonic-gate 	 * Increase file descriptor limit to the most it can possibly
2558*7c478bd9Sstevel@tonic-gate 	 * be.
2559*7c478bd9Sstevel@tonic-gate 	 */
2560*7c478bd9Sstevel@tonic-gate 	if (getrlimit(RLIMIT_NOFILE, &rlim) < 0) {
2561*7c478bd9Sstevel@tonic-gate 		warning(gettext("getrlimit for fd's failed; %m\n"));
2562*7c478bd9Sstevel@tonic-gate 	}
2563*7c478bd9Sstevel@tonic-gate 
2564*7c478bd9Sstevel@tonic-gate 	rlim.rlim_cur = rlim.rlim_max;
2565*7c478bd9Sstevel@tonic-gate 
2566*7c478bd9Sstevel@tonic-gate 	if (setrlimit(RLIMIT_NOFILE, &rlim) < 0) {
2567*7c478bd9Sstevel@tonic-gate 		warning(gettext("setrlimit for fd's failed; %m\n"));
2568*7c478bd9Sstevel@tonic-gate 	}
2569*7c478bd9Sstevel@tonic-gate 
2570*7c478bd9Sstevel@tonic-gate 	server_door = door_create(main_server, (void *)&server_data, 0);
2571*7c478bd9Sstevel@tonic-gate 	if (server_door == -1) {
2572*7c478bd9Sstevel@tonic-gate 		debug(1, "main door_create");
2573*7c478bd9Sstevel@tonic-gate 		exit(1);
2574*7c478bd9Sstevel@tonic-gate 	}
2575*7c478bd9Sstevel@tonic-gate 
2576*7c478bd9Sstevel@tonic-gate 	(void) unlink(smedia_service);
2577*7c478bd9Sstevel@tonic-gate 	fd = open(smedia_service, O_RDWR|O_CREAT|O_EXCL, 0644);
2578*7c478bd9Sstevel@tonic-gate 	if (fd < 0) {
2579*7c478bd9Sstevel@tonic-gate 		debug(5, "could not open %s.\n", smedia_service);
2580*7c478bd9Sstevel@tonic-gate 		exit(1);
2581*7c478bd9Sstevel@tonic-gate 	}
2582*7c478bd9Sstevel@tonic-gate 	(void) close(fd);
2583*7c478bd9Sstevel@tonic-gate 	server_fd = fattach(server_door, smedia_service);
2584*7c478bd9Sstevel@tonic-gate 	if (server_fd == -1) {
2585*7c478bd9Sstevel@tonic-gate 		debug(1, "main fattach");
2586*7c478bd9Sstevel@tonic-gate 		exit(1);
2587*7c478bd9Sstevel@tonic-gate 	}
2588*7c478bd9Sstevel@tonic-gate 	server_data.sd_door = server_door;
2589*7c478bd9Sstevel@tonic-gate 	server_data.sd_fd = server_fd;
2590*7c478bd9Sstevel@tonic-gate 
2591*7c478bd9Sstevel@tonic-gate 	/*
2592*7c478bd9Sstevel@tonic-gate 	 * setup signal handlers for post-init
2593*7c478bd9Sstevel@tonic-gate 	 */
2594*7c478bd9Sstevel@tonic-gate 
2595*7c478bd9Sstevel@tonic-gate 	act.sa_sigaction = hup_handler;
2596*7c478bd9Sstevel@tonic-gate 	(void) sigemptyset(&act.sa_mask);
2597*7c478bd9Sstevel@tonic-gate 	act.sa_flags = SA_SIGINFO;
2598*7c478bd9Sstevel@tonic-gate 	if (sigaction(SIGHUP, &act, NULL) == -1)
2599*7c478bd9Sstevel@tonic-gate 		warning(gettext(SIGACT_FAILED), strsignal(SIGHUP),
2600*7c478bd9Sstevel@tonic-gate 		    strerror(errno));
2601*7c478bd9Sstevel@tonic-gate 
2602*7c478bd9Sstevel@tonic-gate 	act.sa_sigaction = term_handler;
2603*7c478bd9Sstevel@tonic-gate 	(void) sigemptyset(&act.sa_mask);
2604*7c478bd9Sstevel@tonic-gate 	act.sa_flags = SA_SIGINFO;
2605*7c478bd9Sstevel@tonic-gate 	if (sigaction(SIGTERM, &act, NULL) == -1)
2606*7c478bd9Sstevel@tonic-gate 		warning(gettext(SIGACT_FAILED), strsignal(SIGTERM),
2607*7c478bd9Sstevel@tonic-gate 		    strerror(errno));
2608*7c478bd9Sstevel@tonic-gate 
2609*7c478bd9Sstevel@tonic-gate 	act.sa_sigaction = sig_handler;
2610*7c478bd9Sstevel@tonic-gate 	(void) sigemptyset(&act.sa_mask);
2611*7c478bd9Sstevel@tonic-gate 	act.sa_flags = SA_SIGINFO;
2612*7c478bd9Sstevel@tonic-gate 	if (sigaction(SIGINT, &act, NULL) == -1)
2613*7c478bd9Sstevel@tonic-gate 		warning(gettext(SIGACT_FAILED), strsignal(SIGHUP),
2614*7c478bd9Sstevel@tonic-gate 		    strerror(errno));
2615*7c478bd9Sstevel@tonic-gate 
2616*7c478bd9Sstevel@tonic-gate 	act.sa_sigaction = sig_handler;
2617*7c478bd9Sstevel@tonic-gate 	(void) sigemptyset(&act.sa_mask);
2618*7c478bd9Sstevel@tonic-gate 	act.sa_flags = SA_SIGINFO;
2619*7c478bd9Sstevel@tonic-gate 	if (sigaction(SIGQUIT, &act, NULL) == -1)
2620*7c478bd9Sstevel@tonic-gate 		warning(gettext(SIGACT_FAILED), strsignal(SIGHUP),
2621*7c478bd9Sstevel@tonic-gate 		    strerror(errno));
2622*7c478bd9Sstevel@tonic-gate 	debug(10, "init_server completed successfully\n");
2623*7c478bd9Sstevel@tonic-gate 
2624*7c478bd9Sstevel@tonic-gate 	server_data.sd_init_state = INIT_DONE;
2625*7c478bd9Sstevel@tonic-gate 	return (NULL);
2626*7c478bd9Sstevel@tonic-gate }
2627*7c478bd9Sstevel@tonic-gate 
2628*7c478bd9Sstevel@tonic-gate static int
2629*7c478bd9Sstevel@tonic-gate server_exists()
2630*7c478bd9Sstevel@tonic-gate {
2631*7c478bd9Sstevel@tonic-gate 	door_arg_t		darg;
2632*7c478bd9Sstevel@tonic-gate 	smedia_reqping_t	req_ping;
2633*7c478bd9Sstevel@tonic-gate 	smedia_retping_t	*ret_ping;
2634*7c478bd9Sstevel@tonic-gate 	int			doorh;
2635*7c478bd9Sstevel@tonic-gate 	door_info_t		dinfo;
2636*7c478bd9Sstevel@tonic-gate 	char    rbuf[sizeof (smedia_services_t) + sizeof (door_desc_t)];
2637*7c478bd9Sstevel@tonic-gate 
2638*7c478bd9Sstevel@tonic-gate 	doorh = open(smedia_service, O_RDONLY);
2639*7c478bd9Sstevel@tonic-gate 	if (doorh < 0)
2640*7c478bd9Sstevel@tonic-gate 		return (0);
2641*7c478bd9Sstevel@tonic-gate 	if (door_info(doorh, &dinfo) < 0) {
2642*7c478bd9Sstevel@tonic-gate 		(void) close(doorh);
2643*7c478bd9Sstevel@tonic-gate 		return (0);
2644*7c478bd9Sstevel@tonic-gate 	}
2645*7c478bd9Sstevel@tonic-gate 
2646*7c478bd9Sstevel@tonic-gate 	if (dinfo.di_attributes & DOOR_REVOKED) {
2647*7c478bd9Sstevel@tonic-gate 		(void) close(doorh);
2648*7c478bd9Sstevel@tonic-gate 		return (0);
2649*7c478bd9Sstevel@tonic-gate 	}
2650*7c478bd9Sstevel@tonic-gate 
2651*7c478bd9Sstevel@tonic-gate 	req_ping.cnum = SMEDIA_CNUM_PING;
2652*7c478bd9Sstevel@tonic-gate 
2653*7c478bd9Sstevel@tonic-gate 	darg.data_ptr = (char *)&req_ping;
2654*7c478bd9Sstevel@tonic-gate 	darg.data_size = sizeof (smedia_reqping_t);
2655*7c478bd9Sstevel@tonic-gate 	darg.desc_ptr = NULL;
2656*7c478bd9Sstevel@tonic-gate 	darg.desc_num = 0;
2657*7c478bd9Sstevel@tonic-gate 	darg.rbuf = rbuf;
2658*7c478bd9Sstevel@tonic-gate 	darg.rsize = sizeof (rbuf);
2659*7c478bd9Sstevel@tonic-gate 
2660*7c478bd9Sstevel@tonic-gate 	if (door_call(doorh, &darg) < 0) {
2661*7c478bd9Sstevel@tonic-gate 		(void) close(doorh);
2662*7c478bd9Sstevel@tonic-gate 		return (0);
2663*7c478bd9Sstevel@tonic-gate 	}
2664*7c478bd9Sstevel@tonic-gate 	ret_ping = (smedia_retping_t *)((void *)darg.data_ptr);
2665*7c478bd9Sstevel@tonic-gate 	if (ret_ping->cnum != SMEDIA_CNUM_PING) {
2666*7c478bd9Sstevel@tonic-gate 		(void) close(doorh);
2667*7c478bd9Sstevel@tonic-gate 		return (0);
2668*7c478bd9Sstevel@tonic-gate 	}
2669*7c478bd9Sstevel@tonic-gate 
2670*7c478bd9Sstevel@tonic-gate 	(void) close(doorh);
2671*7c478bd9Sstevel@tonic-gate 	return (1);
2672*7c478bd9Sstevel@tonic-gate }
2673*7c478bd9Sstevel@tonic-gate 
2674*7c478bd9Sstevel@tonic-gate static int
2675*7c478bd9Sstevel@tonic-gate get_run_level()
2676*7c478bd9Sstevel@tonic-gate {
2677*7c478bd9Sstevel@tonic-gate 	int	run_level;
2678*7c478bd9Sstevel@tonic-gate 	struct utmpx	*utmpp;
2679*7c478bd9Sstevel@tonic-gate 
2680*7c478bd9Sstevel@tonic-gate 	setutxent();
2681*7c478bd9Sstevel@tonic-gate 	while ((utmpp = getutxent()) != NULL) {
2682*7c478bd9Sstevel@tonic-gate 		if (utmpp->ut_type == RUN_LVL) {
2683*7c478bd9Sstevel@tonic-gate 			run_level = atoi(
2684*7c478bd9Sstevel@tonic-gate 				&utmpp->ut_line[strlen("run-level ")]);
2685*7c478bd9Sstevel@tonic-gate 		}
2686*7c478bd9Sstevel@tonic-gate 	}
2687*7c478bd9Sstevel@tonic-gate 	return (run_level);
2688*7c478bd9Sstevel@tonic-gate }
2689*7c478bd9Sstevel@tonic-gate 
2690*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/
2691*7c478bd9Sstevel@tonic-gate static void *
2692*7c478bd9Sstevel@tonic-gate closedown(void *arg)
2693*7c478bd9Sstevel@tonic-gate {
2694*7c478bd9Sstevel@tonic-gate 
2695*7c478bd9Sstevel@tonic-gate 	int	current_run_level;
2696*7c478bd9Sstevel@tonic-gate 
2697*7c478bd9Sstevel@tonic-gate 	/*CONSTCOND*/
2698*7c478bd9Sstevel@tonic-gate #ifndef lint
2699*7c478bd9Sstevel@tonic-gate 	while (1) {
2700*7c478bd9Sstevel@tonic-gate #endif
2701*7c478bd9Sstevel@tonic-gate 		(void) sleep(SVC_CLOSEDOWN/2);
2702*7c478bd9Sstevel@tonic-gate 
2703*7c478bd9Sstevel@tonic-gate 		/*
2704*7c478bd9Sstevel@tonic-gate 		 * If the server was started at init level 1
2705*7c478bd9Sstevel@tonic-gate 		 * and the current init level is 1 then
2706*7c478bd9Sstevel@tonic-gate 		 * do not exit from server. This server will run
2707*7c478bd9Sstevel@tonic-gate 		 * until it is explicitly stopped by the user.
2708*7c478bd9Sstevel@tonic-gate 		 */
2709*7c478bd9Sstevel@tonic-gate 		if (svcstart_level == 1) {
2710*7c478bd9Sstevel@tonic-gate 			current_run_level = get_run_level();
2711*7c478bd9Sstevel@tonic-gate 			if (current_run_level == 1)
2712*7c478bd9Sstevel@tonic-gate #ifndef lint
2713*7c478bd9Sstevel@tonic-gate 				continue;
2714*7c478bd9Sstevel@tonic-gate #else
2715*7c478bd9Sstevel@tonic-gate 				return (NULL);
2716*7c478bd9Sstevel@tonic-gate #endif
2717*7c478bd9Sstevel@tonic-gate 			/*
2718*7c478bd9Sstevel@tonic-gate 			 * who ever started the server at level 1 has
2719*7c478bd9Sstevel@tonic-gate 			 * forgotten to stop the server. we will kill ourself.
2720*7c478bd9Sstevel@tonic-gate 			 */
2721*7c478bd9Sstevel@tonic-gate 			debug(5,
2722*7c478bd9Sstevel@tonic-gate 			"Terminating the server started at init level 1\n");
2723*7c478bd9Sstevel@tonic-gate 			exit(0);
2724*7c478bd9Sstevel@tonic-gate 		}
2725*7c478bd9Sstevel@tonic-gate 
2726*7c478bd9Sstevel@tonic-gate 		if (mutex_trylock(&svcstate_lock) != 0)
2727*7c478bd9Sstevel@tonic-gate #ifndef lint
2728*7c478bd9Sstevel@tonic-gate 			continue;
2729*7c478bd9Sstevel@tonic-gate #else
2730*7c478bd9Sstevel@tonic-gate 			return (NULL);
2731*7c478bd9Sstevel@tonic-gate #endif
2732*7c478bd9Sstevel@tonic-gate 
2733*7c478bd9Sstevel@tonic-gate 		if (svcstate == _IDLE && svccount == 0) {
2734*7c478bd9Sstevel@tonic-gate 			int size;
2735*7c478bd9Sstevel@tonic-gate 			int i, openfd = 0;
2736*7c478bd9Sstevel@tonic-gate 
2737*7c478bd9Sstevel@tonic-gate 			size = svc_max_pollfd;
2738*7c478bd9Sstevel@tonic-gate 			for (i = 0; i < size && openfd < 2; i++)
2739*7c478bd9Sstevel@tonic-gate 				if (svc_pollfd[i].fd >= 0)
2740*7c478bd9Sstevel@tonic-gate 					openfd++;
2741*7c478bd9Sstevel@tonic-gate 			if (openfd <= 1) {
2742*7c478bd9Sstevel@tonic-gate 				debug(5,
2743*7c478bd9Sstevel@tonic-gate 				"Exiting the server from closedown routine.\n");
2744*7c478bd9Sstevel@tonic-gate 				exit(0);
2745*7c478bd9Sstevel@tonic-gate 			}
2746*7c478bd9Sstevel@tonic-gate 		} else
2747*7c478bd9Sstevel@tonic-gate 			svcstate = _IDLE;
2748*7c478bd9Sstevel@tonic-gate 
2749*7c478bd9Sstevel@tonic-gate 		(void) mutex_unlock(&svcstate_lock);
2750*7c478bd9Sstevel@tonic-gate #ifndef lint
2751*7c478bd9Sstevel@tonic-gate 	}
2752*7c478bd9Sstevel@tonic-gate #else
2753*7c478bd9Sstevel@tonic-gate 	return (NULL);
2754*7c478bd9Sstevel@tonic-gate #endif
2755*7c478bd9Sstevel@tonic-gate 
2756*7c478bd9Sstevel@tonic-gate }
2757*7c478bd9Sstevel@tonic-gate 
2758*7c478bd9Sstevel@tonic-gate static void
2759*7c478bd9Sstevel@tonic-gate usage()
2760*7c478bd9Sstevel@tonic-gate {
2761*7c478bd9Sstevel@tonic-gate 	warning(gettext("usage: %s [-L loglevel] level of debug information\n"),
2762*7c478bd9Sstevel@tonic-gate 		prog_name);
2763*7c478bd9Sstevel@tonic-gate }
2764*7c478bd9Sstevel@tonic-gate 
2765*7c478bd9Sstevel@tonic-gate 
2766*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/
2767*7c478bd9Sstevel@tonic-gate void
2768*7c478bd9Sstevel@tonic-gate main(int argc, char **argv)
2769*7c478bd9Sstevel@tonic-gate {
2770*7c478bd9Sstevel@tonic-gate 	int c;
2771*7c478bd9Sstevel@tonic-gate 	pthread_attr_t	attr;
2772*7c478bd9Sstevel@tonic-gate 
2773*7c478bd9Sstevel@tonic-gate 	(void) setlocale(LC_ALL, "");
2774*7c478bd9Sstevel@tonic-gate #if !defined(TEXT_DOMAIN)
2775*7c478bd9Sstevel@tonic-gate #define	TEXT_DOMAIN "SYS_TEST"
2776*7c478bd9Sstevel@tonic-gate #endif
2777*7c478bd9Sstevel@tonic-gate 	(void) textdomain(TEXT_DOMAIN);
2778*7c478bd9Sstevel@tonic-gate 
2779*7c478bd9Sstevel@tonic-gate 	prog_name = argv[0];
2780*7c478bd9Sstevel@tonic-gate 
2781*7c478bd9Sstevel@tonic-gate 	(void) sigset(SIGPIPE, SIG_IGN);
2782*7c478bd9Sstevel@tonic-gate 
2783*7c478bd9Sstevel@tonic-gate 	while ((c = getopt(argc, argv, "L:")) != -1) {
2784*7c478bd9Sstevel@tonic-gate 		switch (c) {
2785*7c478bd9Sstevel@tonic-gate 		case 'L':
2786*7c478bd9Sstevel@tonic-gate 			debug_level = atoi((char *)optarg);
2787*7c478bd9Sstevel@tonic-gate 			break;
2788*7c478bd9Sstevel@tonic-gate 		default:
2789*7c478bd9Sstevel@tonic-gate 			usage();
2790*7c478bd9Sstevel@tonic-gate 			break;
2791*7c478bd9Sstevel@tonic-gate 		}
2792*7c478bd9Sstevel@tonic-gate 	}
2793*7c478bd9Sstevel@tonic-gate 
2794*7c478bd9Sstevel@tonic-gate 	/*
2795*7c478bd9Sstevel@tonic-gate 	 * If stdin looks like a TLI endpoint, we assume
2796*7c478bd9Sstevel@tonic-gate 	 * that we were started by a port monitor. If
2797*7c478bd9Sstevel@tonic-gate 	 * t_getstate fails with TBADF, this is not a
2798*7c478bd9Sstevel@tonic-gate 	 * TLI endpoint.
2799*7c478bd9Sstevel@tonic-gate 	 */
2800*7c478bd9Sstevel@tonic-gate 	if (t_getstate(0) != -1 || t_errno != TBADF) {
2801*7c478bd9Sstevel@tonic-gate 		char *netid;
2802*7c478bd9Sstevel@tonic-gate 		struct netconfig *nconf = NULL;
2803*7c478bd9Sstevel@tonic-gate 		SVCXPRT *transp;
2804*7c478bd9Sstevel@tonic-gate 		int pmclose;
2805*7c478bd9Sstevel@tonic-gate 
2806*7c478bd9Sstevel@tonic-gate 		openlog(prog_name, LOG_PID, LOG_DAEMON);
2807*7c478bd9Sstevel@tonic-gate 
2808*7c478bd9Sstevel@tonic-gate 		debug(1, gettext("server started by port monitor.\n"));
2809*7c478bd9Sstevel@tonic-gate 		if ((netid = getenv("NLSPROVIDER")) == NULL) {
2810*7c478bd9Sstevel@tonic-gate 		/* started from inetd */
2811*7c478bd9Sstevel@tonic-gate 			pmclose = 1;
2812*7c478bd9Sstevel@tonic-gate 		} else {
2813*7c478bd9Sstevel@tonic-gate 			if ((nconf = getnetconfigent(netid)) == NULL)
2814*7c478bd9Sstevel@tonic-gate 				syslog(LOG_ERR, gettext(
2815*7c478bd9Sstevel@tonic-gate 					"cannot get transport info"));
2816*7c478bd9Sstevel@tonic-gate 
2817*7c478bd9Sstevel@tonic-gate 			pmclose = (t_getstate(0) != T_DATAXFER);
2818*7c478bd9Sstevel@tonic-gate 		}
2819*7c478bd9Sstevel@tonic-gate 		if ((transp = svc_tli_create(0, nconf, NULL, 0, 0)) == NULL) {
2820*7c478bd9Sstevel@tonic-gate 			syslog(LOG_ERR, gettext("cannot create server handle"));
2821*7c478bd9Sstevel@tonic-gate 			exit(1);
2822*7c478bd9Sstevel@tonic-gate 		}
2823*7c478bd9Sstevel@tonic-gate 		if (nconf)
2824*7c478bd9Sstevel@tonic-gate 			freenetconfigent(nconf);
2825*7c478bd9Sstevel@tonic-gate 		if (!svc_reg(transp, SMSERVERPROG, SMSERVERVERS,
2826*7c478bd9Sstevel@tonic-gate 			smserverprog_1, 0)) {
2827*7c478bd9Sstevel@tonic-gate 			syslog(LOG_ERR, gettext(
2828*7c478bd9Sstevel@tonic-gate 			"unable to register (SMSERVERPROG, SMSERVERVERS)."));
2829*7c478bd9Sstevel@tonic-gate 			exit(1);
2830*7c478bd9Sstevel@tonic-gate 		}
2831*7c478bd9Sstevel@tonic-gate 		svcstart_level = get_run_level();
2832*7c478bd9Sstevel@tonic-gate 		if (pmclose) {
2833*7c478bd9Sstevel@tonic-gate 			(void) pthread_attr_init(&attr);
2834*7c478bd9Sstevel@tonic-gate 			(void) pthread_attr_setscope(&attr,
2835*7c478bd9Sstevel@tonic-gate 				PTHREAD_SCOPE_SYSTEM | PTHREAD_CREATE_DETACHED);
2836*7c478bd9Sstevel@tonic-gate 			if (pthread_create(NULL, &attr, closedown, NULL) != 0) {
2837*7c478bd9Sstevel@tonic-gate 				syslog(LOG_ERR, gettext(
2838*7c478bd9Sstevel@tonic-gate 					"cannot create closedown thread"));
2839*7c478bd9Sstevel@tonic-gate 				exit(1);
2840*7c478bd9Sstevel@tonic-gate 			}
2841*7c478bd9Sstevel@tonic-gate 			(void) pthread_attr_destroy(&attr);
2842*7c478bd9Sstevel@tonic-gate 		}
2843*7c478bd9Sstevel@tonic-gate 		svc_run();
2844*7c478bd9Sstevel@tonic-gate 		exit(1);
2845*7c478bd9Sstevel@tonic-gate 		/* NOTREACHED */
2846*7c478bd9Sstevel@tonic-gate 	} else {
2847*7c478bd9Sstevel@tonic-gate 		/*
2848*7c478bd9Sstevel@tonic-gate 		 * Started by library or manually.
2849*7c478bd9Sstevel@tonic-gate 		 */
2850*7c478bd9Sstevel@tonic-gate 		/*
2851*7c478bd9Sstevel@tonic-gate 		 * Check to see if the server is already running.
2852*7c478bd9Sstevel@tonic-gate 		 * There is no need to log messages in the syslog file
2853*7c478bd9Sstevel@tonic-gate 		 * because server will get launched each time libsmedia
2854*7c478bd9Sstevel@tonic-gate 		 * library calls are made at init 1 level.
2855*7c478bd9Sstevel@tonic-gate 		 * We ensure that only one copy will run.
2856*7c478bd9Sstevel@tonic-gate 		 */
2857*7c478bd9Sstevel@tonic-gate 		debug(1, gettext("server started manually.\n"));
2858*7c478bd9Sstevel@tonic-gate 		if (server_exists()) {
2859*7c478bd9Sstevel@tonic-gate 			exit(0);
2860*7c478bd9Sstevel@tonic-gate 		}
2861*7c478bd9Sstevel@tonic-gate 		svcstart_level = get_run_level();
2862*7c478bd9Sstevel@tonic-gate 		(void) pthread_attr_init(&attr);
2863*7c478bd9Sstevel@tonic-gate 		(void) pthread_attr_setscope(&attr,
2864*7c478bd9Sstevel@tonic-gate 			PTHREAD_SCOPE_SYSTEM | PTHREAD_CREATE_DETACHED);
2865*7c478bd9Sstevel@tonic-gate 		if (pthread_create(NULL, &attr, closedown, NULL) != 0) {
2866*7c478bd9Sstevel@tonic-gate 			syslog(LOG_ERR, gettext(
2867*7c478bd9Sstevel@tonic-gate 				"cannot create closedown thread"));
2868*7c478bd9Sstevel@tonic-gate 			exit(1);
2869*7c478bd9Sstevel@tonic-gate 		}
2870*7c478bd9Sstevel@tonic-gate 		(void) pthread_attr_destroy(&attr);
2871*7c478bd9Sstevel@tonic-gate 		(void) init_server(NULL);
2872*7c478bd9Sstevel@tonic-gate 		for (;;) (void) pause();
2873*7c478bd9Sstevel@tonic-gate 	}
2874*7c478bd9Sstevel@tonic-gate }
2875*7c478bd9Sstevel@tonic-gate 
2876*7c478bd9Sstevel@tonic-gate 
2877*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/
2878*7c478bd9Sstevel@tonic-gate static int32_t
2879*7c478bd9Sstevel@tonic-gate scsi_floppy_write_protect(int32_t fd, smwp_state_t *wp)
2880*7c478bd9Sstevel@tonic-gate {
2881*7c478bd9Sstevel@tonic-gate 	debug(5, "Invalid mode\n");
2882*7c478bd9Sstevel@tonic-gate 	errno = ENOTSUP;
2883*7c478bd9Sstevel@tonic-gate 
2884*7c478bd9Sstevel@tonic-gate 	return (-1);
2885*7c478bd9Sstevel@tonic-gate }
2886*7c478bd9Sstevel@tonic-gate 
2887*7c478bd9Sstevel@tonic-gate /*
2888*7c478bd9Sstevel@tonic-gate  * Generate standard geometry information for SCSI floppy devices. And
2889*7c478bd9Sstevel@tonic-gate  * register the geometry with the SCSI driver. This will expand as more
2890*7c478bd9Sstevel@tonic-gate  * formats are added.
2891*7c478bd9Sstevel@tonic-gate  */
2892*7c478bd9Sstevel@tonic-gate 
2893*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/
2894*7c478bd9Sstevel@tonic-gate static int32_t
2895*7c478bd9Sstevel@tonic-gate get_floppy_geom(int32_t fd, uint32_t capacity, struct dk_geom *dkgeom)
2896*7c478bd9Sstevel@tonic-gate {
2897*7c478bd9Sstevel@tonic-gate 
2898*7c478bd9Sstevel@tonic-gate 
2899*7c478bd9Sstevel@tonic-gate 	debug(5, "get_floppy_geom: capacity = 0x%x\n", capacity);
2900*7c478bd9Sstevel@tonic-gate 
2901*7c478bd9Sstevel@tonic-gate 	switch (capacity) {
2902*7c478bd9Sstevel@tonic-gate 
2903*7c478bd9Sstevel@tonic-gate 		case 0x5A0:
2904*7c478bd9Sstevel@tonic-gate 			/* Double Density 720K */
2905*7c478bd9Sstevel@tonic-gate 			dkgeom->dkg_pcyl = 80;
2906*7c478bd9Sstevel@tonic-gate 			dkgeom->dkg_ncyl = 80;
2907*7c478bd9Sstevel@tonic-gate 			dkgeom->dkg_nhead = 2;
2908*7c478bd9Sstevel@tonic-gate 			dkgeom->dkg_nsect = 9;
2909*7c478bd9Sstevel@tonic-gate 			break;
2910*7c478bd9Sstevel@tonic-gate 		case 0x4D0:
2911*7c478bd9Sstevel@tonic-gate 			/* High Density 1.25MB */
2912*7c478bd9Sstevel@tonic-gate 			dkgeom->dkg_pcyl = 77;
2913*7c478bd9Sstevel@tonic-gate 			dkgeom->dkg_ncyl = 77;
2914*7c478bd9Sstevel@tonic-gate 			dkgeom->dkg_nhead = 2;
2915*7c478bd9Sstevel@tonic-gate 			dkgeom->dkg_nsect = 9;
2916*7c478bd9Sstevel@tonic-gate 			break;
2917*7c478bd9Sstevel@tonic-gate 		case 0xB40:
2918*7c478bd9Sstevel@tonic-gate 			/* High Density 1.44MB */
2919*7c478bd9Sstevel@tonic-gate 
2920*7c478bd9Sstevel@tonic-gate 			dkgeom->dkg_pcyl = 80;
2921*7c478bd9Sstevel@tonic-gate 			dkgeom->dkg_ncyl = 80;
2922*7c478bd9Sstevel@tonic-gate 			dkgeom->dkg_nhead = 2;
2923*7c478bd9Sstevel@tonic-gate 			dkgeom->dkg_nsect = 18;
2924*7c478bd9Sstevel@tonic-gate 			break;
2925*7c478bd9Sstevel@tonic-gate 		case 0x3C300:
2926*7c478bd9Sstevel@tonic-gate 			/* Ultra High density ls-120 120MB */
2927*7c478bd9Sstevel@tonic-gate 			dkgeom->dkg_pcyl = 963;
2928*7c478bd9Sstevel@tonic-gate 			dkgeom->dkg_ncyl = 963;
2929*7c478bd9Sstevel@tonic-gate 			dkgeom->dkg_nhead = 8;
2930*7c478bd9Sstevel@tonic-gate 			dkgeom->dkg_nsect = 32;
2931*7c478bd9Sstevel@tonic-gate 			break;
2932*7c478bd9Sstevel@tonic-gate 		default:
2933*7c478bd9Sstevel@tonic-gate 			debug(5, "unknown capacity type %d\n", capacity);
2934*7c478bd9Sstevel@tonic-gate 			return (-1);
2935*7c478bd9Sstevel@tonic-gate 
2936*7c478bd9Sstevel@tonic-gate 	}
2937*7c478bd9Sstevel@tonic-gate 	debug(5, "get_floppy_geom: setting cyl = %d, nsect = %d, head = %d",
2938*7c478bd9Sstevel@tonic-gate 		dkgeom->dkg_pcyl, dkgeom->dkg_nhead, dkgeom->dkg_nsect);
2939*7c478bd9Sstevel@tonic-gate 	return (0);
2940*7c478bd9Sstevel@tonic-gate 
2941*7c478bd9Sstevel@tonic-gate }
2942*7c478bd9Sstevel@tonic-gate /* ARGSUSED */
2943*7c478bd9Sstevel@tonic-gate int32_t
2944*7c478bd9Sstevel@tonic-gate scsi_floppy_format(int32_t fd, uint_t flavor, uint_t mode)
2945*7c478bd9Sstevel@tonic-gate {
2946*7c478bd9Sstevel@tonic-gate 	struct uscsi_cmd ucmd;
2947*7c478bd9Sstevel@tonic-gate 	uchar_t		cdb[12];
2948*7c478bd9Sstevel@tonic-gate 	int32_t		ret_val;
2949*7c478bd9Sstevel@tonic-gate 	uint32_t	capacity, blocksize;
2950*7c478bd9Sstevel@tonic-gate 	uchar_t		data[12];
2951*7c478bd9Sstevel@tonic-gate 	char 		rq_data[RQ_LEN];
2952*7c478bd9Sstevel@tonic-gate 	int		i;
2953*7c478bd9Sstevel@tonic-gate 	struct dk_geom	dkgeom;
2954*7c478bd9Sstevel@tonic-gate 
2955*7c478bd9Sstevel@tonic-gate 	debug(5, "scsi_floppy_format:\n");
2956*7c478bd9Sstevel@tonic-gate 
2957*7c478bd9Sstevel@tonic-gate 	if ((mode != SM_FORMAT_IMMEDIATE) && (mode != SM_FORMAT_BLOCKED)) {
2958*7c478bd9Sstevel@tonic-gate 		errno = ENOTSUP;
2959*7c478bd9Sstevel@tonic-gate 
2960*7c478bd9Sstevel@tonic-gate 		return (-1);
2961*7c478bd9Sstevel@tonic-gate 	}
2962*7c478bd9Sstevel@tonic-gate 
2963*7c478bd9Sstevel@tonic-gate 	switch (flavor) {
2964*7c478bd9Sstevel@tonic-gate 		case SM_FORMAT_QUICK :
2965*7c478bd9Sstevel@tonic-gate 			debug(1, "Format not supported\n");
2966*7c478bd9Sstevel@tonic-gate 			errno = ENOTSUP;
2967*7c478bd9Sstevel@tonic-gate 			return (-1);
2968*7c478bd9Sstevel@tonic-gate 		case SM_FORMAT_FORCE :
2969*7c478bd9Sstevel@tonic-gate 			break;
2970*7c478bd9Sstevel@tonic-gate 		case SM_FORMAT_LONG :
2971*7c478bd9Sstevel@tonic-gate 			break;
2972*7c478bd9Sstevel@tonic-gate 
2973*7c478bd9Sstevel@tonic-gate 		default :
2974*7c478bd9Sstevel@tonic-gate 			debug(1, "Format option not specified!!\n");
2975*7c478bd9Sstevel@tonic-gate 			errno = ENOTSUP;
2976*7c478bd9Sstevel@tonic-gate 			return (-1);
2977*7c478bd9Sstevel@tonic-gate 	}
2978*7c478bd9Sstevel@tonic-gate 
2979*7c478bd9Sstevel@tonic-gate 	ret_val = get_media_capacity(fd, &capacity, &blocksize);
2980*7c478bd9Sstevel@tonic-gate 
2981*7c478bd9Sstevel@tonic-gate 	if (capacity >= 0x3C300) {
2982*7c478bd9Sstevel@tonic-gate 		/*
2983*7c478bd9Sstevel@tonic-gate 		 * It's an LS-120 media, it does not support track
2984*7c478bd9Sstevel@tonic-gate 		 * formatting.
2985*7c478bd9Sstevel@tonic-gate 		 */
2986*7c478bd9Sstevel@tonic-gate 		return (scsi_ls120_format(fd, flavor, capacity, blocksize));
2987*7c478bd9Sstevel@tonic-gate 	}
2988*7c478bd9Sstevel@tonic-gate 
2989*7c478bd9Sstevel@tonic-gate 	ret_val = get_floppy_geom(fd, capacity, &dkgeom);
2990*7c478bd9Sstevel@tonic-gate 		if (ret_val) {
2991*7c478bd9Sstevel@tonic-gate 			errno = ENOTSUP;
2992*7c478bd9Sstevel@tonic-gate 			return (-1);
2993*7c478bd9Sstevel@tonic-gate 		}
2994*7c478bd9Sstevel@tonic-gate 
2995*7c478bd9Sstevel@tonic-gate 	(void) memset((void *)&data, 0, sizeof (data));
2996*7c478bd9Sstevel@tonic-gate 	(void) memset((void *)&ucmd, 0, sizeof (ucmd));
2997*7c478bd9Sstevel@tonic-gate 	(void) memset((void *)&cdb, 0, sizeof (cdb));
2998*7c478bd9Sstevel@tonic-gate 
2999*7c478bd9Sstevel@tonic-gate 	/* retrieve size discriptor of inserted media */
3000*7c478bd9Sstevel@tonic-gate 	cdb[0] = SCMD_FORMAT;	/* format */
3001*7c478bd9Sstevel@tonic-gate 
3002*7c478bd9Sstevel@tonic-gate 	/*
3003*7c478bd9Sstevel@tonic-gate 	 * Defect list sent by initiator is a complete list of defects.
3004*7c478bd9Sstevel@tonic-gate 	 */
3005*7c478bd9Sstevel@tonic-gate 
3006*7c478bd9Sstevel@tonic-gate 	cdb[1] = (FMTDATA | 0x7);
3007*7c478bd9Sstevel@tonic-gate 
3008*7c478bd9Sstevel@tonic-gate 	cdb[8] = 0xC;   /* parameter list length */
3009*7c478bd9Sstevel@tonic-gate 	data[3] = 0x8;	/* should be always 8 */
3010*7c478bd9Sstevel@tonic-gate 
3011*7c478bd9Sstevel@tonic-gate 	data[4] = (uchar_t)(capacity >> 24);
3012*7c478bd9Sstevel@tonic-gate 	data[5] = (uchar_t)(capacity >> 16);
3013*7c478bd9Sstevel@tonic-gate 	data[6] = (uchar_t)(capacity >> 8);
3014*7c478bd9Sstevel@tonic-gate 	data[7] = (uchar_t)capacity;
3015*7c478bd9Sstevel@tonic-gate 
3016*7c478bd9Sstevel@tonic-gate 	data[9] = (uchar_t)(blocksize >> 16);
3017*7c478bd9Sstevel@tonic-gate 	data[10] = (uchar_t)(blocksize >> 8);
3018*7c478bd9Sstevel@tonic-gate 	data[11] = (uchar_t)blocksize;
3019*7c478bd9Sstevel@tonic-gate 
3020*7c478bd9Sstevel@tonic-gate 	ucmd.uscsi_cdb = (caddr_t)&cdb;
3021*7c478bd9Sstevel@tonic-gate 	ucmd.uscsi_cdblen = CDB_GROUP5;
3022*7c478bd9Sstevel@tonic-gate 	ucmd.uscsi_bufaddr = (caddr_t)data;
3023*7c478bd9Sstevel@tonic-gate 	ucmd.uscsi_buflen = sizeof (data);
3024*7c478bd9Sstevel@tonic-gate 	ucmd.uscsi_timeout = 0x15;
3025*7c478bd9Sstevel@tonic-gate 	ucmd.uscsi_rqlen = RQ_LEN;
3026*7c478bd9Sstevel@tonic-gate 	ucmd.uscsi_rqbuf = rq_data;
3027*7c478bd9Sstevel@tonic-gate 
3028*7c478bd9Sstevel@tonic-gate 	debug(5, "cdb: %x %x %x ... %x", cdb[0], cdb[1], cdb[2], cdb[8]);
3029*7c478bd9Sstevel@tonic-gate 	debug(5, "data: %x %x %x %x\n", data[0], data[1], data[2], data[3]);
3030*7c478bd9Sstevel@tonic-gate 	debug(5, "    : %x %x %x %x\n", data[4], data[5], data[6], data[7]);
3031*7c478bd9Sstevel@tonic-gate 	debug(5, "    : %x %x %x %x\n", data[8], data[9], data[10], data[11]);
3032*7c478bd9Sstevel@tonic-gate 
3033*7c478bd9Sstevel@tonic-gate 	for (i = 0; i < dkgeom.dkg_pcyl; i++) {	/* number of tracks */
3034*7c478bd9Sstevel@tonic-gate 		data[1] = (0xb0 | FOV);
3035*7c478bd9Sstevel@tonic-gate 		cdb[2] = i;
3036*7c478bd9Sstevel@tonic-gate 
3037*7c478bd9Sstevel@tonic-gate 		(void) fflush(stdout);
3038*7c478bd9Sstevel@tonic-gate 		ret_val = do_uscsi_cmd(fd, &ucmd, USCSI_WRITE|USCSI_RQENABLE);
3039*7c478bd9Sstevel@tonic-gate 		info("format side 0 returned : 0x%x\n", ret_val);
3040*7c478bd9Sstevel@tonic-gate 
3041*7c478bd9Sstevel@tonic-gate 		if (ret_val || ucmd.uscsi_status) {
3042*7c478bd9Sstevel@tonic-gate 			debug(5, "Retrieving media info failed: %d - %d\n",
3043*7c478bd9Sstevel@tonic-gate 			    ret_val, ucmd.uscsi_status);
3044*7c478bd9Sstevel@tonic-gate 			if ((rq_data[2] == KEY_DATA_PROTECT) &&
3045*7c478bd9Sstevel@tonic-gate 			    (rq_data[12] == 0x30) && (rq_data[13] == 0)) {
3046*7c478bd9Sstevel@tonic-gate 				debug(5, "Invalid command for media\n");
3047*7c478bd9Sstevel@tonic-gate 				errno = EINVAL;
3048*7c478bd9Sstevel@tonic-gate 			}
3049*7c478bd9Sstevel@tonic-gate 
3050*7c478bd9Sstevel@tonic-gate 			if ((rq_data[2] == KEY_NOT_READY) &&
3051*7c478bd9Sstevel@tonic-gate 			    (rq_data[12] == 0x30)) {
3052*7c478bd9Sstevel@tonic-gate 				debug(5, "Incompatible media.\n");
3053*7c478bd9Sstevel@tonic-gate 				errno = EINVAL;
3054*7c478bd9Sstevel@tonic-gate 			}
3055*7c478bd9Sstevel@tonic-gate 
3056*7c478bd9Sstevel@tonic-gate 			return (-1);
3057*7c478bd9Sstevel@tonic-gate 		}
3058*7c478bd9Sstevel@tonic-gate 		data[1] = (0xb0 | FOV) + 1;
3059*7c478bd9Sstevel@tonic-gate 		ret_val = do_uscsi_cmd(fd, &ucmd, USCSI_WRITE|USCSI_RQENABLE);
3060*7c478bd9Sstevel@tonic-gate 		info("format side 1 returned : 0x%x\n", ret_val);
3061*7c478bd9Sstevel@tonic-gate 
3062*7c478bd9Sstevel@tonic-gate 		if (ret_val || ucmd.uscsi_status) {
3063*7c478bd9Sstevel@tonic-gate 			debug(5, "Retrieving media info failed: %d - %d\n",
3064*7c478bd9Sstevel@tonic-gate 			    ret_val, ucmd.uscsi_status);
3065*7c478bd9Sstevel@tonic-gate 			if ((rq_data[2] == KEY_DATA_PROTECT) &&
3066*7c478bd9Sstevel@tonic-gate 			    (rq_data[12] == 0x30) && (rq_data[13] == 0)) {
3067*7c478bd9Sstevel@tonic-gate 				(void) info("Invalid command for media\n");
3068*7c478bd9Sstevel@tonic-gate 				errno = EINVAL;
3069*7c478bd9Sstevel@tonic-gate 			}
3070*7c478bd9Sstevel@tonic-gate 
3071*7c478bd9Sstevel@tonic-gate 			if ((rq_data[2] == KEY_NOT_READY) &&
3072*7c478bd9Sstevel@tonic-gate 			    (rq_data[12] == 0x30)) {
3073*7c478bd9Sstevel@tonic-gate 				debug(5, "Incompatible media.\n");
3074*7c478bd9Sstevel@tonic-gate 				errno = EINVAL;
3075*7c478bd9Sstevel@tonic-gate 			}
3076*7c478bd9Sstevel@tonic-gate 
3077*7c478bd9Sstevel@tonic-gate 			return (-1);
3078*7c478bd9Sstevel@tonic-gate 		}
3079*7c478bd9Sstevel@tonic-gate 	}
3080*7c478bd9Sstevel@tonic-gate 
3081*7c478bd9Sstevel@tonic-gate 	debug(5, "formatting done!");
3082*7c478bd9Sstevel@tonic-gate 	return (0);
3083*7c478bd9Sstevel@tonic-gate }
3084*7c478bd9Sstevel@tonic-gate 
3085*7c478bd9Sstevel@tonic-gate 
3086*7c478bd9Sstevel@tonic-gate /* ARGSUSED */
3087*7c478bd9Sstevel@tonic-gate int32_t
3088*7c478bd9Sstevel@tonic-gate scsi_floppy_media_status(int32_t fd)
3089*7c478bd9Sstevel@tonic-gate {
3090*7c478bd9Sstevel@tonic-gate 	struct mode_header_g1 modeh;
3091*7c478bd9Sstevel@tonic-gate 	struct uscsi_cmd ucmd;
3092*7c478bd9Sstevel@tonic-gate 	uchar_t cdb[10];
3093*7c478bd9Sstevel@tonic-gate 	int32_t ret_val;
3094*7c478bd9Sstevel@tonic-gate 	int32_t cur_status;
3095*7c478bd9Sstevel@tonic-gate 	char rq_data[RQ_LEN];
3096*7c478bd9Sstevel@tonic-gate 
3097*7c478bd9Sstevel@tonic-gate 	debug(5, "SCSI MEDIA STATUS CALLED \n");
3098*7c478bd9Sstevel@tonic-gate 
3099*7c478bd9Sstevel@tonic-gate 	(void) memset((void *) &modeh, 0, sizeof (modeh));
3100*7c478bd9Sstevel@tonic-gate 	(void) memset((void *) &ucmd, 0, sizeof (ucmd));
3101*7c478bd9Sstevel@tonic-gate 	(void) memset(cdb, 0, sizeof (cdb));
3102*7c478bd9Sstevel@tonic-gate 	/*
3103*7c478bd9Sstevel@tonic-gate 	 * issue 10 byte mode sense (0x5A)
3104*7c478bd9Sstevel@tonic-gate 	 */
3105*7c478bd9Sstevel@tonic-gate 	cdb[0] = SCMD_MODE_SENSE_G1;
3106*7c478bd9Sstevel@tonic-gate 	cdb[7] = sizeof (modeh) >> 8;
3107*7c478bd9Sstevel@tonic-gate 	cdb[8] = sizeof (modeh) & 0xff;
3108*7c478bd9Sstevel@tonic-gate 
3109*7c478bd9Sstevel@tonic-gate 	ucmd.uscsi_cdb = (caddr_t)cdb;
3110*7c478bd9Sstevel@tonic-gate 	ucmd.uscsi_cdblen = CDB_GROUP1;
3111*7c478bd9Sstevel@tonic-gate 	ucmd.uscsi_bufaddr = (caddr_t)&modeh;
3112*7c478bd9Sstevel@tonic-gate 	ucmd.uscsi_buflen = sizeof (modeh);
3113*7c478bd9Sstevel@tonic-gate 	ucmd.uscsi_timeout = 120;	/* If 0, HBA hangs forever */
3114*7c478bd9Sstevel@tonic-gate 	ucmd.uscsi_rqlen = RQ_LEN;
3115*7c478bd9Sstevel@tonic-gate 	ucmd.uscsi_rqbuf = rq_data;
3116*7c478bd9Sstevel@tonic-gate 	ret_val = do_uscsi_cmd(fd, &ucmd, USCSI_READ|USCSI_RQENABLE);
3117*7c478bd9Sstevel@tonic-gate 	if (ret_val || ucmd.uscsi_status) {
3118*7c478bd9Sstevel@tonic-gate 		/*
3119*7c478bd9Sstevel@tonic-gate 		 * UFI devices may not respond to the 0 mode page.
3120*7c478bd9Sstevel@tonic-gate 		 * retry with the error recovery page(0x01)
3121*7c478bd9Sstevel@tonic-gate 		 */
3122*7c478bd9Sstevel@tonic-gate 		if (ucmd.uscsi_status & STATUS_CHECK) {
3123*7c478bd9Sstevel@tonic-gate 			cdb[2] = 0x1;	/* page code */
3124*7c478bd9Sstevel@tonic-gate 			ret_val = do_uscsi_cmd(fd, &ucmd,
3125*7c478bd9Sstevel@tonic-gate 					USCSI_READ|USCSI_RQENABLE);
3126*7c478bd9Sstevel@tonic-gate 		}
3127*7c478bd9Sstevel@tonic-gate 		if (ret_val || ucmd.uscsi_status) {
3128*7c478bd9Sstevel@tonic-gate 			debug(1, "Modesense failed: %d - %d\n",
3129*7c478bd9Sstevel@tonic-gate 				ret_val, ucmd.uscsi_status);
3130*7c478bd9Sstevel@tonic-gate 			return (-1);
3131*7c478bd9Sstevel@tonic-gate 		}
3132*7c478bd9Sstevel@tonic-gate 	}
3133*7c478bd9Sstevel@tonic-gate 	debug(5, "Modesense succeeded: 0x%x\n", modeh.device_specific);
3134*7c478bd9Sstevel@tonic-gate 
3135*7c478bd9Sstevel@tonic-gate 	if (modeh.device_specific & 0x80) {
3136*7c478bd9Sstevel@tonic-gate 		cur_status = SM_WRITE_PROTECT_NOPASSWD;
3137*7c478bd9Sstevel@tonic-gate 	} else {
3138*7c478bd9Sstevel@tonic-gate 		cur_status = SM_WRITE_PROTECT_DISABLE;
3139*7c478bd9Sstevel@tonic-gate 	}
3140*7c478bd9Sstevel@tonic-gate 	return (cur_status);
3141*7c478bd9Sstevel@tonic-gate }
3142