4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
28 #include <stdio_ext.h>
35 #include <sys/types.h>
39 #include <sys/mkdev.h>
41 #include <sys/scsi/scsi.h>
42 #include <sys/scsi/generic/commands.h>
50 #include <sys/resource.h>
51 #include <netconfig.h>
52 #include <sys/smedia.h>
60 * The comments below would help in understanding what is being attempted
63 * The server can be started either by inetd or by the client directly.
64 * Normally the server is started by inetd when the client invokes the
65 * appropriate libsmedia library call(smedia_get_handle).
66 * However since the inetd runs only at init level 2 and above a mechanism
67 * is provided for the server to be started if an attempt is made to use
68 * the libsmedia calls in maintenence mode(init level 1).
69 * The main() routine determines how the server was invoked and takes
70 * the necessary action.
71 * When started by inetd it registers itself as an RPC program.
72 * The server also implements a mechanism by which it removes itself
73 * after a period of inactivity. The period of inactivity is specified
74 * by SVC_CLOSEDOWN which is set at 180 secs.
75 * The logic of detecting inactivity is as follows:
77 * Two variables svcstate and svccount are used to determine if the server
79 * The svcstate is set to 1(_SERVED) when ever the server does any operation
80 * on behalf of the client.
81 * The svccount indicates the number of active clients who have established
82 * a connection with the server. A connection is established when the
83 * libsmedia call smedia_get_handle() succeeds.
84 * The connection is broken when the client calls smedia_free_handle() OR
86 * A thread called closedown is started up when server is started.
87 * This thread runs periodically and monitors both svcstate and svccount.
88 * If svcstate is IDLE and svccount is 0 then server exits.
89 * The svcstate is set to IDLE by the closedown thread. It is set to _SERVED
90 * by server. It is possible for the state to be _SERVED and the svccount
91 * to be 0. The server could be kept busy by client calls of smedia_get_handle
92 * that do not succeed. This is the reason for using both svcstate and svccount
93 * to determine the true server state.
95 * The communication between client and server is thru door calls.
96 * Below are the door descriptors available to communicate to the server.
98 * main_door_descriptor:
99 * ---------------------
100 * This is a predefined descriptor used by client to establish a
101 * connection with the server. This descriptor is available to the client
102 * as /var/log/smedia_svc
103 * The client uses the main_door_descriptor to obtain a dedicated
104 * client_door_descriptor for itself. The smedia_get_handle call communicates
105 * to the server using the main_door_descriptor and obtains the
106 * client_door_descriptor which is stored in the handle structure.
107 * All other libsmedia calls use the client_door_descriptor to communicate
110 * client_door_descriptor:
111 * -----------------------
112 * This is the door descriptor that is used by the clients to
113 * request server to perform the necessary tasks. This door descriptor is
114 * available only to the client for whom it was created.
116 * death_door_descriptor:
117 * ----------------------
118 * The sole function of this descriptor HAD been to inform the server of
119 * the untimely death of the client. This descriptor is no longer used, though
120 * it is still created, as libsmedia expects to use it. This descriptor's
121 * service procedure had used pthread cancellation(5) to terminate the thread of
122 * the associated client_door_descriptor. The client_door_descriptor now
123 * handles the scenarios where a door_call/client are aborted/terminated.
127 * This is the routine associated with the main_door_descriptor.
128 * This is the routine that handles the smedia_get_handle() call
129 * of the client. If the door call to this routine succeeds it creates a
130 * client_door_descriptor that is used by the client in subsequent library
132 * This client_door_descriptor is passed to the client thru the door_return
133 * call. This client_door_descriptor cannot be used by any other process other
134 * than the client process that obtained it.
135 * In addition to the client_door_descriptor a death_door_descriptor is also
136 * created by the main server and passed on to the client. The client does not
137 * use the death_door_descriptor.
141 * This is the routine that handles the libsmedia calls of the
142 * client. In the current implementation the server takes control of the
143 * number of threads that handle the door calls. This is done by creating the
144 * door descriptor as DOOR_PRIVATE.
145 * The server runs only one thread per handle. This makes the implementation
146 * simple as we do not have to use mutex to make the code MT safe.
147 * The server thread has a data structure door_data_t associated with it.
151 * This is the data structure that is created by the main_servproc when it
152 * creates the client_door_descriptor. The door mechanism has a way to associate
153 * a cookie with the door descriptor. door_data_t is the cookie for the
154 * client_door_descriptor. This cookie is passed to the server function that
155 * handles the client_door_descriptor calls. In our case it is the
156 * client_servproc routine.
157 * The key elements of the door_data_t are the following:
159 * dd_fd file descriptor for the device.
160 * dd_buf The shared memory buffer between client-server.
161 * dd_thread The thread that handles the door_calls.
165 * The main purpose of trapping the signals is to exit gracefully
166 * from the server after recording the appropriate message in the syslog.
167 * This will help the administrator to determine the cause of failure of the
168 * server by examining the log file.
172 * This routine frees up all the resources allocated for the client.
173 * Resources include the file descriptor, shared memory, threads.
177 * In order to reduce the overheads of moving large amounts of data
178 * during raw read/write operations, the server uses the mmapped data of
179 * client. The smedia_raw_read, smedia_raw_write library calls mmap the
180 * memory and pass on the file descriptor that maps the memory to the server.
181 * The server subsequently uses this mmapped memory during the IO.
182 * If the mmapped memory changes in size, the server is informed and it
183 * remaps the memory to the changed size.
186 #define DEFAULT_VERBOSE 1
187 #define DEFAULT_DEBUG 1
189 #define DEFAULT_VERBOSE 0
190 #define DEFAULT_DEBUG 0
193 #define N_BADSIGS (sizeof (badsigs)/sizeof (badsigs[0]))
196 #define SVC_CLOSEDOWN 180
199 * We will NOT be permitting the following USCI cmd options.
203 * Tagged commands to device
204 * Explicitly setting SYNC/ASYNC mode of operations.
205 * POLLED MODE of operation.
206 * Explicitly setting NO DISCONNECT features.
207 * use of RESERVED flags.
209 #define FORBIDDEN_FLAGS (USCSI_RESET | USCSI_RESET_ALL | USCSI_RENEGOT \
210 | USCSI_ASYNC | USCSI_SYNC | USCSI_NOINTR | \
211 USCSI_NOTAG | USCSI_NOPARITY | USCSI_NODISCON \
214 /* States a server can be in wrt request */
219 static char *prog_name
;
220 static int svcstate
= _IDLE
; /* Set when a request is serviced */
221 static int svccount
= 0; /* Number of requests being serviced */
222 static int svcstart_level
= 0; /* init level when server was started */
223 static mutex_t svcstate_lock
; /* lock for svcstate, svccount */
225 extern void smserverprog_1(struct svc_req
*, SVCXPRT
*);
230 #define SIGACT_FAILED "Failed to install signal handler for %s: %s"
231 #define BADSIG_MSG "Thread %d Caught signal %d addr=%p trapno=%d pc=%p"
233 static int badsigs
[] = {SIGSEGV
, SIGBUS
, SIGFPE
, SIGILL
};
235 /* global variables */
236 int verbose
= DEFAULT_VERBOSE
;
237 int debug_level
= DEFAULT_DEBUG
;
238 char *smediad_devdir
= DEFAULT_SMEDIAD_DEVDIR
;
240 thread_key_t door_key
;
242 server_data_t server_data
;
244 static int server_door
, server_fd
;
246 static int32_t do_uscsi_cmd(int32_t file
, struct uscsi_cmd
*uscsi_cmd
,
248 static void client_servproc(void *cookie
, char *argp
, size_t arg_size
,
249 door_desc_t
*dp
, uint_t ndesc
);
250 static void cleanup(door_data_t
*);
251 static void *init_server(void *);
252 static int32_t scsi_reassign_block(int32_t fd
, diskaddr_t
);
253 static int32_t get_mode_page(int32_t fd
, uchar_t pc
, uchar_t page_code
,
254 uchar_t
*md_data
, uchar_t data_len
);
255 static int32_t get_device_type(char *v_name
);
256 static int32_t get_device_type_scsi(int32_t fd
, struct scsi_inquiry
*inq
);
258 static int32_t scsi_format(int32_t fd
, uint_t flavor
, uint_t mode
);
259 static int32_t scsi_media_status(int32_t fd
);
260 static int32_t scsi_write_protect(int32_t fd
, smwp_state_t
*wp
);
261 static int32_t scsi_floppy_media_status(int32_t fd
);
262 static int32_t scsi_floppy_write_protect(int32_t fd
, smwp_state_t
*wp
);
263 static int32_t scsi_floppy_format(int32_t, uint_t
, uint_t
);
264 static int32_t get_floppy_geom(int32_t fd
, uint32_t capacity
,
265 struct dk_geom
*dkgeom
);
266 static int32_t get_media_capacity(int32_t fd
, uint32_t *capacity
,
267 uint32_t *blocksize
);
269 static int32_t scsi_ls120_format(uint_t fd
, uint_t flavor
, uint32_t capacity
,
272 static void *sm_server_thread(void *arg
);
273 static void sm_door_server_create(door_info_t
*dip
);
274 static void term_handler(int sig
, siginfo_t
*siginfo
, void *sigctx
);
275 static void hup_handler(int sig
, siginfo_t
*siginfo
, void *sigctx
);
276 static void sig_handler(int sig
, siginfo_t
*siginfo
, void *sigctx
);
277 static void badsig_handler(int sig
, siginfo_t
*siginfo
, void *sigctx
);
278 static void server_badsig_handler(int sig
, siginfo_t
*siginfo
, void *sigctx
);
279 static char *xlate_state(int32_t);
280 static uint32_t get_sector_size(int fd
);
281 static int32_t raw_read(door_data_t
*door_dp
, smedia_services_t
*req
);
282 static int32_t raw_write(door_data_t
*door_dp
, smedia_services_t
*req
);
283 static int32_t reassign_block(door_data_t
*door_dp
, smedia_services_t
*req
);
284 static int32_t set_protection_status(door_data_t
*door_dp
,
285 smedia_services_t
*req
);
286 static int32_t set_shfd(door_data_t
*door_dp
, int32_t fd
,
287 smedia_services_t
*req
);
289 static void door_ret_err(smedia_reterror_t
*reterror
, int32_t err
);
290 static void my_door_return(char *data_ptr
, size_t data_size
,
291 door_desc_t
*desc_ptr
, uint_t num_desc
);
292 static int32_t invalid_uscsi_operation(door_data_t
*, struct uscsi_cmd
*);
294 #define W_E_MASK 0x80
296 static smserver_info server_info
;
299 invalid_uscsi_operation(door_data_t
*door_dp
, struct uscsi_cmd
*ucmd
)
302 if (door_dp
->dd_dkinfo
.dki_ctype
!= DKC_CDROM
) {
304 "Invalid device type(0x%x) found for uscsi cmd.\n",
305 door_dp
->dd_dkinfo
.dki_ctype
);
309 if (ucmd
->uscsi_flags
& FORBIDDEN_FLAGS
) {
311 "Invalid flags(0x%x) set in uscsi cmd. cdb[0]=0x%x\n",
312 ucmd
->uscsi_flags
, ucmd
->uscsi_cdb
[0]);
316 if (ucmd
->uscsi_cdb
[0] == SCMD_COPY
||
317 ucmd
->uscsi_cdb
[0] == SCMD_COPY_VERIFY
||
318 ucmd
->uscsi_cdb
[0] == SCMD_COMPARE
||
319 ucmd
->uscsi_cdb
[0] == SCMD_WRITE_BUFFER
) {
321 "Invalid command(0x%x) found in cdb.\n",
330 get_sector_size(int fd
)
332 uint32_t sector_size
;
333 struct uscsi_cmd ucmd
;
337 char rq_data
[RQ_LEN
];
339 cdb
.scc_cmd
= SCMD_READ_CAPACITY
;
340 ucmd
.uscsi_cdb
= (caddr_t
)&cdb
;
341 ucmd
.uscsi_cdblen
= CDB_GROUP1
;
342 ucmd
.uscsi_bufaddr
= (caddr_t
)&rc_data
;
343 ucmd
.uscsi_buflen
= sizeof (rc_data
);
344 ucmd
.uscsi_timeout
= 120; /* If 0, HBA hangs forever */
345 ucmd
.uscsi_rqlen
= RQ_LEN
;
346 ucmd
.uscsi_rqbuf
= rq_data
;
348 ret_val
= do_uscsi_cmd(fd
,
349 &ucmd
, USCSI_READ
|USCSI_RQENABLE
);
350 if (ret_val
|| ucmd
.uscsi_status
) {
351 debug(5, "Read capacity : %d - %d errno = %d\n",
352 ret_val
, ucmd
.uscsi_status
, errno
);
355 sector_size
= ntohl(rc_data
[1]);
357 debug(5, "sector size = 0x%x(%d)\n",
358 sector_size
, sector_size
);
359 return (sector_size
);
363 xlate_state(int32_t state
)
367 case SM_WRITE_PROTECT_DISABLE
:
368 return ("PROTECTION_DISABLED");
369 case SM_WRITE_PROTECT_PASSWD
:
370 return ("WRITE_PROTECT_PASSWD");
371 case SM_WRITE_PROTECT_NOPASSWD
:
372 return ("WRITE_PROTECT_NOPASSWD");
373 case SM_READ_WRITE_PROTECT
:
374 return ("READ_WRITE_PROTECT");
375 case SM_TEMP_UNLOCK_MODE
:
376 return ("PROTECTION DISABLED");
378 return ("UNKNOWN_STATE");
383 xlate_cnum(smedia_callnumber_t cnum
)
387 case SMEDIA_CNUM_OPEN_FD
:
388 return ("SMEDIA_CNUM_OPEN_FD");
389 case SMEDIA_CNUM_GET_DEVICE_INFO
:
390 return ("SMEDIA_CNUM_GET_DEVICE_INFO");
391 case SMEDIA_CNUM_GET_MEDIUM_PROPERTY
:
392 return ("SMEDIA_CNUM_GET_MEDIUM_PROPERTY");
393 case SMEDIA_CNUM_GET_PROTECTION_STATUS
:
394 return ("SMEDIA_CNUM_GET_PROTECTION_STATUS");
395 case SMEDIA_CNUM_SET_PROTECTION_STATUS
:
396 return ("SMEDIA_CNUM_SET_PROTECTION_STATUS");
397 case SMEDIA_CNUM_RAW_READ
:
398 return ("SMEDIA_CNUM_RAW_READ");
399 case SMEDIA_CNUM_RAW_WRITE
:
400 return (" SMEDIA_CNUM_RAW_WRITE");
401 case SMEDIA_CNUM_FORMAT
:
402 return ("SMEDIA_CNUM_FORMAT");
403 case SMEDIA_CNUM_CHECK_FORMAT_STATUS
:
404 return ("SMEDIA_CNUM_CHECK_FORMAT_STATUS");
405 case SMEDIA_CNUM_EJECT
:
406 return ("SMEDIA_CNUM_EJECT");
407 case SMEDIA_CNUM_REASSIGN_BLOCK
:
408 return ("SMEDIA_CNUM_REASSIGN_BLOCK");
409 case SMEDIA_CNUM_SET_SHFD
:
410 return ("SMEDIA_CNUM_SET_SHFD");
411 case SMEDIA_CNUM_PING
:
412 return ("SMEDIA_CNUM_PING");
413 case SMEDIA_CNUM_USCSI_CMD
:
414 return ("SMEDIA_CNUM_USCSI_CMD");
416 return ("UNKNOWN_CNUM");
422 smserverproc_get_serverinfo_1(void *argp
, CLIENT
*clnt
)
424 (void) mutex_lock(&svcstate_lock
);
426 (void) mutex_unlock(&svcstate_lock
);
427 server_info
.vernum
= SMSERVERVERS
;
428 server_info
.status
= 0;
429 (void) mutex_lock(&server_data
.sd_init_lock
);
430 if (server_data
.sd_init_state
== INIT_NOT_DONE
) {
431 server_data
.sd_init_state
= INIT_IN_PROGRESS
;
432 debug(5, "Initialising server\n");
433 (void) init_server(NULL
);
435 if (server_data
.sd_init_state
!= INIT_DONE
) {
436 debug(1, "init_server did not do the job. "
437 "init_state=%d\n", server_data
.sd_init_state
);
438 server_data
.sd_init_state
= INIT_NOT_DONE
;
439 (void) mutex_unlock(&server_data
.sd_init_lock
);
440 server_info
.status
= -1;
441 return (&server_info
);
443 (void) mutex_unlock(&server_data
.sd_init_lock
);
445 debug(5, "smserverproc thread %d running....\n", pthread_self());
446 return (&server_info
);
451 server_badsig_handler(int sig
, siginfo_t
*siginfo
, void *sigctx
)
454 fatal(gettext(BADSIG_MSG
), pthread_self(), sig
, siginfo
->si_addr
,
460 do_uscsi_cmd(int32_t file
, struct uscsi_cmd
*uscsi_cmd
, int32_t flag
)
465 * Set function flags for driver.
467 uscsi_cmd
->uscsi_flags
= USCSI_ISOLATE
;
470 uscsi_cmd
->uscsi_flags
|= USCSI_DIAGNOSE
;
472 uscsi_cmd
->uscsi_flags
|= USCSI_SILENT
;
475 uscsi_cmd
->uscsi_flags
|= flag
;
478 ret_val
= ioctl(file
, USCSICMD
, uscsi_cmd
);
479 if (ret_val
== 0 && uscsi_cmd
->uscsi_status
== 0) {
488 get_device_type(char *v_name
)
492 for (i
= 0; i
< 8; i
++) {
493 v_name
[i
] = toupper(v_name
[i
]);
495 if (strstr(v_name
, "IOMEGA")) {
496 return (SCSI_IOMEGA
);
498 if (strstr(v_name
, "FD") ||
499 strstr(v_name
, "LS-120")) {
500 return (SCSI_FLOPPY
);
502 return (SCSI_GENERIC
);
507 get_device_type_scsi(int32_t fd
, struct scsi_inquiry
*inq
)
510 struct uscsi_cmd ucmd
;
513 char rq_data
[RQ_LEN
];
515 (void) memset(inq
, 0, sizeof (struct scsi_inquiry
));
516 (void) memset(&ucmd
, 0, sizeof (ucmd
));
517 (void) memset(&cdb
, 0, sizeof (union scsi_cdb
));
518 cdb
.scc_cmd
= SCMD_INQUIRY
;
519 FORMG0COUNT(&cdb
, sizeof (struct scsi_inquiry
));
520 ucmd
.uscsi_cdb
= (caddr_t
)&cdb
;
521 ucmd
.uscsi_cdblen
= CDB_GROUP0
;
522 ucmd
.uscsi_bufaddr
= (caddr_t
)inq
;
523 ucmd
.uscsi_buflen
= sizeof (struct scsi_inquiry
);
524 ucmd
.uscsi_timeout
= 120; /* If 0, HBA hangs forever */
525 ucmd
.uscsi_rqlen
= RQ_LEN
;
526 ucmd
.uscsi_rqbuf
= rq_data
;
527 ret_val
= do_uscsi_cmd(fd
, &ucmd
, USCSI_READ
|USCSI_RQENABLE
);
528 if (ret_val
|| ucmd
.uscsi_status
) {
529 debug(5, "INQUIRY failed: rv = %d uscsi_status = "
530 "%d errno = %d\n", ret_val
, ucmd
.uscsi_status
, errno
);
534 dev_type
= get_device_type(inq
->inq_vid
);
536 debug(5, "dev_type %d\n", dev_type
);
542 get_media_capacity(int32_t fd
, uint32_t *capacity
, uint32_t *blocksize
)
544 struct uscsi_cmd ucmd
;
548 char rq_data
[RQ_LEN
];
550 debug(5, "get_media_capacity:\n");
552 (void) memset(&data
, 0, sizeof (data
));
553 (void) memset(&ucmd
, 0, sizeof (ucmd
));
554 (void) memset(&cdb
, 0, sizeof (cdb
));
556 /* retrieve size discriptor of inserted media */
557 cdb
[0] = SCMD_READ_FORMAT_CAP
;
558 cdb
[8] = 0x14; /* data size */
560 /* Fill in the USCSI fields */
561 ucmd
.uscsi_cdb
= (caddr_t
)&cdb
;
562 ucmd
.uscsi_cdblen
= CDB_GROUP5
;
563 ucmd
.uscsi_bufaddr
= (caddr_t
)data
;
564 ucmd
.uscsi_buflen
= sizeof (data
);
565 ucmd
.uscsi_timeout
= 120;
566 ucmd
.uscsi_rqlen
= RQ_LEN
;
567 ucmd
.uscsi_rqbuf
= rq_data
;
568 ret_val
= do_uscsi_cmd(fd
, &ucmd
, USCSI_READ
|USCSI_RQENABLE
);
570 if (ret_val
|| ucmd
.uscsi_status
) {
571 debug(5, "Retrieving media info failed: %d - %d\n", ret_val
,
574 if ((rq_data
[2] == KEY_DATA_PROTECT
) && (rq_data
[12] == 0x30) &&
575 (rq_data
[13] == 0)) {
576 (void) debug(1, "Invalid command for media\n");
582 /* No media, bail out */
583 if (data
[8] == 0x3) {
584 (void) debug(5, "no media in drive\n");
589 * Generate capacity and blocksize information
592 *capacity
= (uint32_t)((data
[4] << 24) + (data
[5] << 16) +
593 (data
[6] << 8) + data
[7]);
595 debug(1, "capacity is %x %x %x %x = %x", data
[4], data
[5], data
[6],
598 *blocksize
= (uint32_t)((data
[9] << 16) + (data
[10] << 8) + data
[11]);
604 scsi_zip_format(int32_t fd
, uint_t flavor
, uint_t mode
)
606 struct uscsi_cmd ucmd
;
607 struct scsi_inquiry inq
;
612 char rq_data
[RQ_LEN
];
616 if ((mode
!= SM_FORMAT_IMMEDIATE
) &&
617 (mode
!= SM_FORMAT_BLOCKED
)) {
622 * Do an inquiry and try to figure out if it an
623 * IOMEGA JAZ 2GB device.
626 (void) memset(&inq
, 0, sizeof (inq
));
627 (void) memset(&ucmd
, 0, sizeof (ucmd
));
628 (void) memset(&cdb
, 0, sizeof (cdb
));
629 (void) memset(&rq_data
, 0, sizeof (rq_data
));
630 cdb
[0] = SCMD_INQUIRY
;
631 cdb
[4] = sizeof (inq
);
632 ucmd
.uscsi_cdb
= (caddr_t
)&cdb
;
633 ucmd
.uscsi_cdblen
= CDB_GROUP0
;
634 ucmd
.uscsi_bufaddr
= (caddr_t
)&inq
;
635 ucmd
.uscsi_buflen
= sizeof (inq
);
636 ucmd
.uscsi_timeout
= 120; /* If 0, HBA hangs forever */
637 ucmd
.uscsi_rqlen
= RQ_LEN
;
638 ucmd
.uscsi_rqbuf
= rq_data
;
639 ret_val
= do_uscsi_cmd(fd
, &ucmd
, USCSI_READ
|USCSI_RQENABLE
);
640 if (ret_val
|| ucmd
.uscsi_status
) {
641 debug(5, "inquiry failed: %d - %d errno = %d\n",
642 ret_val
, ucmd
.uscsi_status
, errno
);
643 return (ucmd
.uscsi_status
);
646 (void) memset(&rc_data
, 0, sizeof (rc_data
));
647 (void) memset(&ucmd
, 0, sizeof (ucmd
));
648 (void) memset(&cdb
, 0, sizeof (cdb
));
649 cdb
[0] = SCMD_READ_CAPACITY
;
650 ucmd
.uscsi_cdb
= (caddr_t
)&cdb
;
651 ucmd
.uscsi_cdblen
= CDB_GROUP1
;
652 ucmd
.uscsi_bufaddr
= (caddr_t
)&rc_data
;
653 ucmd
.uscsi_buflen
= sizeof (rc_data
);
654 ucmd
.uscsi_timeout
= 120; /* If 0, HBA hangs forever */
656 ret_val
= do_uscsi_cmd(fd
, &ucmd
, USCSI_READ
);
657 if (ret_val
|| ucmd
.uscsi_status
) {
658 debug(5, "Read capacity : %d - %d errno = %d\n",
659 ret_val
, ucmd
.uscsi_status
, errno
);
660 return (ucmd
.uscsi_status
);
663 capacity
= ntohl(rc_data
[0]);
665 (void) memset(&data
, 0, sizeof (data
));
666 (void) memset(&ucmd
, 0, sizeof (ucmd
));
667 (void) memset(&cdb
, 0, sizeof (cdb
));
668 cdb
[0] = SCMD_FORMAT
;
670 * Defect list sent by initiator is a complete list of defects.
672 cdb
[1] = (FMTDATA
| CMPLIST
);
674 * Target should examine the setting of the DPRY, DCRT, STPF, IP
680 case SM_FORMAT_QUICK
:
682 * Target should not perform any vendor specific
683 * medium certification process or format verification
685 data
[1] = (FOV
| DCRT
);
687 * Defect list sent is an addition to the existing
692 case SM_FORMAT_FORCE
:
693 if (strstr(inq
.inq_pid
, "jaz")) {
695 "LONG Format of JAZ media not supported\n");
700 * Formatting a write-protected or read/write
701 * protected cartridge is allowed.
702 * This is a vendor specific Format Option.
706 case SM_FORMAT_LONG
:
707 if (strstr(inq
.inq_pid
, "jaz")) {
709 "LONG Format of JAZ media not supported\n");
714 * Defect list sent is an addition to the existing
720 debug(1, "Format option %d not supported!!\n",
726 if (mode
== SM_FORMAT_IMMEDIATE
) {
728 debug(5, "immediate_flag set\n");
731 ucmd
.uscsi_cdb
= (caddr_t
)&cdb
;
732 debug(5, "cdb: %x ", cdb
[0]);
733 debug(5, "%x %x ", cdb
[1], cdb
[2]);
734 debug(5, "%x %x %x\n", cdb
[3], cdb
[4], cdb
[5]);
735 debug(5, "data: %x %x %x %x\n", data
[0], data
[1], data
[2], data
[3]);
737 ucmd
.uscsi_cdblen
= CDB_GROUP0
;
738 ucmd
.uscsi_bufaddr
= (caddr_t
)data
;
739 ucmd
.uscsi_buflen
= sizeof (data
);
740 ucmd
.uscsi_timeout
= FORMAT_TIMEOUT(capacity
);
741 ucmd
.uscsi_rqlen
= RQ_LEN
;
742 ucmd
.uscsi_rqbuf
= rq_data
;
743 ret_val
= do_uscsi_cmd(fd
, &ucmd
, USCSI_WRITE
|USCSI_RQENABLE
);
744 if (ret_val
|| ucmd
.uscsi_status
) {
745 debug(5, "Format failed : %d - uscsi_status = %d errno = %d\n",
747 ucmd
.uscsi_status
, errno
);
748 if ((rq_data
[2] == KEY_DATA_PROTECT
) ||
749 (rq_data
[2] == KEY_ILLEGAL_REQUEST
))
751 if ((rq_data
[2] == KEY_MEDIUM_ERROR
) ||
752 (rq_data
[2] == KEY_HARDWARE_ERROR
))
761 scsi_ls120_format(uint_t fd
, uint_t flavor
, uint32_t capacity
,
764 struct uscsi_cmd ucmd
;
768 char rq_data
[RQ_LEN
];
770 debug(5, "scsi_ls120_format:\n");
772 (void) memset(&ucmd
, 0, sizeof (ucmd
));
773 (void) memset(&cdb
, 0, sizeof (cdb
));
774 (void) memset(&rq_data
, 0, sizeof (rq_data
));
776 cdb
[0] = SCMD_FORMAT
;
777 cdb
[1] = (FMTDATA
| 0x7);
778 cdb
[8] = 0x0C; /* parameter list length */
784 data
[4] = (capacity
>> 24) & 0xff;
785 data
[5] = (capacity
>> 16) & 0xff;
786 data
[6] = (capacity
>> 8) & 0xff;
787 data
[7] = capacity
& 0xff;
790 data
[9] = (blocksize
>> 16) & 0xff;
791 data
[10] = (blocksize
>> 8) & 0xff;
792 data
[11] = blocksize
& 0xff;
794 debug(5, "cdb: %x %x %x ... %x", cdb
[0], cdb
[1], cdb
[2], cdb
[8]);
795 debug(5, "data: %x %x %x %x\n", data
[0], data
[1], data
[2], data
[3]);
796 debug(5, " : %x %x %x %x\n", data
[4], data
[5], data
[6], data
[7]);
797 debug(5, " : %x %x %x %x\n", data
[8], data
[9], data
[10], data
[11]);
800 case SM_FORMAT_QUICK
:
801 debug(1, "Format not supported\n");
804 case SM_FORMAT_FORCE
:
806 case SM_FORMAT_LONG
:
809 debug(1, "Format option not specified!!\n");
814 ucmd
.uscsi_cdb
= (caddr_t
)&cdb
;
817 ucmd
.uscsi_cdblen
= CDB_GROUP5
;
818 ucmd
.uscsi_bufaddr
= (caddr_t
)data
;
819 ucmd
.uscsi_buflen
= sizeof (data
);
820 ucmd
.uscsi_timeout
= 0x12c0;
821 ucmd
.uscsi_rqlen
= RQ_LEN
;
822 ucmd
.uscsi_rqbuf
= rq_data
;
823 (void) fflush(stdout
);
825 ret_val
= do_uscsi_cmd(fd
, &ucmd
, USCSI_WRITE
|USCSI_RQENABLE
);
826 if (ret_val
|| ucmd
.uscsi_status
) {
827 debug(1, "Format failed failed: %d - %d\n", ret_val
,
830 if ((rq_data
[2] == KEY_DATA_PROTECT
) &&
831 (rq_data
[12] == 0x30) && (rq_data
[13] == 0)) {
833 debug(1, "Invalid command for media\n");
837 if ((rq_data
[2] == KEY_NOT_READY
) && (rq_data
[12] == 0x30)) {
838 debug(1, "Incompatible media.\n");
849 scsi_format(int32_t fd
, uint_t flavor
, uint_t mode
)
851 struct uscsi_cmd ucmd
;
852 struct scsi_inquiry inq
;
856 char rq_data
[RQ_LEN
];
862 if ((mode
!= SM_FORMAT_IMMEDIATE
) &&
863 (mode
!= SM_FORMAT_BLOCKED
)) {
869 * Do an inquiry and try to figure out if it an
870 * IOMEGA JAZ 2GB device.
873 (void) memset(&inq
, 0, sizeof (inq
));
874 (void) memset(&ucmd
, 0, sizeof (ucmd
));
875 (void) memset(&cdb
, 0, sizeof (cdb
));
876 (void) memset(&rq_data
, 0, sizeof (rq_data
));
877 cdb
[0] = SCMD_INQUIRY
;
878 cdb
[4] = sizeof (inq
);
879 ucmd
.uscsi_cdb
= (caddr_t
)&cdb
;
880 ucmd
.uscsi_cdblen
= CDB_GROUP0
;
881 ucmd
.uscsi_bufaddr
= (caddr_t
)&inq
;
882 ucmd
.uscsi_buflen
= sizeof (inq
);
883 ucmd
.uscsi_timeout
= 120; /* If 0, HBA hangs forever */
884 ucmd
.uscsi_rqlen
= RQ_LEN
;
885 ucmd
.uscsi_rqbuf
= rq_data
;
886 ret_val
= do_uscsi_cmd(fd
, &ucmd
, USCSI_READ
|USCSI_RQENABLE
);
887 if (ret_val
|| ucmd
.uscsi_status
) {
888 debug(5, "inquiry failed: %d - %d errno = %d\n",
889 ret_val
, ucmd
.uscsi_status
, errno
);
890 return (ucmd
.uscsi_status
);
893 (void) memset(&rc_data
, 0, sizeof (rc_data
));
894 (void) memset(&ucmd
, 0, sizeof (ucmd
));
895 (void) memset(&cdb
, 0, sizeof (cdb
));
896 cdb
[0] = SCMD_READ_CAPACITY
;
897 ucmd
.uscsi_cdb
= (caddr_t
)&cdb
;
898 ucmd
.uscsi_cdblen
= CDB_GROUP1
;
899 ucmd
.uscsi_bufaddr
= (caddr_t
)&rc_data
;
900 ucmd
.uscsi_buflen
= sizeof (rc_data
);
901 ucmd
.uscsi_timeout
= 120; /* If 0, HBA hangs forever */
903 ret_val
= do_uscsi_cmd(fd
, &ucmd
, USCSI_READ
);
904 if (ret_val
|| ucmd
.uscsi_status
) {
905 debug(5, "Read capacity : %d - %d errno = %d\n",
906 ret_val
, ucmd
.uscsi_status
, errno
);
907 return (ucmd
.uscsi_status
);
910 capacity
= ntohl(rc_data
[0]);
912 (void) memset(&data
, 0, sizeof (data
));
913 (void) memset(&ucmd
, 0, sizeof (ucmd
));
914 (void) memset(&cdb
, 0, sizeof (cdb
));
915 cdb
[0] = SCMD_FORMAT
;
917 * Defect list sent is an addition to the existing
922 * Target should examine the setting of the DPRY, DCRT, STPF, IP
927 if (mode
== SM_FORMAT_IMMEDIATE
) {
929 "SM_FORMAT_IMMEDIATE specified ignored. Performing a long format!\n");
933 case SM_FORMAT_LONG
:
934 if (strstr(inq
.inq_pid
, "jaz")) {
936 "LONG Format of JAZ media not supported\n");
941 * Defect list sent is an addition to the existing
947 debug(1, "Format option %d not supported!!\n",
954 ucmd
.uscsi_cdb
= (caddr_t
)&cdb
;
955 ucmd
.uscsi_cdblen
= CDB_GROUP0
;
956 ucmd
.uscsi_bufaddr
= (caddr_t
)data
;
957 ucmd
.uscsi_buflen
= sizeof (data
);
958 ucmd
.uscsi_timeout
= FORMAT_TIMEOUT(capacity
);
959 ucmd
.uscsi_rqlen
= RQ_LEN
;
960 ucmd
.uscsi_rqbuf
= rq_data
;
961 ret_val
= do_uscsi_cmd(fd
, &ucmd
, USCSI_WRITE
|USCSI_RQENABLE
);
962 if (ret_val
|| ucmd
.uscsi_status
) {
963 debug(5, "Format failed failed: %d - %d errno = %d\n",
964 ret_val
, ucmd
.uscsi_status
, errno
);
965 return (ucmd
.uscsi_status
);
972 scsi_media_status(int32_t fd
)
974 struct mode_header modeh
;
975 struct uscsi_cmd ucmd
;
979 char rq_data
[RQ_LEN
];
981 debug(10, "SCSI MEDIA STATUS CALLED \n");
983 (void) memset(&modeh
, 0, sizeof (modeh
));
984 (void) memset(&ucmd
, 0, sizeof (ucmd
));
985 (void) memset(&cdb
, 0, sizeof (union scsi_cdb
));
986 cdb
.scc_cmd
= SCMD_MODE_SENSE
;
987 cdb
.cdb_opaque
[2] = MODEPAGE_ALLPAGES
;
988 FORMG0COUNT(&cdb
, sizeof (modeh
));
990 ucmd
.uscsi_cdb
= (caddr_t
)&cdb
;
991 ucmd
.uscsi_cdblen
= CDB_GROUP0
;
992 ucmd
.uscsi_bufaddr
= (caddr_t
)&modeh
;
993 ucmd
.uscsi_buflen
= sizeof (modeh
);
994 ucmd
.uscsi_timeout
= 120; /* If 0, HBA hangs forever */
995 ucmd
.uscsi_rqlen
= RQ_LEN
;
996 ucmd
.uscsi_rqbuf
= rq_data
;
997 ret_val
= do_uscsi_cmd(fd
, &ucmd
, USCSI_READ
|USCSI_RQENABLE
);
998 if (ret_val
|| ucmd
.uscsi_status
) {
999 debug(5, "Modesense for 0x3f pages failed: %d-%d errno=%d\n",
1000 ret_val
, ucmd
.uscsi_status
, errno
);
1001 cdb
.cdb_opaque
[2] = 0;
1002 ucmd
.uscsi_rqlen
= RQ_LEN
;
1003 FORMG0COUNT(&cdb
, sizeof (modeh
));
1004 ret_val
= do_uscsi_cmd(fd
, &ucmd
, USCSI_READ
|USCSI_RQENABLE
);
1005 if (ret_val
|| ucmd
.uscsi_status
) {
1006 debug(5, "Modesense failed: %d - %d errno = %d\n",
1007 ret_val
, ucmd
.uscsi_status
, errno
);
1012 if (modeh
.device_specific
& W_E_MASK
) {
1013 cur_status
= SM_WRITE_PROTECT_NOPASSWD
;
1015 cur_status
= SM_WRITE_PROTECT_DISABLE
;
1017 debug(5, "cur status %d\n", cur_status
);
1019 return (cur_status
);
1023 scsi_zip_media_status(int32_t fd
)
1025 struct uscsi_cmd ucmd
;
1030 char rq_data
[RQ_LEN
];
1032 debug(10, "Getting media status\n");
1034 (void) memset(&ucmd
, 0, sizeof (ucmd
));
1035 (void) memset(&cdb
, 0, sizeof (cdb
));
1037 cdb
[0] = IOMEGA_NONSENSE_CMD
;
1038 cdb
[2] = CARTRIDGE_STATUS_PAGE
;
1040 ucmd
.uscsi_cdb
= (caddr_t
)&cdb
;
1041 ucmd
.uscsi_cdblen
= CDB_GROUP0
;
1042 ucmd
.uscsi_bufaddr
= (caddr_t
)data
;
1043 ucmd
.uscsi_buflen
= 64;
1044 ucmd
.uscsi_timeout
= 120; /* If 0, HBA hangs forever */
1045 ucmd
.uscsi_rqlen
= RQ_LEN
;
1046 ucmd
.uscsi_rqbuf
= rq_data
;
1047 status
= do_uscsi_cmd(fd
, &ucmd
, USCSI_READ
|USCSI_RQENABLE
);
1048 if (status
|| ucmd
.uscsi_status
) {
1049 debug(5, "Cartridge protect operation failed: "
1050 "rv = %d uscsi_status = %d errno = %d\n",
1051 status
, ucmd
.uscsi_status
, errno
);
1055 if (data
[DISK_STATUS_OFFSET
+ NON_SENSE_HDR_LEN
] == 4) {
1056 debug(1, "Disk not present. \n");
1059 mode
= data
[PROTECT_MODE_OFFSET
+ NON_SENSE_HDR_LEN
] & 0xF;
1061 debug(5, "MODE 0x%x / %d.\n", mode
, mode
);
1065 status
= SM_WRITE_PROTECT_DISABLE
;
1067 case WRITE_PROTECT_MODE
:
1068 status
= SM_WRITE_PROTECT_NOPASSWD
;
1070 case PASSWD_WRITE_PROTECT_MODE
:
1071 status
= SM_WRITE_PROTECT_PASSWD
;
1073 case READ_WRITE_PROTECT_MODE
:
1074 status
= SM_READ_WRITE_PROTECT
;
1077 if (mode
& TEMP_UNLOCK_MODE
)
1078 status
= SM_TEMP_UNLOCK_MODE
;
1080 status
= SM_STATUS_UNKNOWN
;
1084 debug(5, "status %d \n", status
);
1089 scsi_reassign_block(int32_t fd
, diskaddr_t block
)
1092 struct uscsi_cmd ucmd
;
1095 char rq_data
[RQ_LEN
];
1097 debug(5, "SCSI REASSIGN CALLED block = %lld\n", block
);
1099 (void) memset(&data
, 0, sizeof (data
));
1100 (void) memset(&ucmd
, 0, sizeof (ucmd
));
1101 (void) memset(&cdb
, 0, sizeof (cdb
));
1102 cdb
[0] = SCMD_REASSIGN_BLOCK
;
1104 data
[4] = ((block
& 0xFF000000) >> 24);
1105 data
[5] = ((block
& 0xFF0000) >> 16);
1106 data
[6] = ((block
& 0xFF00) >> 8);
1107 data
[7] = block
& 0xFF;
1109 ucmd
.uscsi_cdb
= (caddr_t
)&cdb
;
1110 ucmd
.uscsi_cdblen
= CDB_GROUP0
;
1111 ucmd
.uscsi_bufaddr
= (caddr_t
)data
;
1112 ucmd
.uscsi_buflen
= sizeof (data
);
1113 ucmd
.uscsi_timeout
= 120; /* If 0, HBA hangs forever */
1114 ucmd
.uscsi_rqlen
= RQ_LEN
;
1115 ucmd
.uscsi_rqbuf
= rq_data
;
1116 ret_val
= do_uscsi_cmd(fd
, &ucmd
, USCSI_WRITE
|USCSI_RQENABLE
);
1117 if (ret_val
|| ucmd
.uscsi_status
) {
1118 debug(5, "Reassign block failed: %d - %d errno = %d\n",
1119 ret_val
, ucmd
.uscsi_status
, errno
);
1127 get_mode_page(int32_t fd
, uchar_t pc
, uchar_t page_code
,
1128 uchar_t
*md_data
, uchar_t data_len
)
1130 struct uscsi_cmd ucmd
;
1133 char rq_data
[RQ_LEN
];
1135 debug(10, "MODE SENSE(6) - page_code = 0x%x\n", page_code
);
1137 (void) memset(md_data
, 0, sizeof (data_len
));
1138 (void) memset(&ucmd
, 0, sizeof (ucmd
));
1139 (void) memset(&cdb
, 0, sizeof (cdb
));
1140 cdb
[0] = SCMD_MODE_SENSE
;
1141 cdb
[2] = (pc
<< 6) | page_code
;
1144 ucmd
.uscsi_cdb
= (caddr_t
)&cdb
;
1145 ucmd
.uscsi_cdblen
= CDB_GROUP0
;
1146 ucmd
.uscsi_bufaddr
= (caddr_t
)md_data
;
1147 ucmd
.uscsi_buflen
= data_len
;
1148 ucmd
.uscsi_timeout
= 120; /* If 0, HBA hangs forever */
1149 ucmd
.uscsi_rqlen
= RQ_LEN
;
1150 ucmd
.uscsi_rqbuf
= rq_data
;
1151 ret_val
= do_uscsi_cmd(fd
, &ucmd
, USCSI_READ
|USCSI_RQENABLE
);
1152 if (ret_val
|| ucmd
.uscsi_status
) {
1153 debug(5, "Modesense failed: %d - %d errno = %d\n",
1154 ret_val
, ucmd
.uscsi_status
, errno
);
1162 scsi_zip_write_protect(int32_t fd
, smwp_state_t
*wp
)
1164 struct uscsi_cmd ucmd
;
1165 struct scsi_inquiry inq
;
1169 char rq_data
[RQ_LEN
];
1171 char *tmp_passwd
= NULL
;
1173 debug(10, "SCSI ZIP WRITE PROTECT CALLED \n");
1176 * Do an inquiry and try to figure out if it an
1177 * ATAPI or SCSI device.
1180 (void) memset(&inq
, 0, sizeof (inq
));
1181 (void) memset(&ucmd
, 0, sizeof (ucmd
));
1182 (void) memset(&cdb
, 0, sizeof (cdb
));
1183 (void) memset(&rq_data
, 0, sizeof (rq_data
));
1184 cdb
[0] = SCMD_INQUIRY
;
1185 cdb
[4] = sizeof (inq
);
1186 ucmd
.uscsi_cdb
= (caddr_t
)&cdb
;
1187 ucmd
.uscsi_cdblen
= CDB_GROUP0
;
1188 ucmd
.uscsi_bufaddr
= (caddr_t
)&inq
;
1189 ucmd
.uscsi_buflen
= sizeof (inq
);
1190 ucmd
.uscsi_timeout
= 120; /* If 0, HBA hangs forever */
1191 ucmd
.uscsi_rqlen
= RQ_LEN
;
1192 ucmd
.uscsi_rqbuf
= rq_data
;
1193 status
= do_uscsi_cmd(fd
, &ucmd
, USCSI_READ
|USCSI_RQENABLE
);
1194 if (status
|| ucmd
.uscsi_status
) {
1195 debug(5, "inquiry failed: %d - %d errno = %d\n",
1196 status
, ucmd
.uscsi_status
, errno
);
1200 if (inq
.inq_ansi
> 0) {
1202 debug(5, "SCSI device\n");
1205 debug(5, "ATAPI device\n");
1208 switch (wp
->sm_new_state
) {
1209 case SM_WRITE_PROTECT_DISABLE
:
1212 case SM_WRITE_PROTECT_NOPASSWD
:
1215 case SM_WRITE_PROTECT_PASSWD
:
1218 case SM_READ_WRITE_PROTECT
:
1221 case SM_TEMP_UNLOCK_MODE
:
1225 debug(1, "Invalid mode 0x%x specified\n",
1232 (void) memset(&ucmd
, 0, sizeof (ucmd
));
1233 (void) memset(&cdb
, 0, sizeof (cdb
));
1234 (void) memset(&rq_data
, 0, sizeof (rq_data
));
1235 cdb
[0] = IOMEGA_CATRIDGE_PROTECT
;
1239 cdb
[4] = wp
->sm_passwd_len
;
1240 ucmd
.uscsi_cdb
= (caddr_t
)&cdb
;
1241 ucmd
.uscsi_cdblen
= CDB_GROUP0
;
1242 if (wa_bit
&& (wp
->sm_passwd_len
& 1)) {
1244 * Oops, ATAPI device with an odd length passwd!
1245 * Allocate a buffer to hold one extra byte.
1247 debug(5, "Odd len passwd for ATAPI device!\n");
1249 tmp_passwd
= (char *)malloc(wp
->sm_passwd_len
+1);
1250 if (tmp_passwd
== NULL
) {
1255 (void) memset(tmp_passwd
, 0, wp
->sm_passwd_len
+1);
1256 (void) memcpy(tmp_passwd
, wp
->sm_passwd
, wp
->sm_passwd_len
);
1257 ucmd
.uscsi_bufaddr
= (caddr_t
)tmp_passwd
;
1258 ucmd
.uscsi_buflen
= wp
->sm_passwd_len
+1;
1260 ucmd
.uscsi_bufaddr
= (caddr_t
)wp
->sm_passwd
;
1261 ucmd
.uscsi_buflen
= wp
->sm_passwd_len
;
1263 ucmd
.uscsi_timeout
= 120; /* If 0, HBA hangs forever */
1264 ucmd
.uscsi_rqlen
= RQ_LEN
;
1265 ucmd
.uscsi_rqbuf
= rq_data
;
1266 status
= do_uscsi_cmd(fd
, &ucmd
, USCSI_WRITE
|USCSI_RQENABLE
);
1267 if (tmp_passwd
!= NULL
) {
1270 if (status
|| ucmd
.uscsi_status
) {
1271 debug(5, "Cartridge-protect operation failed: rv "
1272 "= %d uscsi_status = %d errno = %d\n", status
,
1273 ucmd
.uscsi_status
, errno
);
1274 if ((rq_data
[2] & 0xF) == KEY_ILLEGAL_REQUEST
) {
1275 if (rq_data
[12] == 0x26) {
1277 debug(5, "Protection Request with wrong "
1278 "passwd. errno is being set to EACCES.\n");
1290 scsi_write_protect(int32_t fd
, smwp_state_t
*wp
)
1297 * This thread becomes the server-side thread used in
1298 * the implementation of a door_call between a client
1299 * and the Client Door.
1301 * This thread is customized both by the door_server_create(3c)
1302 * function sm_door_server_create, as well as by itself.
1304 * This thread needs to synchronize with the
1305 * main_servproc[SMEDIA_CNUM_OPEN_FD] door_call in terms of
1306 * both successful and failure scenarios. main_servproc
1307 * locks dd_lock before calling door_create. This thread
1308 * then attempts to lock, but will block until main_servproc
1309 * has either created all doors it requires, or until a
1310 * door_create has failed (door_create's return and the
1311 * creation of an associated thread are asynchronous).
1313 * If door_create failed, this thread will be able to obtain
1314 * dd_lock and call pthread_exit. If all door_create's succeed,
1315 * this thread will obtain dd_lock and commence with
1316 * customizing the thread's attributes. door_bind is called to
1317 * bind this thread to the per-door private thread pool, and
1318 * main_servproc is cond_signal'd to avail it of this fact.
1320 * Finally, this thread calls door_return, which causes it to
1321 * commence its lifetime as a server-side thread in implementation
1322 * of a Client Door door_call.
1325 sm_server_thread(void *arg
)
1327 door_data_t
*door_dp
;
1328 struct sigaction act
;
1332 door_dp
= (door_data_t
*)arg
;
1334 if (door_dp
== NULL
) {
1335 fatal("sm_server_thread[%d]: argument is NULL!!\n",
1340 /* Wait for Client Door to be created */
1341 (void) mutex_lock(&door_dp
->dd_lock
);
1342 if (door_dp
->dd_cdoor_descriptor
< 0) {
1343 debug(5, "sm_server_thread[%d]: door_create() failed",
1345 (void) mutex_unlock(&door_dp
->dd_lock
);
1346 pthread_exit((void *)-2);
1348 (void) mutex_unlock(&door_dp
->dd_lock
);
1350 for (i
= 0; i
< N_BADSIGS
; i
++) {
1351 act
.sa_sigaction
= server_badsig_handler
;
1352 (void) sigemptyset(&act
.sa_mask
);
1353 act
.sa_flags
= SA_SIGINFO
;
1354 if (sigaction(badsigs
[i
], &act
, NULL
) == -1)
1355 warning(gettext(SIGACT_FAILED
), strsignal(badsigs
[i
]),
1358 if (sigemptyset(&door_dp
->dd_newset
) != 0)
1359 warning(gettext("sigemptyset failed. errno = %d\n"),
1361 if ((err
= pthread_sigmask(SIG_BLOCK
, &door_dp
->dd_newset
, NULL
)) != 0)
1362 warning(gettext("pthread_sigmask failed = %d\n"), err
);
1364 /* Bind thread with pool associated with Client Door */
1366 if (door_bind(door_dp
->dd_cdoor_descriptor
) < 0) {
1370 debug(5, "thr[%d] bound to Client Door[%d]", pthread_self(),
1371 door_dp
->dd_cdoor_descriptor
);
1374 * Set these two cancellation(5) attributes. Ensure that the
1375 * pthread we create has cancellation(5) DISABLED and DEFERRED,
1376 * as our implementation is based on this. DEFERRED is the
1377 * default, but set it anyways, in case the defaults change in
1380 if ((err
= pthread_setcancelstate(PTHREAD_CANCEL_DISABLE
, NULL
)) != 0)
1381 warning(gettext("pthread_setcancelstate(PTHREAD_CANCEL_DISABLE)"
1382 " failed = %d\n"), err
);
1383 if ((err
= pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED
,
1385 warning(gettext("pthread_setcanceltype(DEFERRED) "
1386 "failed = %d\n"), err
);
1388 /* Inform main_servproc that door_bind() is complete. */
1389 (void) cond_signal(&door_dp
->dd_cv_bind
);
1392 * Per doors protocol, transfer control to the doors-runtime in
1393 * order to make this thread available to answer future door_call()'s.
1395 (void) door_return(NULL
, 0, NULL
, 0);
1400 * This function cleans up all per-connection resources.
1402 * This function is called when the Client Door's service procedure
1403 * (client_servproc) is called w/ DOOR_UNREF_DATA, which is the
1404 * doors protocol convention stating that the number of file
1405 * descriptors referring to this door has dropped to one.
1406 * client_servproc is passed DOOR_UNREF_DATA because the Client Door
1407 * was door_create'd with the DOOR_UNREF bitflag.
1410 cleanup(door_data_t
*door_dp
)
1412 /* do door_revoke() of Death Door */
1413 if (door_dp
->dd_ddoor_descriptor
>= 0) {
1414 debug(1, "cleanup[%d]: door_revoke() Death Door[%d]",
1415 pthread_self(), door_dp
->dd_ddoor_descriptor
);
1417 if (door_revoke(door_dp
->dd_ddoor_descriptor
) < 0) {
1418 warning(gettext("cleanup[%d]: door_revoke() of Death "
1419 "Door(%d) failed = %d"), pthread_self(),
1420 door_dp
->dd_ddoor_descriptor
, errno
);
1422 door_dp
->dd_ddoor_descriptor
= -1;
1426 /* release memory that is shared between client and (our) server */
1427 if (door_dp
->dd_buffd
>= 0) {
1428 debug(1, "cleanup[%d]: release shared memory", pthread_self());
1429 (void) munmap(door_dp
->dd_buf
, door_dp
->dd_buf_len
);
1430 (void) close(door_dp
->dd_buffd
);
1432 door_dp
->dd_buffd
= -1;
1433 door_dp
->dd_buf
= NULL
;
1434 door_dp
->dd_buf_len
= 0;
1437 /* close the (target) device that the Client is operating on */
1438 if (door_dp
->dd_fd
>= 0) {
1439 debug(1, "cleanup[%d]: close(%d) target device", pthread_self(),
1441 if (close(door_dp
->dd_fd
) < 0) {
1442 warning(gettext("cleanup[%d]: close() of target device"
1443 "failed = %d\n"), pthread_self(), errno
);
1448 * Unbind the current thread from the Client Door's private
1451 debug(1, "cleanup[%d]: door_unbind() of Client Door[%d]",
1452 pthread_self(), door_dp
->dd_cdoor_descriptor
);
1453 if (door_unbind() < 0)
1454 warning("door_unbind() of Client Door[%d] failed = "
1455 "%d", door_dp
->dd_cdoor_descriptor
, errno
);
1457 /* Disallow any future requests to the Client Door */
1458 if (door_dp
->dd_cdoor_descriptor
>= 0) {
1459 debug(1, "cleanup[%d]: door_revoke() Client Door[%d]",
1460 pthread_self(), door_dp
->dd_cdoor_descriptor
);
1462 if (door_revoke(door_dp
->dd_cdoor_descriptor
) < 0) {
1463 warning(gettext("cleanup[%d]: door_revoke() of "
1464 "Client Door[%d] failed = %d"), pthread_self(),
1465 door_dp
->dd_cdoor_descriptor
, errno
);
1470 debug(5, "cleanup[%d] ...exiting\n", pthread_self());
1474 * This is the door_server_create(3c) function used to customize
1475 * creation of the threads used in the handling of our daemon's
1478 * This function is called synchronously as part of door_create(3c).
1479 * Note that door_create(), however, is not synchronous; it can return
1480 * with the created door file descriptor before any associated
1481 * thread has been created. As a result, synchronization is needed
1482 * between door_create() caller and the created pthread. This is
1483 * needed both when each activity succeeds or when either activity
1486 * Specifically, this function ensures that each "connection"
1487 * with the client creates only one thread in the per-door,
1488 * private thread pool. This function locks dd_threadlock and
1489 * then calls pthread_create(). If that succeeds, dd_thread
1490 * is assigned the thread id, and dd_threadlock is unlocked.
1491 * Any per-connection door_create that causes control to flow
1492 * to this function will eventually find that dd_thread is
1493 * non-zero, and control will exit this function.
1495 * In the current implementation, the door_create for the Client Door
1496 * is called first, and the Death Door is door_create'd second.
1497 * As a result, the following function can safely make the static
1498 * assumption that the first door (within a connection) is the
1499 * Client Door. A connection's Client Door and Death Door share
1500 * the same thread as well as the same door_data_t instance.
1503 sm_door_server_create(door_info_t
*dip
)
1505 door_data_t
*door_dp
;
1507 pthread_attr_t attr
;
1514 door_dp
= (door_data_t
*)(uintptr_t)dip
->di_data
;
1516 debug(10, "sm_door_server_create[%d]: entering...\n", pthread_self());
1518 /* create one thread for this door */
1520 (void) mutex_lock(&door_dp
->dd_threadlock
);
1522 if (door_dp
->dd_thread
!= 0) {
1523 debug(8, "sm_door_server_create[%d]: Exiting without creating "
1524 "thread.\n", pthread_self());
1525 (void) mutex_unlock(&door_dp
->dd_threadlock
);
1529 (void) pthread_attr_init(&attr
);
1531 if ((err
= pthread_attr_setscope(&attr
, PTHREAD_SCOPE_SYSTEM
)) != 0)
1532 warning(gettext("pthread_attr_setscope failed = %d\n"), err
);
1533 if ((err
= pthread_attr_setdetachstate(&attr
,
1534 PTHREAD_CREATE_DETACHED
)) != 0)
1535 warning(gettext("pthread_attr_setdetachstate failed = %d\n"),
1538 ret_val
= pthread_create(&tid
, &attr
, sm_server_thread
,
1539 (void *)(uintptr_t)(dip
->di_data
));
1541 warning(gettext("sm_door_server_create[%d]: pthread_create "
1542 "failed = %d\n"), pthread_self(), ret_val
);
1543 (void) mutex_unlock(&door_dp
->dd_threadlock
);
1544 (void) pthread_attr_destroy(&attr
);
1547 (void) pthread_attr_destroy(&attr
);
1548 door_dp
->dd_thread
= tid
;
1550 (void) mutex_unlock(&door_dp
->dd_threadlock
);
1551 debug(5, "Exiting sm_door_server_create[%d] after creating thr[%d].\n",
1552 pthread_self(), tid
);
1556 door_ret_err(smedia_reterror_t
*reterror
, int32_t err
)
1558 reterror
->cnum
= SMEDIA_CNUM_ERROR
;
1559 reterror
->errnum
= err
;
1560 (void) door_return((char *)reterror
, sizeof (smedia_reterror_t
), 0, 0);
1564 my_door_return(char *data_ptr
, size_t data_size
,
1565 door_desc_t
*desc_ptr
, uint_t num_desc
)
1567 (void) door_return(data_ptr
, data_size
, desc_ptr
, num_desc
);
1571 raw_read(door_data_t
*door_dp
, smedia_services_t
*req
)
1573 struct uscsi_cmd ucmd
;
1576 int32_t num_sectors
, sector_size
;
1578 char rq_data
[RQ_LEN
];
1580 (void) memset(&rc_data
, 0, sizeof (rc_data
));
1581 (void) memset(&ucmd
, 0, sizeof (ucmd
));
1582 (void) memset(&cdb
, 0, sizeof (union scsi_cdb
));
1584 if (door_dp
->dd_sector_size
== 0) {
1585 sector_size
= get_sector_size(door_dp
->dd_fd
);
1586 door_dp
->dd_sector_size
= sector_size
;
1587 } else sector_size
= door_dp
->dd_sector_size
;
1589 if ((req
->reqraw_read
.nbytes
> door_dp
->dd_buf_len
) ||
1590 (door_dp
->dd_buf
== NULL
)) {
1594 if ((!req
->reqraw_read
.nbytes
) ||
1595 (req
->reqraw_read
.nbytes
% sector_size
)) {
1600 (void) memset(&cdb
, 0, sizeof (cdb
));
1601 num_sectors
= (uint32_t)req
->reqraw_read
.nbytes
/sector_size
;
1603 cdb
.scc_cmd
= SCMD_READ_G1
;
1604 FORMG1ADDR(&cdb
, (uint32_t)req
->reqraw_read
.blockno
);
1605 FORMG1COUNT(&cdb
, num_sectors
);
1607 ucmd
.uscsi_cdb
= (caddr_t
)&cdb
;
1608 ucmd
.uscsi_cdblen
= CDB_GROUP1
;
1609 ucmd
.uscsi_bufaddr
= (caddr_t
)door_dp
->dd_buf
;
1610 ucmd
.uscsi_buflen
= (uint32_t)req
->reqraw_read
.nbytes
;
1611 ucmd
.uscsi_timeout
= 120; /* If 0, HBA hangs forever */
1612 ucmd
.uscsi_rqlen
= RQ_LEN
;
1613 ucmd
.uscsi_rqbuf
= rq_data
;
1614 ret_val
= do_uscsi_cmd(door_dp
->dd_fd
,
1615 &ucmd
, USCSI_READ
|USCSI_RQENABLE
);
1616 if (ret_val
|| ucmd
.uscsi_status
) {
1617 debug(5, "read failed: %d - %d errno = %d\n",
1618 ret_val
, ucmd
.uscsi_status
, errno
);
1619 debug(5, "buflen = 0x%x resid = 0x%x sector size = %d\n",
1620 ucmd
.uscsi_buflen
, ucmd
.uscsi_resid
, sector_size
);
1621 debug(5, "cdb addr: %x %x %x %x \n", cdb
.g1_addr3
,
1622 cdb
.g1_addr2
, cdb
.g1_addr1
, cdb
.g1_addr0
);
1623 debug(5, "cdb count: %x %x\n", cdb
.g1_count1
,
1627 ret_val
= ucmd
.uscsi_buflen
- ucmd
.uscsi_resid
;
1632 raw_write(door_data_t
*door_dp
, smedia_services_t
*req
)
1634 struct uscsi_cmd ucmd
;
1637 int32_t num_sectors
, sector_size
;
1639 char rq_data
[RQ_LEN
];
1641 (void) memset(&rc_data
, 0, sizeof (rc_data
));
1642 (void) memset(&ucmd
, 0, sizeof (ucmd
));
1643 (void) memset(&cdb
, 0, sizeof (union scsi_cdb
));
1645 if (door_dp
->dd_sector_size
== 0) {
1646 sector_size
= get_sector_size(door_dp
->dd_fd
);
1647 door_dp
->dd_sector_size
= sector_size
;
1648 } else sector_size
= door_dp
->dd_sector_size
;
1651 if ((req
->reqraw_write
.nbytes
> door_dp
->dd_buf_len
) ||
1652 (door_dp
->dd_buf
== NULL
)) {
1656 if ((req
->reqraw_write
.nbytes
% sector_size
)) {
1661 (void) memset(&cdb
, 0, sizeof (cdb
));
1662 num_sectors
= (uint32_t)req
->reqraw_write
.nbytes
/sector_size
;
1664 cdb
.scc_cmd
= SCMD_WRITE_G1
;
1665 FORMG1ADDR(&cdb
, (uint32_t)req
->reqraw_write
.blockno
);
1666 FORMG1COUNT(&cdb
, num_sectors
);
1668 ucmd
.uscsi_cdb
= (caddr_t
)&cdb
;
1669 ucmd
.uscsi_cdblen
= CDB_GROUP1
;
1670 ucmd
.uscsi_bufaddr
= (caddr_t
)door_dp
->dd_buf
;
1671 ucmd
.uscsi_buflen
= (uint32_t)req
->reqraw_write
.nbytes
;
1672 ucmd
.uscsi_timeout
= 120; /* If 0, HBA hangs forever */
1673 ucmd
.uscsi_rqlen
= RQ_LEN
;
1674 ucmd
.uscsi_rqbuf
= rq_data
;
1675 ret_val
= do_uscsi_cmd(door_dp
->dd_fd
,
1676 &ucmd
, USCSI_WRITE
|USCSI_RQENABLE
);
1677 if (ret_val
|| ucmd
.uscsi_status
) {
1678 debug(5, "write failed: %d - %d errno = %d\n",
1679 ret_val
, ucmd
.uscsi_status
, errno
);
1680 debug(5, "buflen = 0x%x resid = 0x%x sector size = %d\n",
1681 ucmd
.uscsi_buflen
, ucmd
.uscsi_resid
, sector_size
);
1682 debug(5, "cdb addr: %x %x %x %x \n", cdb
.g1_addr3
,
1683 cdb
.g1_addr2
, cdb
.g1_addr1
, cdb
.g1_addr0
);
1684 debug(5, "cdb count: %x %x\n", cdb
.g1_count1
,
1688 ret_val
= ucmd
.uscsi_buflen
- ucmd
.uscsi_resid
;
1693 set_protection_status(door_data_t
*door_dp
, smedia_services_t
*req
)
1695 int32_t ret_val
, saved_errno
, status
;
1696 struct scsi_inquiry inq
;
1700 char uname
[MAXUGNAME
+ 1];
1701 char *new_state
, *old_state
;
1704 * Read the current protection state before modifiying.
1706 switch (get_device_type_scsi(door_dp
->dd_fd
, &inq
)) {
1708 status
= scsi_zip_media_status(door_dp
->dd_fd
);
1709 ret_val
= scsi_zip_write_protect(door_dp
->dd_fd
,
1710 &req
->reqset_protection_status
.prot_state
);
1713 info("Formatting floppy");
1714 status
= scsi_floppy_media_status(door_dp
->dd_fd
);
1715 ret_val
= scsi_floppy_write_protect(door_dp
->dd_fd
,
1716 &req
->reqset_protection_status
.prot_state
);
1719 status
= scsi_media_status(door_dp
->dd_fd
);
1720 ret_val
= scsi_write_protect(door_dp
->dd_fd
,
1721 &req
->reqset_protection_status
.prot_state
);
1725 saved_errno
= errno
;
1726 new_state
= xlate_state(
1727 req
->reqset_protection_status
.prot_state
.sm_new_state
);
1728 old_state
= xlate_state(status
);
1730 (void) strlcpy(vid
, inq
.inq_vid
, sizeof (vid
));
1731 (void) strlcpy(pid
, inq
.inq_pid
, sizeof (pid
));
1733 if (errno
== EACCES
) {
1734 pwd
= getpwuid(door_dp
->dd_cred
.dc_ruid
);
1736 (void) strlcpy(uname
,
1737 pwd
->pw_name
, MAXUGNAME
);
1738 } else uname
[0] = 0;
1740 } /* errno == EACCES */
1741 errno
= saved_errno
;
1744 errno
= saved_errno
;
1749 set_shfd(door_data_t
*door_dp
, int32_t fd
, smedia_services_t
*req
)
1752 int32_t ret_val
= 0;
1754 if ((door_dp
->dd_buffd
!= -1) && (door_dp
->dd_buf
!= NULL
)) {
1755 ret_val
= munmap(door_dp
->dd_buf
, door_dp
->dd_buf_len
);
1757 warning(gettext("munmap failed. errno=%d\n"),
1759 (void) close(door_dp
->dd_buffd
);
1761 door_dp
->dd_buffd
= -1;
1762 door_dp
->dd_buf
= 0;
1763 door_dp
->dd_buf_len
= 0;
1766 fbuf
= mmap(NULL
, req
->reqset_shfd
.fdbuf_len
,
1767 PROT_READ
| PROT_WRITE
, MAP_SHARED
, fd
, 0);
1768 if (fbuf
== MAP_FAILED
) {
1770 debug(5, "mmap failed. errno=%d\n", errno
);
1773 door_dp
->dd_buffd
= fd
;
1774 door_dp
->dd_buf
= fbuf
;
1775 door_dp
->dd_buf_len
= req
->reqset_shfd
.fdbuf_len
;
1781 reassign_block(door_data_t
*door_dp
, smedia_services_t
*req
)
1783 struct uscsi_cmd ucmd
;
1786 int32_t sector_size
;
1788 uchar_t mode_data
[MD_LEN
];
1790 if (get_mode_page(door_dp
->dd_fd
, 0, 1,
1791 mode_data
, MD_LEN
) < 0) {
1792 debug(5, "Mode sense failed\n");
1793 ret_val
= scsi_reassign_block(door_dp
->dd_fd
,
1794 req
->reqreassign_block
.blockno
);
1801 * No need to check if enough data is returned for
1803 * It will be 0 otherwise which needs to reassign the block.
1805 if (!(mode_data
[AWRE_OFFSET
] & AWRE
)) {
1806 debug(5, "AWRE bit not set\n");
1807 ret_val
= scsi_reassign_block(door_dp
->dd_fd
,
1808 req
->reqreassign_block
.blockno
);
1813 sector_size
= (mode_data
[BLOCK_LEN_OFFSET
] << 16) |
1814 (mode_data
[BLOCK_LEN_OFFSET
+ 1] << 8) |
1815 mode_data
[BLOCK_LEN_OFFSET
+ 2];
1817 debug(5, "REASSIGN BLOCK: sec size = 0x%x\n", sector_size
);
1818 read_buf
= (char *)malloc(sector_size
);
1819 if (read_buf
== NULL
) {
1820 /* Alloc failed. Atleast reassign the block */
1821 ret_val
= scsi_reassign_block(door_dp
->dd_fd
,
1822 req
->reqreassign_block
.blockno
);
1828 (void) memset(read_buf
, 0, sector_size
);
1829 /* Read the sector */
1830 debug(5, "Reading the block %d\n",
1831 (uint32_t)req
->reqreassign_block
.blockno
);
1833 (void) memset(&ucmd
, 0, sizeof (ucmd
));
1834 (void) memset(&cdb
, 0, sizeof (union scsi_cdb
));
1836 cdb
.scc_cmd
= SCMD_READ_G1
;
1837 FORMG1ADDR(&cdb
, req
->reqreassign_block
.blockno
);
1838 FORMG1COUNT(&cdb
, 1); /* One block */
1840 ucmd
.uscsi_cdb
= (caddr_t
)&cdb
;
1841 ucmd
.uscsi_cdblen
= CDB_GROUP1
;
1842 ucmd
.uscsi_bufaddr
= (caddr_t
)read_buf
;
1843 ucmd
.uscsi_buflen
= sector_size
;
1844 ucmd
.uscsi_timeout
= 120; /* If 0, HBA hangs forever */
1845 (void) do_uscsi_cmd(door_dp
->dd_fd
, &ucmd
, USCSI_READ
);
1847 /* Write the data back */
1849 debug(5, "Writing the block %d\n",
1850 (uint32_t)req
->reqreassign_block
.blockno
);
1851 (void) memset(&ucmd
, 0, sizeof (ucmd
));
1852 (void) memset(&cdb
, 0, sizeof (cdb
));
1854 cdb
.scc_cmd
= SCMD_WRITE_G1
;
1855 FORMG1ADDR(&cdb
, req
->reqreassign_block
.blockno
);
1856 FORMG1COUNT(&cdb
, 1); /* One block */
1858 ucmd
.uscsi_cdb
= (caddr_t
)&cdb
;
1859 ucmd
.uscsi_cdblen
= CDB_GROUP1
;
1860 ucmd
.uscsi_bufaddr
= (caddr_t
)read_buf
;
1861 ucmd
.uscsi_buflen
= sector_size
;
1862 ucmd
.uscsi_timeout
= 120; /* If 0, HBA hangs forever */
1863 ret_val
= do_uscsi_cmd(door_dp
->dd_fd
, &ucmd
, USCSI_WRITE
);
1865 if (ret_val
|| ucmd
.uscsi_status
) {
1866 debug(5, "Reassign failed: %d - %d errno = %d\n",
1867 ret_val
, ucmd
.uscsi_status
, errno
);
1868 ret_val
= scsi_reassign_block(door_dp
->dd_fd
,
1869 req
->reqreassign_block
.blockno
);
1879 close_door_descs(door_desc_t
*dp
, uint_t ndesc
)
1882 int fd
= dp
->d_data
.d_desc
.d_descriptor
;
1883 if (dp
->d_attributes
& DOOR_DESCRIPTOR
)
1891 * This is a Death Door's service procedure.
1893 * This procedure is a NOP because the Death Door functionality
1894 * is no longer used and will be removed in the future.
1898 death_servproc(void *cookie
, char *argp
, size_t arg_size
,
1899 door_desc_t
*dp
, uint_t ndesc
)
1901 debug(1, "death_servproc[%d]: argp = 0x%p "
1902 "Death Door[%d]\n", pthread_self(), (void *)argp
,
1903 ((door_data_t
*)cookie
)->dd_ddoor_descriptor
);
1905 (void) door_return(NULL
, 0, NULL
, 0);
1909 * This is a Client Door's service procedure.
1911 * This procedure is specified in the door_create() of a Client Door,
1912 * and its functionality represents the bulk of services that the
1913 * rpc.smserverd daemon offers.
1916 client_servproc(void *cookie
, char *argp
, size_t arg_size
,
1917 door_desc_t
*dp
, uint_t ndesc
)
1919 smedia_services_t
*req
;
1920 smedia_services_t rmsvc
;
1921 smedia_reterror_t reterror
;
1922 smedia_retraw_read_t retraw_read
;
1923 struct scsi_inquiry inq
;
1924 struct dk_minfo media_info
;
1925 struct dk_geom dkgeom
;
1928 int32_t completed
= 0;
1929 door_data_t
*door_dp
;
1931 struct uscsi_cmd ucmd
;
1933 int32_t ret_val
, err
;
1934 char rq_data
[RQ_LEN
];
1935 uint_t nexpected_desc
;
1937 struct extvtoc extvtoc
;
1939 door_dp
= (door_data_t
*)cookie
;
1940 req
= (smedia_services_t
*)((void *)argp
);
1942 debug(10, "client_servproc[%d]...\n", pthread_self());
1944 if (argp
== DOOR_UNREF_DATA
) {
1945 debug(5, "client_servproc[%d]: req = DOOR_UNREF_DATA\n",
1947 debug(5, "Client has exited. Cleaning up resources\n");
1949 (void) mutex_lock(&svcstate_lock
);
1951 (void) mutex_unlock(&svcstate_lock
);
1957 (void) mutex_lock(&svcstate_lock
);
1959 (void) mutex_unlock(&svcstate_lock
);
1961 rmsvc
.in
.cnum
= req
->in
.cnum
;
1962 debug(5, "client_servproc[%d]: req = %s\n", pthread_self(),
1963 xlate_cnum(req
->in
.cnum
));
1966 * Our caller may have passed more descriptors than we expected.
1967 * If so, we silently close (and ignore) them.
1969 nexpected_desc
= (req
->in
.cnum
== SMEDIA_CNUM_SET_SHFD
) ? 1 : 0;
1970 if (ndesc
> nexpected_desc
) {
1971 close_door_descs(dp
+ nexpected_desc
, ndesc
- nexpected_desc
);
1974 switch (req
->in
.cnum
) {
1976 debug(5, "client_servproc: unknown command %d\n", req
->in
.cnum
);
1977 door_ret_err(&reterror
, ENOTSUP
);
1980 case SMEDIA_CNUM_SET_SHFD
:
1982 door_ret_err(&reterror
, EINVAL
);
1984 * Allocate shared memory for this connection.
1985 * If this connection already has shared memory,
1986 * deallocate before doing the allocation.
1988 ret_val
= set_shfd(door_dp
, dp
->d_data
.d_desc
.d_descriptor
,
1991 reterror
.cnum
= SMEDIA_CNUM_SET_SHFD
;
1992 reterror
.errnum
= 0;
1994 my_door_return((char *)&reterror
,
1995 sizeof (smedia_reterror_t
), 0, 0);
1997 (void) close(dp
->d_data
.d_desc
.d_descriptor
);
1998 door_ret_err(&reterror
, ret_val
);
2002 case SMEDIA_CNUM_RAW_READ
:
2003 debug(10, " arg size = %d blk num=0x%x nbytes = 0x%x \n",
2005 (uint32_t)req
->reqraw_read
.blockno
,
2006 req
->reqraw_read
.nbytes
);
2007 retbuf_size
= sizeof (smedia_retraw_read_t
);
2008 if (req
->reqraw_read
.nbytes
== 0) {
2009 /* Nothing to write */
2010 rmsvc
.retraw_write
.nbytes
= 0;
2011 my_door_return((char *)&rmsvc
,
2012 sizeof (smedia_retraw_write_t
), 0, 0);
2014 retraw_read
.cnum
= SMEDIA_CNUM_RAW_READ
;
2015 ret_val
= raw_read(door_dp
, req
);
2016 if (ret_val
== -1) {
2017 door_ret_err(&reterror
, errno
);
2019 retraw_read
.nbytes
= ret_val
;
2020 my_door_return((char *)&retraw_read
, retbuf_size
, 0, 0);
2023 case SMEDIA_CNUM_USCSI_CMD
:
2024 retbuf_size
= sizeof (smedia_retuscsi_cmd_t
);
2025 rmsvc
.retuscsi_cmd
.cnum
= SMEDIA_CNUM_USCSI_CMD
;
2026 ucmd
.uscsi_flags
= req
->requscsi_cmd
.uscsi_flags
;
2027 ucmd
.uscsi_cdb
= (caddr_t
)&req
->requscsi_cmd
.uscsi_cdb
;
2028 ucmd
.uscsi_cdblen
= req
->requscsi_cmd
.uscsi_cdblen
;
2029 ucmd
.uscsi_bufaddr
= (caddr_t
)door_dp
->dd_buf
;
2030 ucmd
.uscsi_buflen
= req
->requscsi_cmd
.uscsi_buflen
;
2031 ucmd
.uscsi_timeout
= req
->requscsi_cmd
.uscsi_timeout
;
2032 ucmd
.uscsi_rqlen
= req
->requscsi_cmd
.uscsi_rqlen
;
2033 ucmd
.uscsi_rqbuf
= (caddr_t
)&rmsvc
.retuscsi_cmd
.uscsi_rqbuf
;
2034 debug(5, "USCSI CMD 0x%x requested.\n",
2035 req
->requscsi_cmd
.uscsi_cdb
[0]);
2037 * Check the device type and invalid flags specified.
2038 * We permit operations only on CDROM devices types.
2040 errno
= invalid_uscsi_operation(door_dp
, &ucmd
);
2042 door_ret_err(&reterror
, errno
);
2045 if ((req
->requscsi_cmd
.uscsi_buflen
) &&
2046 ((req
->requscsi_cmd
.uscsi_buflen
> door_dp
->dd_buf_len
) ||
2047 (door_dp
->dd_buf
== NULL
))) {
2048 debug(5, "uscsi_cmd failed: uscsi_buflen=0x%x "
2049 "dd_buf_len=0x%x dd_buf=0x%p\n",
2050 req
->requscsi_cmd
.uscsi_buflen
,
2051 door_dp
->dd_buf_len
,
2054 door_ret_err(&reterror
, errno
);
2056 ret_val
= do_uscsi_cmd(door_dp
->dd_fd
,
2057 &ucmd
, req
->requscsi_cmd
.uscsi_flags
);
2058 rmsvc
.retuscsi_cmd
.uscsi_status
= ucmd
.uscsi_status
;
2059 rmsvc
.retuscsi_cmd
.uscsi_resid
= ucmd
.uscsi_resid
;
2060 rmsvc
.retuscsi_cmd
.uscsi_rqstatus
= ucmd
.uscsi_rqstatus
;
2061 rmsvc
.retuscsi_cmd
.uscsi_rqresid
= ucmd
.uscsi_rqresid
;
2062 rmsvc
.retuscsi_cmd
.uscsi_retval
= ret_val
;
2063 rmsvc
.retuscsi_cmd
.uscsi_errno
= errno
;
2064 if (ret_val
|| ucmd
.uscsi_status
) {
2065 debug(5, "uscsi_cmd failed: %d - %d errno = %d\n",
2066 ret_val
, ucmd
.uscsi_status
, errno
);
2068 my_door_return((char *)&rmsvc
, retbuf_size
, 0, 0);
2071 case SMEDIA_CNUM_RAW_WRITE
:
2072 if (req
->reqraw_write
.nbytes
== 0) {
2073 /* Nothing to write */
2074 rmsvc
.retraw_write
.nbytes
= 0;
2075 my_door_return((char *)&rmsvc
,
2076 sizeof (smedia_retraw_write_t
), 0, 0);
2078 ret_val
= raw_write(door_dp
, req
);
2080 door_ret_err(&reterror
, errno
);
2081 rmsvc
.retraw_write
.nbytes
= ret_val
;
2082 my_door_return((char *)&rmsvc
, sizeof (smedia_retraw_write_t
),
2086 case SMEDIA_CNUM_GET_DEVICE_INFO
:
2088 (void) memset(&inq
, 0, sizeof (inq
));
2089 (void) memset(&ucmd
, 0, sizeof (ucmd
));
2090 (void) memset(&cdb
, 0, sizeof (union scsi_cdb
));
2091 cdb
.scc_cmd
= SCMD_INQUIRY
;
2092 FORMG0COUNT(&cdb
, sizeof (inq
));
2093 ucmd
.uscsi_cdb
= (caddr_t
)&cdb
;
2094 ucmd
.uscsi_cdblen
= CDB_GROUP0
;
2095 ucmd
.uscsi_bufaddr
= (caddr_t
)&inq
;
2096 ucmd
.uscsi_buflen
= sizeof (inq
);
2097 ucmd
.uscsi_timeout
= 120; /* If 0, HBA hangs forever */
2098 ucmd
.uscsi_rqlen
= RQ_LEN
;
2099 ucmd
.uscsi_rqbuf
= rq_data
;
2100 ret_val
= do_uscsi_cmd(door_dp
->dd_fd
,
2101 &ucmd
, USCSI_READ
|USCSI_RQENABLE
);
2102 if (ret_val
|| ucmd
.uscsi_status
) {
2103 debug(5, "inquiry failed: %d - %d errno = %d\n",
2104 ret_val
, ucmd
.uscsi_status
, errno
);
2105 door_ret_err(&reterror
, errno
);
2108 debug(5, "%s\n", inq
.inq_vid
);
2109 debug(5, "%s\n", rmsvc
.retget_device_info
.sm_vendor_name
);
2111 (void) strlcpy(rmsvc
.retget_device_info
.sm_vendor_name
,
2113 rmsvc
.retget_device_info
.sm_vendor_name
[8] = 0;
2114 (void) strlcpy(rmsvc
.retget_device_info
.sm_product_name
,
2116 rmsvc
.retget_device_info
.sm_product_name
[16] = 0;
2117 (void) strlcpy(rmsvc
.retget_device_info
.sm_firmware_version
,
2118 inq
.inq_revision
, 4);
2119 rmsvc
.retget_device_info
.sm_firmware_version
[4] = ' ';
2121 &rmsvc
.retget_device_info
.sm_firmware_version
[5],
2122 inq
.inq_serial
, 12);
2123 rmsvc
.retget_device_info
.sm_product_name
[17] = 0;
2125 rmsvc
.retget_device_info
.sm_interface_type
= IF_SCSI
;
2127 debug(5, "Vendor name = %s\n",
2128 rmsvc
.retget_device_info
.sm_vendor_name
);
2129 debug(5, "product name = %s\n",
2130 rmsvc
.retget_device_info
.sm_product_name
);
2131 debug(5, "Firmware revision = %s\n",
2132 rmsvc
.retget_device_info
.sm_firmware_version
);
2134 my_door_return((char *)&rmsvc
.retget_device_info
,
2135 sizeof (smedia_retget_device_info_t
), 0, 0);
2138 case SMEDIA_CNUM_GET_MEDIUM_PROPERTY
:
2140 (void) memset(&rmsvc
.retget_medium_property
.smprop
,
2141 0, sizeof (smmedium_prop_t
));
2143 ret_val
= ioctl(door_dp
->dd_fd
, DKIOCGMEDIAINFO
, &media_info
);
2149 * Devices may fail DKIOCGMEDIAINFO if an unformed
2150 * media is inserted. We can get the capacity
2151 * information from the SCMD_READ_FORMAT_CAP command.
2154 debug(5, "DKIOCGMEDIAINFO failed; using "
2155 "SCMD_READ_FORMAT_CAP");
2156 ret_val
= get_media_capacity(door_dp
->dd_fd
,
2157 &capacity
, &blocksize
);
2160 media_info
.dki_lbsize
= blocksize
;
2161 media_info
.dki_capacity
= capacity
;
2163 debug(5, "SCMD_READ_FORMAT_CAP failed");
2164 door_ret_err(&reterror
, errno
);
2167 rmsvc
.retget_medium_property
.smprop
.sm_blocksize
=
2168 media_info
.dki_lbsize
;
2169 rmsvc
.retget_medium_property
.smprop
.sm_capacity
=
2170 media_info
.dki_capacity
;
2172 rmsvc
.retget_medium_property
.smprop
.sm_media_type
=
2173 media_info
.dki_media_type
;
2175 * These devices show as SCSI devices but we need to treat it
2176 * differently. so we need a seperate class.
2178 if (get_device_type_scsi(door_dp
->dd_fd
, &inq
) == SCSI_FLOPPY
) {
2179 rmsvc
.retget_medium_property
.smprop
.sm_media_type
=
2183 /* Check for EFI type because DKIOCGGEOM does not support EFI */
2184 ret_val
= ioctl(door_dp
->dd_fd
, DKIOCGEXTVTOC
, &extvtoc
);
2185 if (ret_val
< 0 && errno
== ENOTTY
)
2186 ret_val
= ioctl(door_dp
->dd_fd
, DKIOCGVTOC
, &vtoc
);
2188 if (!((ret_val
< 0) && (errno
== ENOTSUP
))) {
2189 ret_val
= ioctl(door_dp
->dd_fd
, DKIOCGGEOM
, &dkgeom
);
2192 * DKIOCGGEOM may fail for unformed floppies.
2193 * We need to generate the appropriate geometry
2196 if (rmsvc
.retget_medium_property
.smprop
.
2197 sm_media_type
== SM_SCSI_FLOPPY
) {
2198 ret_val
= get_floppy_geom(
2200 media_info
.dki_capacity
, &dkgeom
);
2203 debug(5, "Cannot determine "
2205 door_ret_err(&reterror
, errno
);
2209 debug(5, "DKIOCGGEOM ioctl failed");
2210 door_ret_err(&reterror
, errno
);
2213 * Try getting Physical geometry on x86.
2215 ret_val
= ioctl(door_dp
->dd_fd
,
2216 DKIOCG_PHYGEOM
, &dkgeom
);
2218 debug(5, "DKIOCG_PHYGEOM "
2220 door_ret_err(&reterror
, errno
);
2228 * Some faked geometry may not have pcyl filled in so
2229 * later calculations using this field will be
2230 * incorrect. We will substitute it with the number of
2231 * available cylinders.
2233 if (dkgeom
.dkg_pcyl
== 0)
2234 rmsvc
.retget_medium_property
.smprop
.sm_pcyl
=
2237 rmsvc
.retget_medium_property
.smprop
.sm_pcyl
=
2240 rmsvc
.retget_medium_property
.smprop
.sm_nhead
=
2242 rmsvc
.retget_medium_property
.smprop
.sm_nsect
=
2246 debug(1, "properties are: lbasize = %d, cap = %llu",
2247 media_info
.dki_lbsize
, media_info
.dki_capacity
);
2249 my_door_return((char *)&rmsvc
.retget_medium_property
,
2250 sizeof (smedia_retget_medium_property_t
), 0, 0);
2253 case SMEDIA_CNUM_GET_PROTECTION_STATUS
:
2254 switch (get_device_type_scsi(door_dp
->dd_fd
, &inq
)) {
2256 status
= scsi_floppy_media_status(door_dp
->dd_fd
);
2259 status
= scsi_zip_media_status(door_dp
->dd_fd
);
2262 status
= scsi_media_status(door_dp
->dd_fd
);
2265 door_ret_err(&reterror
, errno
);
2268 door_ret_err(&reterror
, errno
);
2270 rmsvc
.retget_protection_status
.prot_state
.sm_new_state
=
2273 my_door_return((char *)&rmsvc
.retget_protection_status
,
2274 sizeof (smedia_retget_protection_status_t
), 0, 0);
2277 case SMEDIA_CNUM_SET_PROTECTION_STATUS
:
2279 ret_val
= set_protection_status(door_dp
, req
);
2281 door_ret_err(&reterror
, errno
);
2283 my_door_return((char *)&rmsvc
.retset_protection_status
,
2284 sizeof (smedia_retset_protection_status_t
),
2288 case SMEDIA_CNUM_FORMAT
:
2289 switch (get_device_type_scsi(door_dp
->dd_fd
, &inq
)) {
2291 info("formatting floppy");
2292 err
= scsi_floppy_format(door_dp
->dd_fd
,
2293 req
->reqformat
.flavor
, req
->reqformat
.mode
);
2297 err
= scsi_zip_format(door_dp
->dd_fd
,
2298 req
->reqformat
.flavor
, req
->reqformat
.mode
);
2301 err
= scsi_format(door_dp
->dd_fd
,
2302 req
->reqformat
.flavor
, req
->reqformat
.mode
);
2305 door_ret_err(&reterror
, ENOTSUP
);
2309 door_ret_err(&reterror
, errno
);
2310 my_door_return((char *)&rmsvc
.retformat
,
2311 sizeof (smedia_retformat_t
), 0, 0);
2315 case SMEDIA_CNUM_CHECK_FORMAT_STATUS
:
2317 (void) memset(&cdb
, 0, sizeof (union scsi_cdb
));
2318 (void) memset(&ucmd
, 0, sizeof (ucmd
));
2319 (void) memset(&data
, 0, sizeof (data
));
2320 cdb
.scc_cmd
= SCMD_REQUEST_SENSE
;
2321 cdb
.g0_count0
= sizeof (data
);
2322 ucmd
.uscsi_cdb
= (caddr_t
)&cdb
;
2323 ucmd
.uscsi_cdblen
= CDB_GROUP0
;
2324 ucmd
.uscsi_bufaddr
= (caddr_t
)&data
;
2325 ucmd
.uscsi_buflen
= sizeof (data
);
2326 ucmd
.uscsi_timeout
= 120; /* If 0, HBA hangs forever */
2327 ucmd
.uscsi_rqlen
= RQ_LEN
;
2328 ucmd
.uscsi_rqbuf
= rq_data
;
2329 ret_val
= do_uscsi_cmd(door_dp
->dd_fd
,
2330 &ucmd
, USCSI_READ
|USCSI_RQENABLE
);
2331 if (ret_val
|| ucmd
.uscsi_status
) {
2332 debug(5, "Request sense failed: %d - %d errno = %d\n",
2333 ret_val
, ucmd
.uscsi_status
, errno
);
2334 door_ret_err(&reterror
, errno
);
2337 if ((data
[0] & 0x7F) == DEFERRED_ERROR
) {
2338 /* Deffered error. The format must have failed */
2339 debug(5, "format failed!\n");
2340 door_ret_err(&reterror
, EIO
);
2343 if (data
[SKSV_OFFSET
] & SKSV_FIELD
) {
2345 (data
[FORMAT_PROGRESS_INDICATOR_OFFSET_0
] << 8)
2346 | data
[FORMAT_PROGRESS_INDICATOR_OFFSET_1
];
2347 completed
= (completed
*100/65536);
2351 rmsvc
.retcheck_format_status
.percent_complete
= completed
;
2352 my_door_return((char *)&rmsvc
.retcheck_format_status
,
2353 sizeof (smedia_retcheck_format_status_t
), 0, 0);
2356 case SMEDIA_CNUM_REASSIGN_BLOCK
:
2358 ret_val
= reassign_block(door_dp
, req
);
2360 door_ret_err(&reterror
, errno
);
2361 my_door_return((char *)&rmsvc
.retreassign_block
,
2362 sizeof (smedia_retreassign_block_t
), 0, 0);
2365 } /* end of switch */
2367 debug(10, "Exiting client server...\n");
2368 my_door_return((char *)&reterror
, sizeof (smedia_reterror_t
), 0, 0);
2372 * This is the service procedure for the door that is associated with
2373 * the (doorfs) filesystem Door that is created at 'smedia_service'.
2377 main_servproc(void *server_data
, char *argp
, size_t arg_size
,
2378 door_desc_t
*dp
, uint_t ndesc
)
2380 smedia_services_t
*req
;
2381 door_cred_t door_credentials
;
2384 smedia_reterror_t reterror
;
2385 smedia_reterror_t retok
;
2388 struct dk_cinfo dkinfo
;
2389 uint_t nexpected_desc
;
2391 debug(10, "Entering main_servproc[%d].\n", pthread_self());
2394 (void) mutex_lock(&svcstate_lock
);
2396 (void) mutex_unlock(&svcstate_lock
);
2398 reterror
.cnum
= SMEDIA_CNUM_ERROR
;
2399 reterror
.errnum
= SMEDIA_FAILURE
;
2402 debug(5, "argp is NULL\n");
2404 close_door_descs(dp
, ndesc
);
2405 my_door_return((char *)&reterror
,
2406 sizeof (smedia_reterror_t
), 0, 0);
2409 req
= (smedia_services_t
*)((void *)argp
);
2411 retok
.cnum
= req
->in
.cnum
;
2414 debug(5, "req = %s arg_size = 0x%x \n",
2415 xlate_cnum(req
->reqopen
.cnum
), arg_size
);
2418 * Our caller may have passed more descriptors than we expected.
2419 * If so, we silently close (and ignore) them.
2421 nexpected_desc
= (req
->in
.cnum
== SMEDIA_CNUM_OPEN_FD
) ? 1 : 0;
2422 if (ndesc
> nexpected_desc
) {
2423 close_door_descs(dp
+ nexpected_desc
, ndesc
- nexpected_desc
);
2426 switch (req
->in
.cnum
) {
2428 debug(5, "main_servproc: unknown command 0x%x\n",
2432 case SMEDIA_CNUM_PING
:
2434 * This service is to indicate that server is up and
2435 * running. It is usually called from another instance of
2436 * server that is started.
2438 reterror
.cnum
= SMEDIA_CNUM_PING
;
2439 reterror
.errnum
= 0;
2440 my_door_return((char *)&reterror
,
2441 sizeof (smedia_reterror_t
), 0, 0);
2445 case SMEDIA_CNUM_OPEN_FD
:
2447 debug(5, "ndesc = %d\n", ndesc
);
2449 my_door_return((char *)&reterror
,
2450 sizeof (smedia_reterror_t
), 0, 0);
2452 debug(5, "Checking file descriptor of target device\n");
2453 if (fstat(didpp
->d_data
.d_desc
.d_descriptor
, &stat
) < 0) {
2454 warning(gettext("main_servproc:fstat failed. "
2455 "errno = %d\n"), errno
);
2456 (void) close(didpp
->d_data
.d_desc
.d_descriptor
);
2457 my_door_return((char *)&reterror
,
2458 sizeof (smedia_reterror_t
), 0, 0);
2460 debug(5, "descriptor = %d st_mode = 0x%lx\n",
2461 didpp
->d_data
.d_desc
.d_descriptor
,
2464 /* Obtain the credentials of the user */
2465 ret_val
= door_cred(&door_credentials
);
2467 warning(gettext("main_servproc:door_cred "
2468 "failed. errno = %d\n"), errno
);
2469 (void) close(didpp
->d_data
.d_desc
.d_descriptor
);
2470 my_door_return((char *)&reterror
,
2471 sizeof (smedia_reterror_t
), 0, 0);
2473 if (ioctl(didpp
->d_data
.d_desc
.d_descriptor
, DKIOCINFO
,
2475 warning(gettext("main_servproc:DKIOCINFO failed. "
2476 "errno = %d\n"), errno
);
2477 (void) close(didpp
->d_data
.d_desc
.d_descriptor
);
2478 my_door_return((char *)&reterror
,
2479 sizeof (smedia_reterror_t
), 0, 0);
2482 ddata
= (door_data_t
*)calloc(1, sizeof (door_data_t
));
2483 if (ddata
== NULL
) {
2484 warning(gettext("main_servproc:calloc failed. "
2485 "errno = %d\n"), errno
);
2486 (void) close(didpp
->d_data
.d_desc
.d_descriptor
);
2487 my_door_return((char *)&reterror
,
2488 sizeof (smedia_reterror_t
), 0, 0);
2490 ddata
->dd_stat
= stat
;
2491 ddata
->dd_cred
= door_credentials
;
2492 ddata
->dd_fd
= didpp
->d_data
.d_desc
.d_descriptor
;
2493 ddata
->dd_buf
= NULL
;
2494 ddata
->dd_buf_len
= 0;
2495 ddata
->dd_buffd
= -1;
2496 ddata
->dd_sector_size
= 0;
2497 ddata
->dd_dkinfo
= dkinfo
;
2498 debug(5, "ddata = 0x%p \n", (void *)ddata
);
2500 /* specify a function that'll customize our door threads */
2501 (void) door_server_create(sm_door_server_create
);
2502 debug(5, "door_server_create called.\n");
2504 (void) mutex_lock(&ddata
->dd_lock
);
2506 /* create Client Door */
2507 ddata
->dd_cdoor_descriptor
=
2508 door_create(client_servproc
,
2509 (void *)ddata
, DOOR_PRIVATE
| DOOR_NO_CANCEL
| DOOR_UNREF
);
2511 if (ddata
->dd_cdoor_descriptor
< 0) {
2512 /* then door_create() failed */
2515 (void) mutex_unlock(&ddata
->dd_lock
);
2517 warning(gettext("main_servproc: door_create of Client "
2518 "Door failed = %d\n"), err
);
2521 /* close target device */
2522 (void) close(didpp
->d_data
.d_desc
.d_descriptor
);
2523 my_door_return((char *)&reterror
,
2524 sizeof (smedia_reterror_t
), 0, 0);
2527 /* create Death Door */
2528 ddata
->dd_ddoor_descriptor
=
2529 door_create(death_servproc
, (void *)ddata
,
2530 DOOR_REFUSE_DESC
| DOOR_NO_CANCEL
);
2531 if (ddata
->dd_ddoor_descriptor
< 0) {
2532 warning(gettext("main_servproc: door_create of Death "
2533 "Door failed = %d\n"), errno
);
2535 (void) door_setparam(ddata
->dd_ddoor_descriptor
,
2536 DOOR_PARAM_DATA_MAX
, 0);
2539 debug(5, "main_servproc[%d]: Client Door = %d, "
2540 "Death Door = %d", pthread_self(),
2541 ddata
->dd_cdoor_descriptor
, ddata
->dd_ddoor_descriptor
);
2543 /* wait until sm_server_thread does door_bind() */
2544 (void) cond_wait(&ddata
->dd_cv_bind
, &ddata
->dd_lock
);
2546 (void) mutex_unlock(&ddata
->dd_lock
);
2548 (void) mutex_lock(&svcstate_lock
);
2550 (void) mutex_unlock(&svcstate_lock
);
2552 if (ddata
->dd_ddoor_descriptor
< 0) {
2553 /* Return only the Client Door to the client. */
2554 ddata
->dd_cdoor
.d_attributes
= (DOOR_DESCRIPTOR
);
2555 my_door_return((char *)&reterror
,
2556 sizeof (smedia_reterror_t
), &ddata
->dd_desc
[0], 1);
2559 * Return the Client Door and Death Door
2562 debug(5, "retok.cnum = 0x%x\n", retok
.cnum
);
2563 ddata
->dd_cdoor
.d_attributes
= (DOOR_DESCRIPTOR
);
2564 ddata
->dd_ddoor
.d_attributes
= (DOOR_DESCRIPTOR
);
2565 my_door_return((char *)&retok
,
2566 sizeof (smedia_reterror_t
), &ddata
->dd_desc
[0], 2);
2571 debug(10, "exiting main_servproc. \n");
2572 my_door_return((char *)&reterror
, sizeof (smedia_reterror_t
), 0, 0);
2577 term_handler(int sig
, siginfo_t
*siginfo
, void *sigctx
)
2579 warning(gettext("thread[%d]: Received signal %d. Ignoring it.\n"),
2586 hup_handler(int sig
, siginfo_t
*siginfo
, void *sigctx
)
2588 warning(gettext("thread[%d]: Received signal %d. Ignoring it.\n"),
2595 sig_handler(int sig
, siginfo_t
*siginfo
, void *sigctx
)
2597 warning(gettext("thread[%d]: Received signal %d. Ignoring it.\n"),
2604 badsig_handler(int sig
, siginfo_t
*siginfo
, void *sigctx
)
2606 fatal(BADSIG_MSG
, pthread_self(), sig
, siginfo
->si_addr
,
2613 init_server(void *argp
)
2616 struct sigaction act
;
2619 debug(10, "init_server running\n");
2621 (void) setlocale(LC_ALL
, "");
2622 #if !defined(TEXT_DOMAIN)
2623 #define TEXT_DOMAIN "SYS_TEST"
2625 (void) textdomain(TEXT_DOMAIN
);
2628 if (geteuid() != 0) fatal("Must be root to execute smserverd\n");
2632 * setup signal handlers.
2635 for (i
= 0; i
< N_BADSIGS
; i
++) {
2636 act
.sa_sigaction
= badsig_handler
;
2637 (void) sigemptyset(&act
.sa_mask
);
2638 act
.sa_flags
= SA_SIGINFO
;
2639 if (sigaction(badsigs
[i
], &act
, NULL
) == -1)
2640 warning(gettext(SIGACT_FAILED
), strsignal(badsigs
[i
]),
2645 * Ignore SIGHUP until all the initialization is done.
2647 act
.sa_handler
= SIG_IGN
;
2648 (void) sigemptyset(&act
.sa_mask
);
2650 if (sigaction(SIGHUP
, &act
, NULL
) == -1)
2651 warning(gettext(SIGACT_FAILED
), strsignal(SIGHUP
),
2654 * Increase file descriptor limit to the most it can possibly
2657 if (getrlimit(RLIMIT_NOFILE
, &rlim
) < 0) {
2658 warning(gettext("getrlimit for fd's failed; %m\n"));
2661 rlim
.rlim_cur
= rlim
.rlim_max
;
2663 if (setrlimit(RLIMIT_NOFILE
, &rlim
) < 0) {
2664 warning(gettext("setrlimit for fd's failed; %m\n"));
2666 (void) enable_extended_FILE_stdio(-1, -1);
2668 server_door
= door_create(main_servproc
, (void *)&server_data
, 0);
2669 if (server_door
== -1) {
2670 debug(1, "main door_create");
2674 (void) unlink(smedia_service
);
2675 fd
= open(smedia_service
, O_RDWR
|O_CREAT
|O_EXCL
, 0644);
2677 debug(5, "could not open %s.\n", smedia_service
);
2681 server_fd
= fattach(server_door
, smedia_service
);
2682 if (server_fd
== -1) {
2683 debug(1, "main fattach");
2686 server_data
.sd_door
= server_door
;
2687 server_data
.sd_fd
= server_fd
;
2690 * setup signal handlers for post-init
2693 act
.sa_sigaction
= hup_handler
;
2694 (void) sigemptyset(&act
.sa_mask
);
2695 act
.sa_flags
= SA_SIGINFO
;
2696 if (sigaction(SIGHUP
, &act
, NULL
) == -1)
2697 warning(gettext(SIGACT_FAILED
), strsignal(SIGHUP
),
2700 act
.sa_sigaction
= term_handler
;
2701 (void) sigemptyset(&act
.sa_mask
);
2702 act
.sa_flags
= SA_SIGINFO
;
2703 if (sigaction(SIGTERM
, &act
, NULL
) == -1)
2704 warning(gettext(SIGACT_FAILED
), strsignal(SIGTERM
),
2707 act
.sa_sigaction
= sig_handler
;
2708 (void) sigemptyset(&act
.sa_mask
);
2709 act
.sa_flags
= SA_SIGINFO
;
2710 if (sigaction(SIGINT
, &act
, NULL
) == -1)
2711 warning(gettext(SIGACT_FAILED
), strsignal(SIGHUP
),
2714 act
.sa_sigaction
= sig_handler
;
2715 (void) sigemptyset(&act
.sa_mask
);
2716 act
.sa_flags
= SA_SIGINFO
;
2717 if (sigaction(SIGQUIT
, &act
, NULL
) == -1)
2718 warning(gettext(SIGACT_FAILED
), strsignal(SIGHUP
),
2720 debug(10, "init_server completed successfully\n");
2722 server_data
.sd_init_state
= INIT_DONE
;
2730 smedia_reqping_t req_ping
;
2731 smedia_retping_t
*ret_ping
;
2734 char rbuf
[sizeof (smedia_services_t
) + sizeof (door_desc_t
)];
2736 doorh
= open(smedia_service
, O_RDONLY
);
2739 if (door_info(doorh
, &dinfo
) < 0) {
2740 (void) close(doorh
);
2743 if (dinfo
.di_attributes
& DOOR_REVOKED
) {
2744 (void) close(doorh
);
2748 req_ping
.cnum
= SMEDIA_CNUM_PING
;
2750 darg
.data_ptr
= (char *)&req_ping
;
2751 darg
.data_size
= sizeof (smedia_reqping_t
);
2752 darg
.desc_ptr
= NULL
;
2755 darg
.rsize
= sizeof (rbuf
);
2757 if (door_call(doorh
, &darg
) < 0) {
2758 (void) close(doorh
);
2761 ret_ping
= (smedia_retping_t
*)((void *)darg
.data_ptr
);
2762 if (ret_ping
->cnum
!= SMEDIA_CNUM_PING
) {
2763 (void) close(doorh
);
2767 (void) close(doorh
);
2775 struct utmpx
*utmpp
;
2778 while ((utmpp
= getutxent()) != NULL
) {
2779 if (utmpp
->ut_type
== RUN_LVL
) {
2781 &utmpp
->ut_line
[strlen("run-level ")]);
2789 closedown(void *arg
)
2792 int current_run_level
;
2796 (void) sleep(SVC_CLOSEDOWN
/2);
2799 * If the server was started at init level 1
2800 * and the current init level is 1 then
2801 * do not exit from server. This server will run
2802 * until it is explicitly stopped by the user.
2804 if (svcstart_level
== 1) {
2805 current_run_level
= get_run_level();
2806 if (current_run_level
== 1)
2809 * who ever started the server at level 1 has
2810 * forgotten to stop the server. we will kill ourself.
2813 "Terminating the server started at init level 1\n");
2817 if (mutex_trylock(&svcstate_lock
) != 0)
2819 if (svcstate
== _IDLE
&& svccount
== 0) {
2823 size
= svc_max_pollfd
;
2824 for (i
= 0; i
< size
&& openfd
< 2; i
++)
2825 if (svc_pollfd
[i
].fd
>= 0)
2829 "Exiting the server from closedown routine.\n");
2835 (void) mutex_unlock(&svcstate_lock
);
2843 warning(gettext("usage: %s [-L loglevel] level of debug information\n"),
2850 main(int argc
, char **argv
)
2853 pthread_attr_t attr
;
2855 (void) setlocale(LC_ALL
, "");
2856 #if !defined(TEXT_DOMAIN)
2857 #define TEXT_DOMAIN "SYS_TEST"
2859 (void) textdomain(TEXT_DOMAIN
);
2861 prog_name
= argv
[0];
2863 (void) sigset(SIGPIPE
, SIG_IGN
);
2865 while ((c
= getopt(argc
, argv
, "L:")) != -1) {
2868 debug_level
= atoi((char *)optarg
);
2877 * If stdin looks like a TLI endpoint, we assume
2878 * that we were started by a port monitor. If
2879 * t_getstate fails with TBADF, this is not a
2882 if (t_getstate(0) != -1 || t_errno
!= TBADF
) {
2884 struct netconfig
*nconf
= NULL
;
2888 openlog(prog_name
, LOG_PID
, LOG_DAEMON
);
2890 debug(1, gettext("server started by port monitor.\n"));
2891 if ((netid
= getenv("NLSPROVIDER")) == NULL
) {
2892 /* started from inetd */
2895 if ((nconf
= getnetconfigent(netid
)) == NULL
)
2896 syslog(LOG_ERR
, gettext(
2897 "cannot get transport info"));
2899 pmclose
= (t_getstate(0) != T_DATAXFER
);
2901 if ((transp
= svc_tli_create(0, nconf
, NULL
, 0, 0)) == NULL
) {
2902 syslog(LOG_ERR
, gettext("cannot create server handle"));
2906 freenetconfigent(nconf
);
2907 if (!svc_reg(transp
, SMSERVERPROG
, SMSERVERVERS
,
2908 smserverprog_1
, 0)) {
2909 syslog(LOG_ERR
, gettext(
2910 "unable to register (SMSERVERPROG, SMSERVERVERS)."));
2913 svcstart_level
= get_run_level();
2915 (void) pthread_attr_init(&attr
);
2916 (void) pthread_attr_setscope(&attr
,
2917 PTHREAD_SCOPE_SYSTEM
);
2918 (void) pthread_attr_setdetachstate(&attr
,
2919 PTHREAD_CREATE_DETACHED
);
2920 if (pthread_create(NULL
, &attr
, closedown
, NULL
) != 0) {
2921 syslog(LOG_ERR
, gettext(
2922 "cannot create closedown thread"));
2925 (void) pthread_attr_destroy(&attr
);
2932 * Started by library or manually.
2935 * Check to see if the server is already running.
2936 * There is no need to log messages in the syslog file
2937 * because server will get launched each time libsmedia
2938 * library calls are made at init 1 level.
2939 * We ensure that only one copy will run.
2941 debug(1, gettext("server started manually.\n"));
2942 if (server_exists()) {
2945 svcstart_level
= get_run_level();
2946 (void) pthread_attr_init(&attr
);
2947 (void) pthread_attr_setscope(&attr
,
2948 PTHREAD_SCOPE_SYSTEM
);
2949 (void) pthread_attr_setdetachstate(&attr
,
2950 PTHREAD_CREATE_DETACHED
);
2951 if (pthread_create(NULL
, &attr
, closedown
, NULL
) != 0) {
2952 syslog(LOG_ERR
, gettext(
2953 "cannot create closedown thread"));
2956 (void) pthread_attr_destroy(&attr
);
2957 (void) init_server(NULL
);
2958 for (;;) (void) pause();
2966 scsi_floppy_write_protect(int32_t fd
, smwp_state_t
*wp
)
2968 debug(5, "Invalid mode\n");
2975 * Generate standard geometry information for SCSI floppy devices. And
2976 * register the geometry with the SCSI driver. This will expand as more
2977 * formats are added.
2982 get_floppy_geom(int32_t fd
, uint32_t capacity
, struct dk_geom
*dkgeom
)
2986 debug(5, "get_floppy_geom: capacity = 0x%x\n", capacity
);
2991 /* Double Density 720K */
2992 dkgeom
->dkg_pcyl
= 80;
2993 dkgeom
->dkg_ncyl
= 80;
2994 dkgeom
->dkg_nhead
= 2;
2995 dkgeom
->dkg_nsect
= 9;
2998 /* High Density 1.25MB */
2999 dkgeom
->dkg_pcyl
= 77;
3000 dkgeom
->dkg_ncyl
= 77;
3001 dkgeom
->dkg_nhead
= 2;
3002 dkgeom
->dkg_nsect
= 9;
3005 /* High Density 1.44MB */
3007 dkgeom
->dkg_pcyl
= 80;
3008 dkgeom
->dkg_ncyl
= 80;
3009 dkgeom
->dkg_nhead
= 2;
3010 dkgeom
->dkg_nsect
= 18;
3013 /* Ultra High density ls-120 120MB */
3014 dkgeom
->dkg_pcyl
= 963;
3015 dkgeom
->dkg_ncyl
= 963;
3016 dkgeom
->dkg_nhead
= 8;
3017 dkgeom
->dkg_nsect
= 32;
3020 debug(5, "unknown capacity type %d\n", capacity
);
3024 debug(5, "get_floppy_geom: setting cyl = %d, nsect = %d, head = %d",
3025 dkgeom
->dkg_pcyl
, dkgeom
->dkg_nhead
, dkgeom
->dkg_nsect
);
3031 scsi_floppy_format(int32_t fd
, uint_t flavor
, uint_t mode
)
3033 struct uscsi_cmd ucmd
;
3036 uint32_t capacity
, blocksize
;
3038 char rq_data
[RQ_LEN
];
3040 struct dk_geom dkgeom
;
3042 debug(5, "scsi_floppy_format:\n");
3044 if ((mode
!= SM_FORMAT_IMMEDIATE
) && (mode
!= SM_FORMAT_BLOCKED
)) {
3051 case SM_FORMAT_QUICK
:
3052 debug(1, "Format not supported\n");
3055 case SM_FORMAT_FORCE
:
3057 case SM_FORMAT_LONG
:
3061 debug(1, "Format option not specified!!\n");
3066 ret_val
= get_media_capacity(fd
, &capacity
, &blocksize
);
3068 if (capacity
>= 0x3C300) {
3070 * It's an LS-120 media, it does not support track
3073 return (scsi_ls120_format(fd
, flavor
, capacity
, blocksize
));
3076 ret_val
= get_floppy_geom(fd
, capacity
, &dkgeom
);
3082 (void) memset(&data
, 0, sizeof (data
));
3083 (void) memset(&ucmd
, 0, sizeof (ucmd
));
3084 (void) memset(&cdb
, 0, sizeof (cdb
));
3086 /* retrieve size discriptor of inserted media */
3087 cdb
[0] = SCMD_FORMAT
; /* format */
3090 * Defect list sent by initiator is a complete list of defects.
3093 cdb
[1] = (FMTDATA
| 0x7);
3095 cdb
[8] = 0xC; /* parameter list length */
3096 data
[3] = 0x8; /* should be always 8 */
3098 data
[4] = (uchar_t
)(capacity
>> 24);
3099 data
[5] = (uchar_t
)(capacity
>> 16);
3100 data
[6] = (uchar_t
)(capacity
>> 8);
3101 data
[7] = (uchar_t
)capacity
;
3103 data
[9] = (uchar_t
)(blocksize
>> 16);
3104 data
[10] = (uchar_t
)(blocksize
>> 8);
3105 data
[11] = (uchar_t
)blocksize
;
3107 ucmd
.uscsi_cdb
= (caddr_t
)&cdb
;
3108 ucmd
.uscsi_cdblen
= CDB_GROUP5
;
3109 ucmd
.uscsi_bufaddr
= (caddr_t
)data
;
3110 ucmd
.uscsi_buflen
= sizeof (data
);
3111 ucmd
.uscsi_timeout
= 0x15;
3112 ucmd
.uscsi_rqlen
= RQ_LEN
;
3113 ucmd
.uscsi_rqbuf
= rq_data
;
3115 debug(5, "cdb: %x %x %x ... %x", cdb
[0], cdb
[1], cdb
[2], cdb
[8]);
3116 debug(5, "data: %x %x %x %x\n", data
[0], data
[1], data
[2], data
[3]);
3117 debug(5, " : %x %x %x %x\n", data
[4], data
[5], data
[6], data
[7]);
3118 debug(5, " : %x %x %x %x\n", data
[8], data
[9], data
[10], data
[11]);
3120 for (i
= 0; i
< dkgeom
.dkg_pcyl
; i
++) { /* number of tracks */
3121 data
[1] = (0xb0 | FOV
);
3124 (void) fflush(stdout
);
3125 ret_val
= do_uscsi_cmd(fd
, &ucmd
, USCSI_WRITE
|USCSI_RQENABLE
);
3126 info("format side 0 returned : 0x%x\n", ret_val
);
3128 if (ret_val
|| ucmd
.uscsi_status
) {
3129 debug(5, "Retrieving media info failed: %d - %d\n",
3130 ret_val
, ucmd
.uscsi_status
);
3131 if ((rq_data
[2] == KEY_DATA_PROTECT
) &&
3132 (rq_data
[12] == 0x30) && (rq_data
[13] == 0)) {
3133 debug(5, "Invalid command for media\n");
3137 if ((rq_data
[2] == KEY_NOT_READY
) &&
3138 (rq_data
[12] == 0x30)) {
3139 debug(5, "Incompatible media.\n");
3145 data
[1] = (0xb0 | FOV
) + 1;
3146 ret_val
= do_uscsi_cmd(fd
, &ucmd
, USCSI_WRITE
|USCSI_RQENABLE
);
3147 info("format side 1 returned : 0x%x\n", ret_val
);
3149 if (ret_val
|| ucmd
.uscsi_status
) {
3150 debug(5, "Retrieving media info failed: %d - %d\n",
3151 ret_val
, ucmd
.uscsi_status
);
3152 if ((rq_data
[2] == KEY_DATA_PROTECT
) &&
3153 (rq_data
[12] == 0x30) && (rq_data
[13] == 0)) {
3154 (void) info("Invalid command for media\n");
3158 if ((rq_data
[2] == KEY_NOT_READY
) &&
3159 (rq_data
[12] == 0x30)) {
3160 debug(5, "Incompatible media.\n");
3168 debug(5, "formatting done!");
3175 scsi_floppy_media_status(int32_t fd
)
3177 struct mode_header_g1 modeh
;
3178 struct uscsi_cmd ucmd
;
3182 char rq_data
[RQ_LEN
];
3184 debug(5, "SCSI MEDIA STATUS CALLED \n");
3186 (void) memset(&modeh
, 0, sizeof (modeh
));
3187 (void) memset(&ucmd
, 0, sizeof (ucmd
));
3188 (void) memset(cdb
, 0, sizeof (cdb
));
3190 * issue 10 byte mode sense (0x5A)
3192 cdb
[0] = SCMD_MODE_SENSE_G1
;
3193 cdb
[7] = sizeof (modeh
) >> 8;
3194 cdb
[8] = sizeof (modeh
) & 0xff;
3196 ucmd
.uscsi_cdb
= (caddr_t
)cdb
;
3197 ucmd
.uscsi_cdblen
= CDB_GROUP1
;
3198 ucmd
.uscsi_bufaddr
= (caddr_t
)&modeh
;
3199 ucmd
.uscsi_buflen
= sizeof (modeh
);
3200 ucmd
.uscsi_timeout
= 120; /* If 0, HBA hangs forever */
3201 ucmd
.uscsi_rqlen
= RQ_LEN
;
3202 ucmd
.uscsi_rqbuf
= rq_data
;
3203 ret_val
= do_uscsi_cmd(fd
, &ucmd
, USCSI_READ
|USCSI_RQENABLE
);
3204 if (ret_val
|| ucmd
.uscsi_status
) {
3206 * UFI devices may not respond to the 0 mode page.
3207 * retry with the error recovery page(0x01)
3209 if (ucmd
.uscsi_status
& STATUS_CHECK
) {
3210 cdb
[2] = 0x1; /* page code */
3211 ret_val
= do_uscsi_cmd(fd
, &ucmd
,
3212 USCSI_READ
|USCSI_RQENABLE
);
3214 if (ret_val
|| ucmd
.uscsi_status
) {
3215 debug(1, "Modesense failed: %d - %d\n",
3216 ret_val
, ucmd
.uscsi_status
);
3220 debug(5, "Modesense succeeded: 0x%x\n", modeh
.device_specific
);
3222 if (modeh
.device_specific
& 0x80) {
3223 cur_status
= SM_WRITE_PROTECT_NOPASSWD
;
3225 cur_status
= SM_WRITE_PROTECT_DISABLE
;
3227 return (cur_status
);