10Sstevel@tonic-gate /*
20Sstevel@tonic-gate * CDDL HEADER START
30Sstevel@tonic-gate *
40Sstevel@tonic-gate * The contents of this file are subject to the terms of the
51914Scasper * Common Development and Distribution License (the "License").
61914Scasper * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate *
80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate * See the License for the specific language governing permissions
110Sstevel@tonic-gate * and limitations under the License.
120Sstevel@tonic-gate *
130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate *
190Sstevel@tonic-gate * CDDL HEADER END
200Sstevel@tonic-gate */
216247Sraf
220Sstevel@tonic-gate /*
236247Sraf * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
240Sstevel@tonic-gate * Use is subject to license terms.
250Sstevel@tonic-gate */
260Sstevel@tonic-gate
270Sstevel@tonic-gate #include <stdio.h>
281914Scasper #include <stdio_ext.h>
290Sstevel@tonic-gate #include <errno.h>
300Sstevel@tonic-gate #include <ctype.h>
310Sstevel@tonic-gate #include <syslog.h>
320Sstevel@tonic-gate #include <signal.h>
330Sstevel@tonic-gate #include <limits.h>
340Sstevel@tonic-gate #include <unistd.h>
350Sstevel@tonic-gate #include <sys/types.h>
360Sstevel@tonic-gate #include <sys/mman.h>
370Sstevel@tonic-gate #include <stdlib.h>
380Sstevel@tonic-gate #include <sys/stat.h>
390Sstevel@tonic-gate #include <sys/mkdev.h>
400Sstevel@tonic-gate #include <fcntl.h>
410Sstevel@tonic-gate #include <sys/scsi/scsi.h>
420Sstevel@tonic-gate #include <sys/scsi/generic/commands.h>
430Sstevel@tonic-gate #include <string.h>
440Sstevel@tonic-gate #include <door.h>
450Sstevel@tonic-gate #include <pwd.h>
460Sstevel@tonic-gate #include <thread.h>
470Sstevel@tonic-gate #include <synch.h>
480Sstevel@tonic-gate #include <pthread.h>
490Sstevel@tonic-gate #include <locale.h>
500Sstevel@tonic-gate #include <sys/resource.h>
510Sstevel@tonic-gate #include <netconfig.h>
520Sstevel@tonic-gate #include <sys/smedia.h>
530Sstevel@tonic-gate #include "smserver.h"
540Sstevel@tonic-gate #include <rpc/rpc.h>
550Sstevel@tonic-gate #include "smed.h"
560Sstevel@tonic-gate #include "myaudit.h"
570Sstevel@tonic-gate #include <bsm/libbsm.h>
580Sstevel@tonic-gate #include <bsm/audit_uevents.h>
590Sstevel@tonic-gate #include <utmpx.h>
600Sstevel@tonic-gate
610Sstevel@tonic-gate
620Sstevel@tonic-gate /*
630Sstevel@tonic-gate * The comments below would help in understanding what is being attempted
640Sstevel@tonic-gate * in the server.
650Sstevel@tonic-gate *
660Sstevel@tonic-gate * The server can be started either by inetd or by the client directly.
670Sstevel@tonic-gate * Normally the server is started by inetd when the client invokes the
680Sstevel@tonic-gate * appropriate libsmedia library call(smedia_get_handle).
690Sstevel@tonic-gate * However since the inetd runs only at init level 2 and above a mechanism
700Sstevel@tonic-gate * is provided for the server to be started if an attempt is made to use
710Sstevel@tonic-gate * the libsmedia calls in maintenence mode(init level 1).
720Sstevel@tonic-gate * The main() routine determines how the server was invoked and takes
730Sstevel@tonic-gate * the necessary action.
740Sstevel@tonic-gate * When started by inetd it registers itself as an RPC program.
750Sstevel@tonic-gate * The server also implements a mechanism by which it removes itself
760Sstevel@tonic-gate * after a period of inactivity. The period of inactivity is specified
770Sstevel@tonic-gate * by SVC_CLOSEDOWN which is set at 180 secs.
780Sstevel@tonic-gate * The logic of detecting inactivity is as follows:
790Sstevel@tonic-gate *
800Sstevel@tonic-gate * Two variables svcstate and svccount are used to determine if the server
810Sstevel@tonic-gate * is IDLE.
820Sstevel@tonic-gate * The svcstate is set to 1(_SERVED) when ever the server does any operation
830Sstevel@tonic-gate * on behalf of the client.
840Sstevel@tonic-gate * The svccount indicates the number of active clients who have established
850Sstevel@tonic-gate * a connection with the server. A connection is established when the
860Sstevel@tonic-gate * libsmedia call smedia_get_handle() succeeds.
870Sstevel@tonic-gate * The connection is broken when the client calls smedia_free_handle() OR
880Sstevel@tonic-gate * exits.
890Sstevel@tonic-gate * A thread called closedown is started up when server is started.
900Sstevel@tonic-gate * This thread runs periodically and monitors both svcstate and svccount.
910Sstevel@tonic-gate * If svcstate is IDLE and svccount is 0 then server exits.
920Sstevel@tonic-gate * The svcstate is set to IDLE by the closedown thread. It is set to _SERVED
930Sstevel@tonic-gate * by server. It is possible for the state to be _SERVED and the svccount
940Sstevel@tonic-gate * to be 0. The server could be kept busy by client calls of smedia_get_handle
950Sstevel@tonic-gate * that do not succeed. This is the reason for using both svcstate and svccount
960Sstevel@tonic-gate * to determine the true server state.
970Sstevel@tonic-gate *
980Sstevel@tonic-gate * The communication between client and server is thru door calls.
990Sstevel@tonic-gate * Below are the door descriptors available to communicate to the server.
1000Sstevel@tonic-gate *
1010Sstevel@tonic-gate * main_door_descriptor:
1020Sstevel@tonic-gate * ---------------------
1030Sstevel@tonic-gate * This is a predefined descriptor used by client to establish a
1040Sstevel@tonic-gate * connection with the server. This descriptor is available to the client
1050Sstevel@tonic-gate * as /var/adm/smedia_svc
1061137Sarutz * The client uses the main_door_descriptor to obtain a dedicated
1070Sstevel@tonic-gate * client_door_descriptor for itself. The smedia_get_handle call communicates
1080Sstevel@tonic-gate * to the server using the main_door_descriptor and obtains the
1090Sstevel@tonic-gate * client_door_descriptor which is stored in the handle structure.
1100Sstevel@tonic-gate * All other libsmedia calls use the client_door_descriptor to communicate
1110Sstevel@tonic-gate * with the server.
1120Sstevel@tonic-gate *
1130Sstevel@tonic-gate * client_door_descriptor:
1140Sstevel@tonic-gate * -----------------------
1150Sstevel@tonic-gate * This is the door descriptor that is used by the clients to
1160Sstevel@tonic-gate * request server to perform the necessary tasks. This door descriptor is
1170Sstevel@tonic-gate * available only to the client for whom it was created.
1180Sstevel@tonic-gate *
1190Sstevel@tonic-gate * death_door_descriptor:
1200Sstevel@tonic-gate * ----------------------
1211137Sarutz * The sole function of this descriptor HAD been to inform the server of
1221137Sarutz * the untimely death of the client. This descriptor is no longer used, though
1231137Sarutz * it is still created, as libsmedia expects to use it. This descriptor's
1241137Sarutz * service procedure had used pthread cancellation(5) to terminate the thread of
1251137Sarutz * the associated client_door_descriptor. The client_door_descriptor now
1261137Sarutz * handles the scenarios where a door_call/client are aborted/terminated.
1270Sstevel@tonic-gate *
1281137Sarutz * main_servproc()
1290Sstevel@tonic-gate * -------------
1300Sstevel@tonic-gate * This is the routine associated with the main_door_descriptor.
1310Sstevel@tonic-gate * This is the routine that handles the smedia_get_handle() call
1320Sstevel@tonic-gate * of the client. If the door call to this routine succeeds it creates a
1330Sstevel@tonic-gate * client_door_descriptor that is used by the client in subsequent library
1340Sstevel@tonic-gate * calls.
1350Sstevel@tonic-gate * This client_door_descriptor is passed to the client thru the door_return
1360Sstevel@tonic-gate * call. This client_door_descriptor cannot be used by any other process other
1370Sstevel@tonic-gate * than the client process that obtained it.
1380Sstevel@tonic-gate * In addition to the client_door_descriptor a death_door_descriptor is also
1390Sstevel@tonic-gate * created by the main server and passed on to the client. The client does not
1401137Sarutz * use the death_door_descriptor.
1410Sstevel@tonic-gate *
1421137Sarutz * client_servproc()
1430Sstevel@tonic-gate * ---------------
1440Sstevel@tonic-gate * This is the routine that handles the libsmedia calls of the
1450Sstevel@tonic-gate * client. In the current implementation the server takes control of the
1460Sstevel@tonic-gate * number of threads that handle the door calls. This is done by creating the
1470Sstevel@tonic-gate * door descriptor as DOOR_PRIVATE.
1480Sstevel@tonic-gate * The server runs only one thread per handle. This makes the implementation
1490Sstevel@tonic-gate * simple as we do not have to use mutex to make the code MT safe.
1501137Sarutz * The server thread has a data structure door_data_t associated with it.
1510Sstevel@tonic-gate *
1520Sstevel@tonic-gate * door_data_t
1530Sstevel@tonic-gate * -----------
1541137Sarutz * This is the data structure that is created by the main_servproc when it
1550Sstevel@tonic-gate * creates the client_door_descriptor. The door mechanism has a way to associate
1560Sstevel@tonic-gate * a cookie with the door descriptor. door_data_t is the cookie for the
1571137Sarutz * client_door_descriptor. This cookie is passed to the server function that
1581137Sarutz * handles the client_door_descriptor calls. In our case it is the
1591137Sarutz * client_servproc routine.
1600Sstevel@tonic-gate * The key elements of the door_data_t are the following:
1610Sstevel@tonic-gate *
1620Sstevel@tonic-gate * dd_fd file descriptor for the device.
1630Sstevel@tonic-gate * dd_buf The shared memory buffer between client-server.
1640Sstevel@tonic-gate * dd_thread The thread that handles the door_calls.
1650Sstevel@tonic-gate *
1660Sstevel@tonic-gate * signal handling:
1670Sstevel@tonic-gate * ----------------
1680Sstevel@tonic-gate * The main purpose of trapping the signals is to exit gracefully
1690Sstevel@tonic-gate * from the server after recording the appropriate message in the syslog.
1700Sstevel@tonic-gate * This will help the administrator to determine the cause of failure of the
1710Sstevel@tonic-gate * server by examining the log file.
1720Sstevel@tonic-gate *
1730Sstevel@tonic-gate * cleanup()
1740Sstevel@tonic-gate * ---------
1750Sstevel@tonic-gate * This routine frees up all the resources allocated for the client.
1761137Sarutz * Resources include the file descriptor, shared memory, threads.
1770Sstevel@tonic-gate *
1780Sstevel@tonic-gate * shared memory
1790Sstevel@tonic-gate * -------------
1800Sstevel@tonic-gate * In order to reduce the overheads of moving large amounts of data
1810Sstevel@tonic-gate * during raw read/write operations, the server uses the mmapped data of
1820Sstevel@tonic-gate * client. The smedia_raw_read, smedia_raw_write library calls mmap the
1830Sstevel@tonic-gate * memory and pass on the file descriptor that maps the memory to the server.
1840Sstevel@tonic-gate * The server subsequently uses this mmapped memory during the IO.
1850Sstevel@tonic-gate * If the mmapped memory changes in size, the server is informed and it
1860Sstevel@tonic-gate * remaps the memory to the changed size.
1870Sstevel@tonic-gate */
1880Sstevel@tonic-gate #ifdef DEBUG
1890Sstevel@tonic-gate #define DEFAULT_VERBOSE 1
1900Sstevel@tonic-gate #define DEFAULT_DEBUG 1
1910Sstevel@tonic-gate #else
1920Sstevel@tonic-gate #define DEFAULT_VERBOSE 0
1930Sstevel@tonic-gate #define DEFAULT_DEBUG 0
1940Sstevel@tonic-gate #endif
1950Sstevel@tonic-gate
1960Sstevel@tonic-gate #define N_BADSIGS (sizeof (badsigs)/sizeof (badsigs[0]))
1970Sstevel@tonic-gate #define MD_LEN 30
1980Sstevel@tonic-gate #define MAXUGNAME 10
1990Sstevel@tonic-gate #define SVC_CLOSEDOWN 180
2000Sstevel@tonic-gate
2010Sstevel@tonic-gate /*
2020Sstevel@tonic-gate * We will NOT be permitting the following USCI cmd options.
2030Sstevel@tonic-gate *
2040Sstevel@tonic-gate * RESET of target
2050Sstevel@tonic-gate * RESET of Bus.
2060Sstevel@tonic-gate * Tagged commands to device
2070Sstevel@tonic-gate * Explicitly setting SYNC/ASYNC mode of operations.
2080Sstevel@tonic-gate * POLLED MODE of operation.
2090Sstevel@tonic-gate * Explicitly setting NO DISCONNECT features.
2100Sstevel@tonic-gate * use of RESERVED flags.
2110Sstevel@tonic-gate */
2120Sstevel@tonic-gate #define FORBIDDEN_FLAGS (USCSI_RESET | USCSI_RESET_ALL | USCSI_RENEGOT \
2130Sstevel@tonic-gate | USCSI_ASYNC | USCSI_SYNC | USCSI_NOINTR | \
2140Sstevel@tonic-gate USCSI_NOTAG | USCSI_NOPARITY | USCSI_NODISCON \
2150Sstevel@tonic-gate | USCSI_RESERVED)
2160Sstevel@tonic-gate
2170Sstevel@tonic-gate /* States a server can be in wrt request */
2180Sstevel@tonic-gate
2190Sstevel@tonic-gate #define _IDLE 0
2200Sstevel@tonic-gate #define _SERVED 1
2210Sstevel@tonic-gate
2220Sstevel@tonic-gate static char *prog_name;
2230Sstevel@tonic-gate static int svcstate = _IDLE; /* Set when a request is serviced */
2240Sstevel@tonic-gate static int svccount = 0; /* Number of requests being serviced */
2250Sstevel@tonic-gate static int svcstart_level = 0; /* init level when server was started */
2260Sstevel@tonic-gate static mutex_t svcstate_lock; /* lock for svcstate, svccount */
2270Sstevel@tonic-gate
2280Sstevel@tonic-gate extern void smserverprog_1(struct svc_req *, SVCXPRT *);
2290Sstevel@tonic-gate
2300Sstevel@tonic-gate /*
2310Sstevel@tonic-gate * Log messages
2320Sstevel@tonic-gate */
2330Sstevel@tonic-gate #define SIGACT_FAILED "Failed to install signal handler for %s: %s"
2340Sstevel@tonic-gate #define BADSIG_MSG "Thread %d Caught signal %d addr=%p trapno=%d pc=%p"
2350Sstevel@tonic-gate
2360Sstevel@tonic-gate static int badsigs[] = {SIGSEGV, SIGBUS, SIGFPE, SIGILL};
2370Sstevel@tonic-gate
2380Sstevel@tonic-gate /* global variables */
2390Sstevel@tonic-gate int verbose = DEFAULT_VERBOSE;
2400Sstevel@tonic-gate int debug_level = DEFAULT_DEBUG;
2410Sstevel@tonic-gate char *smediad_devdir = DEFAULT_SMEDIAD_DEVDIR;
2420Sstevel@tonic-gate
2430Sstevel@tonic-gate thread_key_t door_key;
2440Sstevel@tonic-gate
2450Sstevel@tonic-gate server_data_t server_data;
2460Sstevel@tonic-gate
2470Sstevel@tonic-gate static int server_door, server_fd;
2480Sstevel@tonic-gate
2490Sstevel@tonic-gate static int32_t do_uscsi_cmd(int32_t file, struct uscsi_cmd *uscsi_cmd,
2500Sstevel@tonic-gate int32_t flag);
2511137Sarutz static void client_servproc(void *cookie, char *argp, size_t arg_size,
2520Sstevel@tonic-gate door_desc_t *dp, uint_t ndesc);
2530Sstevel@tonic-gate static void cleanup(door_data_t *);
2540Sstevel@tonic-gate static void *init_server(void *);
2550Sstevel@tonic-gate static int32_t scsi_reassign_block(int32_t fd, diskaddr_t);
2560Sstevel@tonic-gate static int32_t get_mode_page(int32_t fd, uchar_t pc, uchar_t page_code,
2571137Sarutz uchar_t *md_data, uchar_t data_len);
2580Sstevel@tonic-gate static int32_t get_device_type(char *v_name);
2590Sstevel@tonic-gate static int32_t get_device_type_scsi(int32_t fd, struct scsi_inquiry *inq);
2600Sstevel@tonic-gate
2610Sstevel@tonic-gate static int32_t scsi_format(int32_t fd, uint_t flavor, uint_t mode);
2620Sstevel@tonic-gate static int32_t scsi_media_status(int32_t fd);
2630Sstevel@tonic-gate static int32_t scsi_write_protect(int32_t fd, smwp_state_t *wp);
2640Sstevel@tonic-gate static int32_t scsi_floppy_media_status(int32_t fd);
2650Sstevel@tonic-gate static int32_t scsi_floppy_write_protect(int32_t fd, smwp_state_t *wp);
2660Sstevel@tonic-gate static int32_t scsi_floppy_format(int32_t, uint_t, uint_t);
2670Sstevel@tonic-gate static int32_t get_floppy_geom(int32_t fd, uint32_t capacity,
2680Sstevel@tonic-gate struct dk_geom *dkgeom);
2690Sstevel@tonic-gate static int32_t get_media_capacity(int32_t fd, uint32_t *capacity,
2700Sstevel@tonic-gate uint32_t *blocksize);
2710Sstevel@tonic-gate
2720Sstevel@tonic-gate static int32_t scsi_ls120_format(uint_t fd, uint_t flavor, uint32_t capacity,
2730Sstevel@tonic-gate uint32_t blocksize);
2740Sstevel@tonic-gate
2751137Sarutz static void *sm_server_thread(void *arg);
2761137Sarutz static void sm_door_server_create(door_info_t *dip);
2770Sstevel@tonic-gate static void term_handler(int sig, siginfo_t *siginfo, void *sigctx);
2780Sstevel@tonic-gate static void hup_handler(int sig, siginfo_t *siginfo, void *sigctx);
2790Sstevel@tonic-gate static void sig_handler(int sig, siginfo_t *siginfo, void *sigctx);
2800Sstevel@tonic-gate static void badsig_handler(int sig, siginfo_t *siginfo, void *sigctx);
2810Sstevel@tonic-gate static void server_badsig_handler(int sig, siginfo_t *siginfo, void *sigctx);
2820Sstevel@tonic-gate static char *xlate_state(int32_t);
2830Sstevel@tonic-gate static uint32_t get_sector_size(int fd);
2840Sstevel@tonic-gate static int32_t raw_read(door_data_t *door_dp, smedia_services_t *req);
2850Sstevel@tonic-gate static int32_t raw_write(door_data_t *door_dp, smedia_services_t *req);
2860Sstevel@tonic-gate static int32_t reassign_block(door_data_t *door_dp, smedia_services_t *req);
2870Sstevel@tonic-gate static int32_t set_protection_status(door_data_t *door_dp,
2880Sstevel@tonic-gate smedia_services_t *req);
2890Sstevel@tonic-gate static int32_t set_shfd(door_data_t *door_dp, int32_t fd,
2900Sstevel@tonic-gate smedia_services_t *req);
2910Sstevel@tonic-gate
2920Sstevel@tonic-gate static void door_ret_err(smedia_reterror_t *reterror, int32_t err);
2930Sstevel@tonic-gate static void my_door_return(char *data_ptr, size_t data_size,
2940Sstevel@tonic-gate door_desc_t *desc_ptr, uint_t num_desc);
2950Sstevel@tonic-gate static int32_t invalid_uscsi_operation(door_data_t *, struct uscsi_cmd *);
2960Sstevel@tonic-gate
2970Sstevel@tonic-gate #define W_E_MASK 0x80
2980Sstevel@tonic-gate
2990Sstevel@tonic-gate static smserver_info server_info;
3000Sstevel@tonic-gate
3010Sstevel@tonic-gate static int32_t
invalid_uscsi_operation(door_data_t * door_dp,struct uscsi_cmd * ucmd)3020Sstevel@tonic-gate invalid_uscsi_operation(door_data_t *door_dp, struct uscsi_cmd *ucmd)
3030Sstevel@tonic-gate {
3040Sstevel@tonic-gate
3050Sstevel@tonic-gate if (door_dp->dd_dkinfo.dki_ctype != DKC_CDROM) {
3060Sstevel@tonic-gate debug(5,
3070Sstevel@tonic-gate "Invalid device type(0x%x) found for uscsi cmd.\n",
3080Sstevel@tonic-gate door_dp->dd_dkinfo.dki_ctype);
3090Sstevel@tonic-gate errno = EINVAL;
3100Sstevel@tonic-gate return (EINVAL);
3110Sstevel@tonic-gate }
3120Sstevel@tonic-gate if (ucmd->uscsi_flags & FORBIDDEN_FLAGS) {
3130Sstevel@tonic-gate debug(5,
3140Sstevel@tonic-gate "Invalid flags(0x%x) set in uscsi cmd. cdb[0]=0x%x\n",
3150Sstevel@tonic-gate ucmd->uscsi_flags, ucmd->uscsi_cdb[0]);
3160Sstevel@tonic-gate errno = EINVAL;
3170Sstevel@tonic-gate return (EINVAL);
3180Sstevel@tonic-gate }
3190Sstevel@tonic-gate if (ucmd->uscsi_cdb[0] == SCMD_COPY ||
3200Sstevel@tonic-gate ucmd->uscsi_cdb[0] == SCMD_COPY_VERIFY ||
3210Sstevel@tonic-gate ucmd->uscsi_cdb[0] == SCMD_COMPARE ||
3220Sstevel@tonic-gate ucmd->uscsi_cdb[0] == SCMD_WRITE_BUFFER) {
3230Sstevel@tonic-gate debug(5,
3240Sstevel@tonic-gate "Invalid command(0x%x) found in cdb.\n",
3250Sstevel@tonic-gate ucmd->uscsi_cdb[0]);
3260Sstevel@tonic-gate errno = EINVAL;
3270Sstevel@tonic-gate return (EINVAL);
3280Sstevel@tonic-gate }
3290Sstevel@tonic-gate return (0);
3300Sstevel@tonic-gate }
3310Sstevel@tonic-gate
3320Sstevel@tonic-gate static uint32_t
get_sector_size(int fd)3330Sstevel@tonic-gate get_sector_size(int fd)
3340Sstevel@tonic-gate {
3350Sstevel@tonic-gate uint32_t sector_size;
3360Sstevel@tonic-gate struct uscsi_cmd ucmd;
3370Sstevel@tonic-gate union scsi_cdb cdb;
3380Sstevel@tonic-gate int32_t ret_val;
3390Sstevel@tonic-gate uint32_t rc_data[2];
3400Sstevel@tonic-gate char rq_data[RQ_LEN];
3410Sstevel@tonic-gate
3420Sstevel@tonic-gate cdb.scc_cmd = SCMD_READ_CAPACITY;
3430Sstevel@tonic-gate ucmd.uscsi_cdb = (caddr_t)&cdb;
3440Sstevel@tonic-gate ucmd.uscsi_cdblen = CDB_GROUP1;
3450Sstevel@tonic-gate ucmd.uscsi_bufaddr = (caddr_t)&rc_data;
3460Sstevel@tonic-gate ucmd.uscsi_buflen = sizeof (rc_data);
3470Sstevel@tonic-gate ucmd.uscsi_timeout = 120; /* If 0, HBA hangs forever */
3480Sstevel@tonic-gate ucmd.uscsi_rqlen = RQ_LEN;
3490Sstevel@tonic-gate ucmd.uscsi_rqbuf = rq_data;
3500Sstevel@tonic-gate
3510Sstevel@tonic-gate ret_val = do_uscsi_cmd(fd,
3520Sstevel@tonic-gate &ucmd, USCSI_READ|USCSI_RQENABLE);
3530Sstevel@tonic-gate if (ret_val || ucmd.uscsi_status) {
3540Sstevel@tonic-gate debug(5, "Read capacity : %d - %d errno = %d\n",
3550Sstevel@tonic-gate ret_val, ucmd.uscsi_status, errno);
3560Sstevel@tonic-gate sector_size = 512;
3570Sstevel@tonic-gate } else {
3580Sstevel@tonic-gate sector_size = ntohl(rc_data[1]);
3590Sstevel@tonic-gate }
3600Sstevel@tonic-gate debug(5, "sector size = 0x%x(%d)\n",
3610Sstevel@tonic-gate sector_size, sector_size);
3620Sstevel@tonic-gate return (sector_size);
3630Sstevel@tonic-gate }
3640Sstevel@tonic-gate
3650Sstevel@tonic-gate static char *
xlate_state(int32_t state)3660Sstevel@tonic-gate xlate_state(int32_t state)
3670Sstevel@tonic-gate {
3680Sstevel@tonic-gate switch (state) {
3690Sstevel@tonic-gate
3700Sstevel@tonic-gate case SM_WRITE_PROTECT_DISABLE:
3710Sstevel@tonic-gate return ("PROTECTION_DISABLED");
3720Sstevel@tonic-gate case SM_WRITE_PROTECT_PASSWD:
3730Sstevel@tonic-gate return ("WRITE_PROTECT_PASSWD");
3740Sstevel@tonic-gate case SM_WRITE_PROTECT_NOPASSWD:
3750Sstevel@tonic-gate return ("WRITE_PROTECT_NOPASSWD");
3760Sstevel@tonic-gate case SM_READ_WRITE_PROTECT:
3770Sstevel@tonic-gate return ("READ_WRITE_PROTECT");
3780Sstevel@tonic-gate case SM_TEMP_UNLOCK_MODE:
3790Sstevel@tonic-gate return ("PROTECTION DISABLED");
3800Sstevel@tonic-gate default:
3810Sstevel@tonic-gate return ("UNKNOWN_STATE");
3820Sstevel@tonic-gate }
3830Sstevel@tonic-gate }
3840Sstevel@tonic-gate
3850Sstevel@tonic-gate static char *
xlate_cnum(smedia_callnumber_t cnum)3860Sstevel@tonic-gate xlate_cnum(smedia_callnumber_t cnum)
3870Sstevel@tonic-gate {
3880Sstevel@tonic-gate switch (cnum) {
3890Sstevel@tonic-gate
3900Sstevel@tonic-gate case SMEDIA_CNUM_OPEN_FD:
3910Sstevel@tonic-gate return ("SMEDIA_CNUM_OPEN_FD");
3920Sstevel@tonic-gate case SMEDIA_CNUM_GET_DEVICE_INFO:
3930Sstevel@tonic-gate return ("SMEDIA_CNUM_GET_DEVICE_INFO");
3940Sstevel@tonic-gate case SMEDIA_CNUM_GET_MEDIUM_PROPERTY:
3950Sstevel@tonic-gate return ("SMEDIA_CNUM_GET_MEDIUM_PROPERTY");
3960Sstevel@tonic-gate case SMEDIA_CNUM_GET_PROTECTION_STATUS:
3970Sstevel@tonic-gate return ("SMEDIA_CNUM_GET_PROTECTION_STATUS");
3980Sstevel@tonic-gate case SMEDIA_CNUM_SET_PROTECTION_STATUS:
3990Sstevel@tonic-gate return ("SMEDIA_CNUM_SET_PROTECTION_STATUS");
4000Sstevel@tonic-gate case SMEDIA_CNUM_RAW_READ:
4010Sstevel@tonic-gate return ("SMEDIA_CNUM_RAW_READ");
4020Sstevel@tonic-gate case SMEDIA_CNUM_RAW_WRITE:
4030Sstevel@tonic-gate return (" SMEDIA_CNUM_RAW_WRITE");
4040Sstevel@tonic-gate case SMEDIA_CNUM_FORMAT:
4050Sstevel@tonic-gate return ("SMEDIA_CNUM_FORMAT");
4060Sstevel@tonic-gate case SMEDIA_CNUM_CHECK_FORMAT_STATUS:
4070Sstevel@tonic-gate return ("SMEDIA_CNUM_CHECK_FORMAT_STATUS");
4080Sstevel@tonic-gate case SMEDIA_CNUM_EJECT:
4090Sstevel@tonic-gate return ("SMEDIA_CNUM_EJECT");
4100Sstevel@tonic-gate case SMEDIA_CNUM_REASSIGN_BLOCK:
4110Sstevel@tonic-gate return ("SMEDIA_CNUM_REASSIGN_BLOCK");
4120Sstevel@tonic-gate case SMEDIA_CNUM_SET_SHFD:
4130Sstevel@tonic-gate return ("SMEDIA_CNUM_SET_SHFD");
4140Sstevel@tonic-gate case SMEDIA_CNUM_PING:
4150Sstevel@tonic-gate return ("SMEDIA_CNUM_PING");
4160Sstevel@tonic-gate case SMEDIA_CNUM_USCSI_CMD:
4170Sstevel@tonic-gate return ("SMEDIA_CNUM_USCSI_CMD");
4180Sstevel@tonic-gate default:
4190Sstevel@tonic-gate return ("UNKNOWN_CNUM");
4200Sstevel@tonic-gate }
4210Sstevel@tonic-gate }
4220Sstevel@tonic-gate
4230Sstevel@tonic-gate /*ARGSUSED*/
4240Sstevel@tonic-gate smserver_info *
smserverproc_get_serverinfo_1(void * argp,CLIENT * clnt)4250Sstevel@tonic-gate smserverproc_get_serverinfo_1(void *argp, CLIENT *clnt)
4260Sstevel@tonic-gate {
4270Sstevel@tonic-gate (void) mutex_lock(&svcstate_lock);
4280Sstevel@tonic-gate svcstate = _SERVED;
4290Sstevel@tonic-gate (void) mutex_unlock(&svcstate_lock);
4300Sstevel@tonic-gate server_info.vernum = SMSERVERVERS;
4310Sstevel@tonic-gate server_info.status = 0;
4320Sstevel@tonic-gate (void) mutex_lock(&server_data.sd_init_lock);
4330Sstevel@tonic-gate if (server_data.sd_init_state == INIT_NOT_DONE) {
4340Sstevel@tonic-gate server_data.sd_init_state = INIT_IN_PROGRESS;
4350Sstevel@tonic-gate debug(5, "Initialising server\n");
4360Sstevel@tonic-gate (void) init_server(NULL);
4370Sstevel@tonic-gate }
4380Sstevel@tonic-gate if (server_data.sd_init_state != INIT_DONE) {
4391137Sarutz debug(1, "init_server did not do the job. "
4401137Sarutz "init_state=%d\n", server_data.sd_init_state);
4410Sstevel@tonic-gate server_data.sd_init_state = INIT_NOT_DONE;
4420Sstevel@tonic-gate (void) mutex_unlock(&server_data.sd_init_lock);
4430Sstevel@tonic-gate server_info.status = -1;
4440Sstevel@tonic-gate return (&server_info);
4450Sstevel@tonic-gate }
4460Sstevel@tonic-gate (void) mutex_unlock(&server_data.sd_init_lock);
4470Sstevel@tonic-gate
4480Sstevel@tonic-gate debug(5, "smserverproc thread %d running....\n", pthread_self());
4490Sstevel@tonic-gate return (&server_info);
4500Sstevel@tonic-gate }
4510Sstevel@tonic-gate
4520Sstevel@tonic-gate /*ARGSUSED*/
4530Sstevel@tonic-gate static void
server_badsig_handler(int sig,siginfo_t * siginfo,void * sigctx)4540Sstevel@tonic-gate server_badsig_handler(int sig, siginfo_t *siginfo, void *sigctx)
4550Sstevel@tonic-gate {
4560Sstevel@tonic-gate
4570Sstevel@tonic-gate fatal(gettext(BADSIG_MSG), pthread_self(), sig, siginfo->si_addr,
4580Sstevel@tonic-gate siginfo->si_trapno,
4590Sstevel@tonic-gate siginfo->si_pc);
4600Sstevel@tonic-gate }
4610Sstevel@tonic-gate
4620Sstevel@tonic-gate static int32_t
do_uscsi_cmd(int32_t file,struct uscsi_cmd * uscsi_cmd,int32_t flag)4630Sstevel@tonic-gate do_uscsi_cmd(int32_t file, struct uscsi_cmd *uscsi_cmd, int32_t flag)
4640Sstevel@tonic-gate {
4650Sstevel@tonic-gate int32_t ret_val;
4660Sstevel@tonic-gate
4670Sstevel@tonic-gate /*
4680Sstevel@tonic-gate * Set function flags for driver.
4690Sstevel@tonic-gate */
4700Sstevel@tonic-gate uscsi_cmd->uscsi_flags = USCSI_ISOLATE;
4710Sstevel@tonic-gate
4720Sstevel@tonic-gate #ifdef DEBUG
4730Sstevel@tonic-gate uscsi_cmd->uscsi_flags |= USCSI_DIAGNOSE;
4740Sstevel@tonic-gate #else
4750Sstevel@tonic-gate uscsi_cmd->uscsi_flags |= USCSI_SILENT;
4760Sstevel@tonic-gate #endif /* DEBUG */
4770Sstevel@tonic-gate
4780Sstevel@tonic-gate uscsi_cmd->uscsi_flags |= flag;
4790Sstevel@tonic-gate
4800Sstevel@tonic-gate errno = 0;
4810Sstevel@tonic-gate ret_val = ioctl(file, USCSICMD, uscsi_cmd);
4820Sstevel@tonic-gate if (ret_val == 0 && uscsi_cmd->uscsi_status == 0) {
4830Sstevel@tonic-gate return (ret_val);
4840Sstevel@tonic-gate }
4850Sstevel@tonic-gate if (!errno)
4860Sstevel@tonic-gate errno = EIO;
4870Sstevel@tonic-gate return (-1);
4880Sstevel@tonic-gate }
4890Sstevel@tonic-gate
4900Sstevel@tonic-gate static int32_t
get_device_type(char * v_name)4910Sstevel@tonic-gate get_device_type(char *v_name)
4920Sstevel@tonic-gate {
4930Sstevel@tonic-gate int32_t i;
4940Sstevel@tonic-gate
4950Sstevel@tonic-gate for (i = 0; i < 8; i++) {
4960Sstevel@tonic-gate v_name[i] = toupper(v_name[i]);
4970Sstevel@tonic-gate }
4980Sstevel@tonic-gate if (strstr(v_name, "IOMEGA")) {
4990Sstevel@tonic-gate return (SCSI_IOMEGA);
5000Sstevel@tonic-gate }
5010Sstevel@tonic-gate if (strstr(v_name, "FD") ||
5020Sstevel@tonic-gate strstr(v_name, "LS-120")) {
5030Sstevel@tonic-gate return (SCSI_FLOPPY);
5040Sstevel@tonic-gate }
5050Sstevel@tonic-gate return (SCSI_GENERIC);
5060Sstevel@tonic-gate
5070Sstevel@tonic-gate }
5080Sstevel@tonic-gate
5090Sstevel@tonic-gate static int32_t
get_device_type_scsi(int32_t fd,struct scsi_inquiry * inq)5100Sstevel@tonic-gate get_device_type_scsi(int32_t fd, struct scsi_inquiry *inq)
5110Sstevel@tonic-gate {
5120Sstevel@tonic-gate int32_t dev_type;
5130Sstevel@tonic-gate struct uscsi_cmd ucmd;
5140Sstevel@tonic-gate union scsi_cdb cdb;
5150Sstevel@tonic-gate int32_t ret_val;
5160Sstevel@tonic-gate char rq_data[RQ_LEN];
5170Sstevel@tonic-gate
5180Sstevel@tonic-gate (void) memset((void *) inq, 0, sizeof (struct scsi_inquiry));
5190Sstevel@tonic-gate (void) memset((void *) &ucmd, 0, sizeof (ucmd));
5200Sstevel@tonic-gate (void) memset((void *) &cdb, 0, sizeof (union scsi_cdb));
5210Sstevel@tonic-gate cdb.scc_cmd = SCMD_INQUIRY;
5220Sstevel@tonic-gate FORMG0COUNT(&cdb, sizeof (struct scsi_inquiry));
5230Sstevel@tonic-gate ucmd.uscsi_cdb = (caddr_t)&cdb;
5240Sstevel@tonic-gate ucmd.uscsi_cdblen = CDB_GROUP0;
5250Sstevel@tonic-gate ucmd.uscsi_bufaddr = (caddr_t)inq;
5260Sstevel@tonic-gate ucmd.uscsi_buflen = sizeof (struct scsi_inquiry);
5270Sstevel@tonic-gate ucmd.uscsi_timeout = 120; /* If 0, HBA hangs forever */
5280Sstevel@tonic-gate ucmd.uscsi_rqlen = RQ_LEN;
5290Sstevel@tonic-gate ucmd.uscsi_rqbuf = rq_data;
5300Sstevel@tonic-gate ret_val = do_uscsi_cmd(fd, &ucmd, USCSI_READ|USCSI_RQENABLE);
5310Sstevel@tonic-gate if (ret_val || ucmd.uscsi_status) {
5321137Sarutz debug(5, "INQUIRY failed: rv = %d uscsi_status = "
5331137Sarutz "%d errno = %d\n", ret_val, ucmd.uscsi_status, errno);
5340Sstevel@tonic-gate return (-1);
5350Sstevel@tonic-gate }
5360Sstevel@tonic-gate
5370Sstevel@tonic-gate dev_type = get_device_type(inq->inq_vid);
5380Sstevel@tonic-gate
5390Sstevel@tonic-gate debug(5, "dev_type %d\n", dev_type);
5400Sstevel@tonic-gate return (dev_type);
5410Sstevel@tonic-gate
5420Sstevel@tonic-gate }
5430Sstevel@tonic-gate
5440Sstevel@tonic-gate static int32_t
get_media_capacity(int32_t fd,uint32_t * capacity,uint32_t * blocksize)5450Sstevel@tonic-gate get_media_capacity(int32_t fd, uint32_t *capacity, uint32_t *blocksize)
5460Sstevel@tonic-gate {
5470Sstevel@tonic-gate struct uscsi_cmd ucmd;
5480Sstevel@tonic-gate uchar_t cdb[12];
5490Sstevel@tonic-gate int32_t ret_val;
5500Sstevel@tonic-gate uchar_t data[20];
5510Sstevel@tonic-gate char rq_data[RQ_LEN];
5520Sstevel@tonic-gate
5530Sstevel@tonic-gate debug(5, "get_media_capacity:\n");
5540Sstevel@tonic-gate
5550Sstevel@tonic-gate (void) memset((void *)&data, 0, sizeof (data));
5560Sstevel@tonic-gate (void) memset((void *)&ucmd, 0, sizeof (ucmd));
5570Sstevel@tonic-gate (void) memset((void *)&cdb, 0, sizeof (cdb));
5580Sstevel@tonic-gate
5590Sstevel@tonic-gate /* retrieve size discriptor of inserted media */
5600Sstevel@tonic-gate cdb[0] = SCMD_READ_FORMAT_CAP;
5610Sstevel@tonic-gate cdb[8] = 0x14; /* data size */
5620Sstevel@tonic-gate
5630Sstevel@tonic-gate /* Fill in the USCSI fields */
5640Sstevel@tonic-gate ucmd.uscsi_cdb = (caddr_t)&cdb;
5650Sstevel@tonic-gate ucmd.uscsi_cdblen = CDB_GROUP5;
5660Sstevel@tonic-gate ucmd.uscsi_bufaddr = (caddr_t)data;
5670Sstevel@tonic-gate ucmd.uscsi_buflen = sizeof (data);
5680Sstevel@tonic-gate ucmd.uscsi_timeout = 120;
5690Sstevel@tonic-gate ucmd.uscsi_rqlen = RQ_LEN;
5700Sstevel@tonic-gate ucmd.uscsi_rqbuf = rq_data;
5710Sstevel@tonic-gate ret_val = do_uscsi_cmd(fd, &ucmd, USCSI_READ|USCSI_RQENABLE);
5720Sstevel@tonic-gate
5730Sstevel@tonic-gate if (ret_val || ucmd.uscsi_status) {
5740Sstevel@tonic-gate debug(5, "Retrieving media info failed: %d - %d\n", ret_val,
5750Sstevel@tonic-gate ucmd.uscsi_status);
5760Sstevel@tonic-gate
5770Sstevel@tonic-gate if ((rq_data[2] == KEY_DATA_PROTECT) && (rq_data[12] == 0x30) &&
5780Sstevel@tonic-gate (rq_data[13] == 0)) {
5790Sstevel@tonic-gate (void) debug(1, "Invalid command for media\n");
5800Sstevel@tonic-gate errno = EINVAL;
5810Sstevel@tonic-gate }
5820Sstevel@tonic-gate return (-1);
5830Sstevel@tonic-gate }
5840Sstevel@tonic-gate
5850Sstevel@tonic-gate /* No media, bail out */
5860Sstevel@tonic-gate if (data[8] == 0x3) {
5870Sstevel@tonic-gate (void) debug(5, "no media in drive\n");
5880Sstevel@tonic-gate return (-1);
5890Sstevel@tonic-gate }
5900Sstevel@tonic-gate
5910Sstevel@tonic-gate /*
5920Sstevel@tonic-gate * Generate capacity and blocksize information
5930Sstevel@tonic-gate */
5940Sstevel@tonic-gate
5950Sstevel@tonic-gate *capacity = (uint32_t)((data[4] << 24) + (data[5] << 16) +
5960Sstevel@tonic-gate (data[6] << 8) + data[7]);
5970Sstevel@tonic-gate
5980Sstevel@tonic-gate debug(1, "capacity is %x %x %x %x = %x", data[4], data[5], data[6],
5990Sstevel@tonic-gate data[7], *capacity);
6000Sstevel@tonic-gate
6010Sstevel@tonic-gate *blocksize = (uint32_t)((data[9] << 16) + (data[10] << 8) + data[11]);
6020Sstevel@tonic-gate
6030Sstevel@tonic-gate return (0);
6040Sstevel@tonic-gate }
6050Sstevel@tonic-gate
6060Sstevel@tonic-gate static int32_t
scsi_zip_format(int32_t fd,uint_t flavor,uint_t mode)6070Sstevel@tonic-gate scsi_zip_format(int32_t fd, uint_t flavor, uint_t mode)
6080Sstevel@tonic-gate {
6090Sstevel@tonic-gate struct uscsi_cmd ucmd;
6100Sstevel@tonic-gate struct scsi_inquiry inq;
6110Sstevel@tonic-gate uchar_t cdb[12];
6120Sstevel@tonic-gate int32_t ret_val;
6130Sstevel@tonic-gate uchar_t data[4];
6140Sstevel@tonic-gate uint32_t rc_data[2];
6150Sstevel@tonic-gate char rq_data[RQ_LEN];
6160Sstevel@tonic-gate uint32_t capacity;
6170Sstevel@tonic-gate
6180Sstevel@tonic-gate
6190Sstevel@tonic-gate if ((mode != SM_FORMAT_IMMEDIATE) &&
6200Sstevel@tonic-gate (mode != SM_FORMAT_BLOCKED)) {
6210Sstevel@tonic-gate errno = ENOTSUP;
6220Sstevel@tonic-gate return (ENOTSUP);
6230Sstevel@tonic-gate }
6240Sstevel@tonic-gate /*
6250Sstevel@tonic-gate * Do an inquiry and try to figure out if it an
6260Sstevel@tonic-gate * IOMEGA JAZ 2GB device.
6270Sstevel@tonic-gate */
6280Sstevel@tonic-gate
6290Sstevel@tonic-gate (void) memset((void *) &inq, 0, sizeof (inq));
6300Sstevel@tonic-gate (void) memset((void *) &ucmd, 0, sizeof (ucmd));
6310Sstevel@tonic-gate (void) memset((void *) &cdb, 0, sizeof (cdb));
6320Sstevel@tonic-gate (void) memset((void *) &rq_data, 0, sizeof (rq_data));
6330Sstevel@tonic-gate cdb[0] = SCMD_INQUIRY;
6340Sstevel@tonic-gate cdb[4] = sizeof (inq);
6350Sstevel@tonic-gate ucmd.uscsi_cdb = (caddr_t)&cdb;
6360Sstevel@tonic-gate ucmd.uscsi_cdblen = CDB_GROUP0;
6370Sstevel@tonic-gate ucmd.uscsi_bufaddr = (caddr_t)&inq;
6380Sstevel@tonic-gate ucmd.uscsi_buflen = sizeof (inq);
6390Sstevel@tonic-gate ucmd.uscsi_timeout = 120; /* If 0, HBA hangs forever */
6400Sstevel@tonic-gate ucmd.uscsi_rqlen = RQ_LEN;
6410Sstevel@tonic-gate ucmd.uscsi_rqbuf = rq_data;
6420Sstevel@tonic-gate ret_val = do_uscsi_cmd(fd, &ucmd, USCSI_READ|USCSI_RQENABLE);
6430Sstevel@tonic-gate if (ret_val || ucmd.uscsi_status) {
6440Sstevel@tonic-gate debug(5, "inquiry failed: %d - %d errno = %d\n",
6450Sstevel@tonic-gate ret_val, ucmd.uscsi_status, errno);
6460Sstevel@tonic-gate return (ucmd.uscsi_status);
6470Sstevel@tonic-gate }
6480Sstevel@tonic-gate
6490Sstevel@tonic-gate (void) memset((void *) &rc_data, 0, sizeof (rc_data));
6500Sstevel@tonic-gate (void) memset((void *) &ucmd, 0, sizeof (ucmd));
6510Sstevel@tonic-gate (void) memset((void *) &cdb, 0, sizeof (cdb));
6520Sstevel@tonic-gate cdb[0] = SCMD_READ_CAPACITY;
6530Sstevel@tonic-gate ucmd.uscsi_cdb = (caddr_t)&cdb;
6540Sstevel@tonic-gate ucmd.uscsi_cdblen = CDB_GROUP1;
6550Sstevel@tonic-gate ucmd.uscsi_bufaddr = (caddr_t)&rc_data;
6560Sstevel@tonic-gate ucmd.uscsi_buflen = sizeof (rc_data);
6570Sstevel@tonic-gate ucmd.uscsi_timeout = 120; /* If 0, HBA hangs forever */
6580Sstevel@tonic-gate
6590Sstevel@tonic-gate ret_val = do_uscsi_cmd(fd, &ucmd, USCSI_READ);
6600Sstevel@tonic-gate if (ret_val || ucmd.uscsi_status) {
6610Sstevel@tonic-gate debug(5, "Read capacity : %d - %d errno = %d\n",
6620Sstevel@tonic-gate ret_val, ucmd.uscsi_status, errno);
6630Sstevel@tonic-gate return (ucmd.uscsi_status);
6640Sstevel@tonic-gate }
6650Sstevel@tonic-gate
6660Sstevel@tonic-gate capacity = ntohl(rc_data[0]);
6670Sstevel@tonic-gate
6680Sstevel@tonic-gate (void) memset((void *)&data, 0, sizeof (data));
6690Sstevel@tonic-gate (void) memset((void *)&ucmd, 0, sizeof (ucmd));
6700Sstevel@tonic-gate (void) memset((void *)&cdb, 0, sizeof (cdb));
6710Sstevel@tonic-gate cdb[0] = SCMD_FORMAT;
6720Sstevel@tonic-gate /*
6730Sstevel@tonic-gate * Defect list sent by initiator is a complete list of defects.
6740Sstevel@tonic-gate */
6750Sstevel@tonic-gate cdb[1] = (FMTDATA | CMPLIST);
6760Sstevel@tonic-gate /*
6770Sstevel@tonic-gate * Target should examine the setting of the DPRY, DCRT, STPF, IP
6780Sstevel@tonic-gate * and DSP bits.
6790Sstevel@tonic-gate */
6800Sstevel@tonic-gate data[1] = FOV;
6810Sstevel@tonic-gate
6820Sstevel@tonic-gate switch (flavor) {
6830Sstevel@tonic-gate case SM_FORMAT_QUICK :
6840Sstevel@tonic-gate /*
6850Sstevel@tonic-gate * Target should not perform any vendor specific
6860Sstevel@tonic-gate * medium certification process or format verification
6870Sstevel@tonic-gate */
6880Sstevel@tonic-gate data[1] = (FOV | DCRT);
6890Sstevel@tonic-gate /*
6900Sstevel@tonic-gate * Defect list sent is an addition to the existing
6910Sstevel@tonic-gate * list of defects.
6920Sstevel@tonic-gate */
6930Sstevel@tonic-gate cdb[1] = FMTDATA;
6940Sstevel@tonic-gate break;
6950Sstevel@tonic-gate case SM_FORMAT_FORCE :
6960Sstevel@tonic-gate if (strstr(inq.inq_pid, "jaz")) {
6970Sstevel@tonic-gate debug(1,
6980Sstevel@tonic-gate "LONG Format of JAZ media not supported\n");
6990Sstevel@tonic-gate errno = ENOTSUP;
7000Sstevel@tonic-gate return (ENOTSUP);
7010Sstevel@tonic-gate }
7020Sstevel@tonic-gate /*
7030Sstevel@tonic-gate * Formatting a write-protected or read/write
7040Sstevel@tonic-gate * protected cartridge is allowed.
7050Sstevel@tonic-gate * This is a vendor specific Format Option.
7060Sstevel@tonic-gate */
7070Sstevel@tonic-gate cdb[2] = 0x20;
7080Sstevel@tonic-gate break;
7090Sstevel@tonic-gate case SM_FORMAT_LONG :
7100Sstevel@tonic-gate if (strstr(inq.inq_pid, "jaz")) {
7110Sstevel@tonic-gate debug(1,
7120Sstevel@tonic-gate "LONG Format of JAZ media not supported\n");
7130Sstevel@tonic-gate errno = ENOTSUP;
7140Sstevel@tonic-gate return (ENOTSUP);
7150Sstevel@tonic-gate }
7160Sstevel@tonic-gate /*
7170Sstevel@tonic-gate * Defect list sent is an addition to the existing
7180Sstevel@tonic-gate * list of defects.
7190Sstevel@tonic-gate */
7200Sstevel@tonic-gate cdb[1] = FMTDATA;
7210Sstevel@tonic-gate break;
7220Sstevel@tonic-gate default :
7230Sstevel@tonic-gate debug(1, "Format option %d not supported!!\n",
7240Sstevel@tonic-gate flavor);
7250Sstevel@tonic-gate errno = ENOTSUP;
7260Sstevel@tonic-gate return (ENOTSUP);
7270Sstevel@tonic-gate }
7280Sstevel@tonic-gate
7290Sstevel@tonic-gate if (mode == SM_FORMAT_IMMEDIATE) {
7300Sstevel@tonic-gate data[1] |= IMMED;
7310Sstevel@tonic-gate debug(5, "immediate_flag set\n");
7320Sstevel@tonic-gate }
7330Sstevel@tonic-gate
7340Sstevel@tonic-gate ucmd.uscsi_cdb = (caddr_t)&cdb;
7350Sstevel@tonic-gate debug(5, "cdb: %x ", cdb[0]);
7360Sstevel@tonic-gate debug(5, "%x %x ", cdb[1], cdb[2]);
7370Sstevel@tonic-gate debug(5, "%x %x %x\n", cdb[3], cdb[4], cdb[5]);
7380Sstevel@tonic-gate debug(5, "data: %x %x %x %x\n", data[0], data[1], data[2], data[3]);
7390Sstevel@tonic-gate
7400Sstevel@tonic-gate ucmd.uscsi_cdblen = CDB_GROUP0;
7410Sstevel@tonic-gate ucmd.uscsi_bufaddr = (caddr_t)data;
7420Sstevel@tonic-gate ucmd.uscsi_buflen = sizeof (data);
7430Sstevel@tonic-gate ucmd.uscsi_timeout = FORMAT_TIMEOUT(capacity);
7440Sstevel@tonic-gate ucmd.uscsi_rqlen = RQ_LEN;
7450Sstevel@tonic-gate ucmd.uscsi_rqbuf = rq_data;
7460Sstevel@tonic-gate ret_val = do_uscsi_cmd(fd, &ucmd, USCSI_WRITE|USCSI_RQENABLE);
7470Sstevel@tonic-gate if (ret_val || ucmd.uscsi_status) {
7480Sstevel@tonic-gate debug(5, "Format failed : %d - uscsi_status = %d errno = %d\n",
7490Sstevel@tonic-gate ret_val,
7500Sstevel@tonic-gate ucmd.uscsi_status, errno);
7510Sstevel@tonic-gate if ((rq_data[2] == KEY_DATA_PROTECT) ||
7520Sstevel@tonic-gate (rq_data[2] == KEY_ILLEGAL_REQUEST))
7530Sstevel@tonic-gate errno = EINVAL;
7540Sstevel@tonic-gate if ((rq_data[2] == KEY_MEDIUM_ERROR) ||
7550Sstevel@tonic-gate (rq_data[2] == KEY_HARDWARE_ERROR))
7560Sstevel@tonic-gate errno = EIO;
7570Sstevel@tonic-gate return (errno);
7580Sstevel@tonic-gate }
7590Sstevel@tonic-gate
7600Sstevel@tonic-gate return (0);
7610Sstevel@tonic-gate }
7620Sstevel@tonic-gate
7630Sstevel@tonic-gate static int32_t
scsi_ls120_format(uint_t fd,uint_t flavor,uint32_t capacity,uint32_t blocksize)7640Sstevel@tonic-gate scsi_ls120_format(uint_t fd, uint_t flavor, uint32_t capacity,
7650Sstevel@tonic-gate uint32_t blocksize)
7660Sstevel@tonic-gate {
7670Sstevel@tonic-gate struct uscsi_cmd ucmd;
7680Sstevel@tonic-gate uchar_t cdb[12];
7690Sstevel@tonic-gate int32_t ret_val;
7700Sstevel@tonic-gate uchar_t data[12];
7710Sstevel@tonic-gate char rq_data[RQ_LEN];
7720Sstevel@tonic-gate
7730Sstevel@tonic-gate debug(5, "scsi_ls120_format:\n");
7740Sstevel@tonic-gate
7750Sstevel@tonic-gate (void) memset((void *) &ucmd, 0, sizeof (ucmd));
7760Sstevel@tonic-gate (void) memset((void *) &cdb, 0, sizeof (cdb));
7770Sstevel@tonic-gate (void) memset((void *) &rq_data, 0, sizeof (rq_data));
7780Sstevel@tonic-gate
7790Sstevel@tonic-gate cdb[0] = SCMD_FORMAT;
7800Sstevel@tonic-gate cdb[1] = (FMTDATA | 0x7);
7810Sstevel@tonic-gate cdb[8] = 0x0C; /* parameter list length */
7820Sstevel@tonic-gate
7830Sstevel@tonic-gate data[1] = 0x80;
7840Sstevel@tonic-gate data[3] = 0x08;
7850Sstevel@tonic-gate
7860Sstevel@tonic-gate
7870Sstevel@tonic-gate data[4] = (capacity >> 24) & 0xff;
7880Sstevel@tonic-gate data[5] = (capacity >> 16) & 0xff;
7890Sstevel@tonic-gate data[6] = (capacity >> 8) & 0xff;
7900Sstevel@tonic-gate data[7] = capacity & 0xff;
7910Sstevel@tonic-gate
7920Sstevel@tonic-gate
7930Sstevel@tonic-gate data[9] = (blocksize >> 16) & 0xff;
7940Sstevel@tonic-gate data[10] = (blocksize >> 8) & 0xff;
7950Sstevel@tonic-gate data[11] = blocksize & 0xff;
7960Sstevel@tonic-gate
7970Sstevel@tonic-gate debug(5, "cdb: %x %x %x ... %x", cdb[0], cdb[1], cdb[2], cdb[8]);
7980Sstevel@tonic-gate debug(5, "data: %x %x %x %x\n", data[0], data[1], data[2], data[3]);
7990Sstevel@tonic-gate debug(5, " : %x %x %x %x\n", data[4], data[5], data[6], data[7]);
8000Sstevel@tonic-gate debug(5, " : %x %x %x %x\n", data[8], data[9], data[10], data[11]);
8010Sstevel@tonic-gate
8020Sstevel@tonic-gate switch (flavor) {
8030Sstevel@tonic-gate case SM_FORMAT_QUICK :
8040Sstevel@tonic-gate debug(1, "Format not supported\n");
8050Sstevel@tonic-gate errno = ENOTSUP;
8060Sstevel@tonic-gate return (-1);
8070Sstevel@tonic-gate case SM_FORMAT_FORCE :
8080Sstevel@tonic-gate break;
8090Sstevel@tonic-gate case SM_FORMAT_LONG :
8100Sstevel@tonic-gate break;
8110Sstevel@tonic-gate default :
8120Sstevel@tonic-gate debug(1, "Format option not specified!!\n");
8130Sstevel@tonic-gate errno = ENOTSUP;
8140Sstevel@tonic-gate return (-1);
8150Sstevel@tonic-gate }
8160Sstevel@tonic-gate
8170Sstevel@tonic-gate ucmd.uscsi_cdb = (caddr_t)&cdb;
8180Sstevel@tonic-gate
8190Sstevel@tonic-gate
8200Sstevel@tonic-gate ucmd.uscsi_cdblen = CDB_GROUP5;
8210Sstevel@tonic-gate ucmd.uscsi_bufaddr = (caddr_t)data;
8220Sstevel@tonic-gate ucmd.uscsi_buflen = sizeof (data);
8230Sstevel@tonic-gate ucmd.uscsi_timeout = 0x12c0;
8240Sstevel@tonic-gate ucmd.uscsi_rqlen = RQ_LEN;
8250Sstevel@tonic-gate ucmd.uscsi_rqbuf = rq_data;
8260Sstevel@tonic-gate (void) fflush(stdout);
8270Sstevel@tonic-gate
8280Sstevel@tonic-gate ret_val = do_uscsi_cmd(fd, &ucmd, USCSI_WRITE|USCSI_RQENABLE);
8290Sstevel@tonic-gate if (ret_val || ucmd.uscsi_status) {
8300Sstevel@tonic-gate debug(1, "Format failed failed: %d - %d\n", ret_val,
8310Sstevel@tonic-gate ucmd.uscsi_status);
8320Sstevel@tonic-gate
8330Sstevel@tonic-gate if ((rq_data[2] == KEY_DATA_PROTECT) &&
8340Sstevel@tonic-gate (rq_data[12] == 0x30) && (rq_data[13] == 0)) {
8350Sstevel@tonic-gate
8360Sstevel@tonic-gate debug(1, "Invalid command for media\n");
8370Sstevel@tonic-gate errno = EINVAL;
8380Sstevel@tonic-gate }
8390Sstevel@tonic-gate
8400Sstevel@tonic-gate if ((rq_data[2] == KEY_NOT_READY) && (rq_data[12] == 0x30)) {
8410Sstevel@tonic-gate debug(1, "Incompatible media.\n");
8420Sstevel@tonic-gate errno = EINVAL;
8430Sstevel@tonic-gate }
8440Sstevel@tonic-gate
8450Sstevel@tonic-gate return (-1);
8460Sstevel@tonic-gate }
8470Sstevel@tonic-gate
8480Sstevel@tonic-gate return (0);
8490Sstevel@tonic-gate }
8500Sstevel@tonic-gate
8510Sstevel@tonic-gate static int32_t
scsi_format(int32_t fd,uint_t flavor,uint_t mode)8520Sstevel@tonic-gate scsi_format(int32_t fd, uint_t flavor, uint_t mode)
8530Sstevel@tonic-gate {
8540Sstevel@tonic-gate struct uscsi_cmd ucmd;
8550Sstevel@tonic-gate struct scsi_inquiry inq;
8560Sstevel@tonic-gate uchar_t cdb[12];
8570Sstevel@tonic-gate int32_t ret_val;
8580Sstevel@tonic-gate uchar_t data[4];
8590Sstevel@tonic-gate char rq_data[RQ_LEN];
8600Sstevel@tonic-gate uint32_t rc_data[2];
8610Sstevel@tonic-gate uint32_t capacity;
8620Sstevel@tonic-gate
8630Sstevel@tonic-gate
8640Sstevel@tonic-gate
8650Sstevel@tonic-gate if ((mode != SM_FORMAT_IMMEDIATE) &&
8660Sstevel@tonic-gate (mode != SM_FORMAT_BLOCKED)) {
8670Sstevel@tonic-gate errno = ENOTSUP;
8680Sstevel@tonic-gate return (-1);
8690Sstevel@tonic-gate }
8700Sstevel@tonic-gate
8710Sstevel@tonic-gate /*
8720Sstevel@tonic-gate * Do an inquiry and try to figure out if it an
8730Sstevel@tonic-gate * IOMEGA JAZ 2GB device.
8740Sstevel@tonic-gate */
8750Sstevel@tonic-gate
8760Sstevel@tonic-gate (void) memset((void *) &inq, 0, sizeof (inq));
8770Sstevel@tonic-gate (void) memset((void *) &ucmd, 0, sizeof (ucmd));
8780Sstevel@tonic-gate (void) memset((void *) &cdb, 0, sizeof (cdb));
8790Sstevel@tonic-gate (void) memset((void *) &rq_data, 0, sizeof (rq_data));
8800Sstevel@tonic-gate cdb[0] = SCMD_INQUIRY;
8810Sstevel@tonic-gate cdb[4] = sizeof (inq);
8820Sstevel@tonic-gate ucmd.uscsi_cdb = (caddr_t)&cdb;
8830Sstevel@tonic-gate ucmd.uscsi_cdblen = CDB_GROUP0;
8840Sstevel@tonic-gate ucmd.uscsi_bufaddr = (caddr_t)&inq;
8850Sstevel@tonic-gate ucmd.uscsi_buflen = sizeof (inq);
8860Sstevel@tonic-gate ucmd.uscsi_timeout = 120; /* If 0, HBA hangs forever */
8870Sstevel@tonic-gate ucmd.uscsi_rqlen = RQ_LEN;
8880Sstevel@tonic-gate ucmd.uscsi_rqbuf = rq_data;
8890Sstevel@tonic-gate ret_val = do_uscsi_cmd(fd, &ucmd, USCSI_READ|USCSI_RQENABLE);
8900Sstevel@tonic-gate if (ret_val || ucmd.uscsi_status) {
8910Sstevel@tonic-gate debug(5, "inquiry failed: %d - %d errno = %d\n",
8920Sstevel@tonic-gate ret_val, ucmd.uscsi_status, errno);
8930Sstevel@tonic-gate return (ucmd.uscsi_status);
8940Sstevel@tonic-gate }
8950Sstevel@tonic-gate
8960Sstevel@tonic-gate (void) memset((void *) &rc_data, 0, sizeof (rc_data));
8970Sstevel@tonic-gate (void) memset((void *) &ucmd, 0, sizeof (ucmd));
8980Sstevel@tonic-gate (void) memset((void *) &cdb, 0, sizeof (cdb));
8990Sstevel@tonic-gate cdb[0] = SCMD_READ_CAPACITY;
9000Sstevel@tonic-gate ucmd.uscsi_cdb = (caddr_t)&cdb;
9010Sstevel@tonic-gate ucmd.uscsi_cdblen = CDB_GROUP1;
9020Sstevel@tonic-gate ucmd.uscsi_bufaddr = (caddr_t)&rc_data;
9030Sstevel@tonic-gate ucmd.uscsi_buflen = sizeof (rc_data);
9040Sstevel@tonic-gate ucmd.uscsi_timeout = 120; /* If 0, HBA hangs forever */
9050Sstevel@tonic-gate
9060Sstevel@tonic-gate ret_val = do_uscsi_cmd(fd, &ucmd, USCSI_READ);
9070Sstevel@tonic-gate if (ret_val || ucmd.uscsi_status) {
9080Sstevel@tonic-gate debug(5, "Read capacity : %d - %d errno = %d\n",
9090Sstevel@tonic-gate ret_val, ucmd.uscsi_status, errno);
9100Sstevel@tonic-gate return (ucmd.uscsi_status);
9110Sstevel@tonic-gate }
9120Sstevel@tonic-gate
9130Sstevel@tonic-gate capacity = ntohl(rc_data[0]);
9140Sstevel@tonic-gate
9150Sstevel@tonic-gate (void) memset((void *)&data, 0, sizeof (data));
9160Sstevel@tonic-gate (void) memset((void *)&ucmd, 0, sizeof (ucmd));
9170Sstevel@tonic-gate (void) memset((void *)&cdb, 0, sizeof (cdb));
9180Sstevel@tonic-gate cdb[0] = SCMD_FORMAT;
9190Sstevel@tonic-gate /*
9200Sstevel@tonic-gate * Defect list sent is an addition to the existing
9210Sstevel@tonic-gate * list of defects.
9220Sstevel@tonic-gate */
9230Sstevel@tonic-gate cdb[1] = FMTDATA;
9240Sstevel@tonic-gate /*
9250Sstevel@tonic-gate * Target should examine the setting of the DPRY, DCRT, STPF, IP
9260Sstevel@tonic-gate * and DSP bits.
9270Sstevel@tonic-gate */
9280Sstevel@tonic-gate data[1] = FOV;
9290Sstevel@tonic-gate
9300Sstevel@tonic-gate if (mode == SM_FORMAT_IMMEDIATE) {
9310Sstevel@tonic-gate debug(5,
9320Sstevel@tonic-gate "SM_FORMAT_IMMEDIATE specified ignored. Performing a long format!\n");
9330Sstevel@tonic-gate }
9340Sstevel@tonic-gate
9350Sstevel@tonic-gate switch (flavor) {
9360Sstevel@tonic-gate case SM_FORMAT_LONG :
9370Sstevel@tonic-gate if (strstr(inq.inq_pid, "jaz")) {
9380Sstevel@tonic-gate debug(1,
9390Sstevel@tonic-gate "LONG Format of JAZ media not supported\n");
9400Sstevel@tonic-gate errno = ENOTSUP;
9410Sstevel@tonic-gate return (ENOTSUP);
9420Sstevel@tonic-gate }
9430Sstevel@tonic-gate /*
9440Sstevel@tonic-gate * Defect list sent is an addition to the existing
9450Sstevel@tonic-gate * list of defects.
9460Sstevel@tonic-gate */
9470Sstevel@tonic-gate cdb[1] = FMTDATA;
9480Sstevel@tonic-gate break;
9490Sstevel@tonic-gate default :
9500Sstevel@tonic-gate debug(1, "Format option %d not supported!!\n",
9510Sstevel@tonic-gate flavor);
9520Sstevel@tonic-gate errno = ENOTSUP;
9530Sstevel@tonic-gate return (ENOTSUP);
9540Sstevel@tonic-gate }
9550Sstevel@tonic-gate
9560Sstevel@tonic-gate
9570Sstevel@tonic-gate ucmd.uscsi_cdb = (caddr_t)&cdb;
9580Sstevel@tonic-gate ucmd.uscsi_cdblen = CDB_GROUP0;
9590Sstevel@tonic-gate ucmd.uscsi_bufaddr = (caddr_t)data;
9600Sstevel@tonic-gate ucmd.uscsi_buflen = sizeof (data);
9610Sstevel@tonic-gate ucmd.uscsi_timeout = FORMAT_TIMEOUT(capacity);
9620Sstevel@tonic-gate ucmd.uscsi_rqlen = RQ_LEN;
9630Sstevel@tonic-gate ucmd.uscsi_rqbuf = rq_data;
9640Sstevel@tonic-gate ret_val = do_uscsi_cmd(fd, &ucmd, USCSI_WRITE|USCSI_RQENABLE);
9650Sstevel@tonic-gate if (ret_val || ucmd.uscsi_status) {
9660Sstevel@tonic-gate debug(5, "Format failed failed: %d - %d errno = %d\n",
9670Sstevel@tonic-gate ret_val, ucmd.uscsi_status, errno);
9680Sstevel@tonic-gate return (ucmd.uscsi_status);
9690Sstevel@tonic-gate }
9700Sstevel@tonic-gate
9710Sstevel@tonic-gate return (0);
9720Sstevel@tonic-gate }
9730Sstevel@tonic-gate
9740Sstevel@tonic-gate static int32_t
scsi_media_status(int32_t fd)9750Sstevel@tonic-gate scsi_media_status(int32_t fd)
9760Sstevel@tonic-gate {
9770Sstevel@tonic-gate struct mode_header modeh;
9780Sstevel@tonic-gate struct uscsi_cmd ucmd;
9790Sstevel@tonic-gate union scsi_cdb cdb;
9801137Sarutz int32_t ret_val;
9810Sstevel@tonic-gate int32_t cur_status;
9820Sstevel@tonic-gate char rq_data[RQ_LEN];
9830Sstevel@tonic-gate
9840Sstevel@tonic-gate debug(10, "SCSI MEDIA STATUS CALLED \n");
9850Sstevel@tonic-gate
9860Sstevel@tonic-gate (void) memset((void *) &modeh, 0, sizeof (modeh));
9870Sstevel@tonic-gate (void) memset((void *) &ucmd, 0, sizeof (ucmd));
9880Sstevel@tonic-gate (void) memset((void *) &cdb, 0, sizeof (union scsi_cdb));
9890Sstevel@tonic-gate cdb.scc_cmd = SCMD_MODE_SENSE;
9901984Scg149915 cdb.cdb_opaque[2] = MODEPAGE_ALLPAGES;
9910Sstevel@tonic-gate FORMG0COUNT(&cdb, sizeof (modeh));
9921984Scg149915
9930Sstevel@tonic-gate ucmd.uscsi_cdb = (caddr_t)&cdb;
9940Sstevel@tonic-gate ucmd.uscsi_cdblen = CDB_GROUP0;
9950Sstevel@tonic-gate ucmd.uscsi_bufaddr = (caddr_t)&modeh;
9960Sstevel@tonic-gate ucmd.uscsi_buflen = sizeof (modeh);
9970Sstevel@tonic-gate ucmd.uscsi_timeout = 120; /* If 0, HBA hangs forever */
9980Sstevel@tonic-gate ucmd.uscsi_rqlen = RQ_LEN;
9990Sstevel@tonic-gate ucmd.uscsi_rqbuf = rq_data;
10000Sstevel@tonic-gate ret_val = do_uscsi_cmd(fd, &ucmd, USCSI_READ|USCSI_RQENABLE);
10010Sstevel@tonic-gate if (ret_val || ucmd.uscsi_status) {
10021984Scg149915 debug(5, "Modesense for 0x3f pages failed: %d-%d errno=%d\n",
10030Sstevel@tonic-gate ret_val, ucmd.uscsi_status, errno);
10041984Scg149915 cdb.cdb_opaque[2] = 0;
10051984Scg149915 ucmd.uscsi_rqlen = RQ_LEN;
10061984Scg149915 FORMG0COUNT(&cdb, sizeof (modeh));
10071984Scg149915 ret_val = do_uscsi_cmd(fd, &ucmd, USCSI_READ|USCSI_RQENABLE);
10081984Scg149915 if (ret_val || ucmd.uscsi_status) {
10091984Scg149915 debug(5, "Modesense failed: %d - %d errno = %d\n",
10101984Scg149915 ret_val, ucmd.uscsi_status, errno);
10111984Scg149915 return (-1);
10121984Scg149915 }
10130Sstevel@tonic-gate }
10140Sstevel@tonic-gate
10150Sstevel@tonic-gate if (modeh.device_specific & W_E_MASK) {
10160Sstevel@tonic-gate cur_status = SM_WRITE_PROTECT_NOPASSWD;
10170Sstevel@tonic-gate } else {
10180Sstevel@tonic-gate cur_status = SM_WRITE_PROTECT_DISABLE;
10190Sstevel@tonic-gate }
10200Sstevel@tonic-gate debug(5, "cur status %d\n", cur_status);
10210Sstevel@tonic-gate
10220Sstevel@tonic-gate return (cur_status);
10230Sstevel@tonic-gate }
10240Sstevel@tonic-gate
10250Sstevel@tonic-gate static int32_t
scsi_zip_media_status(int32_t fd)10260Sstevel@tonic-gate scsi_zip_media_status(int32_t fd)
10270Sstevel@tonic-gate {
10280Sstevel@tonic-gate struct uscsi_cmd ucmd;
10290Sstevel@tonic-gate uchar_t cdb[12];
10300Sstevel@tonic-gate int32_t status;
10310Sstevel@tonic-gate int32_t mode;
10320Sstevel@tonic-gate uchar_t data[64];
10330Sstevel@tonic-gate char rq_data[RQ_LEN];
10340Sstevel@tonic-gate
10350Sstevel@tonic-gate debug(10, "Getting media status\n");
10360Sstevel@tonic-gate
10370Sstevel@tonic-gate (void) memset((void *)&ucmd, 0, sizeof (ucmd));
10380Sstevel@tonic-gate (void) memset((void *)&cdb, 0, sizeof (cdb));
10390Sstevel@tonic-gate
10400Sstevel@tonic-gate cdb[0] = IOMEGA_NONSENSE_CMD;
10410Sstevel@tonic-gate cdb[2] = CARTRIDGE_STATUS_PAGE;
10420Sstevel@tonic-gate cdb[4] = ND_LENGTH;
10430Sstevel@tonic-gate ucmd.uscsi_cdb = (caddr_t)&cdb;
10440Sstevel@tonic-gate ucmd.uscsi_cdblen = CDB_GROUP0;
10450Sstevel@tonic-gate ucmd.uscsi_bufaddr = (caddr_t)data;
10460Sstevel@tonic-gate ucmd.uscsi_buflen = 64;
10470Sstevel@tonic-gate ucmd.uscsi_timeout = 120; /* If 0, HBA hangs forever */
10480Sstevel@tonic-gate ucmd.uscsi_rqlen = RQ_LEN;
10490Sstevel@tonic-gate ucmd.uscsi_rqbuf = rq_data;
10500Sstevel@tonic-gate status = do_uscsi_cmd(fd, &ucmd, USCSI_READ|USCSI_RQENABLE);
10510Sstevel@tonic-gate if (status || ucmd.uscsi_status) {
10521137Sarutz debug(5, "Cartridge protect operation failed: "
10531137Sarutz "rv = %d uscsi_status = %d errno = %d\n",
10541137Sarutz status, ucmd.uscsi_status, errno);
10550Sstevel@tonic-gate return (-1);
10560Sstevel@tonic-gate }
10570Sstevel@tonic-gate
10580Sstevel@tonic-gate if (data[DISK_STATUS_OFFSET + NON_SENSE_HDR_LEN] == 4) {
10590Sstevel@tonic-gate debug(1, "Disk not present. \n");
10600Sstevel@tonic-gate return (-1);
10610Sstevel@tonic-gate }
10620Sstevel@tonic-gate mode = data[PROTECT_MODE_OFFSET + NON_SENSE_HDR_LEN] & 0xF;
10630Sstevel@tonic-gate
10641137Sarutz debug(5, "MODE 0x%x / %d.\n", mode, mode);
10651137Sarutz
10660Sstevel@tonic-gate switch (mode) {
10670Sstevel@tonic-gate case UNLOCK_MODE:
10680Sstevel@tonic-gate status = SM_WRITE_PROTECT_DISABLE;
10690Sstevel@tonic-gate break;
10700Sstevel@tonic-gate case WRITE_PROTECT_MODE:
10710Sstevel@tonic-gate status = SM_WRITE_PROTECT_NOPASSWD;
10720Sstevel@tonic-gate break;
10730Sstevel@tonic-gate case PASSWD_WRITE_PROTECT_MODE:
10740Sstevel@tonic-gate status = SM_WRITE_PROTECT_PASSWD;
10750Sstevel@tonic-gate break;
10760Sstevel@tonic-gate case READ_WRITE_PROTECT_MODE:
10770Sstevel@tonic-gate status = SM_READ_WRITE_PROTECT;
10780Sstevel@tonic-gate break;
10790Sstevel@tonic-gate default :
10800Sstevel@tonic-gate if (mode & TEMP_UNLOCK_MODE)
10810Sstevel@tonic-gate status = SM_TEMP_UNLOCK_MODE;
10820Sstevel@tonic-gate else
10830Sstevel@tonic-gate status = SM_STATUS_UNKNOWN;
10840Sstevel@tonic-gate break;
10850Sstevel@tonic-gate }
10860Sstevel@tonic-gate
10870Sstevel@tonic-gate debug(5, "status %d \n", status);
10880Sstevel@tonic-gate return (status);
10890Sstevel@tonic-gate }
10900Sstevel@tonic-gate
10911137Sarutz static int32_t
scsi_reassign_block(int32_t fd,diskaddr_t block)10920Sstevel@tonic-gate scsi_reassign_block(int32_t fd, diskaddr_t block)
10930Sstevel@tonic-gate {
10940Sstevel@tonic-gate uchar_t data[8];
10950Sstevel@tonic-gate struct uscsi_cmd ucmd;
10960Sstevel@tonic-gate char cdb[12];
10970Sstevel@tonic-gate int32_t ret_val;
10980Sstevel@tonic-gate char rq_data[RQ_LEN];
10990Sstevel@tonic-gate
11000Sstevel@tonic-gate debug(5, "SCSI REASSIGN CALLED block = %lld\n", block);
11010Sstevel@tonic-gate
11020Sstevel@tonic-gate (void) memset((void *) &data, 0, sizeof (data));
11030Sstevel@tonic-gate (void) memset((void *) &ucmd, 0, sizeof (ucmd));
11040Sstevel@tonic-gate (void) memset((void *) &cdb, 0, sizeof (cdb));
11050Sstevel@tonic-gate cdb[0] = SCMD_REASSIGN_BLOCK;
11060Sstevel@tonic-gate data[3] = 4;
11070Sstevel@tonic-gate data[4] = ((block & 0xFF000000) >> 24);
11080Sstevel@tonic-gate data[5] = ((block & 0xFF0000) >> 16);
11090Sstevel@tonic-gate data[6] = ((block & 0xFF00) >> 8);
11100Sstevel@tonic-gate data[7] = block & 0xFF;
11110Sstevel@tonic-gate
11120Sstevel@tonic-gate ucmd.uscsi_cdb = (caddr_t)&cdb;
11130Sstevel@tonic-gate ucmd.uscsi_cdblen = CDB_GROUP0;
11140Sstevel@tonic-gate ucmd.uscsi_bufaddr = (caddr_t)data;
11150Sstevel@tonic-gate ucmd.uscsi_buflen = sizeof (data);
11160Sstevel@tonic-gate ucmd.uscsi_timeout = 120; /* If 0, HBA hangs forever */
11170Sstevel@tonic-gate ucmd.uscsi_rqlen = RQ_LEN;
11180Sstevel@tonic-gate ucmd.uscsi_rqbuf = rq_data;
11190Sstevel@tonic-gate ret_val = do_uscsi_cmd(fd, &ucmd, USCSI_WRITE|USCSI_RQENABLE);
11200Sstevel@tonic-gate if (ret_val || ucmd.uscsi_status) {
11210Sstevel@tonic-gate debug(5, "Reassign block failed: %d - %d errno = %d\n",
11220Sstevel@tonic-gate ret_val, ucmd.uscsi_status, errno);
11230Sstevel@tonic-gate return (-1);
11240Sstevel@tonic-gate }
11250Sstevel@tonic-gate
11260Sstevel@tonic-gate return (0);
11270Sstevel@tonic-gate }
11280Sstevel@tonic-gate
11291137Sarutz static int32_t
get_mode_page(int32_t fd,uchar_t pc,uchar_t page_code,uchar_t * md_data,uchar_t data_len)11300Sstevel@tonic-gate get_mode_page(int32_t fd, uchar_t pc, uchar_t page_code,
11311137Sarutz uchar_t *md_data, uchar_t data_len)
11320Sstevel@tonic-gate {
11330Sstevel@tonic-gate struct uscsi_cmd ucmd;
11340Sstevel@tonic-gate uchar_t cdb[12];
11350Sstevel@tonic-gate int32_t ret_val;
11360Sstevel@tonic-gate char rq_data[RQ_LEN];
11370Sstevel@tonic-gate
11381137Sarutz debug(10, "MODE SENSE(6) - page_code = 0x%x\n", page_code);
11390Sstevel@tonic-gate
11400Sstevel@tonic-gate (void) memset((void *) md_data, 0, sizeof (data_len));
11410Sstevel@tonic-gate (void) memset((void *) &ucmd, 0, sizeof (ucmd));
11420Sstevel@tonic-gate (void) memset((void *) &cdb, 0, sizeof (cdb));
11430Sstevel@tonic-gate cdb[0] = SCMD_MODE_SENSE;
11440Sstevel@tonic-gate cdb[2] = (pc << 6) | page_code;
11450Sstevel@tonic-gate cdb[4] = data_len;
11460Sstevel@tonic-gate
11470Sstevel@tonic-gate ucmd.uscsi_cdb = (caddr_t)&cdb;
11480Sstevel@tonic-gate ucmd.uscsi_cdblen = CDB_GROUP0;
11490Sstevel@tonic-gate ucmd.uscsi_bufaddr = (caddr_t)md_data;
11500Sstevel@tonic-gate ucmd.uscsi_buflen = data_len;
11510Sstevel@tonic-gate ucmd.uscsi_timeout = 120; /* If 0, HBA hangs forever */
11520Sstevel@tonic-gate ucmd.uscsi_rqlen = RQ_LEN;
11530Sstevel@tonic-gate ucmd.uscsi_rqbuf = rq_data;
11540Sstevel@tonic-gate ret_val = do_uscsi_cmd(fd, &ucmd, USCSI_READ|USCSI_RQENABLE);
11550Sstevel@tonic-gate if (ret_val || ucmd.uscsi_status) {
11560Sstevel@tonic-gate debug(5, "Modesense failed: %d - %d errno = %d\n",
11570Sstevel@tonic-gate ret_val, ucmd.uscsi_status, errno);
11580Sstevel@tonic-gate return (-2);
11590Sstevel@tonic-gate }
11600Sstevel@tonic-gate
11610Sstevel@tonic-gate return (0);
11620Sstevel@tonic-gate }
11630Sstevel@tonic-gate
11640Sstevel@tonic-gate static int32_t
scsi_zip_write_protect(int32_t fd,smwp_state_t * wp)11650Sstevel@tonic-gate scsi_zip_write_protect(int32_t fd, smwp_state_t *wp)
11660Sstevel@tonic-gate {
11670Sstevel@tonic-gate struct uscsi_cmd ucmd;
11680Sstevel@tonic-gate struct scsi_inquiry inq;
11690Sstevel@tonic-gate uchar_t cdb[12];
11700Sstevel@tonic-gate int32_t status;
11710Sstevel@tonic-gate int32_t new_mode;
11720Sstevel@tonic-gate char rq_data[RQ_LEN];
11730Sstevel@tonic-gate int32_t wa_bit;
11740Sstevel@tonic-gate char *tmp_passwd = NULL;
11750Sstevel@tonic-gate
11760Sstevel@tonic-gate debug(10, "SCSI ZIP WRITE PROTECT CALLED \n");
11770Sstevel@tonic-gate
11780Sstevel@tonic-gate /*
11790Sstevel@tonic-gate * Do an inquiry and try to figure out if it an
11800Sstevel@tonic-gate * ATAPI or SCSI device.
11810Sstevel@tonic-gate */
11820Sstevel@tonic-gate
11830Sstevel@tonic-gate (void) memset((void *) &inq, 0, sizeof (inq));
11840Sstevel@tonic-gate (void) memset((void *) &ucmd, 0, sizeof (ucmd));
11850Sstevel@tonic-gate (void) memset((void *) &cdb, 0, sizeof (cdb));
11860Sstevel@tonic-gate (void) memset((void *) &rq_data, 0, sizeof (rq_data));
11870Sstevel@tonic-gate cdb[0] = SCMD_INQUIRY;
11880Sstevel@tonic-gate cdb[4] = sizeof (inq);
11890Sstevel@tonic-gate ucmd.uscsi_cdb = (caddr_t)&cdb;
11900Sstevel@tonic-gate ucmd.uscsi_cdblen = CDB_GROUP0;
11910Sstevel@tonic-gate ucmd.uscsi_bufaddr = (caddr_t)&inq;
11920Sstevel@tonic-gate ucmd.uscsi_buflen = sizeof (inq);
11930Sstevel@tonic-gate ucmd.uscsi_timeout = 120; /* If 0, HBA hangs forever */
11940Sstevel@tonic-gate ucmd.uscsi_rqlen = RQ_LEN;
11950Sstevel@tonic-gate ucmd.uscsi_rqbuf = rq_data;
11960Sstevel@tonic-gate status = do_uscsi_cmd(fd, &ucmd, USCSI_READ|USCSI_RQENABLE);
11970Sstevel@tonic-gate if (status || ucmd.uscsi_status) {
11980Sstevel@tonic-gate debug(5, "inquiry failed: %d - %d errno = %d\n",
11990Sstevel@tonic-gate status, ucmd.uscsi_status, errno);
12000Sstevel@tonic-gate return (-1);
12010Sstevel@tonic-gate }
12020Sstevel@tonic-gate
12030Sstevel@tonic-gate if (inq.inq_ansi > 0) {
12040Sstevel@tonic-gate wa_bit = 0;
12050Sstevel@tonic-gate debug(5, "SCSI device\n");
12060Sstevel@tonic-gate } else {
12070Sstevel@tonic-gate wa_bit = 1;
12080Sstevel@tonic-gate debug(5, "ATAPI device\n");
12090Sstevel@tonic-gate }
12100Sstevel@tonic-gate
12110Sstevel@tonic-gate switch (wp->sm_new_state) {
12120Sstevel@tonic-gate case SM_WRITE_PROTECT_DISABLE :
12130Sstevel@tonic-gate new_mode = 0x0;
12140Sstevel@tonic-gate break;
12150Sstevel@tonic-gate case SM_WRITE_PROTECT_NOPASSWD :
12160Sstevel@tonic-gate new_mode = 0x2;
12170Sstevel@tonic-gate break;
12180Sstevel@tonic-gate case SM_WRITE_PROTECT_PASSWD :
12190Sstevel@tonic-gate new_mode = 0x3;
12200Sstevel@tonic-gate break;
12210Sstevel@tonic-gate case SM_READ_WRITE_PROTECT :
12220Sstevel@tonic-gate new_mode = 0x5;
12230Sstevel@tonic-gate break;
12240Sstevel@tonic-gate case SM_TEMP_UNLOCK_MODE :
12250Sstevel@tonic-gate new_mode = 0x8;
12260Sstevel@tonic-gate break;
12270Sstevel@tonic-gate default :
12280Sstevel@tonic-gate debug(1, "Invalid mode 0x%x specified\n",
12290Sstevel@tonic-gate wp->sm_new_state);
12300Sstevel@tonic-gate errno = ENOTSUP;
12310Sstevel@tonic-gate return (-1);
12320Sstevel@tonic-gate }
12330Sstevel@tonic-gate
12340Sstevel@tonic-gate
12350Sstevel@tonic-gate (void) memset((void *)&ucmd, 0, sizeof (ucmd));
12360Sstevel@tonic-gate (void) memset((void *)&cdb, 0, sizeof (cdb));
12370Sstevel@tonic-gate (void) memset((void *) &rq_data, 0, sizeof (rq_data));
12380Sstevel@tonic-gate cdb[0] = IOMEGA_CATRIDGE_PROTECT;
12390Sstevel@tonic-gate cdb[1] |= new_mode;
12400Sstevel@tonic-gate if (wa_bit)
12410Sstevel@tonic-gate cdb[1] |= WA_BIT;
12420Sstevel@tonic-gate cdb[4] = wp->sm_passwd_len;
12430Sstevel@tonic-gate ucmd.uscsi_cdb = (caddr_t)&cdb;
12440Sstevel@tonic-gate ucmd.uscsi_cdblen = CDB_GROUP0;
12450Sstevel@tonic-gate if (wa_bit && (wp->sm_passwd_len & 1)) {
12460Sstevel@tonic-gate /*
12470Sstevel@tonic-gate * Oops, ATAPI device with an odd length passwd!
12480Sstevel@tonic-gate * Allocate a buffer to hold one extra byte.
12490Sstevel@tonic-gate */
12500Sstevel@tonic-gate debug(5, "Odd len passwd for ATAPI device!\n");
12510Sstevel@tonic-gate errno = 0;
12520Sstevel@tonic-gate tmp_passwd = (char *)malloc(wp->sm_passwd_len+1);
12530Sstevel@tonic-gate if (tmp_passwd == NULL) {
12540Sstevel@tonic-gate if (errno == 0)
12550Sstevel@tonic-gate errno = ENOMEM;
12560Sstevel@tonic-gate return (-1);
12570Sstevel@tonic-gate }
12580Sstevel@tonic-gate (void) memset(tmp_passwd, 0, wp->sm_passwd_len+1);
12590Sstevel@tonic-gate (void) memcpy(tmp_passwd, wp->sm_passwd, wp->sm_passwd_len);
12600Sstevel@tonic-gate ucmd.uscsi_bufaddr = (caddr_t)tmp_passwd;
12610Sstevel@tonic-gate ucmd.uscsi_buflen = wp->sm_passwd_len+1;
12620Sstevel@tonic-gate } else {
12630Sstevel@tonic-gate ucmd.uscsi_bufaddr = (caddr_t)wp->sm_passwd;
12640Sstevel@tonic-gate ucmd.uscsi_buflen = wp->sm_passwd_len;
12650Sstevel@tonic-gate }
12660Sstevel@tonic-gate ucmd.uscsi_timeout = 120; /* If 0, HBA hangs forever */
12670Sstevel@tonic-gate ucmd.uscsi_rqlen = RQ_LEN;
12680Sstevel@tonic-gate ucmd.uscsi_rqbuf = rq_data;
12690Sstevel@tonic-gate status = do_uscsi_cmd(fd, &ucmd, USCSI_WRITE|USCSI_RQENABLE);
12700Sstevel@tonic-gate if (tmp_passwd != NULL) {
12710Sstevel@tonic-gate free(tmp_passwd);
12720Sstevel@tonic-gate }
12730Sstevel@tonic-gate if (status || ucmd.uscsi_status) {
12741137Sarutz debug(5, "Cartridge-protect operation failed: rv "
12751137Sarutz "= %d uscsi_status = %d errno = %d\n", status,
12761137Sarutz ucmd.uscsi_status, errno);
12771137Sarutz if ((rq_data[2] & 0xF) == KEY_ILLEGAL_REQUEST) {
12780Sstevel@tonic-gate if (rq_data[12] == 0x26) {
12790Sstevel@tonic-gate /* Wrong passwd */
12801137Sarutz debug(5, "Protection Request with wrong "
12811137Sarutz "passwd. errno is being set to EACCES.\n");
12820Sstevel@tonic-gate errno = EACCES;
12830Sstevel@tonic-gate }
12840Sstevel@tonic-gate }
12850Sstevel@tonic-gate return (-1);
12860Sstevel@tonic-gate }
12870Sstevel@tonic-gate
12880Sstevel@tonic-gate return (0);
12890Sstevel@tonic-gate }
12900Sstevel@tonic-gate
12910Sstevel@tonic-gate /*ARGSUSED*/
12920Sstevel@tonic-gate static int32_t
scsi_write_protect(int32_t fd,smwp_state_t * wp)12930Sstevel@tonic-gate scsi_write_protect(int32_t fd, smwp_state_t *wp)
12940Sstevel@tonic-gate {
12950Sstevel@tonic-gate errno = ENOTSUP;
12960Sstevel@tonic-gate return (-1);
12970Sstevel@tonic-gate }
12980Sstevel@tonic-gate
12991137Sarutz /*
13001137Sarutz * This thread becomes the server-side thread used in
13011137Sarutz * the implementation of a door_call between a client
13021137Sarutz * and the Client Door.
13031137Sarutz *
13041137Sarutz * This thread is customized both by the door_server_create(3c)
13051137Sarutz * function sm_door_server_create, as well as by itself.
13061137Sarutz *
13071137Sarutz * This thread needs to synchronize with the
13081137Sarutz * main_servproc[SMEDIA_CNUM_OPEN_FD] door_call in terms of
13091137Sarutz * both successful and failure scenarios. main_servproc
13101137Sarutz * locks dd_lock before calling door_create. This thread
13111137Sarutz * then attempts to lock, but will block until main_servproc
13121137Sarutz * has either created all doors it requires, or until a
13131137Sarutz * door_create has failed (door_create's return and the
13141137Sarutz * creation of an associated thread are asynchronous).
13151137Sarutz *
13161137Sarutz * If door_create failed, this thread will be able to obtain
13171137Sarutz * dd_lock and call pthread_exit. If all door_create's succeed,
13181137Sarutz * this thread will obtain dd_lock and commence with
13191137Sarutz * customizing the thread's attributes. door_bind is called to
13201137Sarutz * bind this thread to the per-door private thread pool, and
13211137Sarutz * main_servproc is cond_signal'd to avail it of this fact.
13221137Sarutz *
13231137Sarutz * Finally, this thread calls door_return, which causes it to
13241137Sarutz * commence its lifetime as a server-side thread in implementation
13251137Sarutz * of a Client Door door_call.
13261137Sarutz */
13270Sstevel@tonic-gate static void *
sm_server_thread(void * arg)13281137Sarutz sm_server_thread(void *arg)
13290Sstevel@tonic-gate {
13300Sstevel@tonic-gate door_data_t *door_dp;
13311137Sarutz struct sigaction act;
13321137Sarutz int i;
13331137Sarutz int err;
13340Sstevel@tonic-gate
13350Sstevel@tonic-gate door_dp = (door_data_t *)arg;
13360Sstevel@tonic-gate
13370Sstevel@tonic-gate if (door_dp == NULL) {
13381137Sarutz fatal("sm_server_thread[%d]: argument is NULL!!\n",
13391137Sarutz pthread_self());
13400Sstevel@tonic-gate exit(-1);
13410Sstevel@tonic-gate }
13421137Sarutz
13431137Sarutz /* Wait for Client Door to be created */
13440Sstevel@tonic-gate (void) mutex_lock(&door_dp->dd_lock);
13451137Sarutz if (door_dp->dd_cdoor_descriptor < 0) {
13461137Sarutz debug(5, "sm_server_thread[%d]: door_create() failed",
13471137Sarutz pthread_self());
13481137Sarutz (void) mutex_unlock(&door_dp->dd_lock);
13491137Sarutz pthread_exit((void *)-2);
13501137Sarutz }
13510Sstevel@tonic-gate (void) mutex_unlock(&door_dp->dd_lock);
13520Sstevel@tonic-gate
13530Sstevel@tonic-gate for (i = 0; i < N_BADSIGS; i++) {
13540Sstevel@tonic-gate act.sa_sigaction = server_badsig_handler;
13550Sstevel@tonic-gate (void) sigemptyset(&act.sa_mask);
13560Sstevel@tonic-gate act.sa_flags = SA_SIGINFO;
13570Sstevel@tonic-gate if (sigaction(badsigs[i], &act, NULL) == -1)
13580Sstevel@tonic-gate warning(gettext(SIGACT_FAILED), strsignal(badsigs[i]),
13591137Sarutz strerror(errno));
13600Sstevel@tonic-gate }
13610Sstevel@tonic-gate if (sigemptyset(&door_dp->dd_newset) != 0)
13620Sstevel@tonic-gate warning(gettext("sigemptyset failed. errno = %d\n"),
13631137Sarutz errno);
13641137Sarutz if ((err = pthread_sigmask(SIG_BLOCK, &door_dp->dd_newset, NULL)) != 0)
13651137Sarutz warning(gettext("pthread_sigmask failed = %d\n"), err);
13661137Sarutz
13671137Sarutz /* Bind thread with pool associated with Client Door */
13681137Sarutz
13691137Sarutz if (door_bind(door_dp->dd_cdoor_descriptor) < 0) {
13700Sstevel@tonic-gate fatal("door_bind");
13710Sstevel@tonic-gate exit(-1);
13720Sstevel@tonic-gate }
13731137Sarutz debug(5, "thr[%d] bound to Client Door[%d]", pthread_self(),
13741137Sarutz door_dp->dd_cdoor_descriptor);
13751137Sarutz
13760Sstevel@tonic-gate /*
13771137Sarutz * Set these two cancellation(5) attributes. Ensure that the
13781137Sarutz * pthread we create has cancellation(5) DISABLED and DEFERRED,
13791137Sarutz * as our implementation is based on this. DEFERRED is the
13801137Sarutz * default, but set it anyways, in case the defaults change in
13811137Sarutz * the future.
13820Sstevel@tonic-gate */
13831137Sarutz if ((err = pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL)) != 0)
13841137Sarutz warning(gettext("pthread_setcancelstate(PTHREAD_CANCEL_DISABLE)"
13851137Sarutz " failed = %d\n"), err);
13861137Sarutz if ((err = pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED,
13871137Sarutz NULL)) != 0)
13881137Sarutz warning(gettext("pthread_setcanceltype(DEFERRED) "
13891137Sarutz "failed = %d\n"), err);
13901137Sarutz
13911137Sarutz /* Inform main_servproc that door_bind() is complete. */
13921137Sarutz (void) cond_signal(&door_dp->dd_cv_bind);
13931137Sarutz
13940Sstevel@tonic-gate /*
13951137Sarutz * Per doors protocol, transfer control to the doors-runtime in
13961137Sarutz * order to make this thread available to answer future door_call()'s.
13970Sstevel@tonic-gate */
13980Sstevel@tonic-gate (void) door_return(NULL, 0, NULL, 0);
13990Sstevel@tonic-gate return (NULL);
14000Sstevel@tonic-gate }
14010Sstevel@tonic-gate
14021137Sarutz /*
14031137Sarutz * This function cleans up all per-connection resources.
14041137Sarutz *
14051137Sarutz * This function is called when the Client Door's service procedure
14061137Sarutz * (client_servproc) is called w/ DOOR_UNREF_DATA, which is the
14071137Sarutz * doors protocol convention stating that the number of file
14081137Sarutz * descriptors referring to this door has dropped to one.
14091137Sarutz * client_servproc is passed DOOR_UNREF_DATA because the Client Door
14101137Sarutz * was door_create'd with the DOOR_UNREF bitflag.
14111137Sarutz */
14120Sstevel@tonic-gate static void
cleanup(door_data_t * door_dp)14131137Sarutz cleanup(door_data_t *door_dp)
14140Sstevel@tonic-gate {
14151137Sarutz /* do door_revoke() of Death Door */
14161137Sarutz if (door_dp->dd_ddoor_descriptor >= 0) {
14171137Sarutz debug(1, "cleanup[%d]: door_revoke() Death Door[%d]",
14181137Sarutz pthread_self(), door_dp->dd_ddoor_descriptor);
14191137Sarutz
14201137Sarutz if (door_revoke(door_dp->dd_ddoor_descriptor) < 0) {
14211137Sarutz warning(gettext("cleanup[%d]: door_revoke() of Death "
14221137Sarutz "Door(%d) failed = %d"), pthread_self(),
14231137Sarutz door_dp->dd_ddoor_descriptor, errno);
14241137Sarutz } else {
14251137Sarutz door_dp->dd_ddoor_descriptor = -1;
14261137Sarutz }
14270Sstevel@tonic-gate }
14281137Sarutz
14291137Sarutz /* release memory that is shared between client and (our) server */
14301137Sarutz if (door_dp->dd_buffd >= 0) {
14311137Sarutz debug(1, "cleanup[%d]: release shared memory", pthread_self());
14320Sstevel@tonic-gate (void) munmap(door_dp->dd_buf, door_dp->dd_buf_len);
14330Sstevel@tonic-gate (void) close(door_dp->dd_buffd);
14341137Sarutz
14351137Sarutz door_dp->dd_buffd = -1;
14360Sstevel@tonic-gate door_dp->dd_buf = NULL;
14370Sstevel@tonic-gate door_dp->dd_buf_len = 0;
14380Sstevel@tonic-gate }
14390Sstevel@tonic-gate
14401137Sarutz /* close the (target) device that the Client is operating on */
14411137Sarutz if (door_dp->dd_fd >= 0) {
14421137Sarutz debug(1, "cleanup[%d]: close(%d) target device", pthread_self(),
14431137Sarutz door_dp->dd_fd);
14441137Sarutz if (close(door_dp->dd_fd) < 0) {
14451137Sarutz warning(gettext("cleanup[%d]: close() of target device"
14461137Sarutz "failed = %d\n"), pthread_self(), errno);
14471137Sarutz }
14481137Sarutz }
14491137Sarutz
14501137Sarutz /*
14511137Sarutz * Unbind the current thread from the Client Door's private
14521137Sarutz * thread pool.
14531137Sarutz */
14541137Sarutz debug(1, "cleanup[%d]: door_unbind() of Client Door[%d]",
14551137Sarutz pthread_self(), door_dp->dd_cdoor_descriptor);
14561137Sarutz if (door_unbind() < 0)
14571137Sarutz warning("door_unbind() of Client Door[%d] failed = "
14581137Sarutz "%d", door_dp->dd_cdoor_descriptor, errno);
14591137Sarutz
14601137Sarutz /* Disallow any future requests to the Client Door */
14611137Sarutz if (door_dp->dd_cdoor_descriptor >= 0) {
14621137Sarutz debug(1, "cleanup[%d]: door_revoke() Client Door[%d]",
14631137Sarutz pthread_self(), door_dp->dd_cdoor_descriptor);
14641137Sarutz
14651137Sarutz if (door_revoke(door_dp->dd_cdoor_descriptor) < 0) {
14661137Sarutz warning(gettext("cleanup[%d]: door_revoke() of "
14671137Sarutz "Client Door[%d] failed = %d"), pthread_self(),
14681137Sarutz door_dp->dd_cdoor_descriptor, errno);
14691137Sarutz }
14700Sstevel@tonic-gate }
14711137Sarutz
14720Sstevel@tonic-gate free(door_dp);
14731137Sarutz debug(5, "cleanup[%d] ...exiting\n", pthread_self());
14740Sstevel@tonic-gate }
14750Sstevel@tonic-gate
14761137Sarutz /*
14771137Sarutz * This is the door_server_create(3c) function used to customize
14781137Sarutz * creation of the threads used in the handling of our daemon's
14791137Sarutz * door_call(3c)'s.
14801137Sarutz *
14811137Sarutz * This function is called synchronously as part of door_create(3c).
14821137Sarutz * Note that door_create(), however, is not synchronous; it can return
14831137Sarutz * with the created door file descriptor before any associated
14841137Sarutz * thread has been created. As a result, synchronization is needed
14851137Sarutz * between door_create() caller and the created pthread. This is
14861137Sarutz * needed both when each activity succeeds or when either activity
14871137Sarutz * fails.
14881137Sarutz *
14891137Sarutz * Specifically, this function ensures that each "connection"
14901137Sarutz * with the client creates only one thread in the per-door,
14911137Sarutz * private thread pool. This function locks dd_threadlock and
14921137Sarutz * then calls pthread_create(). If that succeeds, dd_thread
14931137Sarutz * is assigned the thread id, and dd_threadlock is unlocked.
14941137Sarutz * Any per-connection door_create that causes control to flow
14951137Sarutz * to this function will eventually find that dd_thread is
14961137Sarutz * non-zero, and control will exit this function.
14971137Sarutz *
14981137Sarutz * In the current implementation, the door_create for the Client Door
14991137Sarutz * is called first, and the Death Door is door_create'd second.
15001137Sarutz * As a result, the following function can safely make the static
15011137Sarutz * assumption that the first door (within a connection) is the
15021137Sarutz * Client Door. A connection's Client Door and Death Door share
15031137Sarutz * the same thread as well as the same door_data_t instance.
15041137Sarutz */
15050Sstevel@tonic-gate static void
sm_door_server_create(door_info_t * dip)15061137Sarutz sm_door_server_create(door_info_t *dip)
15070Sstevel@tonic-gate {
15080Sstevel@tonic-gate door_data_t *door_dp;
15090Sstevel@tonic-gate pthread_t tid;
15100Sstevel@tonic-gate pthread_attr_t attr;
15110Sstevel@tonic-gate int ret_val;
15121137Sarutz int err;
15130Sstevel@tonic-gate
15140Sstevel@tonic-gate if (dip == NULL) {
15150Sstevel@tonic-gate return;
15160Sstevel@tonic-gate }
1517796Smathue door_dp = (door_data_t *)(uintptr_t)dip->di_data;
15180Sstevel@tonic-gate
15191137Sarutz debug(10, "sm_door_server_create[%d]: entering...\n", pthread_self());
15200Sstevel@tonic-gate
15210Sstevel@tonic-gate /* create one thread for this door */
15220Sstevel@tonic-gate
15230Sstevel@tonic-gate (void) mutex_lock(&door_dp->dd_threadlock);
15240Sstevel@tonic-gate
15250Sstevel@tonic-gate if (door_dp->dd_thread != 0) {
15261137Sarutz debug(8, "sm_door_server_create[%d]: Exiting without creating "
15271137Sarutz "thread.\n", pthread_self());
15280Sstevel@tonic-gate (void) mutex_unlock(&door_dp->dd_threadlock);
15290Sstevel@tonic-gate return;
15300Sstevel@tonic-gate }
15310Sstevel@tonic-gate
15320Sstevel@tonic-gate (void) pthread_attr_init(&attr);
15331137Sarutz
15341137Sarutz if ((err = pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM)) != 0)
15351137Sarutz warning(gettext("pthread_attr_setscope failed = %d\n"), err);
15361137Sarutz if ((err = pthread_attr_setdetachstate(&attr,
15371137Sarutz PTHREAD_CREATE_DETACHED)) != 0)
15381137Sarutz warning(gettext("pthread_attr_setdetachstate failed = %d\n"),
15391137Sarutz err);
15401137Sarutz
15411137Sarutz ret_val = pthread_create(&tid, &attr, sm_server_thread,
15421137Sarutz (void *)(uintptr_t)(dip->di_data));
15430Sstevel@tonic-gate if (ret_val != 0) {
15441137Sarutz warning(gettext("sm_door_server_create[%d]: pthread_create "
15451137Sarutz "failed = %d\n"), pthread_self(), ret_val);
15460Sstevel@tonic-gate (void) mutex_unlock(&door_dp->dd_threadlock);
15470Sstevel@tonic-gate (void) pthread_attr_destroy(&attr);
15480Sstevel@tonic-gate return;
15490Sstevel@tonic-gate }
15500Sstevel@tonic-gate (void) pthread_attr_destroy(&attr);
15510Sstevel@tonic-gate door_dp->dd_thread = tid;
15520Sstevel@tonic-gate
15530Sstevel@tonic-gate (void) mutex_unlock(&door_dp->dd_threadlock);
15541137Sarutz debug(5, "Exiting sm_door_server_create[%d] after creating thr[%d].\n",
15551137Sarutz pthread_self(), tid);
15560Sstevel@tonic-gate }
15570Sstevel@tonic-gate
15580Sstevel@tonic-gate static void
door_ret_err(smedia_reterror_t * reterror,int32_t err)15590Sstevel@tonic-gate door_ret_err(smedia_reterror_t *reterror, int32_t err)
15600Sstevel@tonic-gate {
15610Sstevel@tonic-gate reterror->cnum = SMEDIA_CNUM_ERROR;
15620Sstevel@tonic-gate reterror->errnum = err;
15630Sstevel@tonic-gate (void) door_return((char *)reterror, sizeof (smedia_reterror_t), 0, 0);
15640Sstevel@tonic-gate }
15650Sstevel@tonic-gate
15660Sstevel@tonic-gate static void
my_door_return(char * data_ptr,size_t data_size,door_desc_t * desc_ptr,uint_t num_desc)15670Sstevel@tonic-gate my_door_return(char *data_ptr, size_t data_size,
15680Sstevel@tonic-gate door_desc_t *desc_ptr, uint_t num_desc)
15690Sstevel@tonic-gate {
15700Sstevel@tonic-gate (void) door_return(data_ptr, data_size, desc_ptr, num_desc);
15710Sstevel@tonic-gate }
15720Sstevel@tonic-gate
15730Sstevel@tonic-gate static int32_t
raw_read(door_data_t * door_dp,smedia_services_t * req)15740Sstevel@tonic-gate raw_read(door_data_t *door_dp, smedia_services_t *req)
15750Sstevel@tonic-gate {
15760Sstevel@tonic-gate struct uscsi_cmd ucmd;
15770Sstevel@tonic-gate union scsi_cdb cdb;
15780Sstevel@tonic-gate int32_t ret_val;
15790Sstevel@tonic-gate int32_t num_sectors, sector_size;
15800Sstevel@tonic-gate int32_t rc_data[2];
15810Sstevel@tonic-gate char rq_data[RQ_LEN];
15820Sstevel@tonic-gate
15830Sstevel@tonic-gate (void) memset((void *) &rc_data, 0, sizeof (rc_data));
15840Sstevel@tonic-gate (void) memset((void *) &ucmd, 0, sizeof (ucmd));
15850Sstevel@tonic-gate (void) memset((void *) &cdb, 0, sizeof (union scsi_cdb));
15860Sstevel@tonic-gate
15870Sstevel@tonic-gate if (door_dp->dd_sector_size == 0) {
15880Sstevel@tonic-gate sector_size = get_sector_size(door_dp->dd_fd);
15890Sstevel@tonic-gate door_dp->dd_sector_size = sector_size;
15900Sstevel@tonic-gate } else sector_size = door_dp->dd_sector_size;
15910Sstevel@tonic-gate
15920Sstevel@tonic-gate if ((req->reqraw_read.nbytes > door_dp->dd_buf_len) ||
15930Sstevel@tonic-gate (door_dp->dd_buf == NULL)) {
15940Sstevel@tonic-gate errno = EINVAL;
15950Sstevel@tonic-gate return (-1);
15960Sstevel@tonic-gate }
15970Sstevel@tonic-gate if ((!req->reqraw_read.nbytes) ||
15980Sstevel@tonic-gate (req->reqraw_read.nbytes % sector_size)) {
15990Sstevel@tonic-gate errno = EINVAL;
16000Sstevel@tonic-gate return (-1);
16010Sstevel@tonic-gate }
16020Sstevel@tonic-gate
16030Sstevel@tonic-gate (void) memset((void *) &cdb, 0, sizeof (cdb));
16040Sstevel@tonic-gate num_sectors = (uint32_t)req->reqraw_read.nbytes/sector_size;
16050Sstevel@tonic-gate
16060Sstevel@tonic-gate cdb.scc_cmd = SCMD_READ_G1;
16070Sstevel@tonic-gate FORMG1ADDR(&cdb, (uint32_t)req->reqraw_read.blockno);
16080Sstevel@tonic-gate FORMG1COUNT(&cdb, num_sectors);
16090Sstevel@tonic-gate
16100Sstevel@tonic-gate ucmd.uscsi_cdb = (caddr_t)&cdb;
16110Sstevel@tonic-gate ucmd.uscsi_cdblen = CDB_GROUP1;
16120Sstevel@tonic-gate ucmd.uscsi_bufaddr = (caddr_t)door_dp->dd_buf;
16130Sstevel@tonic-gate ucmd.uscsi_buflen = (uint32_t)req->reqraw_read.nbytes;
16140Sstevel@tonic-gate ucmd.uscsi_timeout = 120; /* If 0, HBA hangs forever */
16150Sstevel@tonic-gate ucmd.uscsi_rqlen = RQ_LEN;
16160Sstevel@tonic-gate ucmd.uscsi_rqbuf = rq_data;
16170Sstevel@tonic-gate ret_val = do_uscsi_cmd(door_dp->dd_fd,
16180Sstevel@tonic-gate &ucmd, USCSI_READ|USCSI_RQENABLE);
16190Sstevel@tonic-gate if (ret_val || ucmd.uscsi_status) {
16200Sstevel@tonic-gate debug(5, "read failed: %d - %d errno = %d\n",
16210Sstevel@tonic-gate ret_val, ucmd.uscsi_status, errno);
16220Sstevel@tonic-gate debug(5, "buflen = 0x%x resid = 0x%x sector size = %d\n",
16230Sstevel@tonic-gate ucmd.uscsi_buflen, ucmd.uscsi_resid, sector_size);
16240Sstevel@tonic-gate debug(5, "cdb addr: %x %x %x %x \n", cdb.g1_addr3,
16250Sstevel@tonic-gate cdb.g1_addr2, cdb.g1_addr1, cdb.g1_addr0);
16260Sstevel@tonic-gate debug(5, "cdb count: %x %x\n", cdb.g1_count1,
16270Sstevel@tonic-gate cdb.g1_count0);
16280Sstevel@tonic-gate return (-1);
16290Sstevel@tonic-gate }
16300Sstevel@tonic-gate ret_val = ucmd.uscsi_buflen - ucmd.uscsi_resid;
16310Sstevel@tonic-gate return (ret_val);
16320Sstevel@tonic-gate }
16330Sstevel@tonic-gate
16340Sstevel@tonic-gate static int32_t
raw_write(door_data_t * door_dp,smedia_services_t * req)16350Sstevel@tonic-gate raw_write(door_data_t *door_dp, smedia_services_t *req)
16360Sstevel@tonic-gate {
16370Sstevel@tonic-gate struct uscsi_cmd ucmd;
16380Sstevel@tonic-gate union scsi_cdb cdb;
16390Sstevel@tonic-gate int32_t ret_val;
16400Sstevel@tonic-gate int32_t num_sectors, sector_size;
16410Sstevel@tonic-gate int32_t rc_data[2];
16420Sstevel@tonic-gate char rq_data[RQ_LEN];
16430Sstevel@tonic-gate
16440Sstevel@tonic-gate (void) memset((void *) &rc_data, 0, sizeof (rc_data));
16450Sstevel@tonic-gate (void) memset((void *) &ucmd, 0, sizeof (ucmd));
16460Sstevel@tonic-gate (void) memset((void *) &cdb, 0, sizeof (union scsi_cdb));
16470Sstevel@tonic-gate
16480Sstevel@tonic-gate if (door_dp->dd_sector_size == 0) {
16490Sstevel@tonic-gate sector_size = get_sector_size(door_dp->dd_fd);
16500Sstevel@tonic-gate door_dp->dd_sector_size = sector_size;
16510Sstevel@tonic-gate } else sector_size = door_dp->dd_sector_size;
16520Sstevel@tonic-gate
16530Sstevel@tonic-gate
16540Sstevel@tonic-gate if ((req->reqraw_write.nbytes > door_dp->dd_buf_len) ||
16550Sstevel@tonic-gate (door_dp->dd_buf == NULL)) {
16560Sstevel@tonic-gate errno = EINVAL;
16570Sstevel@tonic-gate return (-1);
16580Sstevel@tonic-gate }
16590Sstevel@tonic-gate if ((req->reqraw_write.nbytes % sector_size)) {
16600Sstevel@tonic-gate errno = EINVAL;
16610Sstevel@tonic-gate return (-1);
16620Sstevel@tonic-gate }
16630Sstevel@tonic-gate
16640Sstevel@tonic-gate (void) memset((void *) &cdb, 0, sizeof (cdb));
16650Sstevel@tonic-gate num_sectors = (uint32_t)req->reqraw_write.nbytes/sector_size;
16660Sstevel@tonic-gate
16670Sstevel@tonic-gate cdb.scc_cmd = SCMD_WRITE_G1;
16680Sstevel@tonic-gate FORMG1ADDR(&cdb, (uint32_t)req->reqraw_write.blockno);
16690Sstevel@tonic-gate FORMG1COUNT(&cdb, num_sectors);
16700Sstevel@tonic-gate
16710Sstevel@tonic-gate ucmd.uscsi_cdb = (caddr_t)&cdb;
16720Sstevel@tonic-gate ucmd.uscsi_cdblen = CDB_GROUP1;
16730Sstevel@tonic-gate ucmd.uscsi_bufaddr = (caddr_t)door_dp->dd_buf;
16740Sstevel@tonic-gate ucmd.uscsi_buflen = (uint32_t)req->reqraw_write.nbytes;
16750Sstevel@tonic-gate ucmd.uscsi_timeout = 120; /* If 0, HBA hangs forever */
16760Sstevel@tonic-gate ucmd.uscsi_rqlen = RQ_LEN;
16770Sstevel@tonic-gate ucmd.uscsi_rqbuf = rq_data;
16780Sstevel@tonic-gate ret_val = do_uscsi_cmd(door_dp->dd_fd,
16790Sstevel@tonic-gate &ucmd, USCSI_WRITE|USCSI_RQENABLE);
16800Sstevel@tonic-gate if (ret_val || ucmd.uscsi_status) {
16810Sstevel@tonic-gate debug(5, "write failed: %d - %d errno = %d\n",
16820Sstevel@tonic-gate ret_val, ucmd.uscsi_status, errno);
16830Sstevel@tonic-gate debug(5, "buflen = 0x%x resid = 0x%x sector size = %d\n",
16840Sstevel@tonic-gate ucmd.uscsi_buflen, ucmd.uscsi_resid, sector_size);
16850Sstevel@tonic-gate debug(5, "cdb addr: %x %x %x %x \n", cdb.g1_addr3,
16860Sstevel@tonic-gate cdb.g1_addr2, cdb.g1_addr1, cdb.g1_addr0);
16870Sstevel@tonic-gate debug(5, "cdb count: %x %x\n", cdb.g1_count1,
16880Sstevel@tonic-gate cdb.g1_count0);
16890Sstevel@tonic-gate return (-1);
16900Sstevel@tonic-gate }
16910Sstevel@tonic-gate ret_val = ucmd.uscsi_buflen - ucmd.uscsi_resid;
16920Sstevel@tonic-gate return (ret_val);
16930Sstevel@tonic-gate }
16940Sstevel@tonic-gate
16950Sstevel@tonic-gate static int32_t
set_protection_status(door_data_t * door_dp,smedia_services_t * req)16960Sstevel@tonic-gate set_protection_status(door_data_t *door_dp, smedia_services_t *req)
16970Sstevel@tonic-gate {
16980Sstevel@tonic-gate int32_t ret_val, saved_errno, status;
16990Sstevel@tonic-gate struct scsi_inquiry inq;
17000Sstevel@tonic-gate char vid[9];
17010Sstevel@tonic-gate char pid[17];
17020Sstevel@tonic-gate struct passwd *pwd;
17030Sstevel@tonic-gate char uname[MAXUGNAME + 1];
17040Sstevel@tonic-gate char *new_state, *old_state;
17050Sstevel@tonic-gate
17060Sstevel@tonic-gate /*
17070Sstevel@tonic-gate * Read the current protection state before modifiying.
17080Sstevel@tonic-gate * Needed for audit purposes.
17090Sstevel@tonic-gate */
17100Sstevel@tonic-gate switch (get_device_type_scsi(door_dp->dd_fd, &inq)) {
17110Sstevel@tonic-gate case SCSI_IOMEGA:
17120Sstevel@tonic-gate status = scsi_zip_media_status(door_dp->dd_fd);
17130Sstevel@tonic-gate ret_val = scsi_zip_write_protect(door_dp->dd_fd,
17140Sstevel@tonic-gate &req->reqset_protection_status.prot_state);
17150Sstevel@tonic-gate break;
17160Sstevel@tonic-gate case SCSI_FLOPPY:
17170Sstevel@tonic-gate info("Formatting floppy");
17180Sstevel@tonic-gate status = scsi_floppy_media_status(door_dp->dd_fd);
17190Sstevel@tonic-gate ret_val = scsi_floppy_write_protect(door_dp->dd_fd,
17200Sstevel@tonic-gate &req->reqset_protection_status.prot_state);
17210Sstevel@tonic-gate break;
17220Sstevel@tonic-gate case SCSI_GENERIC:
17230Sstevel@tonic-gate status = scsi_media_status(door_dp->dd_fd);
17240Sstevel@tonic-gate ret_val = scsi_write_protect(door_dp->dd_fd,
17250Sstevel@tonic-gate &req->reqset_protection_status.prot_state);
17260Sstevel@tonic-gate break;
17270Sstevel@tonic-gate }
17280Sstevel@tonic-gate
17290Sstevel@tonic-gate saved_errno = errno;
17300Sstevel@tonic-gate new_state = xlate_state(
17310Sstevel@tonic-gate req->reqset_protection_status.prot_state.sm_new_state);
17320Sstevel@tonic-gate old_state = xlate_state(status);
17330Sstevel@tonic-gate
17340Sstevel@tonic-gate if (can_audit()) {
17350Sstevel@tonic-gate (void) audit_save_me(door_dp);
17360Sstevel@tonic-gate door_dp->audit_text[0] = 0;
17370Sstevel@tonic-gate door_dp->audit_text1[0] = 0;
17380Sstevel@tonic-gate door_dp->audit_event = AUE_smserverd;
17390Sstevel@tonic-gate }
17400Sstevel@tonic-gate (void) strlcpy(vid, inq.inq_vid, sizeof (vid));
17410Sstevel@tonic-gate (void) strlcpy(pid, inq.inq_pid, sizeof (pid));
17420Sstevel@tonic-gate if (ret_val < 0) {
17430Sstevel@tonic-gate if (errno == EACCES) {
17440Sstevel@tonic-gate pwd = getpwuid(door_dp->dd_cred.dc_ruid);
17450Sstevel@tonic-gate if (pwd != NULL) {
17460Sstevel@tonic-gate (void) strlcpy(uname,
17470Sstevel@tonic-gate pwd->pw_name, MAXUGNAME);
17480Sstevel@tonic-gate } else uname[0] = 0;
17490Sstevel@tonic-gate
17500Sstevel@tonic-gate if (can_audit()) {
17510Sstevel@tonic-gate (void) snprintf(door_dp->audit_text,
17520Sstevel@tonic-gate sizeof (door_dp->audit_text),
17530Sstevel@tonic-gate dgettext(TEXT_DOMAIN, "from %s to %s"),
17540Sstevel@tonic-gate old_state, new_state);
17550Sstevel@tonic-gate
17560Sstevel@tonic-gate (void) snprintf(door_dp->audit_text1,
17570Sstevel@tonic-gate sizeof (door_dp->audit_text1),
17580Sstevel@tonic-gate "%s %s (%d,%d)", vid, pid,
17590Sstevel@tonic-gate (int)major(door_dp->dd_stat.st_rdev),
17600Sstevel@tonic-gate (int)minor(door_dp->dd_stat.st_rdev));
17610Sstevel@tonic-gate
17620Sstevel@tonic-gate door_dp->audit_sorf = 1;
17630Sstevel@tonic-gate if (audit_audit(door_dp) == -1)
17640Sstevel@tonic-gate warning("Error in writing audit info\n");
17650Sstevel@tonic-gate }
17660Sstevel@tonic-gate } /* errno == EACCES */
17670Sstevel@tonic-gate errno = saved_errno;
17680Sstevel@tonic-gate return (-1);
17690Sstevel@tonic-gate }
17700Sstevel@tonic-gate if (can_audit()) {
17710Sstevel@tonic-gate (void) snprintf(door_dp->audit_text,
17720Sstevel@tonic-gate sizeof (door_dp->audit_text),
17730Sstevel@tonic-gate dgettext(TEXT_DOMAIN, "from %s to %s"),
17740Sstevel@tonic-gate old_state, new_state);
17750Sstevel@tonic-gate
17760Sstevel@tonic-gate (void) snprintf(door_dp->audit_text1,
17770Sstevel@tonic-gate sizeof (door_dp->audit_text1),
17780Sstevel@tonic-gate "%s %s (%d,%d)", vid, pid,
17790Sstevel@tonic-gate (int)major(door_dp->dd_stat.st_rdev),
17800Sstevel@tonic-gate (int)minor(door_dp->dd_stat.st_rdev));
17810Sstevel@tonic-gate
17820Sstevel@tonic-gate door_dp->audit_sorf = 0;
17830Sstevel@tonic-gate if (audit_audit(door_dp) == -1)
17840Sstevel@tonic-gate warning("Error in writing audit info\n");
17850Sstevel@tonic-gate }
17860Sstevel@tonic-gate errno = saved_errno;
17870Sstevel@tonic-gate return (0);
17880Sstevel@tonic-gate }
17890Sstevel@tonic-gate
17900Sstevel@tonic-gate static int32_t
set_shfd(door_data_t * door_dp,int32_t fd,smedia_services_t * req)17911137Sarutz set_shfd(door_data_t *door_dp, int32_t fd, smedia_services_t *req)
17920Sstevel@tonic-gate {
17930Sstevel@tonic-gate void *fbuf;
17941137Sarutz int32_t ret_val = 0;
17951137Sarutz
17961137Sarutz if ((door_dp->dd_buffd != -1) && (door_dp->dd_buf != NULL)) {
17971137Sarutz ret_val = munmap(door_dp->dd_buf, door_dp->dd_buf_len);
17981137Sarutz if (ret_val == -1)
17991137Sarutz warning(gettext("munmap failed. errno=%d\n"),
18001137Sarutz errno);
18011137Sarutz (void) close(door_dp->dd_buffd);
18021137Sarutz
18031137Sarutz door_dp->dd_buffd = -1;
18041137Sarutz door_dp->dd_buf = 0;
18051137Sarutz door_dp->dd_buf_len = 0;
18060Sstevel@tonic-gate }
18071137Sarutz
18080Sstevel@tonic-gate fbuf = mmap(0, req->reqset_shfd.fdbuf_len,
18091137Sarutz PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
18101137Sarutz if (fbuf == MAP_FAILED) {
18111137Sarutz ret_val = errno;
18120Sstevel@tonic-gate debug(5, "mmap failed. errno=%d\n", errno);
18131137Sarutz return (ret_val);
18140Sstevel@tonic-gate }
18150Sstevel@tonic-gate door_dp->dd_buffd = fd;
18160Sstevel@tonic-gate door_dp->dd_buf = fbuf;
18170Sstevel@tonic-gate door_dp->dd_buf_len = req->reqset_shfd.fdbuf_len;
18181137Sarutz
18190Sstevel@tonic-gate return (0);
18200Sstevel@tonic-gate }
18210Sstevel@tonic-gate
18220Sstevel@tonic-gate static int32_t
reassign_block(door_data_t * door_dp,smedia_services_t * req)18230Sstevel@tonic-gate reassign_block(door_data_t *door_dp, smedia_services_t *req)
18240Sstevel@tonic-gate {
18250Sstevel@tonic-gate struct uscsi_cmd ucmd;
18260Sstevel@tonic-gate union scsi_cdb cdb;
18270Sstevel@tonic-gate int32_t ret_val;
18280Sstevel@tonic-gate int32_t sector_size;
18290Sstevel@tonic-gate char *read_buf;
18300Sstevel@tonic-gate uchar_t mode_data[MD_LEN];
18310Sstevel@tonic-gate
18320Sstevel@tonic-gate if (get_mode_page(door_dp->dd_fd, 0, 1,
18331137Sarutz mode_data, MD_LEN) < 0) {
18340Sstevel@tonic-gate debug(5, "Mode sense failed\n");
18350Sstevel@tonic-gate ret_val = scsi_reassign_block(door_dp->dd_fd,
18361137Sarutz req->reqreassign_block.blockno);
18370Sstevel@tonic-gate if (ret_val != 0)
18380Sstevel@tonic-gate return (-1);
18390Sstevel@tonic-gate return (0);
18400Sstevel@tonic-gate }
18410Sstevel@tonic-gate
18420Sstevel@tonic-gate /*
18430Sstevel@tonic-gate * No need to check if enough data is returned for
18440Sstevel@tonic-gate * AWRE bit or not.
18450Sstevel@tonic-gate * It will be 0 otherwise which needs to reassign the block.
18460Sstevel@tonic-gate */
18470Sstevel@tonic-gate if (!(mode_data[AWRE_OFFSET] & AWRE)) {
18480Sstevel@tonic-gate debug(5, "AWRE bit not set\n");
18490Sstevel@tonic-gate ret_val = scsi_reassign_block(door_dp->dd_fd,
18500Sstevel@tonic-gate req->reqreassign_block.blockno);
18510Sstevel@tonic-gate if (ret_val != 0)
18520Sstevel@tonic-gate return (-1);
18530Sstevel@tonic-gate return (0);
18540Sstevel@tonic-gate }
18550Sstevel@tonic-gate sector_size = (mode_data[BLOCK_LEN_OFFSET] << 16) |
18560Sstevel@tonic-gate (mode_data[BLOCK_LEN_OFFSET + 1] << 8) |
18570Sstevel@tonic-gate mode_data[BLOCK_LEN_OFFSET + 2];
18580Sstevel@tonic-gate
18590Sstevel@tonic-gate debug(5, "REASSIGN BLOCK: sec size = 0x%x\n", sector_size);
18600Sstevel@tonic-gate read_buf = (char *)malloc(sector_size);
18610Sstevel@tonic-gate if (read_buf == NULL) {
18620Sstevel@tonic-gate /* Alloc failed. Atleast reassign the block */
18630Sstevel@tonic-gate ret_val = scsi_reassign_block(door_dp->dd_fd,
18640Sstevel@tonic-gate req->reqreassign_block.blockno);
18650Sstevel@tonic-gate if (ret_val != 0)
18660Sstevel@tonic-gate return (-1);
18670Sstevel@tonic-gate return (0);
18680Sstevel@tonic-gate }
18690Sstevel@tonic-gate
18700Sstevel@tonic-gate (void) memset(read_buf, 0, sector_size);
18710Sstevel@tonic-gate /* Read the sector */
18720Sstevel@tonic-gate debug(5, "Reading the block %d\n",
18730Sstevel@tonic-gate (uint32_t)req->reqreassign_block.blockno);
18740Sstevel@tonic-gate
18750Sstevel@tonic-gate (void) memset((void *) &ucmd, 0, sizeof (ucmd));
18760Sstevel@tonic-gate (void) memset((void *) &cdb, 0, sizeof (union scsi_cdb));
18770Sstevel@tonic-gate
18780Sstevel@tonic-gate cdb.scc_cmd = SCMD_READ_G1;
18790Sstevel@tonic-gate FORMG1ADDR(&cdb, req->reqreassign_block.blockno);
18800Sstevel@tonic-gate FORMG1COUNT(&cdb, 1); /* One block */
18810Sstevel@tonic-gate
18820Sstevel@tonic-gate ucmd.uscsi_cdb = (caddr_t)&cdb;
18830Sstevel@tonic-gate ucmd.uscsi_cdblen = CDB_GROUP1;
18840Sstevel@tonic-gate ucmd.uscsi_bufaddr = (caddr_t)read_buf;
18850Sstevel@tonic-gate ucmd.uscsi_buflen = sector_size;
18860Sstevel@tonic-gate ucmd.uscsi_timeout = 120; /* If 0, HBA hangs forever */
18870Sstevel@tonic-gate (void) do_uscsi_cmd(door_dp->dd_fd, &ucmd, USCSI_READ);
18880Sstevel@tonic-gate
18890Sstevel@tonic-gate /* Write the data back */
18900Sstevel@tonic-gate
18910Sstevel@tonic-gate debug(5, "Writing the block %d\n",
18920Sstevel@tonic-gate (uint32_t)req->reqreassign_block.blockno);
18930Sstevel@tonic-gate (void) memset((void *) &ucmd, 0, sizeof (ucmd));
18940Sstevel@tonic-gate (void) memset((void *) &cdb, 0, sizeof (cdb));
18950Sstevel@tonic-gate
18960Sstevel@tonic-gate cdb.scc_cmd = SCMD_WRITE_G1;
18970Sstevel@tonic-gate FORMG1ADDR(&cdb, req->reqreassign_block.blockno);
18980Sstevel@tonic-gate FORMG1COUNT(&cdb, 1); /* One block */
18990Sstevel@tonic-gate
19000Sstevel@tonic-gate ucmd.uscsi_cdb = (caddr_t)&cdb;
19010Sstevel@tonic-gate ucmd.uscsi_cdblen = CDB_GROUP1;
19020Sstevel@tonic-gate ucmd.uscsi_bufaddr = (caddr_t)read_buf;
19030Sstevel@tonic-gate ucmd.uscsi_buflen = sector_size;
19040Sstevel@tonic-gate ucmd.uscsi_timeout = 120; /* If 0, HBA hangs forever */
19050Sstevel@tonic-gate ret_val = do_uscsi_cmd(door_dp->dd_fd, &ucmd, USCSI_WRITE);
19060Sstevel@tonic-gate free(read_buf);
19070Sstevel@tonic-gate if (ret_val || ucmd.uscsi_status) {
19080Sstevel@tonic-gate debug(5, "Reassign failed: %d - %d errno = %d\n",
19090Sstevel@tonic-gate ret_val, ucmd.uscsi_status, errno);
19100Sstevel@tonic-gate ret_val = scsi_reassign_block(door_dp->dd_fd,
19110Sstevel@tonic-gate req->reqreassign_block.blockno);
19120Sstevel@tonic-gate if (ret_val != 0)
19130Sstevel@tonic-gate return (-1);
19140Sstevel@tonic-gate return (0);
19150Sstevel@tonic-gate }
19160Sstevel@tonic-gate
19170Sstevel@tonic-gate return (0);
19180Sstevel@tonic-gate }
19190Sstevel@tonic-gate
19200Sstevel@tonic-gate static void
close_door_descs(door_desc_t * dp,uint_t ndesc)19210Sstevel@tonic-gate close_door_descs(door_desc_t *dp, uint_t ndesc)
19220Sstevel@tonic-gate {
19230Sstevel@tonic-gate while (ndesc > 0) {
19240Sstevel@tonic-gate int fd = dp->d_data.d_desc.d_descriptor;
19250Sstevel@tonic-gate if (dp->d_attributes & DOOR_DESCRIPTOR)
19260Sstevel@tonic-gate (void) close(fd);
19270Sstevel@tonic-gate dp++;
19280Sstevel@tonic-gate ndesc--;
19290Sstevel@tonic-gate }
19300Sstevel@tonic-gate }
19310Sstevel@tonic-gate
19321137Sarutz /*
19331137Sarutz * This is a Death Door's service procedure.
19341137Sarutz *
19351137Sarutz * This procedure is a NOP because the Death Door functionality
19361137Sarutz * is no longer used and will be removed in the future.
19371137Sarutz */
19381137Sarutz /*ARGSUSED*/
19390Sstevel@tonic-gate static void
death_servproc(void * cookie,char * argp,size_t arg_size,door_desc_t * dp,uint_t ndesc)19401137Sarutz death_servproc(void *cookie, char *argp, size_t arg_size,
19411137Sarutz door_desc_t *dp, uint_t ndesc)
19421137Sarutz {
19431137Sarutz debug(1, "death_servproc[%d]: argp = 0x%p "
19441137Sarutz "Death Door[%d]\n", pthread_self(), (void *)argp,
19451137Sarutz ((door_data_t *)cookie)->dd_ddoor_descriptor);
19461137Sarutz
19471137Sarutz (void) door_return(NULL, 0, NULL, 0);
19481137Sarutz }
19491137Sarutz
19501137Sarutz /*
19511137Sarutz * This is a Client Door's service procedure.
19521137Sarutz *
19531137Sarutz * This procedure is specified in the door_create() of a Client Door,
19541137Sarutz * and its functionality represents the bulk of services that the
19551137Sarutz * rpc.smserverd daemon offers.
19561137Sarutz */
19571137Sarutz static void
client_servproc(void * cookie,char * argp,size_t arg_size,door_desc_t * dp,uint_t ndesc)19581137Sarutz client_servproc(void *cookie, char *argp, size_t arg_size,
19590Sstevel@tonic-gate door_desc_t *dp, uint_t ndesc)
19600Sstevel@tonic-gate {
19610Sstevel@tonic-gate smedia_services_t *req;
19620Sstevel@tonic-gate smedia_services_t rmsvc;
19630Sstevel@tonic-gate smedia_reterror_t reterror;
19640Sstevel@tonic-gate smedia_retraw_read_t retraw_read;
19650Sstevel@tonic-gate struct scsi_inquiry inq;
19660Sstevel@tonic-gate struct dk_minfo media_info;
19670Sstevel@tonic-gate struct dk_geom dkgeom;
19680Sstevel@tonic-gate int32_t status;
19690Sstevel@tonic-gate uchar_t data[18];
19700Sstevel@tonic-gate int32_t completed = 0;
19710Sstevel@tonic-gate door_data_t *door_dp;
19720Sstevel@tonic-gate size_t retbuf_size;
19730Sstevel@tonic-gate struct uscsi_cmd ucmd;
19740Sstevel@tonic-gate union scsi_cdb cdb;
19750Sstevel@tonic-gate int32_t ret_val, err;
19760Sstevel@tonic-gate char rq_data[RQ_LEN];
19771137Sarutz uint_t nexpected_desc;
19780Sstevel@tonic-gate struct vtoc vtoc;
1979*7563SPrasad.Singamsetty@Sun.COM struct extvtoc extvtoc;
19800Sstevel@tonic-gate
19810Sstevel@tonic-gate door_dp = (door_data_t *)cookie;
19820Sstevel@tonic-gate req = (smedia_services_t *)((void *)argp);
19830Sstevel@tonic-gate
19841137Sarutz debug(10, "client_servproc[%d]...\n", pthread_self());
19850Sstevel@tonic-gate
19860Sstevel@tonic-gate if (argp == DOOR_UNREF_DATA) {
19871137Sarutz debug(5, "client_servproc[%d]: req = DOOR_UNREF_DATA\n",
19881137Sarutz pthread_self());
19890Sstevel@tonic-gate debug(5, "Client has exited. Cleaning up resources\n");
19901137Sarutz
19910Sstevel@tonic-gate (void) mutex_lock(&svcstate_lock);
19920Sstevel@tonic-gate svccount--;
19930Sstevel@tonic-gate (void) mutex_unlock(&svcstate_lock);
19941137Sarutz
19950Sstevel@tonic-gate cleanup(door_dp);
19961137Sarutz return;
19970Sstevel@tonic-gate }
19981137Sarutz
19990Sstevel@tonic-gate (void) mutex_lock(&svcstate_lock);
20000Sstevel@tonic-gate svcstate = _SERVED;
20010Sstevel@tonic-gate (void) mutex_unlock(&svcstate_lock);
20020Sstevel@tonic-gate
20030Sstevel@tonic-gate rmsvc.in.cnum = req->in.cnum;
20041137Sarutz debug(5, "client_servproc[%d]: req = %s\n", pthread_self(),
20051137Sarutz xlate_cnum(req->in.cnum));
20060Sstevel@tonic-gate
20070Sstevel@tonic-gate /*
20080Sstevel@tonic-gate * Our caller may have passed more descriptors than we expected.
20090Sstevel@tonic-gate * If so, we silently close (and ignore) them.
20100Sstevel@tonic-gate */
20111137Sarutz nexpected_desc = (req->in.cnum == SMEDIA_CNUM_SET_SHFD) ? 1 : 0;
20121137Sarutz if (ndesc > nexpected_desc) {
20131137Sarutz close_door_descs(dp + nexpected_desc, ndesc - nexpected_desc);
20141137Sarutz }
20150Sstevel@tonic-gate
20160Sstevel@tonic-gate switch (req->in.cnum) {
20170Sstevel@tonic-gate default:
20181137Sarutz debug(5, "client_servproc: unknown command %d\n", req->in.cnum);
20190Sstevel@tonic-gate door_ret_err(&reterror, ENOTSUP);
20200Sstevel@tonic-gate break;
20210Sstevel@tonic-gate
20221137Sarutz case SMEDIA_CNUM_SET_SHFD:
20230Sstevel@tonic-gate if (ndesc == 0)
20240Sstevel@tonic-gate door_ret_err(&reterror, EINVAL);
20250Sstevel@tonic-gate /*
20261137Sarutz * Allocate shared memory for this connection.
20271137Sarutz * If this connection already has shared memory,
20281137Sarutz * deallocate before doing the allocation.
20290Sstevel@tonic-gate */
20301137Sarutz ret_val = set_shfd(door_dp, dp->d_data.d_desc.d_descriptor,
20311137Sarutz req);
20320Sstevel@tonic-gate if (ret_val == 0) {
20330Sstevel@tonic-gate reterror.cnum = SMEDIA_CNUM_SET_SHFD;
20340Sstevel@tonic-gate reterror.errnum = 0;
20351137Sarutz
20360Sstevel@tonic-gate my_door_return((char *)&reterror,
20370Sstevel@tonic-gate sizeof (smedia_reterror_t), 0, 0);
20380Sstevel@tonic-gate } else {
20390Sstevel@tonic-gate (void) close(dp->d_data.d_desc.d_descriptor);
20401137Sarutz door_ret_err(&reterror, ret_val);
20410Sstevel@tonic-gate }
20420Sstevel@tonic-gate break;
20430Sstevel@tonic-gate
20441137Sarutz case SMEDIA_CNUM_RAW_READ:
20450Sstevel@tonic-gate debug(10, " arg size = %d blk num=0x%x nbytes = 0x%x \n",
20460Sstevel@tonic-gate (int)arg_size,
20470Sstevel@tonic-gate (uint32_t)req->reqraw_read.blockno,
20480Sstevel@tonic-gate req->reqraw_read.nbytes);
20490Sstevel@tonic-gate retbuf_size = sizeof (smedia_retraw_read_t);
20500Sstevel@tonic-gate if (req->reqraw_read.nbytes == 0) {
20510Sstevel@tonic-gate /* Nothing to write */
20520Sstevel@tonic-gate rmsvc.retraw_write.nbytes = 0;
20530Sstevel@tonic-gate my_door_return((char *)&rmsvc,
20540Sstevel@tonic-gate sizeof (smedia_retraw_write_t), 0, 0);
20550Sstevel@tonic-gate }
20560Sstevel@tonic-gate retraw_read.cnum = SMEDIA_CNUM_RAW_READ;
20570Sstevel@tonic-gate ret_val = raw_read(door_dp, req);
20580Sstevel@tonic-gate if (ret_val == -1) {
20590Sstevel@tonic-gate door_ret_err(&reterror, errno);
20600Sstevel@tonic-gate }
20610Sstevel@tonic-gate retraw_read.nbytes = ret_val;
20620Sstevel@tonic-gate my_door_return((char *)&retraw_read, retbuf_size, 0, 0);
20630Sstevel@tonic-gate break;
20640Sstevel@tonic-gate
20650Sstevel@tonic-gate case SMEDIA_CNUM_USCSI_CMD:
20660Sstevel@tonic-gate retbuf_size = sizeof (smedia_retuscsi_cmd_t);
20670Sstevel@tonic-gate rmsvc.retuscsi_cmd.cnum = SMEDIA_CNUM_USCSI_CMD;
20680Sstevel@tonic-gate ucmd.uscsi_flags = req->requscsi_cmd.uscsi_flags;
20690Sstevel@tonic-gate ucmd.uscsi_cdb = (caddr_t)&req->requscsi_cmd.uscsi_cdb;
20700Sstevel@tonic-gate ucmd.uscsi_cdblen = req->requscsi_cmd.uscsi_cdblen;
20710Sstevel@tonic-gate ucmd.uscsi_bufaddr = (caddr_t)door_dp->dd_buf;
20720Sstevel@tonic-gate ucmd.uscsi_buflen = req->requscsi_cmd.uscsi_buflen;
20730Sstevel@tonic-gate ucmd.uscsi_timeout = req->requscsi_cmd.uscsi_timeout;
20740Sstevel@tonic-gate ucmd.uscsi_rqlen = req->requscsi_cmd.uscsi_rqlen;
20750Sstevel@tonic-gate ucmd.uscsi_rqbuf = (caddr_t)&rmsvc.retuscsi_cmd.uscsi_rqbuf;
20761137Sarutz debug(5, "USCSI CMD 0x%x requested.\n",
20770Sstevel@tonic-gate req->requscsi_cmd.uscsi_cdb[0]);
20780Sstevel@tonic-gate /*
20790Sstevel@tonic-gate * Check the device type and invalid flags specified.
20800Sstevel@tonic-gate * We permit operations only on CDROM devices types.
20810Sstevel@tonic-gate */
20821137Sarutz errno = invalid_uscsi_operation(door_dp, &ucmd);
20830Sstevel@tonic-gate if (errno) {
20840Sstevel@tonic-gate door_ret_err(&reterror, errno);
20850Sstevel@tonic-gate }
20860Sstevel@tonic-gate
20870Sstevel@tonic-gate if ((req->requscsi_cmd.uscsi_buflen) &&
20880Sstevel@tonic-gate ((req->requscsi_cmd.uscsi_buflen > door_dp->dd_buf_len) ||
20890Sstevel@tonic-gate (door_dp->dd_buf == NULL))) {
20901137Sarutz debug(5, "uscsi_cmd failed: uscsi_buflen=0x%x "
20911137Sarutz "dd_buf_len=0x%x dd_buf=0x%p\n",
20921137Sarutz req->requscsi_cmd.uscsi_buflen,
20931137Sarutz door_dp->dd_buf_len,
20941137Sarutz door_dp->dd_buf);
20950Sstevel@tonic-gate errno = EINVAL;
20960Sstevel@tonic-gate door_ret_err(&reterror, errno);
20970Sstevel@tonic-gate }
20980Sstevel@tonic-gate ret_val = do_uscsi_cmd(door_dp->dd_fd,
20990Sstevel@tonic-gate &ucmd, req->requscsi_cmd.uscsi_flags);
21000Sstevel@tonic-gate rmsvc.retuscsi_cmd.uscsi_status = ucmd.uscsi_status;
21010Sstevel@tonic-gate rmsvc.retuscsi_cmd.uscsi_resid = ucmd.uscsi_resid;
21020Sstevel@tonic-gate rmsvc.retuscsi_cmd.uscsi_rqstatus = ucmd.uscsi_rqstatus;
21030Sstevel@tonic-gate rmsvc.retuscsi_cmd.uscsi_rqresid = ucmd.uscsi_rqresid;
21040Sstevel@tonic-gate rmsvc.retuscsi_cmd.uscsi_retval = ret_val;
21050Sstevel@tonic-gate rmsvc.retuscsi_cmd.uscsi_errno = errno;
21060Sstevel@tonic-gate if (ret_val || ucmd.uscsi_status) {
21070Sstevel@tonic-gate debug(5, "uscsi_cmd failed: %d - %d errno = %d\n",
21080Sstevel@tonic-gate ret_val, ucmd.uscsi_status, errno);
21090Sstevel@tonic-gate }
21100Sstevel@tonic-gate my_door_return((char *)&rmsvc, retbuf_size, 0, 0);
21110Sstevel@tonic-gate break;
21120Sstevel@tonic-gate
21130Sstevel@tonic-gate case SMEDIA_CNUM_RAW_WRITE:
21140Sstevel@tonic-gate if (req->reqraw_write.nbytes == 0) {
21150Sstevel@tonic-gate /* Nothing to write */
21160Sstevel@tonic-gate rmsvc.retraw_write.nbytes = 0;
21170Sstevel@tonic-gate my_door_return((char *)&rmsvc,
21180Sstevel@tonic-gate sizeof (smedia_retraw_write_t), 0, 0);
21190Sstevel@tonic-gate }
21200Sstevel@tonic-gate ret_val = raw_write(door_dp, req);
21210Sstevel@tonic-gate if (ret_val == -1)
21220Sstevel@tonic-gate door_ret_err(&reterror, errno);
21230Sstevel@tonic-gate rmsvc.retraw_write.nbytes = ret_val;
21240Sstevel@tonic-gate my_door_return((char *)&rmsvc, sizeof (smedia_retraw_write_t),
21250Sstevel@tonic-gate 0, 0);
21260Sstevel@tonic-gate break;
21270Sstevel@tonic-gate
21280Sstevel@tonic-gate case SMEDIA_CNUM_GET_DEVICE_INFO:
21290Sstevel@tonic-gate
21300Sstevel@tonic-gate (void) memset((void *) &inq, 0, sizeof (inq));
21310Sstevel@tonic-gate (void) memset((void *) &ucmd, 0, sizeof (ucmd));
21320Sstevel@tonic-gate (void) memset((void *) &cdb, 0, sizeof (union scsi_cdb));
21330Sstevel@tonic-gate cdb.scc_cmd = SCMD_INQUIRY;
21340Sstevel@tonic-gate FORMG0COUNT(&cdb, sizeof (inq));
21350Sstevel@tonic-gate ucmd.uscsi_cdb = (caddr_t)&cdb;
21360Sstevel@tonic-gate ucmd.uscsi_cdblen = CDB_GROUP0;
21370Sstevel@tonic-gate ucmd.uscsi_bufaddr = (caddr_t)&inq;
21380Sstevel@tonic-gate ucmd.uscsi_buflen = sizeof (inq);
21390Sstevel@tonic-gate ucmd.uscsi_timeout = 120; /* If 0, HBA hangs forever */
21400Sstevel@tonic-gate ucmd.uscsi_rqlen = RQ_LEN;
21410Sstevel@tonic-gate ucmd.uscsi_rqbuf = rq_data;
21420Sstevel@tonic-gate ret_val = do_uscsi_cmd(door_dp->dd_fd,
21430Sstevel@tonic-gate &ucmd, USCSI_READ|USCSI_RQENABLE);
21440Sstevel@tonic-gate if (ret_val || ucmd.uscsi_status) {
21450Sstevel@tonic-gate debug(5, "inquiry failed: %d - %d errno = %d\n",
21460Sstevel@tonic-gate ret_val, ucmd.uscsi_status, errno);
21470Sstevel@tonic-gate door_ret_err(&reterror, errno);
21480Sstevel@tonic-gate }
21490Sstevel@tonic-gate
21500Sstevel@tonic-gate debug(5, "%s\n", inq.inq_vid);
21510Sstevel@tonic-gate debug(5, "%s\n", rmsvc.retget_device_info.sm_vendor_name);
21520Sstevel@tonic-gate
21530Sstevel@tonic-gate (void) strlcpy(rmsvc.retget_device_info.sm_vendor_name,
21540Sstevel@tonic-gate inq.inq_vid, 8);
21550Sstevel@tonic-gate rmsvc.retget_device_info.sm_vendor_name[8] = 0;
21560Sstevel@tonic-gate (void) strlcpy(rmsvc.retget_device_info.sm_product_name,
21570Sstevel@tonic-gate inq.inq_pid, 16);
21580Sstevel@tonic-gate rmsvc.retget_device_info.sm_product_name[16] = 0;
21590Sstevel@tonic-gate (void) strlcpy(rmsvc.retget_device_info.sm_firmware_version,
21600Sstevel@tonic-gate inq.inq_revision, 4);
21610Sstevel@tonic-gate rmsvc.retget_device_info.sm_firmware_version[4] = ' ';
21620Sstevel@tonic-gate (void) strlcpy(
21630Sstevel@tonic-gate &rmsvc.retget_device_info.sm_firmware_version[5],
21640Sstevel@tonic-gate inq.inq_serial, 12);
21650Sstevel@tonic-gate rmsvc.retget_device_info.sm_product_name[17] = 0;
21660Sstevel@tonic-gate
21670Sstevel@tonic-gate rmsvc.retget_device_info.sm_interface_type = IF_SCSI;
21680Sstevel@tonic-gate
21691137Sarutz debug(5, "Vendor name = %s\n",
21701137Sarutz rmsvc.retget_device_info.sm_vendor_name);
21711137Sarutz debug(5, "product name = %s\n",
21721137Sarutz rmsvc.retget_device_info.sm_product_name);
21731137Sarutz debug(5, "Firmware revision = %s\n",
21741137Sarutz rmsvc.retget_device_info.sm_firmware_version);
21751137Sarutz
21760Sstevel@tonic-gate my_door_return((char *)&rmsvc.retget_device_info,
21770Sstevel@tonic-gate sizeof (smedia_retget_device_info_t), 0, 0);
21780Sstevel@tonic-gate break;
21790Sstevel@tonic-gate
21800Sstevel@tonic-gate case SMEDIA_CNUM_GET_MEDIUM_PROPERTY:
21810Sstevel@tonic-gate
21820Sstevel@tonic-gate (void) memset((void *)&rmsvc.retget_medium_property.smprop,
21830Sstevel@tonic-gate 0, sizeof (smmedium_prop_t));
21840Sstevel@tonic-gate
21850Sstevel@tonic-gate ret_val = ioctl(door_dp->dd_fd, DKIOCGMEDIAINFO, &media_info);
21860Sstevel@tonic-gate
21870Sstevel@tonic-gate if (ret_val < 0) {
21880Sstevel@tonic-gate uint32_t capacity;
21890Sstevel@tonic-gate uint32_t blocksize;
21900Sstevel@tonic-gate /*
21910Sstevel@tonic-gate * Devices may fail DKIOCGMEDIAINFO if an unformed
21920Sstevel@tonic-gate * media is inserted. We can get the capacity
21930Sstevel@tonic-gate * information from the SCMD_READ_FORMAT_CAP command.
21940Sstevel@tonic-gate */
21950Sstevel@tonic-gate
21961137Sarutz debug(5, "DKIOCGMEDIAINFO failed; using "
21971137Sarutz "SCMD_READ_FORMAT_CAP");
21980Sstevel@tonic-gate ret_val = get_media_capacity(door_dp->dd_fd,
21990Sstevel@tonic-gate &capacity, &blocksize);
22000Sstevel@tonic-gate
22010Sstevel@tonic-gate if (ret_val >= 0) {
22020Sstevel@tonic-gate media_info.dki_lbsize = blocksize;
22030Sstevel@tonic-gate media_info.dki_capacity = capacity;
22040Sstevel@tonic-gate } else {
22050Sstevel@tonic-gate debug(5, "SCMD_READ_FORMAT_CAP failed");
22060Sstevel@tonic-gate door_ret_err(&reterror, errno);
22070Sstevel@tonic-gate }
22080Sstevel@tonic-gate }
22090Sstevel@tonic-gate rmsvc.retget_medium_property.smprop.sm_blocksize =
22100Sstevel@tonic-gate media_info.dki_lbsize;
22110Sstevel@tonic-gate rmsvc.retget_medium_property.smprop.sm_capacity =
22120Sstevel@tonic-gate media_info.dki_capacity;
22130Sstevel@tonic-gate
22140Sstevel@tonic-gate rmsvc.retget_medium_property.smprop.sm_media_type =
22150Sstevel@tonic-gate media_info.dki_media_type;
22160Sstevel@tonic-gate /*
22170Sstevel@tonic-gate * These devices show as SCSI devices but we need to treat it
22180Sstevel@tonic-gate * differently. so we need a seperate class.
22190Sstevel@tonic-gate */
22200Sstevel@tonic-gate if (get_device_type_scsi(door_dp->dd_fd, &inq) == SCSI_FLOPPY) {
22210Sstevel@tonic-gate rmsvc.retget_medium_property.smprop.sm_media_type =
22220Sstevel@tonic-gate SM_SCSI_FLOPPY;
22230Sstevel@tonic-gate }
22240Sstevel@tonic-gate
22250Sstevel@tonic-gate /* Check for EFI type because DKIOCGGEOM does not support EFI */
2226*7563SPrasad.Singamsetty@Sun.COM ret_val = ioctl(door_dp->dd_fd, DKIOCGEXTVTOC, &extvtoc);
2227*7563SPrasad.Singamsetty@Sun.COM if (ret_val < 0 && errno == ENOTTY)
2228*7563SPrasad.Singamsetty@Sun.COM ret_val = ioctl(door_dp->dd_fd, DKIOCGVTOC, &vtoc);
2229*7563SPrasad.Singamsetty@Sun.COM
22300Sstevel@tonic-gate if (!((ret_val < 0) && (errno == ENOTSUP))) {
22310Sstevel@tonic-gate ret_val = ioctl(door_dp->dd_fd, DKIOCGGEOM, &dkgeom);
22320Sstevel@tonic-gate if (ret_val < 0) {
22330Sstevel@tonic-gate /*
22340Sstevel@tonic-gate * DKIOCGGEOM may fail for unformed floppies.
22350Sstevel@tonic-gate * We need to generate the appropriate geometry
22360Sstevel@tonic-gate * information.
22370Sstevel@tonic-gate */
22380Sstevel@tonic-gate if (rmsvc.retget_medium_property.smprop.
22390Sstevel@tonic-gate sm_media_type == SM_SCSI_FLOPPY) {
22400Sstevel@tonic-gate ret_val = get_floppy_geom(
22410Sstevel@tonic-gate door_dp->dd_fd,
22420Sstevel@tonic-gate media_info.dki_capacity, &dkgeom);
22430Sstevel@tonic-gate
22440Sstevel@tonic-gate if (ret_val < 0) {
22450Sstevel@tonic-gate debug(5, "Cannot determine "
22460Sstevel@tonic-gate "media size");
22470Sstevel@tonic-gate door_ret_err(&reterror, errno);
22480Sstevel@tonic-gate }
22490Sstevel@tonic-gate } else {
22500Sstevel@tonic-gate #ifdef sparc
22510Sstevel@tonic-gate debug(5, "DKIOCGGEOM ioctl failed");
22520Sstevel@tonic-gate door_ret_err(&reterror, errno);
22530Sstevel@tonic-gate #else /* !sparc */
22540Sstevel@tonic-gate /*
22550Sstevel@tonic-gate * Try getting Physical geometry on x86.
22560Sstevel@tonic-gate */
22570Sstevel@tonic-gate ret_val = ioctl(door_dp->dd_fd,
22580Sstevel@tonic-gate DKIOCG_PHYGEOM, &dkgeom);
22590Sstevel@tonic-gate if (ret_val < 0) {
22600Sstevel@tonic-gate debug(5, "DKIOCG_PHYGEOM "
22610Sstevel@tonic-gate "ioctl failed");
22620Sstevel@tonic-gate door_ret_err(&reterror, errno);
22630Sstevel@tonic-gate }
22640Sstevel@tonic-gate #endif /* sparc */
22650Sstevel@tonic-gate }
22660Sstevel@tonic-gate }
22670Sstevel@tonic-gate
22680Sstevel@tonic-gate
22690Sstevel@tonic-gate /*
22700Sstevel@tonic-gate * Some faked geometry may not have pcyl filled in so
22710Sstevel@tonic-gate * later calculations using this field will be
22720Sstevel@tonic-gate * incorrect. We will substitute it with the number of
22730Sstevel@tonic-gate * available cylinders.
22740Sstevel@tonic-gate */
22750Sstevel@tonic-gate if (dkgeom.dkg_pcyl == 0)
22760Sstevel@tonic-gate rmsvc.retget_medium_property.smprop.sm_pcyl =
22770Sstevel@tonic-gate dkgeom.dkg_ncyl;
22780Sstevel@tonic-gate else
22790Sstevel@tonic-gate rmsvc.retget_medium_property.smprop.sm_pcyl =
22800Sstevel@tonic-gate dkgeom.dkg_pcyl;
22810Sstevel@tonic-gate
22820Sstevel@tonic-gate rmsvc.retget_medium_property.smprop.sm_nhead =
22830Sstevel@tonic-gate dkgeom.dkg_nhead;
22840Sstevel@tonic-gate rmsvc.retget_medium_property.smprop.sm_nsect =
22850Sstevel@tonic-gate dkgeom.dkg_nsect;
22860Sstevel@tonic-gate }
22870Sstevel@tonic-gate
22880Sstevel@tonic-gate debug(1, "properties are: lbasize = %d, cap = %llu",
22890Sstevel@tonic-gate media_info.dki_lbsize, media_info.dki_capacity);
22900Sstevel@tonic-gate
22910Sstevel@tonic-gate my_door_return((char *)&rmsvc.retget_medium_property,
22920Sstevel@tonic-gate sizeof (smedia_retget_medium_property_t), 0, 0);
22930Sstevel@tonic-gate break;
22940Sstevel@tonic-gate
22950Sstevel@tonic-gate case SMEDIA_CNUM_GET_PROTECTION_STATUS:
22960Sstevel@tonic-gate switch (get_device_type_scsi(door_dp->dd_fd, &inq)) {
22970Sstevel@tonic-gate case SCSI_FLOPPY:
22980Sstevel@tonic-gate status = scsi_floppy_media_status(door_dp->dd_fd);
22990Sstevel@tonic-gate break;
23000Sstevel@tonic-gate case SCSI_IOMEGA:
23010Sstevel@tonic-gate status = scsi_zip_media_status(door_dp->dd_fd);
23020Sstevel@tonic-gate break;
23030Sstevel@tonic-gate case SCSI_GENERIC:
23040Sstevel@tonic-gate status = scsi_media_status(door_dp->dd_fd);
23050Sstevel@tonic-gate break;
23060Sstevel@tonic-gate default:
23070Sstevel@tonic-gate door_ret_err(&reterror, errno);
23080Sstevel@tonic-gate }
23090Sstevel@tonic-gate if (status < 0)
23100Sstevel@tonic-gate door_ret_err(&reterror, errno);
23110Sstevel@tonic-gate
23120Sstevel@tonic-gate rmsvc.retget_protection_status.prot_state.sm_new_state =
23130Sstevel@tonic-gate status;
23140Sstevel@tonic-gate
23150Sstevel@tonic-gate my_door_return((char *)&rmsvc.retget_protection_status,
23160Sstevel@tonic-gate sizeof (smedia_retget_protection_status_t), 0, 0);
23170Sstevel@tonic-gate break;
23180Sstevel@tonic-gate
23190Sstevel@tonic-gate case SMEDIA_CNUM_SET_PROTECTION_STATUS:
23200Sstevel@tonic-gate
23210Sstevel@tonic-gate ret_val = set_protection_status(door_dp, req);
23220Sstevel@tonic-gate if (ret_val == -1)
23230Sstevel@tonic-gate door_ret_err(&reterror, errno);
23240Sstevel@tonic-gate else
23250Sstevel@tonic-gate my_door_return((char *)&rmsvc.retset_protection_status,
23260Sstevel@tonic-gate sizeof (smedia_retset_protection_status_t),
23270Sstevel@tonic-gate 0, 0);
23280Sstevel@tonic-gate break;
23290Sstevel@tonic-gate
23300Sstevel@tonic-gate case SMEDIA_CNUM_FORMAT:
23310Sstevel@tonic-gate switch (get_device_type_scsi(door_dp->dd_fd, &inq)) {
23320Sstevel@tonic-gate case SCSI_FLOPPY:
23330Sstevel@tonic-gate info("formatting floppy");
23340Sstevel@tonic-gate err = scsi_floppy_format(door_dp->dd_fd,
23350Sstevel@tonic-gate req->reqformat.flavor, req->reqformat.mode);
23360Sstevel@tonic-gate
23370Sstevel@tonic-gate break;
23380Sstevel@tonic-gate case SCSI_IOMEGA:
23390Sstevel@tonic-gate err = scsi_zip_format(door_dp->dd_fd,
23400Sstevel@tonic-gate req->reqformat.flavor, req->reqformat.mode);
23410Sstevel@tonic-gate break;
23420Sstevel@tonic-gate case SCSI_GENERIC:
23430Sstevel@tonic-gate err = scsi_format(door_dp->dd_fd,
23440Sstevel@tonic-gate req->reqformat.flavor, req->reqformat.mode);
23450Sstevel@tonic-gate break;
23460Sstevel@tonic-gate default:
23470Sstevel@tonic-gate door_ret_err(&reterror, ENOTSUP);
23480Sstevel@tonic-gate }
23490Sstevel@tonic-gate
23500Sstevel@tonic-gate if (err)
23510Sstevel@tonic-gate door_ret_err(&reterror, errno);
23520Sstevel@tonic-gate my_door_return((char *)&rmsvc.retformat,
23530Sstevel@tonic-gate sizeof (smedia_retformat_t), 0, 0);
23540Sstevel@tonic-gate
23550Sstevel@tonic-gate break;
23560Sstevel@tonic-gate
23570Sstevel@tonic-gate case SMEDIA_CNUM_CHECK_FORMAT_STATUS:
23580Sstevel@tonic-gate
23590Sstevel@tonic-gate (void) memset((void *) &cdb, 0, sizeof (union scsi_cdb));
23600Sstevel@tonic-gate (void) memset((void *) &ucmd, 0, sizeof (ucmd));
23610Sstevel@tonic-gate (void) memset((void *) &data, 0, sizeof (data));
23620Sstevel@tonic-gate cdb.scc_cmd = SCMD_REQUEST_SENSE;
23630Sstevel@tonic-gate cdb.g0_count0 = sizeof (data);
23640Sstevel@tonic-gate ucmd.uscsi_cdb = (caddr_t)&cdb;
23650Sstevel@tonic-gate ucmd.uscsi_cdblen = CDB_GROUP0;
23660Sstevel@tonic-gate ucmd.uscsi_bufaddr = (caddr_t)&data;
23670Sstevel@tonic-gate ucmd.uscsi_buflen = sizeof (data);
23680Sstevel@tonic-gate ucmd.uscsi_timeout = 120; /* If 0, HBA hangs forever */
23690Sstevel@tonic-gate ucmd.uscsi_rqlen = RQ_LEN;
23700Sstevel@tonic-gate ucmd.uscsi_rqbuf = rq_data;
23710Sstevel@tonic-gate ret_val = do_uscsi_cmd(door_dp->dd_fd,
23720Sstevel@tonic-gate &ucmd, USCSI_READ|USCSI_RQENABLE);
23730Sstevel@tonic-gate if (ret_val || ucmd.uscsi_status) {
23740Sstevel@tonic-gate debug(5, "Request sense failed: %d - %d errno = %d\n",
23750Sstevel@tonic-gate ret_val, ucmd.uscsi_status, errno);
23760Sstevel@tonic-gate door_ret_err(&reterror, errno);
23770Sstevel@tonic-gate }
23780Sstevel@tonic-gate
23790Sstevel@tonic-gate if ((data[0] & 0x7F) == DEFERRED_ERROR) {
23800Sstevel@tonic-gate /* Deffered error. The format must have failed */
23810Sstevel@tonic-gate debug(5, "format failed!\n");
23820Sstevel@tonic-gate door_ret_err(&reterror, EIO);
23830Sstevel@tonic-gate }
23840Sstevel@tonic-gate
23850Sstevel@tonic-gate if (data[SKSV_OFFSET] & SKSV_FIELD) {
23860Sstevel@tonic-gate completed =
23870Sstevel@tonic-gate (data[FORMAT_PROGRESS_INDICATOR_OFFSET_0] << 8)
23880Sstevel@tonic-gate | data[FORMAT_PROGRESS_INDICATOR_OFFSET_1];
23890Sstevel@tonic-gate completed = (completed*100/65536);
23900Sstevel@tonic-gate } else {
23910Sstevel@tonic-gate completed = (100);
23920Sstevel@tonic-gate }
23930Sstevel@tonic-gate rmsvc.retcheck_format_status.percent_complete = completed;
23940Sstevel@tonic-gate my_door_return((char *)&rmsvc.retcheck_format_status,
23950Sstevel@tonic-gate sizeof (smedia_retcheck_format_status_t), 0, 0);
23960Sstevel@tonic-gate break;
23970Sstevel@tonic-gate
23980Sstevel@tonic-gate case SMEDIA_CNUM_REASSIGN_BLOCK:
23990Sstevel@tonic-gate
24000Sstevel@tonic-gate ret_val = reassign_block(door_dp, req);
24010Sstevel@tonic-gate if (ret_val == -1)
24020Sstevel@tonic-gate door_ret_err(&reterror, errno);
24030Sstevel@tonic-gate my_door_return((char *)&rmsvc.retreassign_block,
24040Sstevel@tonic-gate sizeof (smedia_retreassign_block_t), 0, 0);
24050Sstevel@tonic-gate break;
24060Sstevel@tonic-gate
24070Sstevel@tonic-gate } /* end of switch */
24080Sstevel@tonic-gate
24090Sstevel@tonic-gate debug(10, "Exiting client server...\n");
24100Sstevel@tonic-gate my_door_return((char *)&reterror, sizeof (smedia_reterror_t), 0, 0);
24110Sstevel@tonic-gate }
24120Sstevel@tonic-gate
24131137Sarutz /*
24141137Sarutz * This is the service procedure for the door that is associated with
24151137Sarutz * the (doorfs) filesystem Door that is created at 'smedia_service'.
24161137Sarutz */
24170Sstevel@tonic-gate /*ARGSUSED*/
24180Sstevel@tonic-gate static void
main_servproc(void * server_data,char * argp,size_t arg_size,door_desc_t * dp,uint_t ndesc)24191137Sarutz main_servproc(void *server_data, char *argp, size_t arg_size,
24200Sstevel@tonic-gate door_desc_t *dp, uint_t ndesc)
24210Sstevel@tonic-gate {
24220Sstevel@tonic-gate smedia_services_t *req;
24230Sstevel@tonic-gate door_cred_t door_credentials;
24240Sstevel@tonic-gate int ret_val;
24250Sstevel@tonic-gate door_data_t *ddata;
24260Sstevel@tonic-gate smedia_reterror_t reterror;
24270Sstevel@tonic-gate smedia_reterror_t retok;
24280Sstevel@tonic-gate struct stat stat;
24290Sstevel@tonic-gate door_desc_t *didpp;
24300Sstevel@tonic-gate struct dk_cinfo dkinfo;
24311137Sarutz uint_t nexpected_desc;
24321137Sarutz
24331137Sarutz debug(10, "Entering main_servproc[%d].\n", pthread_self());
24340Sstevel@tonic-gate
24350Sstevel@tonic-gate didpp = dp;
24360Sstevel@tonic-gate (void) mutex_lock(&svcstate_lock);
24370Sstevel@tonic-gate svcstate = _SERVED;
24380Sstevel@tonic-gate (void) mutex_unlock(&svcstate_lock);
24390Sstevel@tonic-gate
24400Sstevel@tonic-gate reterror.cnum = SMEDIA_CNUM_ERROR;
24410Sstevel@tonic-gate reterror.errnum = SMEDIA_FAILURE;
24421137Sarutz
24430Sstevel@tonic-gate if (argp == NULL) {
24440Sstevel@tonic-gate debug(5, "argp is NULL\n");
24450Sstevel@tonic-gate if (ndesc > 0)
24460Sstevel@tonic-gate close_door_descs(dp, ndesc);
24470Sstevel@tonic-gate my_door_return((char *)&reterror,
24480Sstevel@tonic-gate sizeof (smedia_reterror_t), 0, 0);
24490Sstevel@tonic-gate }
24500Sstevel@tonic-gate
24510Sstevel@tonic-gate req = (smedia_services_t *)((void *)argp);
24521137Sarutz
24530Sstevel@tonic-gate retok.cnum = req->in.cnum;
24540Sstevel@tonic-gate retok.errnum = 0;
24550Sstevel@tonic-gate
24560Sstevel@tonic-gate debug(5, "req = %s arg_size = 0x%x \n",
24571137Sarutz xlate_cnum(req->reqopen.cnum), arg_size);
24580Sstevel@tonic-gate
24590Sstevel@tonic-gate /*
24600Sstevel@tonic-gate * Our caller may have passed more descriptors than we expected.
24610Sstevel@tonic-gate * If so, we silently close (and ignore) them.
24620Sstevel@tonic-gate */
24631137Sarutz nexpected_desc = (req->in.cnum == SMEDIA_CNUM_OPEN_FD) ? 1 : 0;
24641137Sarutz if (ndesc > nexpected_desc) {
24651137Sarutz close_door_descs(dp + nexpected_desc, ndesc - nexpected_desc);
24661137Sarutz }
24670Sstevel@tonic-gate
24680Sstevel@tonic-gate switch (req->in.cnum) {
24690Sstevel@tonic-gate default:
24701137Sarutz debug(5, "main_servproc: unknown command 0x%x\n",
24711137Sarutz req->reqopen.cnum);
24720Sstevel@tonic-gate break;
24730Sstevel@tonic-gate
24741137Sarutz case SMEDIA_CNUM_PING:
24750Sstevel@tonic-gate /*
24760Sstevel@tonic-gate * This service is to indicate that server is up and
24770Sstevel@tonic-gate * running. It is usually called from another instance of
24780Sstevel@tonic-gate * server that is started.
24790Sstevel@tonic-gate */
24800Sstevel@tonic-gate reterror.cnum = SMEDIA_CNUM_PING;
24810Sstevel@tonic-gate reterror.errnum = 0;
24820Sstevel@tonic-gate my_door_return((char *)&reterror,
24831137Sarutz sizeof (smedia_reterror_t), 0, 0);
24840Sstevel@tonic-gate break;
24850Sstevel@tonic-gate
24860Sstevel@tonic-gate
24871137Sarutz case SMEDIA_CNUM_OPEN_FD:
24880Sstevel@tonic-gate
24890Sstevel@tonic-gate debug(5, "ndesc = %d\n", ndesc);
24900Sstevel@tonic-gate if (ndesc == 0) {
24910Sstevel@tonic-gate my_door_return((char *)&reterror,
24921137Sarutz sizeof (smedia_reterror_t), 0, 0);
24930Sstevel@tonic-gate }
24941137Sarutz debug(5, "Checking file descriptor of target device\n");
24950Sstevel@tonic-gate if (fstat(didpp->d_data.d_desc.d_descriptor, &stat) < 0) {
24961137Sarutz warning(gettext("main_servproc:fstat failed. "
24971137Sarutz "errno = %d\n"), errno);
24980Sstevel@tonic-gate (void) close(didpp->d_data.d_desc.d_descriptor);
24990Sstevel@tonic-gate my_door_return((char *)&reterror,
25001137Sarutz sizeof (smedia_reterror_t), 0, 0);
25010Sstevel@tonic-gate }
25020Sstevel@tonic-gate debug(5, "descriptor = %d st_mode = 0x%lx\n",
25031137Sarutz didpp->d_data.d_desc.d_descriptor,
25041137Sarutz stat.st_mode);
25050Sstevel@tonic-gate
25060Sstevel@tonic-gate /* Obtain the credentials of the user */
25070Sstevel@tonic-gate ret_val = door_cred(&door_credentials);
25080Sstevel@tonic-gate if (ret_val < 0) {
25091137Sarutz warning(gettext("main_servproc:door_cred "
25101137Sarutz "failed. errno = %d\n"), errno);
25110Sstevel@tonic-gate (void) close(didpp->d_data.d_desc.d_descriptor);
25120Sstevel@tonic-gate my_door_return((char *)&reterror,
25131137Sarutz sizeof (smedia_reterror_t), 0, 0);
25140Sstevel@tonic-gate }
25150Sstevel@tonic-gate if (ioctl(didpp->d_data.d_desc.d_descriptor, DKIOCINFO,
25160Sstevel@tonic-gate &dkinfo) == -1) {
25171137Sarutz warning(gettext("main_servproc:DKIOCINFO failed. "
25181137Sarutz "errno = %d\n"), errno);
25190Sstevel@tonic-gate (void) close(didpp->d_data.d_desc.d_descriptor);
25200Sstevel@tonic-gate my_door_return((char *)&reterror,
25211137Sarutz sizeof (smedia_reterror_t), 0, 0);
25220Sstevel@tonic-gate }
25230Sstevel@tonic-gate
25240Sstevel@tonic-gate ddata = (door_data_t *)calloc(1, sizeof (door_data_t));
25250Sstevel@tonic-gate if (ddata == NULL) {
25261137Sarutz warning(gettext("main_servproc:calloc failed. "
25271137Sarutz "errno = %d\n"), errno);
25280Sstevel@tonic-gate (void) close(didpp->d_data.d_desc.d_descriptor);
25290Sstevel@tonic-gate my_door_return((char *)&reterror,
25301137Sarutz sizeof (smedia_reterror_t), 0, 0);
25310Sstevel@tonic-gate }
25320Sstevel@tonic-gate ddata->dd_stat = stat;
25330Sstevel@tonic-gate ddata->dd_cred = door_credentials;
25340Sstevel@tonic-gate ddata->dd_fd = didpp->d_data.d_desc.d_descriptor;
25350Sstevel@tonic-gate ddata->dd_buf = NULL;
25360Sstevel@tonic-gate ddata->dd_buf_len = 0;
25370Sstevel@tonic-gate ddata->dd_buffd = -1;
25380Sstevel@tonic-gate ddata->dd_sector_size = 0;
25390Sstevel@tonic-gate ddata->dd_dkinfo = dkinfo;
25401137Sarutz debug(5, "ddata = 0x%p \n", (void *)ddata);
25411137Sarutz
25421137Sarutz /* specify a function that'll customize our door threads */
25431137Sarutz (void) door_server_create(sm_door_server_create);
25440Sstevel@tonic-gate debug(5, "door_server_create called.\n");
25450Sstevel@tonic-gate
25460Sstevel@tonic-gate (void) mutex_lock(&ddata->dd_lock);
25470Sstevel@tonic-gate
25481137Sarutz /* create Client Door */
25491137Sarutz ddata->dd_cdoor_descriptor =
25501137Sarutz door_create(client_servproc,
25511137Sarutz (void *)ddata, DOOR_PRIVATE | DOOR_NO_CANCEL | DOOR_UNREF);
25521137Sarutz
25531137Sarutz if (ddata->dd_cdoor_descriptor < 0) {
25541137Sarutz /* then door_create() failed */
25551137Sarutz int err = errno;
25561137Sarutz
25571137Sarutz (void) mutex_unlock(&ddata->dd_lock);
25581137Sarutz
25591137Sarutz warning(gettext("main_servproc: door_create of Client "
25601137Sarutz "Door failed = %d\n"), err);
25610Sstevel@tonic-gate free(ddata);
25621137Sarutz
25631137Sarutz /* close target device */
25640Sstevel@tonic-gate (void) close(didpp->d_data.d_desc.d_descriptor);
25651137Sarutz my_door_return((char *)&reterror,
25661137Sarutz sizeof (smedia_reterror_t), 0, 0);
25670Sstevel@tonic-gate }
25681137Sarutz
25691137Sarutz /* create Death Door */
25701137Sarutz ddata->dd_ddoor_descriptor =
25711137Sarutz door_create(death_servproc, (void *)ddata,
25721137Sarutz DOOR_REFUSE_DESC | DOOR_NO_CANCEL);
25731137Sarutz if (ddata->dd_ddoor_descriptor < 0) {
25741137Sarutz warning(gettext("main_servproc: door_create of Death "
25751137Sarutz "Door failed = %d\n"), errno);
25761137Sarutz } else {
25771137Sarutz (void) door_setparam(ddata->dd_ddoor_descriptor,
25781137Sarutz DOOR_PARAM_DATA_MAX, 0);
25790Sstevel@tonic-gate }
25801137Sarutz
25811137Sarutz debug(5, "main_servproc[%d]: Client Door = %d, "
25821137Sarutz "Death Door = %d", pthread_self(),
25831137Sarutz ddata->dd_cdoor_descriptor, ddata->dd_ddoor_descriptor);
25840Sstevel@tonic-gate
25850Sstevel@tonic-gate audit_init(ddata);
25860Sstevel@tonic-gate
25871137Sarutz /* wait until sm_server_thread does door_bind() */
25880Sstevel@tonic-gate (void) cond_wait(&ddata->dd_cv_bind, &ddata->dd_lock);
25891137Sarutz
25900Sstevel@tonic-gate (void) mutex_unlock(&ddata->dd_lock);
25910Sstevel@tonic-gate
25920Sstevel@tonic-gate (void) mutex_lock(&svcstate_lock);
25930Sstevel@tonic-gate svccount++;
25940Sstevel@tonic-gate (void) mutex_unlock(&svcstate_lock);
25951137Sarutz
25961137Sarutz if (ddata->dd_ddoor_descriptor < 0) {
25971137Sarutz /* Return only the Client Door to the client. */
25981137Sarutz ddata->dd_cdoor.d_attributes = (DOOR_DESCRIPTOR);
25991137Sarutz my_door_return((char *)&reterror,
26001137Sarutz sizeof (smedia_reterror_t), &ddata->dd_desc[0], 1);
26011137Sarutz } else {
26021137Sarutz /*
26031137Sarutz * Return the Client Door and Death Door
26041137Sarutz * to the client.
26051137Sarutz */
26061137Sarutz debug(5, "retok.cnum = 0x%x\n", retok.cnum);
26071137Sarutz ddata->dd_cdoor.d_attributes = (DOOR_DESCRIPTOR);
26081137Sarutz ddata->dd_ddoor.d_attributes = (DOOR_DESCRIPTOR);
26091137Sarutz my_door_return((char *)&retok,
26101137Sarutz sizeof (smedia_reterror_t), &ddata->dd_desc[0], 2);
26111137Sarutz }
26120Sstevel@tonic-gate break;
26130Sstevel@tonic-gate }
26140Sstevel@tonic-gate
26151137Sarutz debug(10, "exiting main_servproc. \n");
26160Sstevel@tonic-gate my_door_return((char *)&reterror, sizeof (smedia_reterror_t), 0, 0);
26170Sstevel@tonic-gate }
26180Sstevel@tonic-gate
26190Sstevel@tonic-gate /* ARGSUSED */
26200Sstevel@tonic-gate static void
term_handler(int sig,siginfo_t * siginfo,void * sigctx)26210Sstevel@tonic-gate term_handler(int sig, siginfo_t *siginfo, void *sigctx)
26220Sstevel@tonic-gate {
26230Sstevel@tonic-gate warning(gettext("thread[%d]: Received signal %d. Ignoring it.\n"),
26241137Sarutz pthread_self(),
26251137Sarutz sig);
26260Sstevel@tonic-gate }
26270Sstevel@tonic-gate
26280Sstevel@tonic-gate /* ARGSUSED */
26290Sstevel@tonic-gate static void
hup_handler(int sig,siginfo_t * siginfo,void * sigctx)26300Sstevel@tonic-gate hup_handler(int sig, siginfo_t *siginfo, void *sigctx)
26310Sstevel@tonic-gate {
26320Sstevel@tonic-gate warning(gettext("thread[%d]: Received signal %d. Ignoring it.\n"),
26331137Sarutz pthread_self(),
26341137Sarutz sig);
26350Sstevel@tonic-gate }
26360Sstevel@tonic-gate
26370Sstevel@tonic-gate /*ARGSUSED*/
26380Sstevel@tonic-gate static void
sig_handler(int sig,siginfo_t * siginfo,void * sigctx)26390Sstevel@tonic-gate sig_handler(int sig, siginfo_t *siginfo, void *sigctx)
26400Sstevel@tonic-gate {
26410Sstevel@tonic-gate warning(gettext("thread[%d]: Received signal %d. Ignoring it.\n"),
26421137Sarutz pthread_self(),
26431137Sarutz sig);
26440Sstevel@tonic-gate }
26450Sstevel@tonic-gate
26460Sstevel@tonic-gate /*ARGSUSED*/
26470Sstevel@tonic-gate static void
badsig_handler(int sig,siginfo_t * siginfo,void * sigctx)26480Sstevel@tonic-gate badsig_handler(int sig, siginfo_t *siginfo, void *sigctx)
26490Sstevel@tonic-gate {
26500Sstevel@tonic-gate fatal(BADSIG_MSG, pthread_self(), sig, siginfo->si_addr,
26511137Sarutz siginfo->si_trapno,
26521137Sarutz siginfo->si_pc);
26530Sstevel@tonic-gate }
26540Sstevel@tonic-gate
26550Sstevel@tonic-gate /*ARGSUSED*/
26561137Sarutz static void *
init_server(void * argp)26570Sstevel@tonic-gate init_server(void *argp)
26580Sstevel@tonic-gate {
26590Sstevel@tonic-gate int i, fd;
26600Sstevel@tonic-gate struct sigaction act;
26610Sstevel@tonic-gate struct rlimit rlim;
26620Sstevel@tonic-gate
26630Sstevel@tonic-gate debug(10, "init_server running\n");
26640Sstevel@tonic-gate
26650Sstevel@tonic-gate (void) setlocale(LC_ALL, "");
26660Sstevel@tonic-gate #if !defined(TEXT_DOMAIN)
26670Sstevel@tonic-gate #define TEXT_DOMAIN "SYS_TEST"
26680Sstevel@tonic-gate #endif
26690Sstevel@tonic-gate (void) textdomain(TEXT_DOMAIN);
26700Sstevel@tonic-gate
26710Sstevel@tonic-gate
26720Sstevel@tonic-gate if (geteuid() != 0) fatal("Must be root to execute smserverd\n");
26730Sstevel@tonic-gate
26740Sstevel@tonic-gate
26750Sstevel@tonic-gate /*
26760Sstevel@tonic-gate * setup signal handlers.
26770Sstevel@tonic-gate */
26780Sstevel@tonic-gate
26790Sstevel@tonic-gate for (i = 0; i < N_BADSIGS; i++) {
26800Sstevel@tonic-gate act.sa_sigaction = badsig_handler;
26810Sstevel@tonic-gate (void) sigemptyset(&act.sa_mask);
26820Sstevel@tonic-gate act.sa_flags = SA_SIGINFO;
26830Sstevel@tonic-gate if (sigaction(badsigs[i], &act, NULL) == -1)
26840Sstevel@tonic-gate warning(gettext(SIGACT_FAILED), strsignal(badsigs[i]),
26850Sstevel@tonic-gate strerror(errno));
26860Sstevel@tonic-gate }
26870Sstevel@tonic-gate
26880Sstevel@tonic-gate /*
26890Sstevel@tonic-gate * Ignore SIGHUP until all the initialization is done.
26900Sstevel@tonic-gate */
26910Sstevel@tonic-gate act.sa_handler = SIG_IGN;
26920Sstevel@tonic-gate (void) sigemptyset(&act.sa_mask);
26930Sstevel@tonic-gate act.sa_flags = 0;
26940Sstevel@tonic-gate if (sigaction(SIGHUP, &act, NULL) == -1)
26950Sstevel@tonic-gate warning(gettext(SIGACT_FAILED), strsignal(SIGHUP),
26960Sstevel@tonic-gate strerror(errno));
26970Sstevel@tonic-gate /*
26980Sstevel@tonic-gate * Increase file descriptor limit to the most it can possibly
26990Sstevel@tonic-gate * be.
27000Sstevel@tonic-gate */
27010Sstevel@tonic-gate if (getrlimit(RLIMIT_NOFILE, &rlim) < 0) {
27020Sstevel@tonic-gate warning(gettext("getrlimit for fd's failed; %m\n"));
27030Sstevel@tonic-gate }
27040Sstevel@tonic-gate
27050Sstevel@tonic-gate rlim.rlim_cur = rlim.rlim_max;
27060Sstevel@tonic-gate
27070Sstevel@tonic-gate if (setrlimit(RLIMIT_NOFILE, &rlim) < 0) {
27080Sstevel@tonic-gate warning(gettext("setrlimit for fd's failed; %m\n"));
27090Sstevel@tonic-gate }
27101914Scasper (void) enable_extended_FILE_stdio(-1, -1);
27110Sstevel@tonic-gate
27121137Sarutz server_door = door_create(main_servproc, (void *)&server_data, 0);
27130Sstevel@tonic-gate if (server_door == -1) {
27140Sstevel@tonic-gate debug(1, "main door_create");
27150Sstevel@tonic-gate exit(1);
27160Sstevel@tonic-gate }
27170Sstevel@tonic-gate
27180Sstevel@tonic-gate (void) unlink(smedia_service);
27190Sstevel@tonic-gate fd = open(smedia_service, O_RDWR|O_CREAT|O_EXCL, 0644);
27200Sstevel@tonic-gate if (fd < 0) {
27210Sstevel@tonic-gate debug(5, "could not open %s.\n", smedia_service);
27220Sstevel@tonic-gate exit(1);
27230Sstevel@tonic-gate }
27240Sstevel@tonic-gate (void) close(fd);
27250Sstevel@tonic-gate server_fd = fattach(server_door, smedia_service);
27260Sstevel@tonic-gate if (server_fd == -1) {
27270Sstevel@tonic-gate debug(1, "main fattach");
27280Sstevel@tonic-gate exit(1);
27290Sstevel@tonic-gate }
27300Sstevel@tonic-gate server_data.sd_door = server_door;
27310Sstevel@tonic-gate server_data.sd_fd = server_fd;
27320Sstevel@tonic-gate
27330Sstevel@tonic-gate /*
27340Sstevel@tonic-gate * setup signal handlers for post-init
27350Sstevel@tonic-gate */
27360Sstevel@tonic-gate
27370Sstevel@tonic-gate act.sa_sigaction = hup_handler;
27380Sstevel@tonic-gate (void) sigemptyset(&act.sa_mask);
27390Sstevel@tonic-gate act.sa_flags = SA_SIGINFO;
27400Sstevel@tonic-gate if (sigaction(SIGHUP, &act, NULL) == -1)
27410Sstevel@tonic-gate warning(gettext(SIGACT_FAILED), strsignal(SIGHUP),
27420Sstevel@tonic-gate strerror(errno));
27430Sstevel@tonic-gate
27440Sstevel@tonic-gate act.sa_sigaction = term_handler;
27450Sstevel@tonic-gate (void) sigemptyset(&act.sa_mask);
27460Sstevel@tonic-gate act.sa_flags = SA_SIGINFO;
27470Sstevel@tonic-gate if (sigaction(SIGTERM, &act, NULL) == -1)
27480Sstevel@tonic-gate warning(gettext(SIGACT_FAILED), strsignal(SIGTERM),
27490Sstevel@tonic-gate strerror(errno));
27500Sstevel@tonic-gate
27510Sstevel@tonic-gate act.sa_sigaction = sig_handler;
27520Sstevel@tonic-gate (void) sigemptyset(&act.sa_mask);
27530Sstevel@tonic-gate act.sa_flags = SA_SIGINFO;
27540Sstevel@tonic-gate if (sigaction(SIGINT, &act, NULL) == -1)
27550Sstevel@tonic-gate warning(gettext(SIGACT_FAILED), strsignal(SIGHUP),
27560Sstevel@tonic-gate strerror(errno));
27570Sstevel@tonic-gate
27580Sstevel@tonic-gate act.sa_sigaction = sig_handler;
27590Sstevel@tonic-gate (void) sigemptyset(&act.sa_mask);
27600Sstevel@tonic-gate act.sa_flags = SA_SIGINFO;
27610Sstevel@tonic-gate if (sigaction(SIGQUIT, &act, NULL) == -1)
27620Sstevel@tonic-gate warning(gettext(SIGACT_FAILED), strsignal(SIGHUP),
27630Sstevel@tonic-gate strerror(errno));
27640Sstevel@tonic-gate debug(10, "init_server completed successfully\n");
27650Sstevel@tonic-gate
27660Sstevel@tonic-gate server_data.sd_init_state = INIT_DONE;
27670Sstevel@tonic-gate return (NULL);
27680Sstevel@tonic-gate }
27690Sstevel@tonic-gate
27700Sstevel@tonic-gate static int
server_exists()27710Sstevel@tonic-gate server_exists()
27720Sstevel@tonic-gate {
27730Sstevel@tonic-gate door_arg_t darg;
27740Sstevel@tonic-gate smedia_reqping_t req_ping;
27750Sstevel@tonic-gate smedia_retping_t *ret_ping;
27760Sstevel@tonic-gate int doorh;
27770Sstevel@tonic-gate door_info_t dinfo;
27780Sstevel@tonic-gate char rbuf[sizeof (smedia_services_t) + sizeof (door_desc_t)];
27790Sstevel@tonic-gate
27800Sstevel@tonic-gate doorh = open(smedia_service, O_RDONLY);
27810Sstevel@tonic-gate if (doorh < 0)
27820Sstevel@tonic-gate return (0);
27830Sstevel@tonic-gate if (door_info(doorh, &dinfo) < 0) {
27840Sstevel@tonic-gate (void) close(doorh);
27850Sstevel@tonic-gate return (0);
27860Sstevel@tonic-gate }
27870Sstevel@tonic-gate if (dinfo.di_attributes & DOOR_REVOKED) {
27880Sstevel@tonic-gate (void) close(doorh);
27890Sstevel@tonic-gate return (0);
27900Sstevel@tonic-gate }
27910Sstevel@tonic-gate
27920Sstevel@tonic-gate req_ping.cnum = SMEDIA_CNUM_PING;
27930Sstevel@tonic-gate
27940Sstevel@tonic-gate darg.data_ptr = (char *)&req_ping;
27950Sstevel@tonic-gate darg.data_size = sizeof (smedia_reqping_t);
27960Sstevel@tonic-gate darg.desc_ptr = NULL;
27970Sstevel@tonic-gate darg.desc_num = 0;
27980Sstevel@tonic-gate darg.rbuf = rbuf;
27990Sstevel@tonic-gate darg.rsize = sizeof (rbuf);
28000Sstevel@tonic-gate
28010Sstevel@tonic-gate if (door_call(doorh, &darg) < 0) {
28020Sstevel@tonic-gate (void) close(doorh);
28030Sstevel@tonic-gate return (0);
28040Sstevel@tonic-gate }
28050Sstevel@tonic-gate ret_ping = (smedia_retping_t *)((void *)darg.data_ptr);
28060Sstevel@tonic-gate if (ret_ping->cnum != SMEDIA_CNUM_PING) {
28070Sstevel@tonic-gate (void) close(doorh);
28080Sstevel@tonic-gate return (0);
28090Sstevel@tonic-gate }
28100Sstevel@tonic-gate
28110Sstevel@tonic-gate (void) close(doorh);
28120Sstevel@tonic-gate return (1);
28130Sstevel@tonic-gate }
28140Sstevel@tonic-gate
28150Sstevel@tonic-gate static int
get_run_level()28160Sstevel@tonic-gate get_run_level()
28170Sstevel@tonic-gate {
28180Sstevel@tonic-gate int run_level;
28190Sstevel@tonic-gate struct utmpx *utmpp;
28200Sstevel@tonic-gate
28210Sstevel@tonic-gate setutxent();
28220Sstevel@tonic-gate while ((utmpp = getutxent()) != NULL) {
28230Sstevel@tonic-gate if (utmpp->ut_type == RUN_LVL) {
28240Sstevel@tonic-gate run_level = atoi(
28250Sstevel@tonic-gate &utmpp->ut_line[strlen("run-level ")]);
28260Sstevel@tonic-gate }
28270Sstevel@tonic-gate }
28280Sstevel@tonic-gate return (run_level);
28290Sstevel@tonic-gate }
28300Sstevel@tonic-gate
28310Sstevel@tonic-gate /*ARGSUSED*/
28320Sstevel@tonic-gate static void *
closedown(void * arg)28330Sstevel@tonic-gate closedown(void *arg)
28340Sstevel@tonic-gate {
28350Sstevel@tonic-gate
28360Sstevel@tonic-gate int current_run_level;
28370Sstevel@tonic-gate
28380Sstevel@tonic-gate /*CONSTCOND*/
28390Sstevel@tonic-gate #ifndef lint
28400Sstevel@tonic-gate while (1) {
28410Sstevel@tonic-gate #endif
28420Sstevel@tonic-gate (void) sleep(SVC_CLOSEDOWN/2);
28430Sstevel@tonic-gate
28440Sstevel@tonic-gate /*
28450Sstevel@tonic-gate * If the server was started at init level 1
28460Sstevel@tonic-gate * and the current init level is 1 then
28470Sstevel@tonic-gate * do not exit from server. This server will run
28480Sstevel@tonic-gate * until it is explicitly stopped by the user.
28490Sstevel@tonic-gate */
28500Sstevel@tonic-gate if (svcstart_level == 1) {
28510Sstevel@tonic-gate current_run_level = get_run_level();
28520Sstevel@tonic-gate if (current_run_level == 1)
28530Sstevel@tonic-gate #ifndef lint
28540Sstevel@tonic-gate continue;
28550Sstevel@tonic-gate #else
28560Sstevel@tonic-gate return (NULL);
28570Sstevel@tonic-gate #endif
28580Sstevel@tonic-gate /*
28590Sstevel@tonic-gate * who ever started the server at level 1 has
28600Sstevel@tonic-gate * forgotten to stop the server. we will kill ourself.
28610Sstevel@tonic-gate */
28620Sstevel@tonic-gate debug(5,
28630Sstevel@tonic-gate "Terminating the server started at init level 1\n");
28640Sstevel@tonic-gate exit(0);
28650Sstevel@tonic-gate }
28660Sstevel@tonic-gate
28670Sstevel@tonic-gate if (mutex_trylock(&svcstate_lock) != 0)
28680Sstevel@tonic-gate #ifndef lint
28690Sstevel@tonic-gate continue;
28700Sstevel@tonic-gate #else
28710Sstevel@tonic-gate return (NULL);
28720Sstevel@tonic-gate #endif
28730Sstevel@tonic-gate if (svcstate == _IDLE && svccount == 0) {
28740Sstevel@tonic-gate int size;
28750Sstevel@tonic-gate int i, openfd = 0;
28760Sstevel@tonic-gate
28770Sstevel@tonic-gate size = svc_max_pollfd;
28780Sstevel@tonic-gate for (i = 0; i < size && openfd < 2; i++)
28790Sstevel@tonic-gate if (svc_pollfd[i].fd >= 0)
28800Sstevel@tonic-gate openfd++;
28810Sstevel@tonic-gate if (openfd <= 1) {
28820Sstevel@tonic-gate debug(5,
28830Sstevel@tonic-gate "Exiting the server from closedown routine.\n");
28840Sstevel@tonic-gate exit(0);
28850Sstevel@tonic-gate }
28860Sstevel@tonic-gate } else
28870Sstevel@tonic-gate svcstate = _IDLE;
28880Sstevel@tonic-gate
28890Sstevel@tonic-gate (void) mutex_unlock(&svcstate_lock);
28900Sstevel@tonic-gate #ifndef lint
28910Sstevel@tonic-gate }
28920Sstevel@tonic-gate #else
28930Sstevel@tonic-gate return (NULL);
28940Sstevel@tonic-gate #endif
28950Sstevel@tonic-gate
28960Sstevel@tonic-gate }
28970Sstevel@tonic-gate
28980Sstevel@tonic-gate static void
usage()28990Sstevel@tonic-gate usage()
29000Sstevel@tonic-gate {
29010Sstevel@tonic-gate warning(gettext("usage: %s [-L loglevel] level of debug information\n"),
29020Sstevel@tonic-gate prog_name);
29030Sstevel@tonic-gate }
29040Sstevel@tonic-gate
29050Sstevel@tonic-gate
29060Sstevel@tonic-gate /*ARGSUSED*/
2907796Smathue int
main(int argc,char ** argv)29080Sstevel@tonic-gate main(int argc, char **argv)
29090Sstevel@tonic-gate {
29100Sstevel@tonic-gate int c;
29110Sstevel@tonic-gate pthread_attr_t attr;
29120Sstevel@tonic-gate
29130Sstevel@tonic-gate (void) setlocale(LC_ALL, "");
29140Sstevel@tonic-gate #if !defined(TEXT_DOMAIN)
29150Sstevel@tonic-gate #define TEXT_DOMAIN "SYS_TEST"
29160Sstevel@tonic-gate #endif
29170Sstevel@tonic-gate (void) textdomain(TEXT_DOMAIN);
29180Sstevel@tonic-gate
29190Sstevel@tonic-gate prog_name = argv[0];
29200Sstevel@tonic-gate
29210Sstevel@tonic-gate (void) sigset(SIGPIPE, SIG_IGN);
29220Sstevel@tonic-gate
29230Sstevel@tonic-gate while ((c = getopt(argc, argv, "L:")) != -1) {
29240Sstevel@tonic-gate switch (c) {
29250Sstevel@tonic-gate case 'L':
29260Sstevel@tonic-gate debug_level = atoi((char *)optarg);
29270Sstevel@tonic-gate break;
29280Sstevel@tonic-gate default:
29290Sstevel@tonic-gate usage();
29300Sstevel@tonic-gate break;
29310Sstevel@tonic-gate }
29320Sstevel@tonic-gate }
29330Sstevel@tonic-gate
29340Sstevel@tonic-gate /*
29350Sstevel@tonic-gate * If stdin looks like a TLI endpoint, we assume
29360Sstevel@tonic-gate * that we were started by a port monitor. If
29370Sstevel@tonic-gate * t_getstate fails with TBADF, this is not a
29380Sstevel@tonic-gate * TLI endpoint.
29390Sstevel@tonic-gate */
29400Sstevel@tonic-gate if (t_getstate(0) != -1 || t_errno != TBADF) {
29410Sstevel@tonic-gate char *netid;
29420Sstevel@tonic-gate struct netconfig *nconf = NULL;
29430Sstevel@tonic-gate SVCXPRT *transp;
29440Sstevel@tonic-gate int pmclose;
29450Sstevel@tonic-gate
29460Sstevel@tonic-gate openlog(prog_name, LOG_PID, LOG_DAEMON);
29470Sstevel@tonic-gate
29480Sstevel@tonic-gate debug(1, gettext("server started by port monitor.\n"));
29490Sstevel@tonic-gate if ((netid = getenv("NLSPROVIDER")) == NULL) {
29500Sstevel@tonic-gate /* started from inetd */
29510Sstevel@tonic-gate pmclose = 1;
29520Sstevel@tonic-gate } else {
29530Sstevel@tonic-gate if ((nconf = getnetconfigent(netid)) == NULL)
29540Sstevel@tonic-gate syslog(LOG_ERR, gettext(
29550Sstevel@tonic-gate "cannot get transport info"));
29560Sstevel@tonic-gate
29570Sstevel@tonic-gate pmclose = (t_getstate(0) != T_DATAXFER);
29580Sstevel@tonic-gate }
29590Sstevel@tonic-gate if ((transp = svc_tli_create(0, nconf, NULL, 0, 0)) == NULL) {
29600Sstevel@tonic-gate syslog(LOG_ERR, gettext("cannot create server handle"));
29610Sstevel@tonic-gate exit(1);
29620Sstevel@tonic-gate }
29630Sstevel@tonic-gate if (nconf)
29640Sstevel@tonic-gate freenetconfigent(nconf);
29650Sstevel@tonic-gate if (!svc_reg(transp, SMSERVERPROG, SMSERVERVERS,
29660Sstevel@tonic-gate smserverprog_1, 0)) {
29670Sstevel@tonic-gate syslog(LOG_ERR, gettext(
29680Sstevel@tonic-gate "unable to register (SMSERVERPROG, SMSERVERVERS)."));
29690Sstevel@tonic-gate exit(1);
29700Sstevel@tonic-gate }
29710Sstevel@tonic-gate svcstart_level = get_run_level();
29720Sstevel@tonic-gate if (pmclose) {
29730Sstevel@tonic-gate (void) pthread_attr_init(&attr);
29740Sstevel@tonic-gate (void) pthread_attr_setscope(&attr,
29756247Sraf PTHREAD_SCOPE_SYSTEM);
29766247Sraf (void) pthread_attr_setdetachstate(&attr,
29776247Sraf PTHREAD_CREATE_DETACHED);
29780Sstevel@tonic-gate if (pthread_create(NULL, &attr, closedown, NULL) != 0) {
29790Sstevel@tonic-gate syslog(LOG_ERR, gettext(
29800Sstevel@tonic-gate "cannot create closedown thread"));
29810Sstevel@tonic-gate exit(1);
29820Sstevel@tonic-gate }
29830Sstevel@tonic-gate (void) pthread_attr_destroy(&attr);
29840Sstevel@tonic-gate }
29850Sstevel@tonic-gate svc_run();
29860Sstevel@tonic-gate exit(1);
29870Sstevel@tonic-gate /* NOTREACHED */
29880Sstevel@tonic-gate } else {
29890Sstevel@tonic-gate /*
29900Sstevel@tonic-gate * Started by library or manually.
29910Sstevel@tonic-gate */
29920Sstevel@tonic-gate /*
29930Sstevel@tonic-gate * Check to see if the server is already running.
29940Sstevel@tonic-gate * There is no need to log messages in the syslog file
29950Sstevel@tonic-gate * because server will get launched each time libsmedia
29960Sstevel@tonic-gate * library calls are made at init 1 level.
29970Sstevel@tonic-gate * We ensure that only one copy will run.
29980Sstevel@tonic-gate */
29990Sstevel@tonic-gate debug(1, gettext("server started manually.\n"));
30000Sstevel@tonic-gate if (server_exists()) {
30010Sstevel@tonic-gate exit(0);
30020Sstevel@tonic-gate }
30030Sstevel@tonic-gate svcstart_level = get_run_level();
30040Sstevel@tonic-gate (void) pthread_attr_init(&attr);
30050Sstevel@tonic-gate (void) pthread_attr_setscope(&attr,
30066247Sraf PTHREAD_SCOPE_SYSTEM);
30076247Sraf (void) pthread_attr_setdetachstate(&attr,
30086247Sraf PTHREAD_CREATE_DETACHED);
30090Sstevel@tonic-gate if (pthread_create(NULL, &attr, closedown, NULL) != 0) {
30100Sstevel@tonic-gate syslog(LOG_ERR, gettext(
30110Sstevel@tonic-gate "cannot create closedown thread"));
30120Sstevel@tonic-gate exit(1);
30130Sstevel@tonic-gate }
30140Sstevel@tonic-gate (void) pthread_attr_destroy(&attr);
30150Sstevel@tonic-gate (void) init_server(NULL);
30160Sstevel@tonic-gate for (;;) (void) pause();
30170Sstevel@tonic-gate }
3018796Smathue return (0);
30190Sstevel@tonic-gate }
30200Sstevel@tonic-gate
30210Sstevel@tonic-gate
30220Sstevel@tonic-gate /*ARGSUSED*/
30230Sstevel@tonic-gate static int32_t
scsi_floppy_write_protect(int32_t fd,smwp_state_t * wp)30240Sstevel@tonic-gate scsi_floppy_write_protect(int32_t fd, smwp_state_t *wp)
30250Sstevel@tonic-gate {
30260Sstevel@tonic-gate debug(5, "Invalid mode\n");
30270Sstevel@tonic-gate errno = ENOTSUP;
30280Sstevel@tonic-gate
30290Sstevel@tonic-gate return (-1);
30300Sstevel@tonic-gate }
30310Sstevel@tonic-gate
30320Sstevel@tonic-gate /*
30330Sstevel@tonic-gate * Generate standard geometry information for SCSI floppy devices. And
30340Sstevel@tonic-gate * register the geometry with the SCSI driver. This will expand as more
30350Sstevel@tonic-gate * formats are added.
30360Sstevel@tonic-gate */
30370Sstevel@tonic-gate
30380Sstevel@tonic-gate /*ARGSUSED*/
30390Sstevel@tonic-gate static int32_t
get_floppy_geom(int32_t fd,uint32_t capacity,struct dk_geom * dkgeom)30400Sstevel@tonic-gate get_floppy_geom(int32_t fd, uint32_t capacity, struct dk_geom *dkgeom)
30410Sstevel@tonic-gate {
30420Sstevel@tonic-gate
30430Sstevel@tonic-gate
30440Sstevel@tonic-gate debug(5, "get_floppy_geom: capacity = 0x%x\n", capacity);
30450Sstevel@tonic-gate
30460Sstevel@tonic-gate switch (capacity) {
30470Sstevel@tonic-gate
30480Sstevel@tonic-gate case 0x5A0:
30490Sstevel@tonic-gate /* Double Density 720K */
30500Sstevel@tonic-gate dkgeom->dkg_pcyl = 80;
30510Sstevel@tonic-gate dkgeom->dkg_ncyl = 80;
30520Sstevel@tonic-gate dkgeom->dkg_nhead = 2;
30530Sstevel@tonic-gate dkgeom->dkg_nsect = 9;
30540Sstevel@tonic-gate break;
30550Sstevel@tonic-gate case 0x4D0:
30560Sstevel@tonic-gate /* High Density 1.25MB */
30570Sstevel@tonic-gate dkgeom->dkg_pcyl = 77;
30580Sstevel@tonic-gate dkgeom->dkg_ncyl = 77;
30590Sstevel@tonic-gate dkgeom->dkg_nhead = 2;
30600Sstevel@tonic-gate dkgeom->dkg_nsect = 9;
30610Sstevel@tonic-gate break;
30620Sstevel@tonic-gate case 0xB40:
30630Sstevel@tonic-gate /* High Density 1.44MB */
30640Sstevel@tonic-gate
30650Sstevel@tonic-gate dkgeom->dkg_pcyl = 80;
30660Sstevel@tonic-gate dkgeom->dkg_ncyl = 80;
30670Sstevel@tonic-gate dkgeom->dkg_nhead = 2;
30680Sstevel@tonic-gate dkgeom->dkg_nsect = 18;
30690Sstevel@tonic-gate break;
30700Sstevel@tonic-gate case 0x3C300:
30710Sstevel@tonic-gate /* Ultra High density ls-120 120MB */
30720Sstevel@tonic-gate dkgeom->dkg_pcyl = 963;
30730Sstevel@tonic-gate dkgeom->dkg_ncyl = 963;
30740Sstevel@tonic-gate dkgeom->dkg_nhead = 8;
30750Sstevel@tonic-gate dkgeom->dkg_nsect = 32;
30760Sstevel@tonic-gate break;
30770Sstevel@tonic-gate default:
30780Sstevel@tonic-gate debug(5, "unknown capacity type %d\n", capacity);
30790Sstevel@tonic-gate return (-1);
30800Sstevel@tonic-gate
30810Sstevel@tonic-gate }
30820Sstevel@tonic-gate debug(5, "get_floppy_geom: setting cyl = %d, nsect = %d, head = %d",
30830Sstevel@tonic-gate dkgeom->dkg_pcyl, dkgeom->dkg_nhead, dkgeom->dkg_nsect);
30840Sstevel@tonic-gate return (0);
30850Sstevel@tonic-gate
30860Sstevel@tonic-gate }
30870Sstevel@tonic-gate /* ARGSUSED */
30881137Sarutz static int32_t
scsi_floppy_format(int32_t fd,uint_t flavor,uint_t mode)30890Sstevel@tonic-gate scsi_floppy_format(int32_t fd, uint_t flavor, uint_t mode)
30900Sstevel@tonic-gate {
30910Sstevel@tonic-gate struct uscsi_cmd ucmd;
30920Sstevel@tonic-gate uchar_t cdb[12];
30930Sstevel@tonic-gate int32_t ret_val;
30940Sstevel@tonic-gate uint32_t capacity, blocksize;
30950Sstevel@tonic-gate uchar_t data[12];
30960Sstevel@tonic-gate char rq_data[RQ_LEN];
30970Sstevel@tonic-gate int i;
30980Sstevel@tonic-gate struct dk_geom dkgeom;
30990Sstevel@tonic-gate
31000Sstevel@tonic-gate debug(5, "scsi_floppy_format:\n");
31010Sstevel@tonic-gate
31020Sstevel@tonic-gate if ((mode != SM_FORMAT_IMMEDIATE) && (mode != SM_FORMAT_BLOCKED)) {
31030Sstevel@tonic-gate errno = ENOTSUP;
31040Sstevel@tonic-gate
31050Sstevel@tonic-gate return (-1);
31060Sstevel@tonic-gate }
31070Sstevel@tonic-gate
31080Sstevel@tonic-gate switch (flavor) {
31090Sstevel@tonic-gate case SM_FORMAT_QUICK :
31100Sstevel@tonic-gate debug(1, "Format not supported\n");
31110Sstevel@tonic-gate errno = ENOTSUP;
31120Sstevel@tonic-gate return (-1);
31130Sstevel@tonic-gate case SM_FORMAT_FORCE :
31140Sstevel@tonic-gate break;
31150Sstevel@tonic-gate case SM_FORMAT_LONG :
31160Sstevel@tonic-gate break;
31170Sstevel@tonic-gate
31180Sstevel@tonic-gate default :
31190Sstevel@tonic-gate debug(1, "Format option not specified!!\n");
31200Sstevel@tonic-gate errno = ENOTSUP;
31210Sstevel@tonic-gate return (-1);
31220Sstevel@tonic-gate }
31230Sstevel@tonic-gate
31240Sstevel@tonic-gate ret_val = get_media_capacity(fd, &capacity, &blocksize);
31250Sstevel@tonic-gate
31260Sstevel@tonic-gate if (capacity >= 0x3C300) {
31270Sstevel@tonic-gate /*
31280Sstevel@tonic-gate * It's an LS-120 media, it does not support track
31290Sstevel@tonic-gate * formatting.
31300Sstevel@tonic-gate */
31310Sstevel@tonic-gate return (scsi_ls120_format(fd, flavor, capacity, blocksize));
31320Sstevel@tonic-gate }
31330Sstevel@tonic-gate
31340Sstevel@tonic-gate ret_val = get_floppy_geom(fd, capacity, &dkgeom);
31350Sstevel@tonic-gate if (ret_val) {
31360Sstevel@tonic-gate errno = ENOTSUP;
31370Sstevel@tonic-gate return (-1);
31380Sstevel@tonic-gate }
31390Sstevel@tonic-gate
31400Sstevel@tonic-gate (void) memset((void *)&data, 0, sizeof (data));
31410Sstevel@tonic-gate (void) memset((void *)&ucmd, 0, sizeof (ucmd));
31420Sstevel@tonic-gate (void) memset((void *)&cdb, 0, sizeof (cdb));
31430Sstevel@tonic-gate
31440Sstevel@tonic-gate /* retrieve size discriptor of inserted media */
31450Sstevel@tonic-gate cdb[0] = SCMD_FORMAT; /* format */
31460Sstevel@tonic-gate
31470Sstevel@tonic-gate /*
31480Sstevel@tonic-gate * Defect list sent by initiator is a complete list of defects.
31490Sstevel@tonic-gate */
31500Sstevel@tonic-gate
31510Sstevel@tonic-gate cdb[1] = (FMTDATA | 0x7);
31520Sstevel@tonic-gate
31530Sstevel@tonic-gate cdb[8] = 0xC; /* parameter list length */
31540Sstevel@tonic-gate data[3] = 0x8; /* should be always 8 */
31550Sstevel@tonic-gate
31560Sstevel@tonic-gate data[4] = (uchar_t)(capacity >> 24);
31570Sstevel@tonic-gate data[5] = (uchar_t)(capacity >> 16);
31580Sstevel@tonic-gate data[6] = (uchar_t)(capacity >> 8);
31590Sstevel@tonic-gate data[7] = (uchar_t)capacity;
31600Sstevel@tonic-gate
31610Sstevel@tonic-gate data[9] = (uchar_t)(blocksize >> 16);
31620Sstevel@tonic-gate data[10] = (uchar_t)(blocksize >> 8);
31630Sstevel@tonic-gate data[11] = (uchar_t)blocksize;
31640Sstevel@tonic-gate
31650Sstevel@tonic-gate ucmd.uscsi_cdb = (caddr_t)&cdb;
31660Sstevel@tonic-gate ucmd.uscsi_cdblen = CDB_GROUP5;
31670Sstevel@tonic-gate ucmd.uscsi_bufaddr = (caddr_t)data;
31680Sstevel@tonic-gate ucmd.uscsi_buflen = sizeof (data);
31690Sstevel@tonic-gate ucmd.uscsi_timeout = 0x15;
31700Sstevel@tonic-gate ucmd.uscsi_rqlen = RQ_LEN;
31710Sstevel@tonic-gate ucmd.uscsi_rqbuf = rq_data;
31720Sstevel@tonic-gate
31730Sstevel@tonic-gate debug(5, "cdb: %x %x %x ... %x", cdb[0], cdb[1], cdb[2], cdb[8]);
31740Sstevel@tonic-gate debug(5, "data: %x %x %x %x\n", data[0], data[1], data[2], data[3]);
31750Sstevel@tonic-gate debug(5, " : %x %x %x %x\n", data[4], data[5], data[6], data[7]);
31760Sstevel@tonic-gate debug(5, " : %x %x %x %x\n", data[8], data[9], data[10], data[11]);
31770Sstevel@tonic-gate
31780Sstevel@tonic-gate for (i = 0; i < dkgeom.dkg_pcyl; i++) { /* number of tracks */
31790Sstevel@tonic-gate data[1] = (0xb0 | FOV);
31800Sstevel@tonic-gate cdb[2] = i;
31810Sstevel@tonic-gate
31820Sstevel@tonic-gate (void) fflush(stdout);
31830Sstevel@tonic-gate ret_val = do_uscsi_cmd(fd, &ucmd, USCSI_WRITE|USCSI_RQENABLE);
31840Sstevel@tonic-gate info("format side 0 returned : 0x%x\n", ret_val);
31850Sstevel@tonic-gate
31860Sstevel@tonic-gate if (ret_val || ucmd.uscsi_status) {
31870Sstevel@tonic-gate debug(5, "Retrieving media info failed: %d - %d\n",
31880Sstevel@tonic-gate ret_val, ucmd.uscsi_status);
31890Sstevel@tonic-gate if ((rq_data[2] == KEY_DATA_PROTECT) &&
31900Sstevel@tonic-gate (rq_data[12] == 0x30) && (rq_data[13] == 0)) {
31910Sstevel@tonic-gate debug(5, "Invalid command for media\n");
31920Sstevel@tonic-gate errno = EINVAL;
31930Sstevel@tonic-gate }
31940Sstevel@tonic-gate
31950Sstevel@tonic-gate if ((rq_data[2] == KEY_NOT_READY) &&
31960Sstevel@tonic-gate (rq_data[12] == 0x30)) {
31970Sstevel@tonic-gate debug(5, "Incompatible media.\n");
31980Sstevel@tonic-gate errno = EINVAL;
31990Sstevel@tonic-gate }
32000Sstevel@tonic-gate
32010Sstevel@tonic-gate return (-1);
32020Sstevel@tonic-gate }
32030Sstevel@tonic-gate data[1] = (0xb0 | FOV) + 1;
32040Sstevel@tonic-gate ret_val = do_uscsi_cmd(fd, &ucmd, USCSI_WRITE|USCSI_RQENABLE);
32050Sstevel@tonic-gate info("format side 1 returned : 0x%x\n", ret_val);
32060Sstevel@tonic-gate
32070Sstevel@tonic-gate if (ret_val || ucmd.uscsi_status) {
32080Sstevel@tonic-gate debug(5, "Retrieving media info failed: %d - %d\n",
32090Sstevel@tonic-gate ret_val, ucmd.uscsi_status);
32100Sstevel@tonic-gate if ((rq_data[2] == KEY_DATA_PROTECT) &&
32110Sstevel@tonic-gate (rq_data[12] == 0x30) && (rq_data[13] == 0)) {
32120Sstevel@tonic-gate (void) info("Invalid command for media\n");
32130Sstevel@tonic-gate errno = EINVAL;
32140Sstevel@tonic-gate }
32150Sstevel@tonic-gate
32160Sstevel@tonic-gate if ((rq_data[2] == KEY_NOT_READY) &&
32170Sstevel@tonic-gate (rq_data[12] == 0x30)) {
32180Sstevel@tonic-gate debug(5, "Incompatible media.\n");
32190Sstevel@tonic-gate errno = EINVAL;
32200Sstevel@tonic-gate }
32210Sstevel@tonic-gate
32220Sstevel@tonic-gate return (-1);
32230Sstevel@tonic-gate }
32240Sstevel@tonic-gate }
32250Sstevel@tonic-gate
32260Sstevel@tonic-gate debug(5, "formatting done!");
32270Sstevel@tonic-gate return (0);
32280Sstevel@tonic-gate }
32290Sstevel@tonic-gate
32300Sstevel@tonic-gate
32310Sstevel@tonic-gate /* ARGSUSED */
32321137Sarutz static int32_t
scsi_floppy_media_status(int32_t fd)32330Sstevel@tonic-gate scsi_floppy_media_status(int32_t fd)
32340Sstevel@tonic-gate {
32350Sstevel@tonic-gate struct mode_header_g1 modeh;
32360Sstevel@tonic-gate struct uscsi_cmd ucmd;
32370Sstevel@tonic-gate uchar_t cdb[10];
32380Sstevel@tonic-gate int32_t ret_val;
32390Sstevel@tonic-gate int32_t cur_status;
32400Sstevel@tonic-gate char rq_data[RQ_LEN];
32410Sstevel@tonic-gate
32420Sstevel@tonic-gate debug(5, "SCSI MEDIA STATUS CALLED \n");
32430Sstevel@tonic-gate
32440Sstevel@tonic-gate (void) memset((void *) &modeh, 0, sizeof (modeh));
32450Sstevel@tonic-gate (void) memset((void *) &ucmd, 0, sizeof (ucmd));
32460Sstevel@tonic-gate (void) memset(cdb, 0, sizeof (cdb));
32470Sstevel@tonic-gate /*
32480Sstevel@tonic-gate * issue 10 byte mode sense (0x5A)
32490Sstevel@tonic-gate */
32500Sstevel@tonic-gate cdb[0] = SCMD_MODE_SENSE_G1;
32510Sstevel@tonic-gate cdb[7] = sizeof (modeh) >> 8;
32520Sstevel@tonic-gate cdb[8] = sizeof (modeh) & 0xff;
32530Sstevel@tonic-gate
32540Sstevel@tonic-gate ucmd.uscsi_cdb = (caddr_t)cdb;
32550Sstevel@tonic-gate ucmd.uscsi_cdblen = CDB_GROUP1;
32560Sstevel@tonic-gate ucmd.uscsi_bufaddr = (caddr_t)&modeh;
32570Sstevel@tonic-gate ucmd.uscsi_buflen = sizeof (modeh);
32580Sstevel@tonic-gate ucmd.uscsi_timeout = 120; /* If 0, HBA hangs forever */
32590Sstevel@tonic-gate ucmd.uscsi_rqlen = RQ_LEN;
32600Sstevel@tonic-gate ucmd.uscsi_rqbuf = rq_data;
32610Sstevel@tonic-gate ret_val = do_uscsi_cmd(fd, &ucmd, USCSI_READ|USCSI_RQENABLE);
32620Sstevel@tonic-gate if (ret_val || ucmd.uscsi_status) {
32630Sstevel@tonic-gate /*
32640Sstevel@tonic-gate * UFI devices may not respond to the 0 mode page.
32650Sstevel@tonic-gate * retry with the error recovery page(0x01)
32660Sstevel@tonic-gate */
32670Sstevel@tonic-gate if (ucmd.uscsi_status & STATUS_CHECK) {
32680Sstevel@tonic-gate cdb[2] = 0x1; /* page code */
32690Sstevel@tonic-gate ret_val = do_uscsi_cmd(fd, &ucmd,
32700Sstevel@tonic-gate USCSI_READ|USCSI_RQENABLE);
32710Sstevel@tonic-gate }
32720Sstevel@tonic-gate if (ret_val || ucmd.uscsi_status) {
32730Sstevel@tonic-gate debug(1, "Modesense failed: %d - %d\n",
32740Sstevel@tonic-gate ret_val, ucmd.uscsi_status);
32750Sstevel@tonic-gate return (-1);
32760Sstevel@tonic-gate }
32770Sstevel@tonic-gate }
32780Sstevel@tonic-gate debug(5, "Modesense succeeded: 0x%x\n", modeh.device_specific);
32790Sstevel@tonic-gate
32800Sstevel@tonic-gate if (modeh.device_specific & 0x80) {
32810Sstevel@tonic-gate cur_status = SM_WRITE_PROTECT_NOPASSWD;
32820Sstevel@tonic-gate } else {
32830Sstevel@tonic-gate cur_status = SM_WRITE_PROTECT_DISABLE;
32840Sstevel@tonic-gate }
32850Sstevel@tonic-gate return (cur_status);
32860Sstevel@tonic-gate }
3287