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 50Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 60Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 70Sstevel@tonic-gate * with the License. 80Sstevel@tonic-gate * 90Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 100Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 110Sstevel@tonic-gate * See the License for the specific language governing permissions 120Sstevel@tonic-gate * and limitations under the License. 130Sstevel@tonic-gate * 140Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 150Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 160Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 170Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 180Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 190Sstevel@tonic-gate * 200Sstevel@tonic-gate * CDDL HEADER END 210Sstevel@tonic-gate */ 220Sstevel@tonic-gate /* 230Sstevel@tonic-gate * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 240Sstevel@tonic-gate * Use is subject to license terms. 250Sstevel@tonic-gate */ 260Sstevel@tonic-gate 270Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 280Sstevel@tonic-gate 290Sstevel@tonic-gate #include <stdio.h> 300Sstevel@tonic-gate #include <errno.h> 310Sstevel@tonic-gate #include <ctype.h> 320Sstevel@tonic-gate #include <syslog.h> 330Sstevel@tonic-gate #include <signal.h> 340Sstevel@tonic-gate #include <limits.h> 350Sstevel@tonic-gate #include <unistd.h> 360Sstevel@tonic-gate #include <sys/types.h> 370Sstevel@tonic-gate #include <sys/mman.h> 380Sstevel@tonic-gate #include <stdlib.h> 390Sstevel@tonic-gate #include <sys/stat.h> 400Sstevel@tonic-gate #include <sys/mkdev.h> 410Sstevel@tonic-gate #include <fcntl.h> 420Sstevel@tonic-gate #include <sys/scsi/scsi.h> 430Sstevel@tonic-gate #include <sys/scsi/generic/commands.h> 440Sstevel@tonic-gate #include <string.h> 450Sstevel@tonic-gate #include <door.h> 460Sstevel@tonic-gate #include <pwd.h> 470Sstevel@tonic-gate #include <thread.h> 480Sstevel@tonic-gate #include <synch.h> 490Sstevel@tonic-gate #include <pthread.h> 500Sstevel@tonic-gate #include <locale.h> 510Sstevel@tonic-gate #include <sys/resource.h> 520Sstevel@tonic-gate #include <netconfig.h> 530Sstevel@tonic-gate #include <sys/smedia.h> 540Sstevel@tonic-gate #include "smserver.h" 550Sstevel@tonic-gate #include <rpc/rpc.h> 560Sstevel@tonic-gate #include "smed.h" 570Sstevel@tonic-gate #include "myaudit.h" 580Sstevel@tonic-gate #include <bsm/libbsm.h> 590Sstevel@tonic-gate #include <bsm/audit_uevents.h> 600Sstevel@tonic-gate #include <utmpx.h> 610Sstevel@tonic-gate 620Sstevel@tonic-gate 630Sstevel@tonic-gate /* 640Sstevel@tonic-gate * The comments below would help in understanding what is being attempted 650Sstevel@tonic-gate * in the server. 660Sstevel@tonic-gate * 670Sstevel@tonic-gate * The server can be started either by inetd or by the client directly. 680Sstevel@tonic-gate * Normally the server is started by inetd when the client invokes the 690Sstevel@tonic-gate * appropriate libsmedia library call(smedia_get_handle). 700Sstevel@tonic-gate * However since the inetd runs only at init level 2 and above a mechanism 710Sstevel@tonic-gate * is provided for the server to be started if an attempt is made to use 720Sstevel@tonic-gate * the libsmedia calls in maintenence mode(init level 1). 730Sstevel@tonic-gate * The main() routine determines how the server was invoked and takes 740Sstevel@tonic-gate * the necessary action. 750Sstevel@tonic-gate * When started by inetd it registers itself as an RPC program. 760Sstevel@tonic-gate * The server also implements a mechanism by which it removes itself 770Sstevel@tonic-gate * after a period of inactivity. The period of inactivity is specified 780Sstevel@tonic-gate * by SVC_CLOSEDOWN which is set at 180 secs. 790Sstevel@tonic-gate * The logic of detecting inactivity is as follows: 800Sstevel@tonic-gate * 810Sstevel@tonic-gate * Two variables svcstate and svccount are used to determine if the server 820Sstevel@tonic-gate * is IDLE. 830Sstevel@tonic-gate * The svcstate is set to 1(_SERVED) when ever the server does any operation 840Sstevel@tonic-gate * on behalf of the client. 850Sstevel@tonic-gate * The svccount indicates the number of active clients who have established 860Sstevel@tonic-gate * a connection with the server. A connection is established when the 870Sstevel@tonic-gate * libsmedia call smedia_get_handle() succeeds. 880Sstevel@tonic-gate * The connection is broken when the client calls smedia_free_handle() OR 890Sstevel@tonic-gate * exits. 900Sstevel@tonic-gate * A thread called closedown is started up when server is started. 910Sstevel@tonic-gate * This thread runs periodically and monitors both svcstate and svccount. 920Sstevel@tonic-gate * If svcstate is IDLE and svccount is 0 then server exits. 930Sstevel@tonic-gate * The svcstate is set to IDLE by the closedown thread. It is set to _SERVED 940Sstevel@tonic-gate * by server. It is possible for the state to be _SERVED and the svccount 950Sstevel@tonic-gate * to be 0. The server could be kept busy by client calls of smedia_get_handle 960Sstevel@tonic-gate * that do not succeed. This is the reason for using both svcstate and svccount 970Sstevel@tonic-gate * to determine the true server state. 980Sstevel@tonic-gate * 990Sstevel@tonic-gate * The communication between client and server is thru door calls. 1000Sstevel@tonic-gate * Below are the door descriptors available to communicate to the server. 1010Sstevel@tonic-gate * 1020Sstevel@tonic-gate * main_door_descriptor: 1030Sstevel@tonic-gate * --------------------- 1040Sstevel@tonic-gate * This is a predefined descriptor used by client to establish a 1050Sstevel@tonic-gate * connection with the server. This descriptor is available to the client 1060Sstevel@tonic-gate * as /var/adm/smedia_svc 107*1137Sarutz * The client uses the main_door_descriptor to obtain a dedicated 1080Sstevel@tonic-gate * client_door_descriptor for itself. The smedia_get_handle call communicates 1090Sstevel@tonic-gate * to the server using the main_door_descriptor and obtains the 1100Sstevel@tonic-gate * client_door_descriptor which is stored in the handle structure. 1110Sstevel@tonic-gate * All other libsmedia calls use the client_door_descriptor to communicate 1120Sstevel@tonic-gate * with the server. 1130Sstevel@tonic-gate * 1140Sstevel@tonic-gate * client_door_descriptor: 1150Sstevel@tonic-gate * ----------------------- 1160Sstevel@tonic-gate * This is the door descriptor that is used by the clients to 1170Sstevel@tonic-gate * request server to perform the necessary tasks. This door descriptor is 1180Sstevel@tonic-gate * available only to the client for whom it was created. 1190Sstevel@tonic-gate * 1200Sstevel@tonic-gate * death_door_descriptor: 1210Sstevel@tonic-gate * ---------------------- 122*1137Sarutz * The sole function of this descriptor HAD been to inform the server of 123*1137Sarutz * the untimely death of the client. This descriptor is no longer used, though 124*1137Sarutz * it is still created, as libsmedia expects to use it. This descriptor's 125*1137Sarutz * service procedure had used pthread cancellation(5) to terminate the thread of 126*1137Sarutz * the associated client_door_descriptor. The client_door_descriptor now 127*1137Sarutz * handles the scenarios where a door_call/client are aborted/terminated. 1280Sstevel@tonic-gate * 129*1137Sarutz * main_servproc() 1300Sstevel@tonic-gate * ------------- 1310Sstevel@tonic-gate * This is the routine associated with the main_door_descriptor. 1320Sstevel@tonic-gate * This is the routine that handles the smedia_get_handle() call 1330Sstevel@tonic-gate * of the client. If the door call to this routine succeeds it creates a 1340Sstevel@tonic-gate * client_door_descriptor that is used by the client in subsequent library 1350Sstevel@tonic-gate * calls. 1360Sstevel@tonic-gate * This client_door_descriptor is passed to the client thru the door_return 1370Sstevel@tonic-gate * call. This client_door_descriptor cannot be used by any other process other 1380Sstevel@tonic-gate * than the client process that obtained it. 1390Sstevel@tonic-gate * In addition to the client_door_descriptor a death_door_descriptor is also 1400Sstevel@tonic-gate * created by the main server and passed on to the client. The client does not 141*1137Sarutz * use the death_door_descriptor. 1420Sstevel@tonic-gate * 143*1137Sarutz * client_servproc() 1440Sstevel@tonic-gate * --------------- 1450Sstevel@tonic-gate * This is the routine that handles the libsmedia calls of the 1460Sstevel@tonic-gate * client. In the current implementation the server takes control of the 1470Sstevel@tonic-gate * number of threads that handle the door calls. This is done by creating the 1480Sstevel@tonic-gate * door descriptor as DOOR_PRIVATE. 1490Sstevel@tonic-gate * The server runs only one thread per handle. This makes the implementation 1500Sstevel@tonic-gate * simple as we do not have to use mutex to make the code MT safe. 151*1137Sarutz * The server thread has a data structure door_data_t associated with it. 1520Sstevel@tonic-gate * 1530Sstevel@tonic-gate * door_data_t 1540Sstevel@tonic-gate * ----------- 155*1137Sarutz * This is the data structure that is created by the main_servproc when it 1560Sstevel@tonic-gate * creates the client_door_descriptor. The door mechanism has a way to associate 1570Sstevel@tonic-gate * a cookie with the door descriptor. door_data_t is the cookie for the 158*1137Sarutz * client_door_descriptor. This cookie is passed to the server function that 159*1137Sarutz * handles the client_door_descriptor calls. In our case it is the 160*1137Sarutz * client_servproc routine. 1610Sstevel@tonic-gate * The key elements of the door_data_t are the following: 1620Sstevel@tonic-gate * 1630Sstevel@tonic-gate * dd_fd file descriptor for the device. 1640Sstevel@tonic-gate * dd_buf The shared memory buffer between client-server. 1650Sstevel@tonic-gate * dd_thread The thread that handles the door_calls. 1660Sstevel@tonic-gate * 1670Sstevel@tonic-gate * signal handling: 1680Sstevel@tonic-gate * ---------------- 1690Sstevel@tonic-gate * The main purpose of trapping the signals is to exit gracefully 1700Sstevel@tonic-gate * from the server after recording the appropriate message in the syslog. 1710Sstevel@tonic-gate * This will help the administrator to determine the cause of failure of the 1720Sstevel@tonic-gate * server by examining the log file. 1730Sstevel@tonic-gate * 1740Sstevel@tonic-gate * cleanup() 1750Sstevel@tonic-gate * --------- 1760Sstevel@tonic-gate * This routine frees up all the resources allocated for the client. 177*1137Sarutz * Resources include the file descriptor, shared memory, threads. 1780Sstevel@tonic-gate * 1790Sstevel@tonic-gate * shared memory 1800Sstevel@tonic-gate * ------------- 1810Sstevel@tonic-gate * In order to reduce the overheads of moving large amounts of data 1820Sstevel@tonic-gate * during raw read/write operations, the server uses the mmapped data of 1830Sstevel@tonic-gate * client. The smedia_raw_read, smedia_raw_write library calls mmap the 1840Sstevel@tonic-gate * memory and pass on the file descriptor that maps the memory to the server. 1850Sstevel@tonic-gate * The server subsequently uses this mmapped memory during the IO. 1860Sstevel@tonic-gate * If the mmapped memory changes in size, the server is informed and it 1870Sstevel@tonic-gate * remaps the memory to the changed size. 1880Sstevel@tonic-gate */ 1890Sstevel@tonic-gate #ifdef DEBUG 1900Sstevel@tonic-gate #define DEFAULT_VERBOSE 1 1910Sstevel@tonic-gate #define DEFAULT_DEBUG 1 1920Sstevel@tonic-gate #else 1930Sstevel@tonic-gate #define DEFAULT_VERBOSE 0 1940Sstevel@tonic-gate #define DEFAULT_DEBUG 0 1950Sstevel@tonic-gate #endif 1960Sstevel@tonic-gate 1970Sstevel@tonic-gate #define N_BADSIGS (sizeof (badsigs)/sizeof (badsigs[0])) 1980Sstevel@tonic-gate #define MD_LEN 30 1990Sstevel@tonic-gate #define MAXUGNAME 10 2000Sstevel@tonic-gate #define SVC_CLOSEDOWN 180 2010Sstevel@tonic-gate 2020Sstevel@tonic-gate /* 2030Sstevel@tonic-gate * We will NOT be permitting the following USCI cmd options. 2040Sstevel@tonic-gate * 2050Sstevel@tonic-gate * RESET of target 2060Sstevel@tonic-gate * RESET of Bus. 2070Sstevel@tonic-gate * Tagged commands to device 2080Sstevel@tonic-gate * Explicitly setting SYNC/ASYNC mode of operations. 2090Sstevel@tonic-gate * POLLED MODE of operation. 2100Sstevel@tonic-gate * Explicitly setting NO DISCONNECT features. 2110Sstevel@tonic-gate * use of RESERVED flags. 2120Sstevel@tonic-gate */ 2130Sstevel@tonic-gate #define FORBIDDEN_FLAGS (USCSI_RESET | USCSI_RESET_ALL | USCSI_RENEGOT \ 2140Sstevel@tonic-gate | USCSI_ASYNC | USCSI_SYNC | USCSI_NOINTR | \ 2150Sstevel@tonic-gate USCSI_NOTAG | USCSI_NOPARITY | USCSI_NODISCON \ 2160Sstevel@tonic-gate | USCSI_RESERVED) 2170Sstevel@tonic-gate 2180Sstevel@tonic-gate /* States a server can be in wrt request */ 2190Sstevel@tonic-gate 2200Sstevel@tonic-gate #define _IDLE 0 2210Sstevel@tonic-gate #define _SERVED 1 2220Sstevel@tonic-gate 2230Sstevel@tonic-gate static char *prog_name; 2240Sstevel@tonic-gate static int svcstate = _IDLE; /* Set when a request is serviced */ 2250Sstevel@tonic-gate static int svccount = 0; /* Number of requests being serviced */ 2260Sstevel@tonic-gate static int svcstart_level = 0; /* init level when server was started */ 2270Sstevel@tonic-gate static mutex_t svcstate_lock; /* lock for svcstate, svccount */ 2280Sstevel@tonic-gate 2290Sstevel@tonic-gate extern void smserverprog_1(struct svc_req *, SVCXPRT *); 2300Sstevel@tonic-gate 2310Sstevel@tonic-gate /* 2320Sstevel@tonic-gate * Log messages 2330Sstevel@tonic-gate */ 2340Sstevel@tonic-gate #define SIGACT_FAILED "Failed to install signal handler for %s: %s" 2350Sstevel@tonic-gate #define BADSIG_MSG "Thread %d Caught signal %d addr=%p trapno=%d pc=%p" 2360Sstevel@tonic-gate 2370Sstevel@tonic-gate static int badsigs[] = {SIGSEGV, SIGBUS, SIGFPE, SIGILL}; 2380Sstevel@tonic-gate 2390Sstevel@tonic-gate /* global variables */ 2400Sstevel@tonic-gate int verbose = DEFAULT_VERBOSE; 2410Sstevel@tonic-gate int debug_level = DEFAULT_DEBUG; 2420Sstevel@tonic-gate char *smediad_devdir = DEFAULT_SMEDIAD_DEVDIR; 2430Sstevel@tonic-gate 2440Sstevel@tonic-gate thread_key_t door_key; 2450Sstevel@tonic-gate 2460Sstevel@tonic-gate server_data_t server_data; 2470Sstevel@tonic-gate 2480Sstevel@tonic-gate static int server_door, server_fd; 2490Sstevel@tonic-gate 2500Sstevel@tonic-gate static int32_t do_uscsi_cmd(int32_t file, struct uscsi_cmd *uscsi_cmd, 2510Sstevel@tonic-gate int32_t flag); 252*1137Sarutz static void client_servproc(void *cookie, char *argp, size_t arg_size, 2530Sstevel@tonic-gate door_desc_t *dp, uint_t ndesc); 2540Sstevel@tonic-gate static void cleanup(door_data_t *); 2550Sstevel@tonic-gate static void *init_server(void *); 2560Sstevel@tonic-gate static int32_t scsi_reassign_block(int32_t fd, diskaddr_t); 2570Sstevel@tonic-gate static int32_t get_mode_page(int32_t fd, uchar_t pc, uchar_t page_code, 258*1137Sarutz uchar_t *md_data, uchar_t data_len); 2590Sstevel@tonic-gate static int32_t get_device_type(char *v_name); 2600Sstevel@tonic-gate static int32_t get_device_type_scsi(int32_t fd, struct scsi_inquiry *inq); 2610Sstevel@tonic-gate 2620Sstevel@tonic-gate static int32_t scsi_format(int32_t fd, uint_t flavor, uint_t mode); 2630Sstevel@tonic-gate static int32_t scsi_media_status(int32_t fd); 2640Sstevel@tonic-gate static int32_t scsi_write_protect(int32_t fd, smwp_state_t *wp); 2650Sstevel@tonic-gate static int32_t scsi_floppy_media_status(int32_t fd); 2660Sstevel@tonic-gate static int32_t scsi_floppy_write_protect(int32_t fd, smwp_state_t *wp); 2670Sstevel@tonic-gate static int32_t scsi_floppy_format(int32_t, uint_t, uint_t); 2680Sstevel@tonic-gate static int32_t get_floppy_geom(int32_t fd, uint32_t capacity, 2690Sstevel@tonic-gate struct dk_geom *dkgeom); 2700Sstevel@tonic-gate static int32_t get_media_capacity(int32_t fd, uint32_t *capacity, 2710Sstevel@tonic-gate uint32_t *blocksize); 2720Sstevel@tonic-gate 2730Sstevel@tonic-gate static int32_t scsi_ls120_format(uint_t fd, uint_t flavor, uint32_t capacity, 2740Sstevel@tonic-gate uint32_t blocksize); 2750Sstevel@tonic-gate 276*1137Sarutz static void *sm_server_thread(void *arg); 277*1137Sarutz static void sm_door_server_create(door_info_t *dip); 2780Sstevel@tonic-gate static void term_handler(int sig, siginfo_t *siginfo, void *sigctx); 2790Sstevel@tonic-gate static void hup_handler(int sig, siginfo_t *siginfo, void *sigctx); 2800Sstevel@tonic-gate static void sig_handler(int sig, siginfo_t *siginfo, void *sigctx); 2810Sstevel@tonic-gate static void badsig_handler(int sig, siginfo_t *siginfo, void *sigctx); 2820Sstevel@tonic-gate static void server_badsig_handler(int sig, siginfo_t *siginfo, void *sigctx); 2830Sstevel@tonic-gate static char *xlate_state(int32_t); 2840Sstevel@tonic-gate static uint32_t get_sector_size(int fd); 2850Sstevel@tonic-gate static int32_t raw_read(door_data_t *door_dp, smedia_services_t *req); 2860Sstevel@tonic-gate static int32_t raw_write(door_data_t *door_dp, smedia_services_t *req); 2870Sstevel@tonic-gate static int32_t reassign_block(door_data_t *door_dp, smedia_services_t *req); 2880Sstevel@tonic-gate static int32_t set_protection_status(door_data_t *door_dp, 2890Sstevel@tonic-gate smedia_services_t *req); 2900Sstevel@tonic-gate static int32_t set_shfd(door_data_t *door_dp, int32_t fd, 2910Sstevel@tonic-gate smedia_services_t *req); 2920Sstevel@tonic-gate 2930Sstevel@tonic-gate static void door_ret_err(smedia_reterror_t *reterror, int32_t err); 2940Sstevel@tonic-gate static void my_door_return(char *data_ptr, size_t data_size, 2950Sstevel@tonic-gate door_desc_t *desc_ptr, uint_t num_desc); 2960Sstevel@tonic-gate static int32_t invalid_uscsi_operation(door_data_t *, struct uscsi_cmd *); 2970Sstevel@tonic-gate 2980Sstevel@tonic-gate #define W_E_MASK 0x80 2990Sstevel@tonic-gate 3000Sstevel@tonic-gate static smserver_info server_info; 3010Sstevel@tonic-gate 3020Sstevel@tonic-gate static int32_t 3030Sstevel@tonic-gate invalid_uscsi_operation(door_data_t *door_dp, struct uscsi_cmd *ucmd) 3040Sstevel@tonic-gate { 3050Sstevel@tonic-gate 3060Sstevel@tonic-gate if (door_dp->dd_dkinfo.dki_ctype != DKC_CDROM) { 3070Sstevel@tonic-gate debug(5, 3080Sstevel@tonic-gate "Invalid device type(0x%x) found for uscsi cmd.\n", 3090Sstevel@tonic-gate door_dp->dd_dkinfo.dki_ctype); 3100Sstevel@tonic-gate errno = EINVAL; 3110Sstevel@tonic-gate return (EINVAL); 3120Sstevel@tonic-gate } 3130Sstevel@tonic-gate if (ucmd->uscsi_flags & FORBIDDEN_FLAGS) { 3140Sstevel@tonic-gate debug(5, 3150Sstevel@tonic-gate "Invalid flags(0x%x) set in uscsi cmd. cdb[0]=0x%x\n", 3160Sstevel@tonic-gate ucmd->uscsi_flags, ucmd->uscsi_cdb[0]); 3170Sstevel@tonic-gate errno = EINVAL; 3180Sstevel@tonic-gate return (EINVAL); 3190Sstevel@tonic-gate } 3200Sstevel@tonic-gate if (ucmd->uscsi_cdb[0] == SCMD_COPY || 3210Sstevel@tonic-gate ucmd->uscsi_cdb[0] == SCMD_COPY_VERIFY || 3220Sstevel@tonic-gate ucmd->uscsi_cdb[0] == SCMD_COMPARE || 3230Sstevel@tonic-gate ucmd->uscsi_cdb[0] == SCMD_WRITE_BUFFER) { 3240Sstevel@tonic-gate debug(5, 3250Sstevel@tonic-gate "Invalid command(0x%x) found in cdb.\n", 3260Sstevel@tonic-gate ucmd->uscsi_cdb[0]); 3270Sstevel@tonic-gate errno = EINVAL; 3280Sstevel@tonic-gate return (EINVAL); 3290Sstevel@tonic-gate } 3300Sstevel@tonic-gate return (0); 3310Sstevel@tonic-gate } 3320Sstevel@tonic-gate 3330Sstevel@tonic-gate static uint32_t 3340Sstevel@tonic-gate get_sector_size(int fd) 3350Sstevel@tonic-gate { 3360Sstevel@tonic-gate uint32_t sector_size; 3370Sstevel@tonic-gate struct uscsi_cmd ucmd; 3380Sstevel@tonic-gate union scsi_cdb cdb; 3390Sstevel@tonic-gate int32_t ret_val; 3400Sstevel@tonic-gate uint32_t rc_data[2]; 3410Sstevel@tonic-gate char rq_data[RQ_LEN]; 3420Sstevel@tonic-gate 3430Sstevel@tonic-gate cdb.scc_cmd = SCMD_READ_CAPACITY; 3440Sstevel@tonic-gate ucmd.uscsi_cdb = (caddr_t)&cdb; 3450Sstevel@tonic-gate ucmd.uscsi_cdblen = CDB_GROUP1; 3460Sstevel@tonic-gate ucmd.uscsi_bufaddr = (caddr_t)&rc_data; 3470Sstevel@tonic-gate ucmd.uscsi_buflen = sizeof (rc_data); 3480Sstevel@tonic-gate ucmd.uscsi_timeout = 120; /* If 0, HBA hangs forever */ 3490Sstevel@tonic-gate ucmd.uscsi_rqlen = RQ_LEN; 3500Sstevel@tonic-gate ucmd.uscsi_rqbuf = rq_data; 3510Sstevel@tonic-gate 3520Sstevel@tonic-gate ret_val = do_uscsi_cmd(fd, 3530Sstevel@tonic-gate &ucmd, USCSI_READ|USCSI_RQENABLE); 3540Sstevel@tonic-gate if (ret_val || ucmd.uscsi_status) { 3550Sstevel@tonic-gate debug(5, "Read capacity : %d - %d errno = %d\n", 3560Sstevel@tonic-gate ret_val, ucmd.uscsi_status, errno); 3570Sstevel@tonic-gate sector_size = 512; 3580Sstevel@tonic-gate } else { 3590Sstevel@tonic-gate sector_size = ntohl(rc_data[1]); 3600Sstevel@tonic-gate } 3610Sstevel@tonic-gate debug(5, "sector size = 0x%x(%d)\n", 3620Sstevel@tonic-gate sector_size, sector_size); 3630Sstevel@tonic-gate return (sector_size); 3640Sstevel@tonic-gate } 3650Sstevel@tonic-gate 3660Sstevel@tonic-gate static char * 3670Sstevel@tonic-gate xlate_state(int32_t state) 3680Sstevel@tonic-gate { 3690Sstevel@tonic-gate switch (state) { 3700Sstevel@tonic-gate 3710Sstevel@tonic-gate case SM_WRITE_PROTECT_DISABLE: 3720Sstevel@tonic-gate return ("PROTECTION_DISABLED"); 3730Sstevel@tonic-gate case SM_WRITE_PROTECT_PASSWD: 3740Sstevel@tonic-gate return ("WRITE_PROTECT_PASSWD"); 3750Sstevel@tonic-gate case SM_WRITE_PROTECT_NOPASSWD: 3760Sstevel@tonic-gate return ("WRITE_PROTECT_NOPASSWD"); 3770Sstevel@tonic-gate case SM_READ_WRITE_PROTECT: 3780Sstevel@tonic-gate return ("READ_WRITE_PROTECT"); 3790Sstevel@tonic-gate case SM_TEMP_UNLOCK_MODE: 3800Sstevel@tonic-gate return ("PROTECTION DISABLED"); 3810Sstevel@tonic-gate default: 3820Sstevel@tonic-gate return ("UNKNOWN_STATE"); 3830Sstevel@tonic-gate } 3840Sstevel@tonic-gate } 3850Sstevel@tonic-gate 3860Sstevel@tonic-gate static char * 3870Sstevel@tonic-gate xlate_cnum(smedia_callnumber_t cnum) 3880Sstevel@tonic-gate { 3890Sstevel@tonic-gate switch (cnum) { 3900Sstevel@tonic-gate 3910Sstevel@tonic-gate case SMEDIA_CNUM_OPEN_FD: 3920Sstevel@tonic-gate return ("SMEDIA_CNUM_OPEN_FD"); 3930Sstevel@tonic-gate case SMEDIA_CNUM_GET_DEVICE_INFO: 3940Sstevel@tonic-gate return ("SMEDIA_CNUM_GET_DEVICE_INFO"); 3950Sstevel@tonic-gate case SMEDIA_CNUM_GET_MEDIUM_PROPERTY: 3960Sstevel@tonic-gate return ("SMEDIA_CNUM_GET_MEDIUM_PROPERTY"); 3970Sstevel@tonic-gate case SMEDIA_CNUM_GET_PROTECTION_STATUS: 3980Sstevel@tonic-gate return ("SMEDIA_CNUM_GET_PROTECTION_STATUS"); 3990Sstevel@tonic-gate case SMEDIA_CNUM_SET_PROTECTION_STATUS: 4000Sstevel@tonic-gate return ("SMEDIA_CNUM_SET_PROTECTION_STATUS"); 4010Sstevel@tonic-gate case SMEDIA_CNUM_RAW_READ: 4020Sstevel@tonic-gate return ("SMEDIA_CNUM_RAW_READ"); 4030Sstevel@tonic-gate case SMEDIA_CNUM_RAW_WRITE: 4040Sstevel@tonic-gate return (" SMEDIA_CNUM_RAW_WRITE"); 4050Sstevel@tonic-gate case SMEDIA_CNUM_FORMAT: 4060Sstevel@tonic-gate return ("SMEDIA_CNUM_FORMAT"); 4070Sstevel@tonic-gate case SMEDIA_CNUM_CHECK_FORMAT_STATUS: 4080Sstevel@tonic-gate return ("SMEDIA_CNUM_CHECK_FORMAT_STATUS"); 4090Sstevel@tonic-gate case SMEDIA_CNUM_EJECT: 4100Sstevel@tonic-gate return ("SMEDIA_CNUM_EJECT"); 4110Sstevel@tonic-gate case SMEDIA_CNUM_REASSIGN_BLOCK: 4120Sstevel@tonic-gate return ("SMEDIA_CNUM_REASSIGN_BLOCK"); 4130Sstevel@tonic-gate case SMEDIA_CNUM_SET_SHFD: 4140Sstevel@tonic-gate return ("SMEDIA_CNUM_SET_SHFD"); 4150Sstevel@tonic-gate case SMEDIA_CNUM_PING: 4160Sstevel@tonic-gate return ("SMEDIA_CNUM_PING"); 4170Sstevel@tonic-gate case SMEDIA_CNUM_USCSI_CMD: 4180Sstevel@tonic-gate return ("SMEDIA_CNUM_USCSI_CMD"); 4190Sstevel@tonic-gate default: 4200Sstevel@tonic-gate return ("UNKNOWN_CNUM"); 4210Sstevel@tonic-gate } 4220Sstevel@tonic-gate } 4230Sstevel@tonic-gate 4240Sstevel@tonic-gate /*ARGSUSED*/ 4250Sstevel@tonic-gate smserver_info * 4260Sstevel@tonic-gate smserverproc_get_serverinfo_1(void *argp, CLIENT *clnt) 4270Sstevel@tonic-gate { 4280Sstevel@tonic-gate (void) mutex_lock(&svcstate_lock); 4290Sstevel@tonic-gate svcstate = _SERVED; 4300Sstevel@tonic-gate (void) mutex_unlock(&svcstate_lock); 4310Sstevel@tonic-gate server_info.vernum = SMSERVERVERS; 4320Sstevel@tonic-gate server_info.status = 0; 4330Sstevel@tonic-gate (void) mutex_lock(&server_data.sd_init_lock); 4340Sstevel@tonic-gate if (server_data.sd_init_state == INIT_NOT_DONE) { 4350Sstevel@tonic-gate server_data.sd_init_state = INIT_IN_PROGRESS; 4360Sstevel@tonic-gate debug(5, "Initialising server\n"); 4370Sstevel@tonic-gate (void) init_server(NULL); 4380Sstevel@tonic-gate } 4390Sstevel@tonic-gate if (server_data.sd_init_state != INIT_DONE) { 440*1137Sarutz debug(1, "init_server did not do the job. " 441*1137Sarutz "init_state=%d\n", server_data.sd_init_state); 4420Sstevel@tonic-gate server_data.sd_init_state = INIT_NOT_DONE; 4430Sstevel@tonic-gate (void) mutex_unlock(&server_data.sd_init_lock); 4440Sstevel@tonic-gate server_info.status = -1; 4450Sstevel@tonic-gate return (&server_info); 4460Sstevel@tonic-gate } 4470Sstevel@tonic-gate (void) mutex_unlock(&server_data.sd_init_lock); 4480Sstevel@tonic-gate 4490Sstevel@tonic-gate debug(5, "smserverproc thread %d running....\n", pthread_self()); 4500Sstevel@tonic-gate return (&server_info); 4510Sstevel@tonic-gate } 4520Sstevel@tonic-gate 4530Sstevel@tonic-gate /*ARGSUSED*/ 4540Sstevel@tonic-gate static void 4550Sstevel@tonic-gate server_badsig_handler(int sig, siginfo_t *siginfo, void *sigctx) 4560Sstevel@tonic-gate { 4570Sstevel@tonic-gate 4580Sstevel@tonic-gate fatal(gettext(BADSIG_MSG), pthread_self(), sig, siginfo->si_addr, 4590Sstevel@tonic-gate siginfo->si_trapno, 4600Sstevel@tonic-gate siginfo->si_pc); 4610Sstevel@tonic-gate } 4620Sstevel@tonic-gate 4630Sstevel@tonic-gate static int32_t 4640Sstevel@tonic-gate do_uscsi_cmd(int32_t file, struct uscsi_cmd *uscsi_cmd, int32_t flag) 4650Sstevel@tonic-gate { 4660Sstevel@tonic-gate int32_t ret_val; 4670Sstevel@tonic-gate 4680Sstevel@tonic-gate /* 4690Sstevel@tonic-gate * Set function flags for driver. 4700Sstevel@tonic-gate */ 4710Sstevel@tonic-gate uscsi_cmd->uscsi_flags = USCSI_ISOLATE; 4720Sstevel@tonic-gate 4730Sstevel@tonic-gate #ifdef DEBUG 4740Sstevel@tonic-gate uscsi_cmd->uscsi_flags |= USCSI_DIAGNOSE; 4750Sstevel@tonic-gate #else 4760Sstevel@tonic-gate uscsi_cmd->uscsi_flags |= USCSI_SILENT; 4770Sstevel@tonic-gate #endif /* DEBUG */ 4780Sstevel@tonic-gate 4790Sstevel@tonic-gate uscsi_cmd->uscsi_flags |= flag; 4800Sstevel@tonic-gate 4810Sstevel@tonic-gate errno = 0; 4820Sstevel@tonic-gate ret_val = ioctl(file, USCSICMD, uscsi_cmd); 4830Sstevel@tonic-gate if (ret_val == 0 && uscsi_cmd->uscsi_status == 0) { 4840Sstevel@tonic-gate return (ret_val); 4850Sstevel@tonic-gate } 4860Sstevel@tonic-gate if (!errno) 4870Sstevel@tonic-gate errno = EIO; 4880Sstevel@tonic-gate return (-1); 4890Sstevel@tonic-gate } 4900Sstevel@tonic-gate 4910Sstevel@tonic-gate static int32_t 4920Sstevel@tonic-gate get_device_type(char *v_name) 4930Sstevel@tonic-gate { 4940Sstevel@tonic-gate int32_t i; 4950Sstevel@tonic-gate 4960Sstevel@tonic-gate for (i = 0; i < 8; i++) { 4970Sstevel@tonic-gate v_name[i] = toupper(v_name[i]); 4980Sstevel@tonic-gate } 4990Sstevel@tonic-gate if (strstr(v_name, "IOMEGA")) { 5000Sstevel@tonic-gate return (SCSI_IOMEGA); 5010Sstevel@tonic-gate } 5020Sstevel@tonic-gate if (strstr(v_name, "FD") || 5030Sstevel@tonic-gate strstr(v_name, "LS-120")) { 5040Sstevel@tonic-gate return (SCSI_FLOPPY); 5050Sstevel@tonic-gate } 5060Sstevel@tonic-gate return (SCSI_GENERIC); 5070Sstevel@tonic-gate 5080Sstevel@tonic-gate } 5090Sstevel@tonic-gate 5100Sstevel@tonic-gate static int32_t 5110Sstevel@tonic-gate get_device_type_scsi(int32_t fd, struct scsi_inquiry *inq) 5120Sstevel@tonic-gate { 5130Sstevel@tonic-gate int32_t dev_type; 5140Sstevel@tonic-gate struct uscsi_cmd ucmd; 5150Sstevel@tonic-gate union scsi_cdb cdb; 5160Sstevel@tonic-gate int32_t ret_val; 5170Sstevel@tonic-gate char rq_data[RQ_LEN]; 5180Sstevel@tonic-gate 5190Sstevel@tonic-gate (void) memset((void *) inq, 0, sizeof (struct scsi_inquiry)); 5200Sstevel@tonic-gate (void) memset((void *) &ucmd, 0, sizeof (ucmd)); 5210Sstevel@tonic-gate (void) memset((void *) &cdb, 0, sizeof (union scsi_cdb)); 5220Sstevel@tonic-gate cdb.scc_cmd = SCMD_INQUIRY; 5230Sstevel@tonic-gate FORMG0COUNT(&cdb, sizeof (struct scsi_inquiry)); 5240Sstevel@tonic-gate ucmd.uscsi_cdb = (caddr_t)&cdb; 5250Sstevel@tonic-gate ucmd.uscsi_cdblen = CDB_GROUP0; 5260Sstevel@tonic-gate ucmd.uscsi_bufaddr = (caddr_t)inq; 5270Sstevel@tonic-gate ucmd.uscsi_buflen = sizeof (struct scsi_inquiry); 5280Sstevel@tonic-gate ucmd.uscsi_timeout = 120; /* If 0, HBA hangs forever */ 5290Sstevel@tonic-gate ucmd.uscsi_rqlen = RQ_LEN; 5300Sstevel@tonic-gate ucmd.uscsi_rqbuf = rq_data; 5310Sstevel@tonic-gate ret_val = do_uscsi_cmd(fd, &ucmd, USCSI_READ|USCSI_RQENABLE); 5320Sstevel@tonic-gate if (ret_val || ucmd.uscsi_status) { 533*1137Sarutz debug(5, "INQUIRY failed: rv = %d uscsi_status = " 534*1137Sarutz "%d errno = %d\n", ret_val, ucmd.uscsi_status, errno); 5350Sstevel@tonic-gate return (-1); 5360Sstevel@tonic-gate } 5370Sstevel@tonic-gate 5380Sstevel@tonic-gate dev_type = get_device_type(inq->inq_vid); 5390Sstevel@tonic-gate 5400Sstevel@tonic-gate debug(5, "dev_type %d\n", dev_type); 5410Sstevel@tonic-gate return (dev_type); 5420Sstevel@tonic-gate 5430Sstevel@tonic-gate } 5440Sstevel@tonic-gate 5450Sstevel@tonic-gate static int32_t 5460Sstevel@tonic-gate get_media_capacity(int32_t fd, uint32_t *capacity, uint32_t *blocksize) 5470Sstevel@tonic-gate { 5480Sstevel@tonic-gate struct uscsi_cmd ucmd; 5490Sstevel@tonic-gate uchar_t cdb[12]; 5500Sstevel@tonic-gate int32_t ret_val; 5510Sstevel@tonic-gate uchar_t data[20]; 5520Sstevel@tonic-gate char rq_data[RQ_LEN]; 5530Sstevel@tonic-gate 5540Sstevel@tonic-gate debug(5, "get_media_capacity:\n"); 5550Sstevel@tonic-gate 5560Sstevel@tonic-gate (void) memset((void *)&data, 0, sizeof (data)); 5570Sstevel@tonic-gate (void) memset((void *)&ucmd, 0, sizeof (ucmd)); 5580Sstevel@tonic-gate (void) memset((void *)&cdb, 0, sizeof (cdb)); 5590Sstevel@tonic-gate 5600Sstevel@tonic-gate /* retrieve size discriptor of inserted media */ 5610Sstevel@tonic-gate cdb[0] = SCMD_READ_FORMAT_CAP; 5620Sstevel@tonic-gate cdb[8] = 0x14; /* data size */ 5630Sstevel@tonic-gate 5640Sstevel@tonic-gate /* Fill in the USCSI fields */ 5650Sstevel@tonic-gate ucmd.uscsi_cdb = (caddr_t)&cdb; 5660Sstevel@tonic-gate ucmd.uscsi_cdblen = CDB_GROUP5; 5670Sstevel@tonic-gate ucmd.uscsi_bufaddr = (caddr_t)data; 5680Sstevel@tonic-gate ucmd.uscsi_buflen = sizeof (data); 5690Sstevel@tonic-gate ucmd.uscsi_timeout = 120; 5700Sstevel@tonic-gate ucmd.uscsi_rqlen = RQ_LEN; 5710Sstevel@tonic-gate ucmd.uscsi_rqbuf = rq_data; 5720Sstevel@tonic-gate ret_val = do_uscsi_cmd(fd, &ucmd, USCSI_READ|USCSI_RQENABLE); 5730Sstevel@tonic-gate 5740Sstevel@tonic-gate if (ret_val || ucmd.uscsi_status) { 5750Sstevel@tonic-gate debug(5, "Retrieving media info failed: %d - %d\n", ret_val, 5760Sstevel@tonic-gate ucmd.uscsi_status); 5770Sstevel@tonic-gate 5780Sstevel@tonic-gate if ((rq_data[2] == KEY_DATA_PROTECT) && (rq_data[12] == 0x30) && 5790Sstevel@tonic-gate (rq_data[13] == 0)) { 5800Sstevel@tonic-gate (void) debug(1, "Invalid command for media\n"); 5810Sstevel@tonic-gate errno = EINVAL; 5820Sstevel@tonic-gate } 5830Sstevel@tonic-gate return (-1); 5840Sstevel@tonic-gate } 5850Sstevel@tonic-gate 5860Sstevel@tonic-gate /* No media, bail out */ 5870Sstevel@tonic-gate if (data[8] == 0x3) { 5880Sstevel@tonic-gate (void) debug(5, "no media in drive\n"); 5890Sstevel@tonic-gate return (-1); 5900Sstevel@tonic-gate } 5910Sstevel@tonic-gate 5920Sstevel@tonic-gate /* 5930Sstevel@tonic-gate * Generate capacity and blocksize information 5940Sstevel@tonic-gate */ 5950Sstevel@tonic-gate 5960Sstevel@tonic-gate *capacity = (uint32_t)((data[4] << 24) + (data[5] << 16) + 5970Sstevel@tonic-gate (data[6] << 8) + data[7]); 5980Sstevel@tonic-gate 5990Sstevel@tonic-gate debug(1, "capacity is %x %x %x %x = %x", data[4], data[5], data[6], 6000Sstevel@tonic-gate data[7], *capacity); 6010Sstevel@tonic-gate 6020Sstevel@tonic-gate *blocksize = (uint32_t)((data[9] << 16) + (data[10] << 8) + data[11]); 6030Sstevel@tonic-gate 6040Sstevel@tonic-gate return (0); 6050Sstevel@tonic-gate } 6060Sstevel@tonic-gate 6070Sstevel@tonic-gate static int32_t 6080Sstevel@tonic-gate scsi_zip_format(int32_t fd, uint_t flavor, uint_t mode) 6090Sstevel@tonic-gate { 6100Sstevel@tonic-gate struct uscsi_cmd ucmd; 6110Sstevel@tonic-gate struct scsi_inquiry inq; 6120Sstevel@tonic-gate uchar_t cdb[12]; 6130Sstevel@tonic-gate int32_t ret_val; 6140Sstevel@tonic-gate uchar_t data[4]; 6150Sstevel@tonic-gate uint32_t rc_data[2]; 6160Sstevel@tonic-gate char rq_data[RQ_LEN]; 6170Sstevel@tonic-gate uint32_t capacity; 6180Sstevel@tonic-gate 6190Sstevel@tonic-gate 6200Sstevel@tonic-gate if ((mode != SM_FORMAT_IMMEDIATE) && 6210Sstevel@tonic-gate (mode != SM_FORMAT_BLOCKED)) { 6220Sstevel@tonic-gate errno = ENOTSUP; 6230Sstevel@tonic-gate return (ENOTSUP); 6240Sstevel@tonic-gate } 6250Sstevel@tonic-gate /* 6260Sstevel@tonic-gate * Do an inquiry and try to figure out if it an 6270Sstevel@tonic-gate * IOMEGA JAZ 2GB device. 6280Sstevel@tonic-gate */ 6290Sstevel@tonic-gate 6300Sstevel@tonic-gate (void) memset((void *) &inq, 0, sizeof (inq)); 6310Sstevel@tonic-gate (void) memset((void *) &ucmd, 0, sizeof (ucmd)); 6320Sstevel@tonic-gate (void) memset((void *) &cdb, 0, sizeof (cdb)); 6330Sstevel@tonic-gate (void) memset((void *) &rq_data, 0, sizeof (rq_data)); 6340Sstevel@tonic-gate cdb[0] = SCMD_INQUIRY; 6350Sstevel@tonic-gate cdb[4] = sizeof (inq); 6360Sstevel@tonic-gate ucmd.uscsi_cdb = (caddr_t)&cdb; 6370Sstevel@tonic-gate ucmd.uscsi_cdblen = CDB_GROUP0; 6380Sstevel@tonic-gate ucmd.uscsi_bufaddr = (caddr_t)&inq; 6390Sstevel@tonic-gate ucmd.uscsi_buflen = sizeof (inq); 6400Sstevel@tonic-gate ucmd.uscsi_timeout = 120; /* If 0, HBA hangs forever */ 6410Sstevel@tonic-gate ucmd.uscsi_rqlen = RQ_LEN; 6420Sstevel@tonic-gate ucmd.uscsi_rqbuf = rq_data; 6430Sstevel@tonic-gate ret_val = do_uscsi_cmd(fd, &ucmd, USCSI_READ|USCSI_RQENABLE); 6440Sstevel@tonic-gate if (ret_val || ucmd.uscsi_status) { 6450Sstevel@tonic-gate debug(5, "inquiry failed: %d - %d errno = %d\n", 6460Sstevel@tonic-gate ret_val, ucmd.uscsi_status, errno); 6470Sstevel@tonic-gate return (ucmd.uscsi_status); 6480Sstevel@tonic-gate } 6490Sstevel@tonic-gate 6500Sstevel@tonic-gate (void) memset((void *) &rc_data, 0, sizeof (rc_data)); 6510Sstevel@tonic-gate (void) memset((void *) &ucmd, 0, sizeof (ucmd)); 6520Sstevel@tonic-gate (void) memset((void *) &cdb, 0, sizeof (cdb)); 6530Sstevel@tonic-gate cdb[0] = SCMD_READ_CAPACITY; 6540Sstevel@tonic-gate ucmd.uscsi_cdb = (caddr_t)&cdb; 6550Sstevel@tonic-gate ucmd.uscsi_cdblen = CDB_GROUP1; 6560Sstevel@tonic-gate ucmd.uscsi_bufaddr = (caddr_t)&rc_data; 6570Sstevel@tonic-gate ucmd.uscsi_buflen = sizeof (rc_data); 6580Sstevel@tonic-gate ucmd.uscsi_timeout = 120; /* If 0, HBA hangs forever */ 6590Sstevel@tonic-gate 6600Sstevel@tonic-gate ret_val = do_uscsi_cmd(fd, &ucmd, USCSI_READ); 6610Sstevel@tonic-gate if (ret_val || ucmd.uscsi_status) { 6620Sstevel@tonic-gate debug(5, "Read capacity : %d - %d errno = %d\n", 6630Sstevel@tonic-gate ret_val, ucmd.uscsi_status, errno); 6640Sstevel@tonic-gate return (ucmd.uscsi_status); 6650Sstevel@tonic-gate } 6660Sstevel@tonic-gate 6670Sstevel@tonic-gate capacity = ntohl(rc_data[0]); 6680Sstevel@tonic-gate 6690Sstevel@tonic-gate (void) memset((void *)&data, 0, sizeof (data)); 6700Sstevel@tonic-gate (void) memset((void *)&ucmd, 0, sizeof (ucmd)); 6710Sstevel@tonic-gate (void) memset((void *)&cdb, 0, sizeof (cdb)); 6720Sstevel@tonic-gate cdb[0] = SCMD_FORMAT; 6730Sstevel@tonic-gate /* 6740Sstevel@tonic-gate * Defect list sent by initiator is a complete list of defects. 6750Sstevel@tonic-gate */ 6760Sstevel@tonic-gate cdb[1] = (FMTDATA | CMPLIST); 6770Sstevel@tonic-gate /* 6780Sstevel@tonic-gate * Target should examine the setting of the DPRY, DCRT, STPF, IP 6790Sstevel@tonic-gate * and DSP bits. 6800Sstevel@tonic-gate */ 6810Sstevel@tonic-gate data[1] = FOV; 6820Sstevel@tonic-gate 6830Sstevel@tonic-gate switch (flavor) { 6840Sstevel@tonic-gate case SM_FORMAT_QUICK : 6850Sstevel@tonic-gate /* 6860Sstevel@tonic-gate * Target should not perform any vendor specific 6870Sstevel@tonic-gate * medium certification process or format verification 6880Sstevel@tonic-gate */ 6890Sstevel@tonic-gate data[1] = (FOV | DCRT); 6900Sstevel@tonic-gate /* 6910Sstevel@tonic-gate * Defect list sent is an addition to the existing 6920Sstevel@tonic-gate * list of defects. 6930Sstevel@tonic-gate */ 6940Sstevel@tonic-gate cdb[1] = FMTDATA; 6950Sstevel@tonic-gate break; 6960Sstevel@tonic-gate case SM_FORMAT_FORCE : 6970Sstevel@tonic-gate if (strstr(inq.inq_pid, "jaz")) { 6980Sstevel@tonic-gate debug(1, 6990Sstevel@tonic-gate "LONG Format of JAZ media not supported\n"); 7000Sstevel@tonic-gate errno = ENOTSUP; 7010Sstevel@tonic-gate return (ENOTSUP); 7020Sstevel@tonic-gate } 7030Sstevel@tonic-gate /* 7040Sstevel@tonic-gate * Formatting a write-protected or read/write 7050Sstevel@tonic-gate * protected cartridge is allowed. 7060Sstevel@tonic-gate * This is a vendor specific Format Option. 7070Sstevel@tonic-gate */ 7080Sstevel@tonic-gate cdb[2] = 0x20; 7090Sstevel@tonic-gate break; 7100Sstevel@tonic-gate case SM_FORMAT_LONG : 7110Sstevel@tonic-gate if (strstr(inq.inq_pid, "jaz")) { 7120Sstevel@tonic-gate debug(1, 7130Sstevel@tonic-gate "LONG Format of JAZ media not supported\n"); 7140Sstevel@tonic-gate errno = ENOTSUP; 7150Sstevel@tonic-gate return (ENOTSUP); 7160Sstevel@tonic-gate } 7170Sstevel@tonic-gate /* 7180Sstevel@tonic-gate * Defect list sent is an addition to the existing 7190Sstevel@tonic-gate * list of defects. 7200Sstevel@tonic-gate */ 7210Sstevel@tonic-gate cdb[1] = FMTDATA; 7220Sstevel@tonic-gate break; 7230Sstevel@tonic-gate default : 7240Sstevel@tonic-gate debug(1, "Format option %d not supported!!\n", 7250Sstevel@tonic-gate flavor); 7260Sstevel@tonic-gate errno = ENOTSUP; 7270Sstevel@tonic-gate return (ENOTSUP); 7280Sstevel@tonic-gate } 7290Sstevel@tonic-gate 7300Sstevel@tonic-gate if (mode == SM_FORMAT_IMMEDIATE) { 7310Sstevel@tonic-gate data[1] |= IMMED; 7320Sstevel@tonic-gate debug(5, "immediate_flag set\n"); 7330Sstevel@tonic-gate } 7340Sstevel@tonic-gate 7350Sstevel@tonic-gate ucmd.uscsi_cdb = (caddr_t)&cdb; 7360Sstevel@tonic-gate debug(5, "cdb: %x ", cdb[0]); 7370Sstevel@tonic-gate debug(5, "%x %x ", cdb[1], cdb[2]); 7380Sstevel@tonic-gate debug(5, "%x %x %x\n", cdb[3], cdb[4], cdb[5]); 7390Sstevel@tonic-gate debug(5, "data: %x %x %x %x\n", data[0], data[1], data[2], data[3]); 7400Sstevel@tonic-gate 7410Sstevel@tonic-gate ucmd.uscsi_cdblen = CDB_GROUP0; 7420Sstevel@tonic-gate ucmd.uscsi_bufaddr = (caddr_t)data; 7430Sstevel@tonic-gate ucmd.uscsi_buflen = sizeof (data); 7440Sstevel@tonic-gate ucmd.uscsi_timeout = FORMAT_TIMEOUT(capacity); 7450Sstevel@tonic-gate ucmd.uscsi_rqlen = RQ_LEN; 7460Sstevel@tonic-gate ucmd.uscsi_rqbuf = rq_data; 7470Sstevel@tonic-gate ret_val = do_uscsi_cmd(fd, &ucmd, USCSI_WRITE|USCSI_RQENABLE); 7480Sstevel@tonic-gate if (ret_val || ucmd.uscsi_status) { 7490Sstevel@tonic-gate debug(5, "Format failed : %d - uscsi_status = %d errno = %d\n", 7500Sstevel@tonic-gate ret_val, 7510Sstevel@tonic-gate ucmd.uscsi_status, errno); 7520Sstevel@tonic-gate if ((rq_data[2] == KEY_DATA_PROTECT) || 7530Sstevel@tonic-gate (rq_data[2] == KEY_ILLEGAL_REQUEST)) 7540Sstevel@tonic-gate errno = EINVAL; 7550Sstevel@tonic-gate if ((rq_data[2] == KEY_MEDIUM_ERROR) || 7560Sstevel@tonic-gate (rq_data[2] == KEY_HARDWARE_ERROR)) 7570Sstevel@tonic-gate errno = EIO; 7580Sstevel@tonic-gate return (errno); 7590Sstevel@tonic-gate } 7600Sstevel@tonic-gate 7610Sstevel@tonic-gate return (0); 7620Sstevel@tonic-gate } 7630Sstevel@tonic-gate 7640Sstevel@tonic-gate static int32_t 7650Sstevel@tonic-gate scsi_ls120_format(uint_t fd, uint_t flavor, uint32_t capacity, 7660Sstevel@tonic-gate uint32_t blocksize) 7670Sstevel@tonic-gate { 7680Sstevel@tonic-gate struct uscsi_cmd ucmd; 7690Sstevel@tonic-gate uchar_t cdb[12]; 7700Sstevel@tonic-gate int32_t ret_val; 7710Sstevel@tonic-gate uchar_t data[12]; 7720Sstevel@tonic-gate char rq_data[RQ_LEN]; 7730Sstevel@tonic-gate 7740Sstevel@tonic-gate debug(5, "scsi_ls120_format:\n"); 7750Sstevel@tonic-gate 7760Sstevel@tonic-gate (void) memset((void *) &ucmd, 0, sizeof (ucmd)); 7770Sstevel@tonic-gate (void) memset((void *) &cdb, 0, sizeof (cdb)); 7780Sstevel@tonic-gate (void) memset((void *) &rq_data, 0, sizeof (rq_data)); 7790Sstevel@tonic-gate 7800Sstevel@tonic-gate cdb[0] = SCMD_FORMAT; 7810Sstevel@tonic-gate cdb[1] = (FMTDATA | 0x7); 7820Sstevel@tonic-gate cdb[8] = 0x0C; /* parameter list length */ 7830Sstevel@tonic-gate 7840Sstevel@tonic-gate data[1] = 0x80; 7850Sstevel@tonic-gate data[3] = 0x08; 7860Sstevel@tonic-gate 7870Sstevel@tonic-gate 7880Sstevel@tonic-gate data[4] = (capacity >> 24) & 0xff; 7890Sstevel@tonic-gate data[5] = (capacity >> 16) & 0xff; 7900Sstevel@tonic-gate data[6] = (capacity >> 8) & 0xff; 7910Sstevel@tonic-gate data[7] = capacity & 0xff; 7920Sstevel@tonic-gate 7930Sstevel@tonic-gate 7940Sstevel@tonic-gate data[9] = (blocksize >> 16) & 0xff; 7950Sstevel@tonic-gate data[10] = (blocksize >> 8) & 0xff; 7960Sstevel@tonic-gate data[11] = blocksize & 0xff; 7970Sstevel@tonic-gate 7980Sstevel@tonic-gate debug(5, "cdb: %x %x %x ... %x", cdb[0], cdb[1], cdb[2], cdb[8]); 7990Sstevel@tonic-gate debug(5, "data: %x %x %x %x\n", data[0], data[1], data[2], data[3]); 8000Sstevel@tonic-gate debug(5, " : %x %x %x %x\n", data[4], data[5], data[6], data[7]); 8010Sstevel@tonic-gate debug(5, " : %x %x %x %x\n", data[8], data[9], data[10], data[11]); 8020Sstevel@tonic-gate 8030Sstevel@tonic-gate switch (flavor) { 8040Sstevel@tonic-gate case SM_FORMAT_QUICK : 8050Sstevel@tonic-gate debug(1, "Format not supported\n"); 8060Sstevel@tonic-gate errno = ENOTSUP; 8070Sstevel@tonic-gate return (-1); 8080Sstevel@tonic-gate case SM_FORMAT_FORCE : 8090Sstevel@tonic-gate break; 8100Sstevel@tonic-gate case SM_FORMAT_LONG : 8110Sstevel@tonic-gate break; 8120Sstevel@tonic-gate default : 8130Sstevel@tonic-gate debug(1, "Format option not specified!!\n"); 8140Sstevel@tonic-gate errno = ENOTSUP; 8150Sstevel@tonic-gate return (-1); 8160Sstevel@tonic-gate } 8170Sstevel@tonic-gate 8180Sstevel@tonic-gate ucmd.uscsi_cdb = (caddr_t)&cdb; 8190Sstevel@tonic-gate 8200Sstevel@tonic-gate 8210Sstevel@tonic-gate ucmd.uscsi_cdblen = CDB_GROUP5; 8220Sstevel@tonic-gate ucmd.uscsi_bufaddr = (caddr_t)data; 8230Sstevel@tonic-gate ucmd.uscsi_buflen = sizeof (data); 8240Sstevel@tonic-gate ucmd.uscsi_timeout = 0x12c0; 8250Sstevel@tonic-gate ucmd.uscsi_rqlen = RQ_LEN; 8260Sstevel@tonic-gate ucmd.uscsi_rqbuf = rq_data; 8270Sstevel@tonic-gate (void) fflush(stdout); 8280Sstevel@tonic-gate 8290Sstevel@tonic-gate ret_val = do_uscsi_cmd(fd, &ucmd, USCSI_WRITE|USCSI_RQENABLE); 8300Sstevel@tonic-gate if (ret_val || ucmd.uscsi_status) { 8310Sstevel@tonic-gate debug(1, "Format failed failed: %d - %d\n", ret_val, 8320Sstevel@tonic-gate ucmd.uscsi_status); 8330Sstevel@tonic-gate 8340Sstevel@tonic-gate if ((rq_data[2] == KEY_DATA_PROTECT) && 8350Sstevel@tonic-gate (rq_data[12] == 0x30) && (rq_data[13] == 0)) { 8360Sstevel@tonic-gate 8370Sstevel@tonic-gate debug(1, "Invalid command for media\n"); 8380Sstevel@tonic-gate errno = EINVAL; 8390Sstevel@tonic-gate } 8400Sstevel@tonic-gate 8410Sstevel@tonic-gate if ((rq_data[2] == KEY_NOT_READY) && (rq_data[12] == 0x30)) { 8420Sstevel@tonic-gate debug(1, "Incompatible media.\n"); 8430Sstevel@tonic-gate errno = EINVAL; 8440Sstevel@tonic-gate } 8450Sstevel@tonic-gate 8460Sstevel@tonic-gate return (-1); 8470Sstevel@tonic-gate } 8480Sstevel@tonic-gate 8490Sstevel@tonic-gate return (0); 8500Sstevel@tonic-gate } 8510Sstevel@tonic-gate 8520Sstevel@tonic-gate static int32_t 8530Sstevel@tonic-gate scsi_format(int32_t fd, uint_t flavor, uint_t mode) 8540Sstevel@tonic-gate { 8550Sstevel@tonic-gate struct uscsi_cmd ucmd; 8560Sstevel@tonic-gate struct scsi_inquiry inq; 8570Sstevel@tonic-gate uchar_t cdb[12]; 8580Sstevel@tonic-gate int32_t ret_val; 8590Sstevel@tonic-gate uchar_t data[4]; 8600Sstevel@tonic-gate char rq_data[RQ_LEN]; 8610Sstevel@tonic-gate uint32_t rc_data[2]; 8620Sstevel@tonic-gate uint32_t capacity; 8630Sstevel@tonic-gate 8640Sstevel@tonic-gate 8650Sstevel@tonic-gate 8660Sstevel@tonic-gate if ((mode != SM_FORMAT_IMMEDIATE) && 8670Sstevel@tonic-gate (mode != SM_FORMAT_BLOCKED)) { 8680Sstevel@tonic-gate errno = ENOTSUP; 8690Sstevel@tonic-gate return (-1); 8700Sstevel@tonic-gate } 8710Sstevel@tonic-gate 8720Sstevel@tonic-gate /* 8730Sstevel@tonic-gate * Do an inquiry and try to figure out if it an 8740Sstevel@tonic-gate * IOMEGA JAZ 2GB device. 8750Sstevel@tonic-gate */ 8760Sstevel@tonic-gate 8770Sstevel@tonic-gate (void) memset((void *) &inq, 0, sizeof (inq)); 8780Sstevel@tonic-gate (void) memset((void *) &ucmd, 0, sizeof (ucmd)); 8790Sstevel@tonic-gate (void) memset((void *) &cdb, 0, sizeof (cdb)); 8800Sstevel@tonic-gate (void) memset((void *) &rq_data, 0, sizeof (rq_data)); 8810Sstevel@tonic-gate cdb[0] = SCMD_INQUIRY; 8820Sstevel@tonic-gate cdb[4] = sizeof (inq); 8830Sstevel@tonic-gate ucmd.uscsi_cdb = (caddr_t)&cdb; 8840Sstevel@tonic-gate ucmd.uscsi_cdblen = CDB_GROUP0; 8850Sstevel@tonic-gate ucmd.uscsi_bufaddr = (caddr_t)&inq; 8860Sstevel@tonic-gate ucmd.uscsi_buflen = sizeof (inq); 8870Sstevel@tonic-gate ucmd.uscsi_timeout = 120; /* If 0, HBA hangs forever */ 8880Sstevel@tonic-gate ucmd.uscsi_rqlen = RQ_LEN; 8890Sstevel@tonic-gate ucmd.uscsi_rqbuf = rq_data; 8900Sstevel@tonic-gate ret_val = do_uscsi_cmd(fd, &ucmd, USCSI_READ|USCSI_RQENABLE); 8910Sstevel@tonic-gate if (ret_val || ucmd.uscsi_status) { 8920Sstevel@tonic-gate debug(5, "inquiry failed: %d - %d errno = %d\n", 8930Sstevel@tonic-gate ret_val, ucmd.uscsi_status, errno); 8940Sstevel@tonic-gate return (ucmd.uscsi_status); 8950Sstevel@tonic-gate } 8960Sstevel@tonic-gate 8970Sstevel@tonic-gate (void) memset((void *) &rc_data, 0, sizeof (rc_data)); 8980Sstevel@tonic-gate (void) memset((void *) &ucmd, 0, sizeof (ucmd)); 8990Sstevel@tonic-gate (void) memset((void *) &cdb, 0, sizeof (cdb)); 9000Sstevel@tonic-gate cdb[0] = SCMD_READ_CAPACITY; 9010Sstevel@tonic-gate ucmd.uscsi_cdb = (caddr_t)&cdb; 9020Sstevel@tonic-gate ucmd.uscsi_cdblen = CDB_GROUP1; 9030Sstevel@tonic-gate ucmd.uscsi_bufaddr = (caddr_t)&rc_data; 9040Sstevel@tonic-gate ucmd.uscsi_buflen = sizeof (rc_data); 9050Sstevel@tonic-gate ucmd.uscsi_timeout = 120; /* If 0, HBA hangs forever */ 9060Sstevel@tonic-gate 9070Sstevel@tonic-gate ret_val = do_uscsi_cmd(fd, &ucmd, USCSI_READ); 9080Sstevel@tonic-gate if (ret_val || ucmd.uscsi_status) { 9090Sstevel@tonic-gate debug(5, "Read capacity : %d - %d errno = %d\n", 9100Sstevel@tonic-gate ret_val, ucmd.uscsi_status, errno); 9110Sstevel@tonic-gate return (ucmd.uscsi_status); 9120Sstevel@tonic-gate } 9130Sstevel@tonic-gate 9140Sstevel@tonic-gate capacity = ntohl(rc_data[0]); 9150Sstevel@tonic-gate 9160Sstevel@tonic-gate (void) memset((void *)&data, 0, sizeof (data)); 9170Sstevel@tonic-gate (void) memset((void *)&ucmd, 0, sizeof (ucmd)); 9180Sstevel@tonic-gate (void) memset((void *)&cdb, 0, sizeof (cdb)); 9190Sstevel@tonic-gate cdb[0] = SCMD_FORMAT; 9200Sstevel@tonic-gate /* 9210Sstevel@tonic-gate * Defect list sent is an addition to the existing 9220Sstevel@tonic-gate * list of defects. 9230Sstevel@tonic-gate */ 9240Sstevel@tonic-gate cdb[1] = FMTDATA; 9250Sstevel@tonic-gate /* 9260Sstevel@tonic-gate * Target should examine the setting of the DPRY, DCRT, STPF, IP 9270Sstevel@tonic-gate * and DSP bits. 9280Sstevel@tonic-gate */ 9290Sstevel@tonic-gate data[1] = FOV; 9300Sstevel@tonic-gate 9310Sstevel@tonic-gate if (mode == SM_FORMAT_IMMEDIATE) { 9320Sstevel@tonic-gate debug(5, 9330Sstevel@tonic-gate "SM_FORMAT_IMMEDIATE specified ignored. Performing a long format!\n"); 9340Sstevel@tonic-gate } 9350Sstevel@tonic-gate 9360Sstevel@tonic-gate switch (flavor) { 9370Sstevel@tonic-gate case SM_FORMAT_LONG : 9380Sstevel@tonic-gate if (strstr(inq.inq_pid, "jaz")) { 9390Sstevel@tonic-gate debug(1, 9400Sstevel@tonic-gate "LONG Format of JAZ media not supported\n"); 9410Sstevel@tonic-gate errno = ENOTSUP; 9420Sstevel@tonic-gate return (ENOTSUP); 9430Sstevel@tonic-gate } 9440Sstevel@tonic-gate /* 9450Sstevel@tonic-gate * Defect list sent is an addition to the existing 9460Sstevel@tonic-gate * list of defects. 9470Sstevel@tonic-gate */ 9480Sstevel@tonic-gate cdb[1] = FMTDATA; 9490Sstevel@tonic-gate break; 9500Sstevel@tonic-gate default : 9510Sstevel@tonic-gate debug(1, "Format option %d not supported!!\n", 9520Sstevel@tonic-gate flavor); 9530Sstevel@tonic-gate errno = ENOTSUP; 9540Sstevel@tonic-gate return (ENOTSUP); 9550Sstevel@tonic-gate } 9560Sstevel@tonic-gate 9570Sstevel@tonic-gate 9580Sstevel@tonic-gate ucmd.uscsi_cdb = (caddr_t)&cdb; 9590Sstevel@tonic-gate ucmd.uscsi_cdblen = CDB_GROUP0; 9600Sstevel@tonic-gate ucmd.uscsi_bufaddr = (caddr_t)data; 9610Sstevel@tonic-gate ucmd.uscsi_buflen = sizeof (data); 9620Sstevel@tonic-gate ucmd.uscsi_timeout = FORMAT_TIMEOUT(capacity); 9630Sstevel@tonic-gate ucmd.uscsi_rqlen = RQ_LEN; 9640Sstevel@tonic-gate ucmd.uscsi_rqbuf = rq_data; 9650Sstevel@tonic-gate ret_val = do_uscsi_cmd(fd, &ucmd, USCSI_WRITE|USCSI_RQENABLE); 9660Sstevel@tonic-gate if (ret_val || ucmd.uscsi_status) { 9670Sstevel@tonic-gate debug(5, "Format failed failed: %d - %d errno = %d\n", 9680Sstevel@tonic-gate ret_val, ucmd.uscsi_status, errno); 9690Sstevel@tonic-gate return (ucmd.uscsi_status); 9700Sstevel@tonic-gate } 9710Sstevel@tonic-gate 9720Sstevel@tonic-gate return (0); 9730Sstevel@tonic-gate } 9740Sstevel@tonic-gate 9750Sstevel@tonic-gate static int32_t 9760Sstevel@tonic-gate scsi_media_status(int32_t fd) 9770Sstevel@tonic-gate { 9780Sstevel@tonic-gate struct mode_header modeh; 9790Sstevel@tonic-gate struct uscsi_cmd ucmd; 9800Sstevel@tonic-gate union scsi_cdb cdb; 981*1137Sarutz int32_t ret_val; 9820Sstevel@tonic-gate int32_t cur_status; 9830Sstevel@tonic-gate char rq_data[RQ_LEN]; 9840Sstevel@tonic-gate 9850Sstevel@tonic-gate debug(10, "SCSI MEDIA STATUS CALLED \n"); 9860Sstevel@tonic-gate 9870Sstevel@tonic-gate (void) memset((void *) &modeh, 0, sizeof (modeh)); 9880Sstevel@tonic-gate (void) memset((void *) &ucmd, 0, sizeof (ucmd)); 9890Sstevel@tonic-gate (void) memset((void *) &cdb, 0, sizeof (union scsi_cdb)); 9900Sstevel@tonic-gate cdb.scc_cmd = SCMD_MODE_SENSE; 9910Sstevel@tonic-gate FORMG0COUNT(&cdb, sizeof (modeh)); 9920Sstevel@tonic-gate ucmd.uscsi_cdb = (caddr_t)&cdb; 9930Sstevel@tonic-gate ucmd.uscsi_cdblen = CDB_GROUP0; 9940Sstevel@tonic-gate ucmd.uscsi_bufaddr = (caddr_t)&modeh; 9950Sstevel@tonic-gate ucmd.uscsi_buflen = sizeof (modeh); 9960Sstevel@tonic-gate ucmd.uscsi_timeout = 120; /* If 0, HBA hangs forever */ 9970Sstevel@tonic-gate ucmd.uscsi_rqlen = RQ_LEN; 9980Sstevel@tonic-gate ucmd.uscsi_rqbuf = rq_data; 9990Sstevel@tonic-gate ret_val = do_uscsi_cmd(fd, &ucmd, USCSI_READ|USCSI_RQENABLE); 10000Sstevel@tonic-gate if (ret_val || ucmd.uscsi_status) { 10010Sstevel@tonic-gate debug(5, "Modesense failed: %d - %d errno = %d\n", 10020Sstevel@tonic-gate ret_val, ucmd.uscsi_status, errno); 10030Sstevel@tonic-gate return (-1); 10040Sstevel@tonic-gate } 10050Sstevel@tonic-gate 10060Sstevel@tonic-gate 10070Sstevel@tonic-gate if (modeh.device_specific & W_E_MASK) { 10080Sstevel@tonic-gate cur_status = SM_WRITE_PROTECT_NOPASSWD; 10090Sstevel@tonic-gate } else { 10100Sstevel@tonic-gate cur_status = SM_WRITE_PROTECT_DISABLE; 10110Sstevel@tonic-gate } 10120Sstevel@tonic-gate debug(5, "cur status %d\n", cur_status); 10130Sstevel@tonic-gate 10140Sstevel@tonic-gate return (cur_status); 10150Sstevel@tonic-gate } 10160Sstevel@tonic-gate 10170Sstevel@tonic-gate static int32_t 10180Sstevel@tonic-gate scsi_zip_media_status(int32_t fd) 10190Sstevel@tonic-gate { 10200Sstevel@tonic-gate struct uscsi_cmd ucmd; 10210Sstevel@tonic-gate uchar_t cdb[12]; 10220Sstevel@tonic-gate int32_t status; 10230Sstevel@tonic-gate int32_t mode; 10240Sstevel@tonic-gate uchar_t data[64]; 10250Sstevel@tonic-gate char rq_data[RQ_LEN]; 10260Sstevel@tonic-gate 10270Sstevel@tonic-gate debug(10, "Getting media status\n"); 10280Sstevel@tonic-gate 10290Sstevel@tonic-gate (void) memset((void *)&ucmd, 0, sizeof (ucmd)); 10300Sstevel@tonic-gate (void) memset((void *)&cdb, 0, sizeof (cdb)); 10310Sstevel@tonic-gate 10320Sstevel@tonic-gate cdb[0] = IOMEGA_NONSENSE_CMD; 10330Sstevel@tonic-gate cdb[2] = CARTRIDGE_STATUS_PAGE; 10340Sstevel@tonic-gate cdb[4] = ND_LENGTH; 10350Sstevel@tonic-gate ucmd.uscsi_cdb = (caddr_t)&cdb; 10360Sstevel@tonic-gate ucmd.uscsi_cdblen = CDB_GROUP0; 10370Sstevel@tonic-gate ucmd.uscsi_bufaddr = (caddr_t)data; 10380Sstevel@tonic-gate ucmd.uscsi_buflen = 64; 10390Sstevel@tonic-gate ucmd.uscsi_timeout = 120; /* If 0, HBA hangs forever */ 10400Sstevel@tonic-gate ucmd.uscsi_rqlen = RQ_LEN; 10410Sstevel@tonic-gate ucmd.uscsi_rqbuf = rq_data; 10420Sstevel@tonic-gate status = do_uscsi_cmd(fd, &ucmd, USCSI_READ|USCSI_RQENABLE); 10430Sstevel@tonic-gate if (status || ucmd.uscsi_status) { 1044*1137Sarutz debug(5, "Cartridge protect operation failed: " 1045*1137Sarutz "rv = %d uscsi_status = %d errno = %d\n", 1046*1137Sarutz status, ucmd.uscsi_status, errno); 10470Sstevel@tonic-gate return (-1); 10480Sstevel@tonic-gate } 10490Sstevel@tonic-gate 10500Sstevel@tonic-gate if (data[DISK_STATUS_OFFSET + NON_SENSE_HDR_LEN] == 4) { 10510Sstevel@tonic-gate debug(1, "Disk not present. \n"); 10520Sstevel@tonic-gate return (-1); 10530Sstevel@tonic-gate } 10540Sstevel@tonic-gate mode = data[PROTECT_MODE_OFFSET + NON_SENSE_HDR_LEN] & 0xF; 10550Sstevel@tonic-gate 1056*1137Sarutz debug(5, "MODE 0x%x / %d.\n", mode, mode); 1057*1137Sarutz 10580Sstevel@tonic-gate switch (mode) { 10590Sstevel@tonic-gate case UNLOCK_MODE: 10600Sstevel@tonic-gate status = SM_WRITE_PROTECT_DISABLE; 10610Sstevel@tonic-gate break; 10620Sstevel@tonic-gate case WRITE_PROTECT_MODE: 10630Sstevel@tonic-gate status = SM_WRITE_PROTECT_NOPASSWD; 10640Sstevel@tonic-gate break; 10650Sstevel@tonic-gate case PASSWD_WRITE_PROTECT_MODE: 10660Sstevel@tonic-gate status = SM_WRITE_PROTECT_PASSWD; 10670Sstevel@tonic-gate break; 10680Sstevel@tonic-gate case READ_WRITE_PROTECT_MODE: 10690Sstevel@tonic-gate status = SM_READ_WRITE_PROTECT; 10700Sstevel@tonic-gate break; 10710Sstevel@tonic-gate default : 10720Sstevel@tonic-gate if (mode & TEMP_UNLOCK_MODE) 10730Sstevel@tonic-gate status = SM_TEMP_UNLOCK_MODE; 10740Sstevel@tonic-gate else 10750Sstevel@tonic-gate status = SM_STATUS_UNKNOWN; 10760Sstevel@tonic-gate break; 10770Sstevel@tonic-gate } 10780Sstevel@tonic-gate 10790Sstevel@tonic-gate debug(5, "status %d \n", status); 10800Sstevel@tonic-gate return (status); 10810Sstevel@tonic-gate } 10820Sstevel@tonic-gate 1083*1137Sarutz static int32_t 10840Sstevel@tonic-gate scsi_reassign_block(int32_t fd, diskaddr_t block) 10850Sstevel@tonic-gate { 10860Sstevel@tonic-gate uchar_t data[8]; 10870Sstevel@tonic-gate struct uscsi_cmd ucmd; 10880Sstevel@tonic-gate char cdb[12]; 10890Sstevel@tonic-gate int32_t ret_val; 10900Sstevel@tonic-gate char rq_data[RQ_LEN]; 10910Sstevel@tonic-gate 10920Sstevel@tonic-gate debug(5, "SCSI REASSIGN CALLED block = %lld\n", block); 10930Sstevel@tonic-gate 10940Sstevel@tonic-gate (void) memset((void *) &data, 0, sizeof (data)); 10950Sstevel@tonic-gate (void) memset((void *) &ucmd, 0, sizeof (ucmd)); 10960Sstevel@tonic-gate (void) memset((void *) &cdb, 0, sizeof (cdb)); 10970Sstevel@tonic-gate cdb[0] = SCMD_REASSIGN_BLOCK; 10980Sstevel@tonic-gate data[3] = 4; 10990Sstevel@tonic-gate data[4] = ((block & 0xFF000000) >> 24); 11000Sstevel@tonic-gate data[5] = ((block & 0xFF0000) >> 16); 11010Sstevel@tonic-gate data[6] = ((block & 0xFF00) >> 8); 11020Sstevel@tonic-gate data[7] = block & 0xFF; 11030Sstevel@tonic-gate 11040Sstevel@tonic-gate ucmd.uscsi_cdb = (caddr_t)&cdb; 11050Sstevel@tonic-gate ucmd.uscsi_cdblen = CDB_GROUP0; 11060Sstevel@tonic-gate ucmd.uscsi_bufaddr = (caddr_t)data; 11070Sstevel@tonic-gate ucmd.uscsi_buflen = sizeof (data); 11080Sstevel@tonic-gate ucmd.uscsi_timeout = 120; /* If 0, HBA hangs forever */ 11090Sstevel@tonic-gate ucmd.uscsi_rqlen = RQ_LEN; 11100Sstevel@tonic-gate ucmd.uscsi_rqbuf = rq_data; 11110Sstevel@tonic-gate ret_val = do_uscsi_cmd(fd, &ucmd, USCSI_WRITE|USCSI_RQENABLE); 11120Sstevel@tonic-gate if (ret_val || ucmd.uscsi_status) { 11130Sstevel@tonic-gate debug(5, "Reassign block failed: %d - %d errno = %d\n", 11140Sstevel@tonic-gate ret_val, ucmd.uscsi_status, errno); 11150Sstevel@tonic-gate return (-1); 11160Sstevel@tonic-gate } 11170Sstevel@tonic-gate 11180Sstevel@tonic-gate return (0); 11190Sstevel@tonic-gate } 11200Sstevel@tonic-gate 1121*1137Sarutz static int32_t 11220Sstevel@tonic-gate get_mode_page(int32_t fd, uchar_t pc, uchar_t page_code, 1123*1137Sarutz uchar_t *md_data, uchar_t data_len) 11240Sstevel@tonic-gate { 11250Sstevel@tonic-gate struct uscsi_cmd ucmd; 11260Sstevel@tonic-gate uchar_t cdb[12]; 11270Sstevel@tonic-gate int32_t ret_val; 11280Sstevel@tonic-gate char rq_data[RQ_LEN]; 11290Sstevel@tonic-gate 1130*1137Sarutz debug(10, "MODE SENSE(6) - page_code = 0x%x\n", page_code); 11310Sstevel@tonic-gate 11320Sstevel@tonic-gate (void) memset((void *) md_data, 0, sizeof (data_len)); 11330Sstevel@tonic-gate (void) memset((void *) &ucmd, 0, sizeof (ucmd)); 11340Sstevel@tonic-gate (void) memset((void *) &cdb, 0, sizeof (cdb)); 11350Sstevel@tonic-gate cdb[0] = SCMD_MODE_SENSE; 11360Sstevel@tonic-gate cdb[2] = (pc << 6) | page_code; 11370Sstevel@tonic-gate cdb[4] = data_len; 11380Sstevel@tonic-gate 11390Sstevel@tonic-gate ucmd.uscsi_cdb = (caddr_t)&cdb; 11400Sstevel@tonic-gate ucmd.uscsi_cdblen = CDB_GROUP0; 11410Sstevel@tonic-gate ucmd.uscsi_bufaddr = (caddr_t)md_data; 11420Sstevel@tonic-gate ucmd.uscsi_buflen = data_len; 11430Sstevel@tonic-gate ucmd.uscsi_timeout = 120; /* If 0, HBA hangs forever */ 11440Sstevel@tonic-gate ucmd.uscsi_rqlen = RQ_LEN; 11450Sstevel@tonic-gate ucmd.uscsi_rqbuf = rq_data; 11460Sstevel@tonic-gate ret_val = do_uscsi_cmd(fd, &ucmd, USCSI_READ|USCSI_RQENABLE); 11470Sstevel@tonic-gate if (ret_val || ucmd.uscsi_status) { 11480Sstevel@tonic-gate debug(5, "Modesense failed: %d - %d errno = %d\n", 11490Sstevel@tonic-gate ret_val, ucmd.uscsi_status, errno); 11500Sstevel@tonic-gate return (-2); 11510Sstevel@tonic-gate } 11520Sstevel@tonic-gate 11530Sstevel@tonic-gate return (0); 11540Sstevel@tonic-gate } 11550Sstevel@tonic-gate 11560Sstevel@tonic-gate static int32_t 11570Sstevel@tonic-gate scsi_zip_write_protect(int32_t fd, smwp_state_t *wp) 11580Sstevel@tonic-gate { 11590Sstevel@tonic-gate struct uscsi_cmd ucmd; 11600Sstevel@tonic-gate struct scsi_inquiry inq; 11610Sstevel@tonic-gate uchar_t cdb[12]; 11620Sstevel@tonic-gate int32_t status; 11630Sstevel@tonic-gate int32_t new_mode; 11640Sstevel@tonic-gate char rq_data[RQ_LEN]; 11650Sstevel@tonic-gate int32_t wa_bit; 11660Sstevel@tonic-gate char *tmp_passwd = NULL; 11670Sstevel@tonic-gate 11680Sstevel@tonic-gate debug(10, "SCSI ZIP WRITE PROTECT CALLED \n"); 11690Sstevel@tonic-gate 11700Sstevel@tonic-gate /* 11710Sstevel@tonic-gate * Do an inquiry and try to figure out if it an 11720Sstevel@tonic-gate * ATAPI or SCSI device. 11730Sstevel@tonic-gate */ 11740Sstevel@tonic-gate 11750Sstevel@tonic-gate (void) memset((void *) &inq, 0, sizeof (inq)); 11760Sstevel@tonic-gate (void) memset((void *) &ucmd, 0, sizeof (ucmd)); 11770Sstevel@tonic-gate (void) memset((void *) &cdb, 0, sizeof (cdb)); 11780Sstevel@tonic-gate (void) memset((void *) &rq_data, 0, sizeof (rq_data)); 11790Sstevel@tonic-gate cdb[0] = SCMD_INQUIRY; 11800Sstevel@tonic-gate cdb[4] = sizeof (inq); 11810Sstevel@tonic-gate ucmd.uscsi_cdb = (caddr_t)&cdb; 11820Sstevel@tonic-gate ucmd.uscsi_cdblen = CDB_GROUP0; 11830Sstevel@tonic-gate ucmd.uscsi_bufaddr = (caddr_t)&inq; 11840Sstevel@tonic-gate ucmd.uscsi_buflen = sizeof (inq); 11850Sstevel@tonic-gate ucmd.uscsi_timeout = 120; /* If 0, HBA hangs forever */ 11860Sstevel@tonic-gate ucmd.uscsi_rqlen = RQ_LEN; 11870Sstevel@tonic-gate ucmd.uscsi_rqbuf = rq_data; 11880Sstevel@tonic-gate status = do_uscsi_cmd(fd, &ucmd, USCSI_READ|USCSI_RQENABLE); 11890Sstevel@tonic-gate if (status || ucmd.uscsi_status) { 11900Sstevel@tonic-gate debug(5, "inquiry failed: %d - %d errno = %d\n", 11910Sstevel@tonic-gate status, ucmd.uscsi_status, errno); 11920Sstevel@tonic-gate return (-1); 11930Sstevel@tonic-gate } 11940Sstevel@tonic-gate 11950Sstevel@tonic-gate if (inq.inq_ansi > 0) { 11960Sstevel@tonic-gate wa_bit = 0; 11970Sstevel@tonic-gate debug(5, "SCSI device\n"); 11980Sstevel@tonic-gate } else { 11990Sstevel@tonic-gate wa_bit = 1; 12000Sstevel@tonic-gate debug(5, "ATAPI device\n"); 12010Sstevel@tonic-gate } 12020Sstevel@tonic-gate 12030Sstevel@tonic-gate switch (wp->sm_new_state) { 12040Sstevel@tonic-gate case SM_WRITE_PROTECT_DISABLE : 12050Sstevel@tonic-gate new_mode = 0x0; 12060Sstevel@tonic-gate break; 12070Sstevel@tonic-gate case SM_WRITE_PROTECT_NOPASSWD : 12080Sstevel@tonic-gate new_mode = 0x2; 12090Sstevel@tonic-gate break; 12100Sstevel@tonic-gate case SM_WRITE_PROTECT_PASSWD : 12110Sstevel@tonic-gate new_mode = 0x3; 12120Sstevel@tonic-gate break; 12130Sstevel@tonic-gate case SM_READ_WRITE_PROTECT : 12140Sstevel@tonic-gate new_mode = 0x5; 12150Sstevel@tonic-gate break; 12160Sstevel@tonic-gate case SM_TEMP_UNLOCK_MODE : 12170Sstevel@tonic-gate new_mode = 0x8; 12180Sstevel@tonic-gate break; 12190Sstevel@tonic-gate default : 12200Sstevel@tonic-gate debug(1, "Invalid mode 0x%x specified\n", 12210Sstevel@tonic-gate wp->sm_new_state); 12220Sstevel@tonic-gate errno = ENOTSUP; 12230Sstevel@tonic-gate return (-1); 12240Sstevel@tonic-gate } 12250Sstevel@tonic-gate 12260Sstevel@tonic-gate 12270Sstevel@tonic-gate (void) memset((void *)&ucmd, 0, sizeof (ucmd)); 12280Sstevel@tonic-gate (void) memset((void *)&cdb, 0, sizeof (cdb)); 12290Sstevel@tonic-gate (void) memset((void *) &rq_data, 0, sizeof (rq_data)); 12300Sstevel@tonic-gate cdb[0] = IOMEGA_CATRIDGE_PROTECT; 12310Sstevel@tonic-gate cdb[1] |= new_mode; 12320Sstevel@tonic-gate if (wa_bit) 12330Sstevel@tonic-gate cdb[1] |= WA_BIT; 12340Sstevel@tonic-gate cdb[4] = wp->sm_passwd_len; 12350Sstevel@tonic-gate ucmd.uscsi_cdb = (caddr_t)&cdb; 12360Sstevel@tonic-gate ucmd.uscsi_cdblen = CDB_GROUP0; 12370Sstevel@tonic-gate if (wa_bit && (wp->sm_passwd_len & 1)) { 12380Sstevel@tonic-gate /* 12390Sstevel@tonic-gate * Oops, ATAPI device with an odd length passwd! 12400Sstevel@tonic-gate * Allocate a buffer to hold one extra byte. 12410Sstevel@tonic-gate */ 12420Sstevel@tonic-gate debug(5, "Odd len passwd for ATAPI device!\n"); 12430Sstevel@tonic-gate errno = 0; 12440Sstevel@tonic-gate tmp_passwd = (char *)malloc(wp->sm_passwd_len+1); 12450Sstevel@tonic-gate if (tmp_passwd == NULL) { 12460Sstevel@tonic-gate if (errno == 0) 12470Sstevel@tonic-gate errno = ENOMEM; 12480Sstevel@tonic-gate return (-1); 12490Sstevel@tonic-gate } 12500Sstevel@tonic-gate (void) memset(tmp_passwd, 0, wp->sm_passwd_len+1); 12510Sstevel@tonic-gate (void) memcpy(tmp_passwd, wp->sm_passwd, wp->sm_passwd_len); 12520Sstevel@tonic-gate ucmd.uscsi_bufaddr = (caddr_t)tmp_passwd; 12530Sstevel@tonic-gate ucmd.uscsi_buflen = wp->sm_passwd_len+1; 12540Sstevel@tonic-gate } else { 12550Sstevel@tonic-gate ucmd.uscsi_bufaddr = (caddr_t)wp->sm_passwd; 12560Sstevel@tonic-gate ucmd.uscsi_buflen = wp->sm_passwd_len; 12570Sstevel@tonic-gate } 12580Sstevel@tonic-gate ucmd.uscsi_timeout = 120; /* If 0, HBA hangs forever */ 12590Sstevel@tonic-gate ucmd.uscsi_rqlen = RQ_LEN; 12600Sstevel@tonic-gate ucmd.uscsi_rqbuf = rq_data; 12610Sstevel@tonic-gate status = do_uscsi_cmd(fd, &ucmd, USCSI_WRITE|USCSI_RQENABLE); 12620Sstevel@tonic-gate if (tmp_passwd != NULL) { 12630Sstevel@tonic-gate free(tmp_passwd); 12640Sstevel@tonic-gate } 12650Sstevel@tonic-gate if (status || ucmd.uscsi_status) { 1266*1137Sarutz debug(5, "Cartridge-protect operation failed: rv " 1267*1137Sarutz "= %d uscsi_status = %d errno = %d\n", status, 1268*1137Sarutz ucmd.uscsi_status, errno); 1269*1137Sarutz if ((rq_data[2] & 0xF) == KEY_ILLEGAL_REQUEST) { 12700Sstevel@tonic-gate if (rq_data[12] == 0x26) { 12710Sstevel@tonic-gate /* Wrong passwd */ 1272*1137Sarutz debug(5, "Protection Request with wrong " 1273*1137Sarutz "passwd. errno is being set to EACCES.\n"); 12740Sstevel@tonic-gate errno = EACCES; 12750Sstevel@tonic-gate } 12760Sstevel@tonic-gate } 12770Sstevel@tonic-gate return (-1); 12780Sstevel@tonic-gate } 12790Sstevel@tonic-gate 12800Sstevel@tonic-gate return (0); 12810Sstevel@tonic-gate } 12820Sstevel@tonic-gate 12830Sstevel@tonic-gate /*ARGSUSED*/ 12840Sstevel@tonic-gate static int32_t 12850Sstevel@tonic-gate scsi_write_protect(int32_t fd, smwp_state_t *wp) 12860Sstevel@tonic-gate { 12870Sstevel@tonic-gate errno = ENOTSUP; 12880Sstevel@tonic-gate return (-1); 12890Sstevel@tonic-gate } 12900Sstevel@tonic-gate 1291*1137Sarutz /* 1292*1137Sarutz * This thread becomes the server-side thread used in 1293*1137Sarutz * the implementation of a door_call between a client 1294*1137Sarutz * and the Client Door. 1295*1137Sarutz * 1296*1137Sarutz * This thread is customized both by the door_server_create(3c) 1297*1137Sarutz * function sm_door_server_create, as well as by itself. 1298*1137Sarutz * 1299*1137Sarutz * This thread needs to synchronize with the 1300*1137Sarutz * main_servproc[SMEDIA_CNUM_OPEN_FD] door_call in terms of 1301*1137Sarutz * both successful and failure scenarios. main_servproc 1302*1137Sarutz * locks dd_lock before calling door_create. This thread 1303*1137Sarutz * then attempts to lock, but will block until main_servproc 1304*1137Sarutz * has either created all doors it requires, or until a 1305*1137Sarutz * door_create has failed (door_create's return and the 1306*1137Sarutz * creation of an associated thread are asynchronous). 1307*1137Sarutz * 1308*1137Sarutz * If door_create failed, this thread will be able to obtain 1309*1137Sarutz * dd_lock and call pthread_exit. If all door_create's succeed, 1310*1137Sarutz * this thread will obtain dd_lock and commence with 1311*1137Sarutz * customizing the thread's attributes. door_bind is called to 1312*1137Sarutz * bind this thread to the per-door private thread pool, and 1313*1137Sarutz * main_servproc is cond_signal'd to avail it of this fact. 1314*1137Sarutz * 1315*1137Sarutz * Finally, this thread calls door_return, which causes it to 1316*1137Sarutz * commence its lifetime as a server-side thread in implementation 1317*1137Sarutz * of a Client Door door_call. 1318*1137Sarutz */ 13190Sstevel@tonic-gate static void * 1320*1137Sarutz sm_server_thread(void *arg) 13210Sstevel@tonic-gate { 13220Sstevel@tonic-gate door_data_t *door_dp; 1323*1137Sarutz struct sigaction act; 1324*1137Sarutz int i; 1325*1137Sarutz int err; 13260Sstevel@tonic-gate 13270Sstevel@tonic-gate door_dp = (door_data_t *)arg; 13280Sstevel@tonic-gate 13290Sstevel@tonic-gate if (door_dp == NULL) { 1330*1137Sarutz fatal("sm_server_thread[%d]: argument is NULL!!\n", 1331*1137Sarutz pthread_self()); 13320Sstevel@tonic-gate exit(-1); 13330Sstevel@tonic-gate } 1334*1137Sarutz 1335*1137Sarutz /* Wait for Client Door to be created */ 13360Sstevel@tonic-gate (void) mutex_lock(&door_dp->dd_lock); 1337*1137Sarutz if (door_dp->dd_cdoor_descriptor < 0) { 1338*1137Sarutz debug(5, "sm_server_thread[%d]: door_create() failed", 1339*1137Sarutz pthread_self()); 1340*1137Sarutz (void) mutex_unlock(&door_dp->dd_lock); 1341*1137Sarutz pthread_exit((void *)-2); 1342*1137Sarutz } 13430Sstevel@tonic-gate (void) mutex_unlock(&door_dp->dd_lock); 13440Sstevel@tonic-gate 13450Sstevel@tonic-gate for (i = 0; i < N_BADSIGS; i++) { 13460Sstevel@tonic-gate act.sa_sigaction = server_badsig_handler; 13470Sstevel@tonic-gate (void) sigemptyset(&act.sa_mask); 13480Sstevel@tonic-gate act.sa_flags = SA_SIGINFO; 13490Sstevel@tonic-gate if (sigaction(badsigs[i], &act, NULL) == -1) 13500Sstevel@tonic-gate warning(gettext(SIGACT_FAILED), strsignal(badsigs[i]), 1351*1137Sarutz strerror(errno)); 13520Sstevel@tonic-gate } 13530Sstevel@tonic-gate if (sigemptyset(&door_dp->dd_newset) != 0) 13540Sstevel@tonic-gate warning(gettext("sigemptyset failed. errno = %d\n"), 1355*1137Sarutz errno); 1356*1137Sarutz if ((err = pthread_sigmask(SIG_BLOCK, &door_dp->dd_newset, NULL)) != 0) 1357*1137Sarutz warning(gettext("pthread_sigmask failed = %d\n"), err); 1358*1137Sarutz 1359*1137Sarutz /* Bind thread with pool associated with Client Door */ 1360*1137Sarutz 1361*1137Sarutz if (door_bind(door_dp->dd_cdoor_descriptor) < 0) { 13620Sstevel@tonic-gate fatal("door_bind"); 13630Sstevel@tonic-gate exit(-1); 13640Sstevel@tonic-gate } 1365*1137Sarutz debug(5, "thr[%d] bound to Client Door[%d]", pthread_self(), 1366*1137Sarutz door_dp->dd_cdoor_descriptor); 1367*1137Sarutz 13680Sstevel@tonic-gate /* 1369*1137Sarutz * Set these two cancellation(5) attributes. Ensure that the 1370*1137Sarutz * pthread we create has cancellation(5) DISABLED and DEFERRED, 1371*1137Sarutz * as our implementation is based on this. DEFERRED is the 1372*1137Sarutz * default, but set it anyways, in case the defaults change in 1373*1137Sarutz * the future. 13740Sstevel@tonic-gate */ 1375*1137Sarutz if ((err = pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL)) != 0) 1376*1137Sarutz warning(gettext("pthread_setcancelstate(PTHREAD_CANCEL_DISABLE)" 1377*1137Sarutz " failed = %d\n"), err); 1378*1137Sarutz if ((err = pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, 1379*1137Sarutz NULL)) != 0) 1380*1137Sarutz warning(gettext("pthread_setcanceltype(DEFERRED) " 1381*1137Sarutz "failed = %d\n"), err); 1382*1137Sarutz 1383*1137Sarutz /* Inform main_servproc that door_bind() is complete. */ 1384*1137Sarutz (void) cond_signal(&door_dp->dd_cv_bind); 1385*1137Sarutz 13860Sstevel@tonic-gate /* 1387*1137Sarutz * Per doors protocol, transfer control to the doors-runtime in 1388*1137Sarutz * order to make this thread available to answer future door_call()'s. 13890Sstevel@tonic-gate */ 13900Sstevel@tonic-gate (void) door_return(NULL, 0, NULL, 0); 13910Sstevel@tonic-gate return (NULL); 13920Sstevel@tonic-gate } 13930Sstevel@tonic-gate 1394*1137Sarutz /* 1395*1137Sarutz * This function cleans up all per-connection resources. 1396*1137Sarutz * 1397*1137Sarutz * This function is called when the Client Door's service procedure 1398*1137Sarutz * (client_servproc) is called w/ DOOR_UNREF_DATA, which is the 1399*1137Sarutz * doors protocol convention stating that the number of file 1400*1137Sarutz * descriptors referring to this door has dropped to one. 1401*1137Sarutz * client_servproc is passed DOOR_UNREF_DATA because the Client Door 1402*1137Sarutz * was door_create'd with the DOOR_UNREF bitflag. 1403*1137Sarutz */ 14040Sstevel@tonic-gate static void 1405*1137Sarutz cleanup(door_data_t *door_dp) 14060Sstevel@tonic-gate { 1407*1137Sarutz /* do door_revoke() of Death Door */ 1408*1137Sarutz if (door_dp->dd_ddoor_descriptor >= 0) { 1409*1137Sarutz debug(1, "cleanup[%d]: door_revoke() Death Door[%d]", 1410*1137Sarutz pthread_self(), door_dp->dd_ddoor_descriptor); 1411*1137Sarutz 1412*1137Sarutz if (door_revoke(door_dp->dd_ddoor_descriptor) < 0) { 1413*1137Sarutz warning(gettext("cleanup[%d]: door_revoke() of Death " 1414*1137Sarutz "Door(%d) failed = %d"), pthread_self(), 1415*1137Sarutz door_dp->dd_ddoor_descriptor, errno); 1416*1137Sarutz } else { 1417*1137Sarutz door_dp->dd_ddoor_descriptor = -1; 1418*1137Sarutz } 14190Sstevel@tonic-gate } 1420*1137Sarutz 1421*1137Sarutz /* release memory that is shared between client and (our) server */ 1422*1137Sarutz if (door_dp->dd_buffd >= 0) { 1423*1137Sarutz debug(1, "cleanup[%d]: release shared memory", pthread_self()); 14240Sstevel@tonic-gate (void) munmap(door_dp->dd_buf, door_dp->dd_buf_len); 14250Sstevel@tonic-gate (void) close(door_dp->dd_buffd); 1426*1137Sarutz 1427*1137Sarutz door_dp->dd_buffd = -1; 14280Sstevel@tonic-gate door_dp->dd_buf = NULL; 14290Sstevel@tonic-gate door_dp->dd_buf_len = 0; 14300Sstevel@tonic-gate } 14310Sstevel@tonic-gate 1432*1137Sarutz /* close the (target) device that the Client is operating on */ 1433*1137Sarutz if (door_dp->dd_fd >= 0) { 1434*1137Sarutz debug(1, "cleanup[%d]: close(%d) target device", pthread_self(), 1435*1137Sarutz door_dp->dd_fd); 1436*1137Sarutz if (close(door_dp->dd_fd) < 0) { 1437*1137Sarutz warning(gettext("cleanup[%d]: close() of target device" 1438*1137Sarutz "failed = %d\n"), pthread_self(), errno); 1439*1137Sarutz } 1440*1137Sarutz } 1441*1137Sarutz 1442*1137Sarutz /* 1443*1137Sarutz * Unbind the current thread from the Client Door's private 1444*1137Sarutz * thread pool. 1445*1137Sarutz */ 1446*1137Sarutz debug(1, "cleanup[%d]: door_unbind() of Client Door[%d]", 1447*1137Sarutz pthread_self(), door_dp->dd_cdoor_descriptor); 1448*1137Sarutz if (door_unbind() < 0) 1449*1137Sarutz warning("door_unbind() of Client Door[%d] failed = " 1450*1137Sarutz "%d", door_dp->dd_cdoor_descriptor, errno); 1451*1137Sarutz 1452*1137Sarutz /* Disallow any future requests to the Client Door */ 1453*1137Sarutz if (door_dp->dd_cdoor_descriptor >= 0) { 1454*1137Sarutz debug(1, "cleanup[%d]: door_revoke() Client Door[%d]", 1455*1137Sarutz pthread_self(), door_dp->dd_cdoor_descriptor); 1456*1137Sarutz 1457*1137Sarutz if (door_revoke(door_dp->dd_cdoor_descriptor) < 0) { 1458*1137Sarutz warning(gettext("cleanup[%d]: door_revoke() of " 1459*1137Sarutz "Client Door[%d] failed = %d"), pthread_self(), 1460*1137Sarutz door_dp->dd_cdoor_descriptor, errno); 1461*1137Sarutz } 14620Sstevel@tonic-gate } 1463*1137Sarutz 14640Sstevel@tonic-gate free(door_dp); 1465*1137Sarutz debug(5, "cleanup[%d] ...exiting\n", pthread_self()); 14660Sstevel@tonic-gate } 14670Sstevel@tonic-gate 1468*1137Sarutz /* 1469*1137Sarutz * This is the door_server_create(3c) function used to customize 1470*1137Sarutz * creation of the threads used in the handling of our daemon's 1471*1137Sarutz * door_call(3c)'s. 1472*1137Sarutz * 1473*1137Sarutz * This function is called synchronously as part of door_create(3c). 1474*1137Sarutz * Note that door_create(), however, is not synchronous; it can return 1475*1137Sarutz * with the created door file descriptor before any associated 1476*1137Sarutz * thread has been created. As a result, synchronization is needed 1477*1137Sarutz * between door_create() caller and the created pthread. This is 1478*1137Sarutz * needed both when each activity succeeds or when either activity 1479*1137Sarutz * fails. 1480*1137Sarutz * 1481*1137Sarutz * Specifically, this function ensures that each "connection" 1482*1137Sarutz * with the client creates only one thread in the per-door, 1483*1137Sarutz * private thread pool. This function locks dd_threadlock and 1484*1137Sarutz * then calls pthread_create(). If that succeeds, dd_thread 1485*1137Sarutz * is assigned the thread id, and dd_threadlock is unlocked. 1486*1137Sarutz * Any per-connection door_create that causes control to flow 1487*1137Sarutz * to this function will eventually find that dd_thread is 1488*1137Sarutz * non-zero, and control will exit this function. 1489*1137Sarutz * 1490*1137Sarutz * In the current implementation, the door_create for the Client Door 1491*1137Sarutz * is called first, and the Death Door is door_create'd second. 1492*1137Sarutz * As a result, the following function can safely make the static 1493*1137Sarutz * assumption that the first door (within a connection) is the 1494*1137Sarutz * Client Door. A connection's Client Door and Death Door share 1495*1137Sarutz * the same thread as well as the same door_data_t instance. 1496*1137Sarutz */ 14970Sstevel@tonic-gate static void 1498*1137Sarutz sm_door_server_create(door_info_t *dip) 14990Sstevel@tonic-gate { 15000Sstevel@tonic-gate door_data_t *door_dp; 15010Sstevel@tonic-gate pthread_t tid; 15020Sstevel@tonic-gate pthread_attr_t attr; 15030Sstevel@tonic-gate int ret_val; 1504*1137Sarutz int err; 15050Sstevel@tonic-gate 15060Sstevel@tonic-gate if (dip == NULL) { 15070Sstevel@tonic-gate return; 15080Sstevel@tonic-gate } 1509796Smathue door_dp = (door_data_t *)(uintptr_t)dip->di_data; 15100Sstevel@tonic-gate 1511*1137Sarutz debug(10, "sm_door_server_create[%d]: entering...\n", pthread_self()); 15120Sstevel@tonic-gate 15130Sstevel@tonic-gate /* create one thread for this door */ 15140Sstevel@tonic-gate 15150Sstevel@tonic-gate (void) mutex_lock(&door_dp->dd_threadlock); 15160Sstevel@tonic-gate 15170Sstevel@tonic-gate if (door_dp->dd_thread != 0) { 1518*1137Sarutz debug(8, "sm_door_server_create[%d]: Exiting without creating " 1519*1137Sarutz "thread.\n", pthread_self()); 15200Sstevel@tonic-gate (void) mutex_unlock(&door_dp->dd_threadlock); 15210Sstevel@tonic-gate return; 15220Sstevel@tonic-gate } 15230Sstevel@tonic-gate 15240Sstevel@tonic-gate (void) pthread_attr_init(&attr); 1525*1137Sarutz 1526*1137Sarutz if ((err = pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM)) != 0) 1527*1137Sarutz warning(gettext("pthread_attr_setscope failed = %d\n"), err); 1528*1137Sarutz if ((err = pthread_attr_setdetachstate(&attr, 1529*1137Sarutz PTHREAD_CREATE_DETACHED)) != 0) 1530*1137Sarutz warning(gettext("pthread_attr_setdetachstate failed = %d\n"), 1531*1137Sarutz err); 1532*1137Sarutz 1533*1137Sarutz ret_val = pthread_create(&tid, &attr, sm_server_thread, 1534*1137Sarutz (void *)(uintptr_t)(dip->di_data)); 15350Sstevel@tonic-gate if (ret_val != 0) { 1536*1137Sarutz warning(gettext("sm_door_server_create[%d]: pthread_create " 1537*1137Sarutz "failed = %d\n"), pthread_self(), ret_val); 15380Sstevel@tonic-gate (void) mutex_unlock(&door_dp->dd_threadlock); 15390Sstevel@tonic-gate (void) pthread_attr_destroy(&attr); 15400Sstevel@tonic-gate return; 15410Sstevel@tonic-gate } 15420Sstevel@tonic-gate (void) pthread_attr_destroy(&attr); 15430Sstevel@tonic-gate door_dp->dd_thread = tid; 15440Sstevel@tonic-gate 15450Sstevel@tonic-gate (void) mutex_unlock(&door_dp->dd_threadlock); 1546*1137Sarutz debug(5, "Exiting sm_door_server_create[%d] after creating thr[%d].\n", 1547*1137Sarutz pthread_self(), tid); 15480Sstevel@tonic-gate } 15490Sstevel@tonic-gate 15500Sstevel@tonic-gate static void 15510Sstevel@tonic-gate door_ret_err(smedia_reterror_t *reterror, int32_t err) 15520Sstevel@tonic-gate { 15530Sstevel@tonic-gate reterror->cnum = SMEDIA_CNUM_ERROR; 15540Sstevel@tonic-gate reterror->errnum = err; 15550Sstevel@tonic-gate (void) door_return((char *)reterror, sizeof (smedia_reterror_t), 0, 0); 15560Sstevel@tonic-gate } 15570Sstevel@tonic-gate 15580Sstevel@tonic-gate static void 15590Sstevel@tonic-gate my_door_return(char *data_ptr, size_t data_size, 15600Sstevel@tonic-gate door_desc_t *desc_ptr, uint_t num_desc) 15610Sstevel@tonic-gate { 15620Sstevel@tonic-gate (void) door_return(data_ptr, data_size, desc_ptr, num_desc); 15630Sstevel@tonic-gate } 15640Sstevel@tonic-gate 15650Sstevel@tonic-gate static int32_t 15660Sstevel@tonic-gate raw_read(door_data_t *door_dp, smedia_services_t *req) 15670Sstevel@tonic-gate { 15680Sstevel@tonic-gate struct uscsi_cmd ucmd; 15690Sstevel@tonic-gate union scsi_cdb cdb; 15700Sstevel@tonic-gate int32_t ret_val; 15710Sstevel@tonic-gate int32_t num_sectors, sector_size; 15720Sstevel@tonic-gate int32_t rc_data[2]; 15730Sstevel@tonic-gate char rq_data[RQ_LEN]; 15740Sstevel@tonic-gate 15750Sstevel@tonic-gate (void) memset((void *) &rc_data, 0, sizeof (rc_data)); 15760Sstevel@tonic-gate (void) memset((void *) &ucmd, 0, sizeof (ucmd)); 15770Sstevel@tonic-gate (void) memset((void *) &cdb, 0, sizeof (union scsi_cdb)); 15780Sstevel@tonic-gate 15790Sstevel@tonic-gate if (door_dp->dd_sector_size == 0) { 15800Sstevel@tonic-gate sector_size = get_sector_size(door_dp->dd_fd); 15810Sstevel@tonic-gate door_dp->dd_sector_size = sector_size; 15820Sstevel@tonic-gate } else sector_size = door_dp->dd_sector_size; 15830Sstevel@tonic-gate 15840Sstevel@tonic-gate if ((req->reqraw_read.nbytes > door_dp->dd_buf_len) || 15850Sstevel@tonic-gate (door_dp->dd_buf == NULL)) { 15860Sstevel@tonic-gate errno = EINVAL; 15870Sstevel@tonic-gate return (-1); 15880Sstevel@tonic-gate } 15890Sstevel@tonic-gate if ((!req->reqraw_read.nbytes) || 15900Sstevel@tonic-gate (req->reqraw_read.nbytes % sector_size)) { 15910Sstevel@tonic-gate errno = EINVAL; 15920Sstevel@tonic-gate return (-1); 15930Sstevel@tonic-gate } 15940Sstevel@tonic-gate 15950Sstevel@tonic-gate (void) memset((void *) &cdb, 0, sizeof (cdb)); 15960Sstevel@tonic-gate num_sectors = (uint32_t)req->reqraw_read.nbytes/sector_size; 15970Sstevel@tonic-gate 15980Sstevel@tonic-gate cdb.scc_cmd = SCMD_READ_G1; 15990Sstevel@tonic-gate FORMG1ADDR(&cdb, (uint32_t)req->reqraw_read.blockno); 16000Sstevel@tonic-gate FORMG1COUNT(&cdb, num_sectors); 16010Sstevel@tonic-gate 16020Sstevel@tonic-gate ucmd.uscsi_cdb = (caddr_t)&cdb; 16030Sstevel@tonic-gate ucmd.uscsi_cdblen = CDB_GROUP1; 16040Sstevel@tonic-gate ucmd.uscsi_bufaddr = (caddr_t)door_dp->dd_buf; 16050Sstevel@tonic-gate ucmd.uscsi_buflen = (uint32_t)req->reqraw_read.nbytes; 16060Sstevel@tonic-gate ucmd.uscsi_timeout = 120; /* If 0, HBA hangs forever */ 16070Sstevel@tonic-gate ucmd.uscsi_rqlen = RQ_LEN; 16080Sstevel@tonic-gate ucmd.uscsi_rqbuf = rq_data; 16090Sstevel@tonic-gate ret_val = do_uscsi_cmd(door_dp->dd_fd, 16100Sstevel@tonic-gate &ucmd, USCSI_READ|USCSI_RQENABLE); 16110Sstevel@tonic-gate if (ret_val || ucmd.uscsi_status) { 16120Sstevel@tonic-gate debug(5, "read failed: %d - %d errno = %d\n", 16130Sstevel@tonic-gate ret_val, ucmd.uscsi_status, errno); 16140Sstevel@tonic-gate debug(5, "buflen = 0x%x resid = 0x%x sector size = %d\n", 16150Sstevel@tonic-gate ucmd.uscsi_buflen, ucmd.uscsi_resid, sector_size); 16160Sstevel@tonic-gate debug(5, "cdb addr: %x %x %x %x \n", cdb.g1_addr3, 16170Sstevel@tonic-gate cdb.g1_addr2, cdb.g1_addr1, cdb.g1_addr0); 16180Sstevel@tonic-gate debug(5, "cdb count: %x %x\n", cdb.g1_count1, 16190Sstevel@tonic-gate cdb.g1_count0); 16200Sstevel@tonic-gate return (-1); 16210Sstevel@tonic-gate } 16220Sstevel@tonic-gate ret_val = ucmd.uscsi_buflen - ucmd.uscsi_resid; 16230Sstevel@tonic-gate return (ret_val); 16240Sstevel@tonic-gate } 16250Sstevel@tonic-gate 16260Sstevel@tonic-gate static int32_t 16270Sstevel@tonic-gate raw_write(door_data_t *door_dp, smedia_services_t *req) 16280Sstevel@tonic-gate { 16290Sstevel@tonic-gate struct uscsi_cmd ucmd; 16300Sstevel@tonic-gate union scsi_cdb cdb; 16310Sstevel@tonic-gate int32_t ret_val; 16320Sstevel@tonic-gate int32_t num_sectors, sector_size; 16330Sstevel@tonic-gate int32_t rc_data[2]; 16340Sstevel@tonic-gate char rq_data[RQ_LEN]; 16350Sstevel@tonic-gate 16360Sstevel@tonic-gate (void) memset((void *) &rc_data, 0, sizeof (rc_data)); 16370Sstevel@tonic-gate (void) memset((void *) &ucmd, 0, sizeof (ucmd)); 16380Sstevel@tonic-gate (void) memset((void *) &cdb, 0, sizeof (union scsi_cdb)); 16390Sstevel@tonic-gate 16400Sstevel@tonic-gate if (door_dp->dd_sector_size == 0) { 16410Sstevel@tonic-gate sector_size = get_sector_size(door_dp->dd_fd); 16420Sstevel@tonic-gate door_dp->dd_sector_size = sector_size; 16430Sstevel@tonic-gate } else sector_size = door_dp->dd_sector_size; 16440Sstevel@tonic-gate 16450Sstevel@tonic-gate 16460Sstevel@tonic-gate if ((req->reqraw_write.nbytes > door_dp->dd_buf_len) || 16470Sstevel@tonic-gate (door_dp->dd_buf == NULL)) { 16480Sstevel@tonic-gate errno = EINVAL; 16490Sstevel@tonic-gate return (-1); 16500Sstevel@tonic-gate } 16510Sstevel@tonic-gate if ((req->reqraw_write.nbytes % sector_size)) { 16520Sstevel@tonic-gate errno = EINVAL; 16530Sstevel@tonic-gate return (-1); 16540Sstevel@tonic-gate } 16550Sstevel@tonic-gate 16560Sstevel@tonic-gate (void) memset((void *) &cdb, 0, sizeof (cdb)); 16570Sstevel@tonic-gate num_sectors = (uint32_t)req->reqraw_write.nbytes/sector_size; 16580Sstevel@tonic-gate 16590Sstevel@tonic-gate cdb.scc_cmd = SCMD_WRITE_G1; 16600Sstevel@tonic-gate FORMG1ADDR(&cdb, (uint32_t)req->reqraw_write.blockno); 16610Sstevel@tonic-gate FORMG1COUNT(&cdb, num_sectors); 16620Sstevel@tonic-gate 16630Sstevel@tonic-gate ucmd.uscsi_cdb = (caddr_t)&cdb; 16640Sstevel@tonic-gate ucmd.uscsi_cdblen = CDB_GROUP1; 16650Sstevel@tonic-gate ucmd.uscsi_bufaddr = (caddr_t)door_dp->dd_buf; 16660Sstevel@tonic-gate ucmd.uscsi_buflen = (uint32_t)req->reqraw_write.nbytes; 16670Sstevel@tonic-gate ucmd.uscsi_timeout = 120; /* If 0, HBA hangs forever */ 16680Sstevel@tonic-gate ucmd.uscsi_rqlen = RQ_LEN; 16690Sstevel@tonic-gate ucmd.uscsi_rqbuf = rq_data; 16700Sstevel@tonic-gate ret_val = do_uscsi_cmd(door_dp->dd_fd, 16710Sstevel@tonic-gate &ucmd, USCSI_WRITE|USCSI_RQENABLE); 16720Sstevel@tonic-gate if (ret_val || ucmd.uscsi_status) { 16730Sstevel@tonic-gate debug(5, "write failed: %d - %d errno = %d\n", 16740Sstevel@tonic-gate ret_val, ucmd.uscsi_status, errno); 16750Sstevel@tonic-gate debug(5, "buflen = 0x%x resid = 0x%x sector size = %d\n", 16760Sstevel@tonic-gate ucmd.uscsi_buflen, ucmd.uscsi_resid, sector_size); 16770Sstevel@tonic-gate debug(5, "cdb addr: %x %x %x %x \n", cdb.g1_addr3, 16780Sstevel@tonic-gate cdb.g1_addr2, cdb.g1_addr1, cdb.g1_addr0); 16790Sstevel@tonic-gate debug(5, "cdb count: %x %x\n", cdb.g1_count1, 16800Sstevel@tonic-gate cdb.g1_count0); 16810Sstevel@tonic-gate return (-1); 16820Sstevel@tonic-gate } 16830Sstevel@tonic-gate ret_val = ucmd.uscsi_buflen - ucmd.uscsi_resid; 16840Sstevel@tonic-gate return (ret_val); 16850Sstevel@tonic-gate } 16860Sstevel@tonic-gate 16870Sstevel@tonic-gate static int32_t 16880Sstevel@tonic-gate set_protection_status(door_data_t *door_dp, smedia_services_t *req) 16890Sstevel@tonic-gate { 16900Sstevel@tonic-gate int32_t ret_val, saved_errno, status; 16910Sstevel@tonic-gate struct scsi_inquiry inq; 16920Sstevel@tonic-gate char vid[9]; 16930Sstevel@tonic-gate char pid[17]; 16940Sstevel@tonic-gate struct passwd *pwd; 16950Sstevel@tonic-gate char uname[MAXUGNAME + 1]; 16960Sstevel@tonic-gate char *new_state, *old_state; 16970Sstevel@tonic-gate 16980Sstevel@tonic-gate /* 16990Sstevel@tonic-gate * Read the current protection state before modifiying. 17000Sstevel@tonic-gate * Needed for audit purposes. 17010Sstevel@tonic-gate */ 17020Sstevel@tonic-gate switch (get_device_type_scsi(door_dp->dd_fd, &inq)) { 17030Sstevel@tonic-gate case SCSI_IOMEGA: 17040Sstevel@tonic-gate status = scsi_zip_media_status(door_dp->dd_fd); 17050Sstevel@tonic-gate ret_val = scsi_zip_write_protect(door_dp->dd_fd, 17060Sstevel@tonic-gate &req->reqset_protection_status.prot_state); 17070Sstevel@tonic-gate break; 17080Sstevel@tonic-gate case SCSI_FLOPPY: 17090Sstevel@tonic-gate info("Formatting floppy"); 17100Sstevel@tonic-gate status = scsi_floppy_media_status(door_dp->dd_fd); 17110Sstevel@tonic-gate ret_val = scsi_floppy_write_protect(door_dp->dd_fd, 17120Sstevel@tonic-gate &req->reqset_protection_status.prot_state); 17130Sstevel@tonic-gate break; 17140Sstevel@tonic-gate case SCSI_GENERIC: 17150Sstevel@tonic-gate status = scsi_media_status(door_dp->dd_fd); 17160Sstevel@tonic-gate ret_val = scsi_write_protect(door_dp->dd_fd, 17170Sstevel@tonic-gate &req->reqset_protection_status.prot_state); 17180Sstevel@tonic-gate break; 17190Sstevel@tonic-gate } 17200Sstevel@tonic-gate 17210Sstevel@tonic-gate saved_errno = errno; 17220Sstevel@tonic-gate new_state = xlate_state( 17230Sstevel@tonic-gate req->reqset_protection_status.prot_state.sm_new_state); 17240Sstevel@tonic-gate old_state = xlate_state(status); 17250Sstevel@tonic-gate 17260Sstevel@tonic-gate if (can_audit()) { 17270Sstevel@tonic-gate (void) audit_save_me(door_dp); 17280Sstevel@tonic-gate door_dp->audit_text[0] = 0; 17290Sstevel@tonic-gate door_dp->audit_text1[0] = 0; 17300Sstevel@tonic-gate door_dp->audit_event = AUE_smserverd; 17310Sstevel@tonic-gate } 17320Sstevel@tonic-gate (void) strlcpy(vid, inq.inq_vid, sizeof (vid)); 17330Sstevel@tonic-gate (void) strlcpy(pid, inq.inq_pid, sizeof (pid)); 17340Sstevel@tonic-gate if (ret_val < 0) { 17350Sstevel@tonic-gate if (errno == EACCES) { 17360Sstevel@tonic-gate pwd = getpwuid(door_dp->dd_cred.dc_ruid); 17370Sstevel@tonic-gate if (pwd != NULL) { 17380Sstevel@tonic-gate (void) strlcpy(uname, 17390Sstevel@tonic-gate pwd->pw_name, MAXUGNAME); 17400Sstevel@tonic-gate } else uname[0] = 0; 17410Sstevel@tonic-gate 17420Sstevel@tonic-gate if (can_audit()) { 17430Sstevel@tonic-gate (void) snprintf(door_dp->audit_text, 17440Sstevel@tonic-gate sizeof (door_dp->audit_text), 17450Sstevel@tonic-gate dgettext(TEXT_DOMAIN, "from %s to %s"), 17460Sstevel@tonic-gate old_state, new_state); 17470Sstevel@tonic-gate 17480Sstevel@tonic-gate (void) snprintf(door_dp->audit_text1, 17490Sstevel@tonic-gate sizeof (door_dp->audit_text1), 17500Sstevel@tonic-gate "%s %s (%d,%d)", vid, pid, 17510Sstevel@tonic-gate (int)major(door_dp->dd_stat.st_rdev), 17520Sstevel@tonic-gate (int)minor(door_dp->dd_stat.st_rdev)); 17530Sstevel@tonic-gate 17540Sstevel@tonic-gate door_dp->audit_sorf = 1; 17550Sstevel@tonic-gate if (audit_audit(door_dp) == -1) 17560Sstevel@tonic-gate warning("Error in writing audit info\n"); 17570Sstevel@tonic-gate } 17580Sstevel@tonic-gate } /* errno == EACCES */ 17590Sstevel@tonic-gate errno = saved_errno; 17600Sstevel@tonic-gate return (-1); 17610Sstevel@tonic-gate } 17620Sstevel@tonic-gate if (can_audit()) { 17630Sstevel@tonic-gate (void) snprintf(door_dp->audit_text, 17640Sstevel@tonic-gate sizeof (door_dp->audit_text), 17650Sstevel@tonic-gate dgettext(TEXT_DOMAIN, "from %s to %s"), 17660Sstevel@tonic-gate old_state, new_state); 17670Sstevel@tonic-gate 17680Sstevel@tonic-gate (void) snprintf(door_dp->audit_text1, 17690Sstevel@tonic-gate sizeof (door_dp->audit_text1), 17700Sstevel@tonic-gate "%s %s (%d,%d)", vid, pid, 17710Sstevel@tonic-gate (int)major(door_dp->dd_stat.st_rdev), 17720Sstevel@tonic-gate (int)minor(door_dp->dd_stat.st_rdev)); 17730Sstevel@tonic-gate 17740Sstevel@tonic-gate door_dp->audit_sorf = 0; 17750Sstevel@tonic-gate if (audit_audit(door_dp) == -1) 17760Sstevel@tonic-gate warning("Error in writing audit info\n"); 17770Sstevel@tonic-gate } 17780Sstevel@tonic-gate errno = saved_errno; 17790Sstevel@tonic-gate return (0); 17800Sstevel@tonic-gate } 17810Sstevel@tonic-gate 17820Sstevel@tonic-gate static int32_t 1783*1137Sarutz set_shfd(door_data_t *door_dp, int32_t fd, smedia_services_t *req) 17840Sstevel@tonic-gate { 17850Sstevel@tonic-gate void *fbuf; 1786*1137Sarutz int32_t ret_val = 0; 1787*1137Sarutz 1788*1137Sarutz if ((door_dp->dd_buffd != -1) && (door_dp->dd_buf != NULL)) { 1789*1137Sarutz ret_val = munmap(door_dp->dd_buf, door_dp->dd_buf_len); 1790*1137Sarutz if (ret_val == -1) 1791*1137Sarutz warning(gettext("munmap failed. errno=%d\n"), 1792*1137Sarutz errno); 1793*1137Sarutz (void) close(door_dp->dd_buffd); 1794*1137Sarutz 1795*1137Sarutz door_dp->dd_buffd = -1; 1796*1137Sarutz door_dp->dd_buf = 0; 1797*1137Sarutz door_dp->dd_buf_len = 0; 17980Sstevel@tonic-gate } 1799*1137Sarutz 18000Sstevel@tonic-gate fbuf = mmap(0, req->reqset_shfd.fdbuf_len, 1801*1137Sarutz PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); 1802*1137Sarutz if (fbuf == MAP_FAILED) { 1803*1137Sarutz ret_val = errno; 18040Sstevel@tonic-gate debug(5, "mmap failed. errno=%d\n", errno); 1805*1137Sarutz return (ret_val); 18060Sstevel@tonic-gate } 18070Sstevel@tonic-gate door_dp->dd_buffd = fd; 18080Sstevel@tonic-gate door_dp->dd_buf = fbuf; 18090Sstevel@tonic-gate door_dp->dd_buf_len = req->reqset_shfd.fdbuf_len; 1810*1137Sarutz 18110Sstevel@tonic-gate return (0); 18120Sstevel@tonic-gate } 18130Sstevel@tonic-gate 18140Sstevel@tonic-gate static int32_t 18150Sstevel@tonic-gate reassign_block(door_data_t *door_dp, smedia_services_t *req) 18160Sstevel@tonic-gate { 18170Sstevel@tonic-gate struct uscsi_cmd ucmd; 18180Sstevel@tonic-gate union scsi_cdb cdb; 18190Sstevel@tonic-gate int32_t ret_val; 18200Sstevel@tonic-gate int32_t sector_size; 18210Sstevel@tonic-gate char *read_buf; 18220Sstevel@tonic-gate uchar_t mode_data[MD_LEN]; 18230Sstevel@tonic-gate 18240Sstevel@tonic-gate if (get_mode_page(door_dp->dd_fd, 0, 1, 1825*1137Sarutz mode_data, MD_LEN) < 0) { 18260Sstevel@tonic-gate debug(5, "Mode sense failed\n"); 18270Sstevel@tonic-gate ret_val = scsi_reassign_block(door_dp->dd_fd, 1828*1137Sarutz req->reqreassign_block.blockno); 18290Sstevel@tonic-gate if (ret_val != 0) 18300Sstevel@tonic-gate return (-1); 18310Sstevel@tonic-gate return (0); 18320Sstevel@tonic-gate } 18330Sstevel@tonic-gate 18340Sstevel@tonic-gate /* 18350Sstevel@tonic-gate * No need to check if enough data is returned for 18360Sstevel@tonic-gate * AWRE bit or not. 18370Sstevel@tonic-gate * It will be 0 otherwise which needs to reassign the block. 18380Sstevel@tonic-gate */ 18390Sstevel@tonic-gate if (!(mode_data[AWRE_OFFSET] & AWRE)) { 18400Sstevel@tonic-gate debug(5, "AWRE bit not set\n"); 18410Sstevel@tonic-gate ret_val = scsi_reassign_block(door_dp->dd_fd, 18420Sstevel@tonic-gate req->reqreassign_block.blockno); 18430Sstevel@tonic-gate if (ret_val != 0) 18440Sstevel@tonic-gate return (-1); 18450Sstevel@tonic-gate return (0); 18460Sstevel@tonic-gate } 18470Sstevel@tonic-gate sector_size = (mode_data[BLOCK_LEN_OFFSET] << 16) | 18480Sstevel@tonic-gate (mode_data[BLOCK_LEN_OFFSET + 1] << 8) | 18490Sstevel@tonic-gate mode_data[BLOCK_LEN_OFFSET + 2]; 18500Sstevel@tonic-gate 18510Sstevel@tonic-gate debug(5, "REASSIGN BLOCK: sec size = 0x%x\n", sector_size); 18520Sstevel@tonic-gate read_buf = (char *)malloc(sector_size); 18530Sstevel@tonic-gate if (read_buf == NULL) { 18540Sstevel@tonic-gate /* Alloc failed. Atleast reassign the block */ 18550Sstevel@tonic-gate ret_val = scsi_reassign_block(door_dp->dd_fd, 18560Sstevel@tonic-gate req->reqreassign_block.blockno); 18570Sstevel@tonic-gate if (ret_val != 0) 18580Sstevel@tonic-gate return (-1); 18590Sstevel@tonic-gate return (0); 18600Sstevel@tonic-gate } 18610Sstevel@tonic-gate 18620Sstevel@tonic-gate (void) memset(read_buf, 0, sector_size); 18630Sstevel@tonic-gate /* Read the sector */ 18640Sstevel@tonic-gate debug(5, "Reading the block %d\n", 18650Sstevel@tonic-gate (uint32_t)req->reqreassign_block.blockno); 18660Sstevel@tonic-gate 18670Sstevel@tonic-gate (void) memset((void *) &ucmd, 0, sizeof (ucmd)); 18680Sstevel@tonic-gate (void) memset((void *) &cdb, 0, sizeof (union scsi_cdb)); 18690Sstevel@tonic-gate 18700Sstevel@tonic-gate cdb.scc_cmd = SCMD_READ_G1; 18710Sstevel@tonic-gate FORMG1ADDR(&cdb, req->reqreassign_block.blockno); 18720Sstevel@tonic-gate FORMG1COUNT(&cdb, 1); /* One block */ 18730Sstevel@tonic-gate 18740Sstevel@tonic-gate ucmd.uscsi_cdb = (caddr_t)&cdb; 18750Sstevel@tonic-gate ucmd.uscsi_cdblen = CDB_GROUP1; 18760Sstevel@tonic-gate ucmd.uscsi_bufaddr = (caddr_t)read_buf; 18770Sstevel@tonic-gate ucmd.uscsi_buflen = sector_size; 18780Sstevel@tonic-gate ucmd.uscsi_timeout = 120; /* If 0, HBA hangs forever */ 18790Sstevel@tonic-gate (void) do_uscsi_cmd(door_dp->dd_fd, &ucmd, USCSI_READ); 18800Sstevel@tonic-gate 18810Sstevel@tonic-gate /* Write the data back */ 18820Sstevel@tonic-gate 18830Sstevel@tonic-gate debug(5, "Writing the block %d\n", 18840Sstevel@tonic-gate (uint32_t)req->reqreassign_block.blockno); 18850Sstevel@tonic-gate (void) memset((void *) &ucmd, 0, sizeof (ucmd)); 18860Sstevel@tonic-gate (void) memset((void *) &cdb, 0, sizeof (cdb)); 18870Sstevel@tonic-gate 18880Sstevel@tonic-gate cdb.scc_cmd = SCMD_WRITE_G1; 18890Sstevel@tonic-gate FORMG1ADDR(&cdb, req->reqreassign_block.blockno); 18900Sstevel@tonic-gate FORMG1COUNT(&cdb, 1); /* One block */ 18910Sstevel@tonic-gate 18920Sstevel@tonic-gate ucmd.uscsi_cdb = (caddr_t)&cdb; 18930Sstevel@tonic-gate ucmd.uscsi_cdblen = CDB_GROUP1; 18940Sstevel@tonic-gate ucmd.uscsi_bufaddr = (caddr_t)read_buf; 18950Sstevel@tonic-gate ucmd.uscsi_buflen = sector_size; 18960Sstevel@tonic-gate ucmd.uscsi_timeout = 120; /* If 0, HBA hangs forever */ 18970Sstevel@tonic-gate ret_val = do_uscsi_cmd(door_dp->dd_fd, &ucmd, USCSI_WRITE); 18980Sstevel@tonic-gate free(read_buf); 18990Sstevel@tonic-gate if (ret_val || ucmd.uscsi_status) { 19000Sstevel@tonic-gate debug(5, "Reassign failed: %d - %d errno = %d\n", 19010Sstevel@tonic-gate ret_val, ucmd.uscsi_status, errno); 19020Sstevel@tonic-gate ret_val = scsi_reassign_block(door_dp->dd_fd, 19030Sstevel@tonic-gate req->reqreassign_block.blockno); 19040Sstevel@tonic-gate if (ret_val != 0) 19050Sstevel@tonic-gate return (-1); 19060Sstevel@tonic-gate return (0); 19070Sstevel@tonic-gate } 19080Sstevel@tonic-gate 19090Sstevel@tonic-gate return (0); 19100Sstevel@tonic-gate } 19110Sstevel@tonic-gate 19120Sstevel@tonic-gate static void 19130Sstevel@tonic-gate close_door_descs(door_desc_t *dp, uint_t ndesc) 19140Sstevel@tonic-gate { 19150Sstevel@tonic-gate while (ndesc > 0) { 19160Sstevel@tonic-gate int fd = dp->d_data.d_desc.d_descriptor; 19170Sstevel@tonic-gate if (dp->d_attributes & DOOR_DESCRIPTOR) 19180Sstevel@tonic-gate (void) close(fd); 19190Sstevel@tonic-gate dp++; 19200Sstevel@tonic-gate ndesc--; 19210Sstevel@tonic-gate } 19220Sstevel@tonic-gate } 19230Sstevel@tonic-gate 1924*1137Sarutz /* 1925*1137Sarutz * This is a Death Door's service procedure. 1926*1137Sarutz * 1927*1137Sarutz * This procedure is a NOP because the Death Door functionality 1928*1137Sarutz * is no longer used and will be removed in the future. 1929*1137Sarutz */ 1930*1137Sarutz /*ARGSUSED*/ 19310Sstevel@tonic-gate static void 1932*1137Sarutz death_servproc(void *cookie, char *argp, size_t arg_size, 1933*1137Sarutz door_desc_t *dp, uint_t ndesc) 1934*1137Sarutz { 1935*1137Sarutz debug(1, "death_servproc[%d]: argp = 0x%p " 1936*1137Sarutz "Death Door[%d]\n", pthread_self(), (void *)argp, 1937*1137Sarutz ((door_data_t *)cookie)->dd_ddoor_descriptor); 1938*1137Sarutz 1939*1137Sarutz (void) door_return(NULL, 0, NULL, 0); 1940*1137Sarutz } 1941*1137Sarutz 1942*1137Sarutz /* 1943*1137Sarutz * This is a Client Door's service procedure. 1944*1137Sarutz * 1945*1137Sarutz * This procedure is specified in the door_create() of a Client Door, 1946*1137Sarutz * and its functionality represents the bulk of services that the 1947*1137Sarutz * rpc.smserverd daemon offers. 1948*1137Sarutz */ 1949*1137Sarutz static void 1950*1137Sarutz client_servproc(void *cookie, char *argp, size_t arg_size, 19510Sstevel@tonic-gate door_desc_t *dp, uint_t ndesc) 19520Sstevel@tonic-gate { 19530Sstevel@tonic-gate smedia_services_t *req; 19540Sstevel@tonic-gate smedia_services_t rmsvc; 19550Sstevel@tonic-gate smedia_reterror_t reterror; 19560Sstevel@tonic-gate smedia_retraw_read_t retraw_read; 19570Sstevel@tonic-gate struct scsi_inquiry inq; 19580Sstevel@tonic-gate struct dk_minfo media_info; 19590Sstevel@tonic-gate struct dk_geom dkgeom; 19600Sstevel@tonic-gate int32_t status; 19610Sstevel@tonic-gate uchar_t data[18]; 19620Sstevel@tonic-gate int32_t completed = 0; 19630Sstevel@tonic-gate door_data_t *door_dp; 19640Sstevel@tonic-gate size_t retbuf_size; 19650Sstevel@tonic-gate struct uscsi_cmd ucmd; 19660Sstevel@tonic-gate union scsi_cdb cdb; 19670Sstevel@tonic-gate int32_t ret_val, err; 19680Sstevel@tonic-gate char rq_data[RQ_LEN]; 1969*1137Sarutz uint_t nexpected_desc; 19700Sstevel@tonic-gate struct vtoc vtoc; 19710Sstevel@tonic-gate 19720Sstevel@tonic-gate door_dp = (door_data_t *)cookie; 19730Sstevel@tonic-gate req = (smedia_services_t *)((void *)argp); 19740Sstevel@tonic-gate 1975*1137Sarutz debug(10, "client_servproc[%d]...\n", pthread_self()); 19760Sstevel@tonic-gate 19770Sstevel@tonic-gate if (argp == DOOR_UNREF_DATA) { 1978*1137Sarutz debug(5, "client_servproc[%d]: req = DOOR_UNREF_DATA\n", 1979*1137Sarutz pthread_self()); 19800Sstevel@tonic-gate debug(5, "Client has exited. Cleaning up resources\n"); 1981*1137Sarutz 19820Sstevel@tonic-gate (void) mutex_lock(&svcstate_lock); 19830Sstevel@tonic-gate svccount--; 19840Sstevel@tonic-gate (void) mutex_unlock(&svcstate_lock); 1985*1137Sarutz 19860Sstevel@tonic-gate cleanup(door_dp); 1987*1137Sarutz return; 19880Sstevel@tonic-gate } 1989*1137Sarutz 19900Sstevel@tonic-gate (void) mutex_lock(&svcstate_lock); 19910Sstevel@tonic-gate svcstate = _SERVED; 19920Sstevel@tonic-gate (void) mutex_unlock(&svcstate_lock); 19930Sstevel@tonic-gate 19940Sstevel@tonic-gate rmsvc.in.cnum = req->in.cnum; 1995*1137Sarutz debug(5, "client_servproc[%d]: req = %s\n", pthread_self(), 1996*1137Sarutz xlate_cnum(req->in.cnum)); 19970Sstevel@tonic-gate 19980Sstevel@tonic-gate /* 19990Sstevel@tonic-gate * Our caller may have passed more descriptors than we expected. 20000Sstevel@tonic-gate * If so, we silently close (and ignore) them. 20010Sstevel@tonic-gate */ 2002*1137Sarutz nexpected_desc = (req->in.cnum == SMEDIA_CNUM_SET_SHFD) ? 1 : 0; 2003*1137Sarutz if (ndesc > nexpected_desc) { 2004*1137Sarutz close_door_descs(dp + nexpected_desc, ndesc - nexpected_desc); 2005*1137Sarutz } 20060Sstevel@tonic-gate 20070Sstevel@tonic-gate switch (req->in.cnum) { 20080Sstevel@tonic-gate default: 2009*1137Sarutz debug(5, "client_servproc: unknown command %d\n", req->in.cnum); 20100Sstevel@tonic-gate door_ret_err(&reterror, ENOTSUP); 20110Sstevel@tonic-gate break; 20120Sstevel@tonic-gate 2013*1137Sarutz case SMEDIA_CNUM_SET_SHFD: 20140Sstevel@tonic-gate if (ndesc == 0) 20150Sstevel@tonic-gate door_ret_err(&reterror, EINVAL); 20160Sstevel@tonic-gate /* 2017*1137Sarutz * Allocate shared memory for this connection. 2018*1137Sarutz * If this connection already has shared memory, 2019*1137Sarutz * deallocate before doing the allocation. 20200Sstevel@tonic-gate */ 2021*1137Sarutz ret_val = set_shfd(door_dp, dp->d_data.d_desc.d_descriptor, 2022*1137Sarutz req); 20230Sstevel@tonic-gate if (ret_val == 0) { 20240Sstevel@tonic-gate reterror.cnum = SMEDIA_CNUM_SET_SHFD; 20250Sstevel@tonic-gate reterror.errnum = 0; 2026*1137Sarutz 20270Sstevel@tonic-gate my_door_return((char *)&reterror, 20280Sstevel@tonic-gate sizeof (smedia_reterror_t), 0, 0); 20290Sstevel@tonic-gate } else { 20300Sstevel@tonic-gate (void) close(dp->d_data.d_desc.d_descriptor); 2031*1137Sarutz door_ret_err(&reterror, ret_val); 20320Sstevel@tonic-gate } 20330Sstevel@tonic-gate break; 20340Sstevel@tonic-gate 2035*1137Sarutz case SMEDIA_CNUM_RAW_READ: 20360Sstevel@tonic-gate debug(10, " arg size = %d blk num=0x%x nbytes = 0x%x \n", 20370Sstevel@tonic-gate (int)arg_size, 20380Sstevel@tonic-gate (uint32_t)req->reqraw_read.blockno, 20390Sstevel@tonic-gate req->reqraw_read.nbytes); 20400Sstevel@tonic-gate retbuf_size = sizeof (smedia_retraw_read_t); 20410Sstevel@tonic-gate if (req->reqraw_read.nbytes == 0) { 20420Sstevel@tonic-gate /* Nothing to write */ 20430Sstevel@tonic-gate rmsvc.retraw_write.nbytes = 0; 20440Sstevel@tonic-gate my_door_return((char *)&rmsvc, 20450Sstevel@tonic-gate sizeof (smedia_retraw_write_t), 0, 0); 20460Sstevel@tonic-gate } 20470Sstevel@tonic-gate retraw_read.cnum = SMEDIA_CNUM_RAW_READ; 20480Sstevel@tonic-gate ret_val = raw_read(door_dp, req); 20490Sstevel@tonic-gate if (ret_val == -1) { 20500Sstevel@tonic-gate door_ret_err(&reterror, errno); 20510Sstevel@tonic-gate } 20520Sstevel@tonic-gate retraw_read.nbytes = ret_val; 20530Sstevel@tonic-gate my_door_return((char *)&retraw_read, retbuf_size, 0, 0); 20540Sstevel@tonic-gate break; 20550Sstevel@tonic-gate 20560Sstevel@tonic-gate case SMEDIA_CNUM_USCSI_CMD: 20570Sstevel@tonic-gate retbuf_size = sizeof (smedia_retuscsi_cmd_t); 20580Sstevel@tonic-gate rmsvc.retuscsi_cmd.cnum = SMEDIA_CNUM_USCSI_CMD; 20590Sstevel@tonic-gate ucmd.uscsi_flags = req->requscsi_cmd.uscsi_flags; 20600Sstevel@tonic-gate ucmd.uscsi_cdb = (caddr_t)&req->requscsi_cmd.uscsi_cdb; 20610Sstevel@tonic-gate ucmd.uscsi_cdblen = req->requscsi_cmd.uscsi_cdblen; 20620Sstevel@tonic-gate ucmd.uscsi_bufaddr = (caddr_t)door_dp->dd_buf; 20630Sstevel@tonic-gate ucmd.uscsi_buflen = req->requscsi_cmd.uscsi_buflen; 20640Sstevel@tonic-gate ucmd.uscsi_timeout = req->requscsi_cmd.uscsi_timeout; 20650Sstevel@tonic-gate ucmd.uscsi_rqlen = req->requscsi_cmd.uscsi_rqlen; 20660Sstevel@tonic-gate ucmd.uscsi_rqbuf = (caddr_t)&rmsvc.retuscsi_cmd.uscsi_rqbuf; 2067*1137Sarutz debug(5, "USCSI CMD 0x%x requested.\n", 20680Sstevel@tonic-gate req->requscsi_cmd.uscsi_cdb[0]); 20690Sstevel@tonic-gate /* 20700Sstevel@tonic-gate * Check the device type and invalid flags specified. 20710Sstevel@tonic-gate * We permit operations only on CDROM devices types. 20720Sstevel@tonic-gate */ 2073*1137Sarutz errno = invalid_uscsi_operation(door_dp, &ucmd); 20740Sstevel@tonic-gate if (errno) { 20750Sstevel@tonic-gate door_ret_err(&reterror, errno); 20760Sstevel@tonic-gate } 20770Sstevel@tonic-gate 20780Sstevel@tonic-gate if ((req->requscsi_cmd.uscsi_buflen) && 20790Sstevel@tonic-gate ((req->requscsi_cmd.uscsi_buflen > door_dp->dd_buf_len) || 20800Sstevel@tonic-gate (door_dp->dd_buf == NULL))) { 2081*1137Sarutz debug(5, "uscsi_cmd failed: uscsi_buflen=0x%x " 2082*1137Sarutz "dd_buf_len=0x%x dd_buf=0x%p\n", 2083*1137Sarutz req->requscsi_cmd.uscsi_buflen, 2084*1137Sarutz door_dp->dd_buf_len, 2085*1137Sarutz door_dp->dd_buf); 20860Sstevel@tonic-gate errno = EINVAL; 20870Sstevel@tonic-gate door_ret_err(&reterror, errno); 20880Sstevel@tonic-gate } 20890Sstevel@tonic-gate ret_val = do_uscsi_cmd(door_dp->dd_fd, 20900Sstevel@tonic-gate &ucmd, req->requscsi_cmd.uscsi_flags); 20910Sstevel@tonic-gate rmsvc.retuscsi_cmd.uscsi_status = ucmd.uscsi_status; 20920Sstevel@tonic-gate rmsvc.retuscsi_cmd.uscsi_resid = ucmd.uscsi_resid; 20930Sstevel@tonic-gate rmsvc.retuscsi_cmd.uscsi_rqstatus = ucmd.uscsi_rqstatus; 20940Sstevel@tonic-gate rmsvc.retuscsi_cmd.uscsi_rqresid = ucmd.uscsi_rqresid; 20950Sstevel@tonic-gate rmsvc.retuscsi_cmd.uscsi_retval = ret_val; 20960Sstevel@tonic-gate rmsvc.retuscsi_cmd.uscsi_errno = errno; 20970Sstevel@tonic-gate if (ret_val || ucmd.uscsi_status) { 20980Sstevel@tonic-gate debug(5, "uscsi_cmd failed: %d - %d errno = %d\n", 20990Sstevel@tonic-gate ret_val, ucmd.uscsi_status, errno); 21000Sstevel@tonic-gate } 21010Sstevel@tonic-gate my_door_return((char *)&rmsvc, retbuf_size, 0, 0); 21020Sstevel@tonic-gate break; 21030Sstevel@tonic-gate 21040Sstevel@tonic-gate case SMEDIA_CNUM_RAW_WRITE: 21050Sstevel@tonic-gate if (req->reqraw_write.nbytes == 0) { 21060Sstevel@tonic-gate /* Nothing to write */ 21070Sstevel@tonic-gate rmsvc.retraw_write.nbytes = 0; 21080Sstevel@tonic-gate my_door_return((char *)&rmsvc, 21090Sstevel@tonic-gate sizeof (smedia_retraw_write_t), 0, 0); 21100Sstevel@tonic-gate } 21110Sstevel@tonic-gate ret_val = raw_write(door_dp, req); 21120Sstevel@tonic-gate if (ret_val == -1) 21130Sstevel@tonic-gate door_ret_err(&reterror, errno); 21140Sstevel@tonic-gate rmsvc.retraw_write.nbytes = ret_val; 21150Sstevel@tonic-gate my_door_return((char *)&rmsvc, sizeof (smedia_retraw_write_t), 21160Sstevel@tonic-gate 0, 0); 21170Sstevel@tonic-gate break; 21180Sstevel@tonic-gate 21190Sstevel@tonic-gate case SMEDIA_CNUM_GET_DEVICE_INFO: 21200Sstevel@tonic-gate 21210Sstevel@tonic-gate (void) memset((void *) &inq, 0, sizeof (inq)); 21220Sstevel@tonic-gate (void) memset((void *) &ucmd, 0, sizeof (ucmd)); 21230Sstevel@tonic-gate (void) memset((void *) &cdb, 0, sizeof (union scsi_cdb)); 21240Sstevel@tonic-gate cdb.scc_cmd = SCMD_INQUIRY; 21250Sstevel@tonic-gate FORMG0COUNT(&cdb, sizeof (inq)); 21260Sstevel@tonic-gate ucmd.uscsi_cdb = (caddr_t)&cdb; 21270Sstevel@tonic-gate ucmd.uscsi_cdblen = CDB_GROUP0; 21280Sstevel@tonic-gate ucmd.uscsi_bufaddr = (caddr_t)&inq; 21290Sstevel@tonic-gate ucmd.uscsi_buflen = sizeof (inq); 21300Sstevel@tonic-gate ucmd.uscsi_timeout = 120; /* If 0, HBA hangs forever */ 21310Sstevel@tonic-gate ucmd.uscsi_rqlen = RQ_LEN; 21320Sstevel@tonic-gate ucmd.uscsi_rqbuf = rq_data; 21330Sstevel@tonic-gate ret_val = do_uscsi_cmd(door_dp->dd_fd, 21340Sstevel@tonic-gate &ucmd, USCSI_READ|USCSI_RQENABLE); 21350Sstevel@tonic-gate if (ret_val || ucmd.uscsi_status) { 21360Sstevel@tonic-gate debug(5, "inquiry failed: %d - %d errno = %d\n", 21370Sstevel@tonic-gate ret_val, ucmd.uscsi_status, errno); 21380Sstevel@tonic-gate door_ret_err(&reterror, errno); 21390Sstevel@tonic-gate } 21400Sstevel@tonic-gate 21410Sstevel@tonic-gate debug(5, "%s\n", inq.inq_vid); 21420Sstevel@tonic-gate debug(5, "%s\n", rmsvc.retget_device_info.sm_vendor_name); 21430Sstevel@tonic-gate 21440Sstevel@tonic-gate (void) strlcpy(rmsvc.retget_device_info.sm_vendor_name, 21450Sstevel@tonic-gate inq.inq_vid, 8); 21460Sstevel@tonic-gate rmsvc.retget_device_info.sm_vendor_name[8] = 0; 21470Sstevel@tonic-gate (void) strlcpy(rmsvc.retget_device_info.sm_product_name, 21480Sstevel@tonic-gate inq.inq_pid, 16); 21490Sstevel@tonic-gate rmsvc.retget_device_info.sm_product_name[16] = 0; 21500Sstevel@tonic-gate (void) strlcpy(rmsvc.retget_device_info.sm_firmware_version, 21510Sstevel@tonic-gate inq.inq_revision, 4); 21520Sstevel@tonic-gate rmsvc.retget_device_info.sm_firmware_version[4] = ' '; 21530Sstevel@tonic-gate (void) strlcpy( 21540Sstevel@tonic-gate &rmsvc.retget_device_info.sm_firmware_version[5], 21550Sstevel@tonic-gate inq.inq_serial, 12); 21560Sstevel@tonic-gate rmsvc.retget_device_info.sm_product_name[17] = 0; 21570Sstevel@tonic-gate 21580Sstevel@tonic-gate rmsvc.retget_device_info.sm_interface_type = IF_SCSI; 21590Sstevel@tonic-gate 2160*1137Sarutz debug(5, "Vendor name = %s\n", 2161*1137Sarutz rmsvc.retget_device_info.sm_vendor_name); 2162*1137Sarutz debug(5, "product name = %s\n", 2163*1137Sarutz rmsvc.retget_device_info.sm_product_name); 2164*1137Sarutz debug(5, "Firmware revision = %s\n", 2165*1137Sarutz rmsvc.retget_device_info.sm_firmware_version); 2166*1137Sarutz 21670Sstevel@tonic-gate my_door_return((char *)&rmsvc.retget_device_info, 21680Sstevel@tonic-gate sizeof (smedia_retget_device_info_t), 0, 0); 21690Sstevel@tonic-gate break; 21700Sstevel@tonic-gate 21710Sstevel@tonic-gate case SMEDIA_CNUM_GET_MEDIUM_PROPERTY: 21720Sstevel@tonic-gate 21730Sstevel@tonic-gate (void) memset((void *)&rmsvc.retget_medium_property.smprop, 21740Sstevel@tonic-gate 0, sizeof (smmedium_prop_t)); 21750Sstevel@tonic-gate 21760Sstevel@tonic-gate ret_val = ioctl(door_dp->dd_fd, DKIOCGMEDIAINFO, &media_info); 21770Sstevel@tonic-gate 21780Sstevel@tonic-gate if (ret_val < 0) { 21790Sstevel@tonic-gate uint32_t capacity; 21800Sstevel@tonic-gate uint32_t blocksize; 21810Sstevel@tonic-gate /* 21820Sstevel@tonic-gate * Devices may fail DKIOCGMEDIAINFO if an unformed 21830Sstevel@tonic-gate * media is inserted. We can get the capacity 21840Sstevel@tonic-gate * information from the SCMD_READ_FORMAT_CAP command. 21850Sstevel@tonic-gate */ 21860Sstevel@tonic-gate 2187*1137Sarutz debug(5, "DKIOCGMEDIAINFO failed; using " 2188*1137Sarutz "SCMD_READ_FORMAT_CAP"); 21890Sstevel@tonic-gate ret_val = get_media_capacity(door_dp->dd_fd, 21900Sstevel@tonic-gate &capacity, &blocksize); 21910Sstevel@tonic-gate 21920Sstevel@tonic-gate if (ret_val >= 0) { 21930Sstevel@tonic-gate media_info.dki_lbsize = blocksize; 21940Sstevel@tonic-gate media_info.dki_capacity = capacity; 21950Sstevel@tonic-gate } else { 21960Sstevel@tonic-gate debug(5, "SCMD_READ_FORMAT_CAP failed"); 21970Sstevel@tonic-gate door_ret_err(&reterror, errno); 21980Sstevel@tonic-gate } 21990Sstevel@tonic-gate } 22000Sstevel@tonic-gate rmsvc.retget_medium_property.smprop.sm_blocksize = 22010Sstevel@tonic-gate media_info.dki_lbsize; 22020Sstevel@tonic-gate rmsvc.retget_medium_property.smprop.sm_capacity = 22030Sstevel@tonic-gate media_info.dki_capacity; 22040Sstevel@tonic-gate 22050Sstevel@tonic-gate rmsvc.retget_medium_property.smprop.sm_media_type = 22060Sstevel@tonic-gate media_info.dki_media_type; 22070Sstevel@tonic-gate /* 22080Sstevel@tonic-gate * These devices show as SCSI devices but we need to treat it 22090Sstevel@tonic-gate * differently. so we need a seperate class. 22100Sstevel@tonic-gate */ 22110Sstevel@tonic-gate if (get_device_type_scsi(door_dp->dd_fd, &inq) == SCSI_FLOPPY) { 22120Sstevel@tonic-gate rmsvc.retget_medium_property.smprop.sm_media_type = 22130Sstevel@tonic-gate SM_SCSI_FLOPPY; 22140Sstevel@tonic-gate } 22150Sstevel@tonic-gate 22160Sstevel@tonic-gate /* Check for EFI type because DKIOCGGEOM does not support EFI */ 22170Sstevel@tonic-gate ret_val = ioctl(door_dp->dd_fd, DKIOCGVTOC, &vtoc); 22180Sstevel@tonic-gate if (!((ret_val < 0) && (errno == ENOTSUP))) { 22190Sstevel@tonic-gate ret_val = ioctl(door_dp->dd_fd, DKIOCGGEOM, &dkgeom); 22200Sstevel@tonic-gate if (ret_val < 0) { 22210Sstevel@tonic-gate /* 22220Sstevel@tonic-gate * DKIOCGGEOM may fail for unformed floppies. 22230Sstevel@tonic-gate * We need to generate the appropriate geometry 22240Sstevel@tonic-gate * information. 22250Sstevel@tonic-gate */ 22260Sstevel@tonic-gate if (rmsvc.retget_medium_property.smprop. 22270Sstevel@tonic-gate sm_media_type == SM_SCSI_FLOPPY) { 22280Sstevel@tonic-gate ret_val = get_floppy_geom( 22290Sstevel@tonic-gate door_dp->dd_fd, 22300Sstevel@tonic-gate media_info.dki_capacity, &dkgeom); 22310Sstevel@tonic-gate 22320Sstevel@tonic-gate if (ret_val < 0) { 22330Sstevel@tonic-gate debug(5, "Cannot determine " 22340Sstevel@tonic-gate "media size"); 22350Sstevel@tonic-gate door_ret_err(&reterror, errno); 22360Sstevel@tonic-gate } 22370Sstevel@tonic-gate } else { 22380Sstevel@tonic-gate #ifdef sparc 22390Sstevel@tonic-gate debug(5, "DKIOCGGEOM ioctl failed"); 22400Sstevel@tonic-gate door_ret_err(&reterror, errno); 22410Sstevel@tonic-gate #else /* !sparc */ 22420Sstevel@tonic-gate /* 22430Sstevel@tonic-gate * Try getting Physical geometry on x86. 22440Sstevel@tonic-gate */ 22450Sstevel@tonic-gate ret_val = ioctl(door_dp->dd_fd, 22460Sstevel@tonic-gate DKIOCG_PHYGEOM, &dkgeom); 22470Sstevel@tonic-gate if (ret_val < 0) { 22480Sstevel@tonic-gate debug(5, "DKIOCG_PHYGEOM " 22490Sstevel@tonic-gate "ioctl failed"); 22500Sstevel@tonic-gate door_ret_err(&reterror, errno); 22510Sstevel@tonic-gate } 22520Sstevel@tonic-gate #endif /* sparc */ 22530Sstevel@tonic-gate } 22540Sstevel@tonic-gate } 22550Sstevel@tonic-gate 22560Sstevel@tonic-gate 22570Sstevel@tonic-gate /* 22580Sstevel@tonic-gate * Some faked geometry may not have pcyl filled in so 22590Sstevel@tonic-gate * later calculations using this field will be 22600Sstevel@tonic-gate * incorrect. We will substitute it with the number of 22610Sstevel@tonic-gate * available cylinders. 22620Sstevel@tonic-gate */ 22630Sstevel@tonic-gate if (dkgeom.dkg_pcyl == 0) 22640Sstevel@tonic-gate rmsvc.retget_medium_property.smprop.sm_pcyl = 22650Sstevel@tonic-gate dkgeom.dkg_ncyl; 22660Sstevel@tonic-gate else 22670Sstevel@tonic-gate rmsvc.retget_medium_property.smprop.sm_pcyl = 22680Sstevel@tonic-gate dkgeom.dkg_pcyl; 22690Sstevel@tonic-gate 22700Sstevel@tonic-gate rmsvc.retget_medium_property.smprop.sm_nhead = 22710Sstevel@tonic-gate dkgeom.dkg_nhead; 22720Sstevel@tonic-gate rmsvc.retget_medium_property.smprop.sm_nsect = 22730Sstevel@tonic-gate dkgeom.dkg_nsect; 22740Sstevel@tonic-gate } 22750Sstevel@tonic-gate 22760Sstevel@tonic-gate debug(1, "properties are: lbasize = %d, cap = %llu", 22770Sstevel@tonic-gate media_info.dki_lbsize, media_info.dki_capacity); 22780Sstevel@tonic-gate 22790Sstevel@tonic-gate my_door_return((char *)&rmsvc.retget_medium_property, 22800Sstevel@tonic-gate sizeof (smedia_retget_medium_property_t), 0, 0); 22810Sstevel@tonic-gate break; 22820Sstevel@tonic-gate 22830Sstevel@tonic-gate case SMEDIA_CNUM_GET_PROTECTION_STATUS: 22840Sstevel@tonic-gate switch (get_device_type_scsi(door_dp->dd_fd, &inq)) { 22850Sstevel@tonic-gate case SCSI_FLOPPY: 22860Sstevel@tonic-gate status = scsi_floppy_media_status(door_dp->dd_fd); 22870Sstevel@tonic-gate break; 22880Sstevel@tonic-gate case SCSI_IOMEGA: 22890Sstevel@tonic-gate status = scsi_zip_media_status(door_dp->dd_fd); 22900Sstevel@tonic-gate break; 22910Sstevel@tonic-gate case SCSI_GENERIC: 22920Sstevel@tonic-gate status = scsi_media_status(door_dp->dd_fd); 22930Sstevel@tonic-gate break; 22940Sstevel@tonic-gate default: 22950Sstevel@tonic-gate door_ret_err(&reterror, errno); 22960Sstevel@tonic-gate } 22970Sstevel@tonic-gate if (status < 0) 22980Sstevel@tonic-gate door_ret_err(&reterror, errno); 22990Sstevel@tonic-gate 23000Sstevel@tonic-gate rmsvc.retget_protection_status.prot_state.sm_new_state = 23010Sstevel@tonic-gate status; 23020Sstevel@tonic-gate 23030Sstevel@tonic-gate my_door_return((char *)&rmsvc.retget_protection_status, 23040Sstevel@tonic-gate sizeof (smedia_retget_protection_status_t), 0, 0); 23050Sstevel@tonic-gate break; 23060Sstevel@tonic-gate 23070Sstevel@tonic-gate case SMEDIA_CNUM_SET_PROTECTION_STATUS: 23080Sstevel@tonic-gate 23090Sstevel@tonic-gate ret_val = set_protection_status(door_dp, req); 23100Sstevel@tonic-gate if (ret_val == -1) 23110Sstevel@tonic-gate door_ret_err(&reterror, errno); 23120Sstevel@tonic-gate else 23130Sstevel@tonic-gate my_door_return((char *)&rmsvc.retset_protection_status, 23140Sstevel@tonic-gate sizeof (smedia_retset_protection_status_t), 23150Sstevel@tonic-gate 0, 0); 23160Sstevel@tonic-gate break; 23170Sstevel@tonic-gate 23180Sstevel@tonic-gate case SMEDIA_CNUM_FORMAT: 23190Sstevel@tonic-gate switch (get_device_type_scsi(door_dp->dd_fd, &inq)) { 23200Sstevel@tonic-gate case SCSI_FLOPPY: 23210Sstevel@tonic-gate info("formatting floppy"); 23220Sstevel@tonic-gate err = scsi_floppy_format(door_dp->dd_fd, 23230Sstevel@tonic-gate req->reqformat.flavor, req->reqformat.mode); 23240Sstevel@tonic-gate 23250Sstevel@tonic-gate break; 23260Sstevel@tonic-gate case SCSI_IOMEGA: 23270Sstevel@tonic-gate err = scsi_zip_format(door_dp->dd_fd, 23280Sstevel@tonic-gate req->reqformat.flavor, req->reqformat.mode); 23290Sstevel@tonic-gate break; 23300Sstevel@tonic-gate case SCSI_GENERIC: 23310Sstevel@tonic-gate err = scsi_format(door_dp->dd_fd, 23320Sstevel@tonic-gate req->reqformat.flavor, req->reqformat.mode); 23330Sstevel@tonic-gate break; 23340Sstevel@tonic-gate default: 23350Sstevel@tonic-gate door_ret_err(&reterror, ENOTSUP); 23360Sstevel@tonic-gate } 23370Sstevel@tonic-gate 23380Sstevel@tonic-gate if (err) 23390Sstevel@tonic-gate door_ret_err(&reterror, errno); 23400Sstevel@tonic-gate my_door_return((char *)&rmsvc.retformat, 23410Sstevel@tonic-gate sizeof (smedia_retformat_t), 0, 0); 23420Sstevel@tonic-gate 23430Sstevel@tonic-gate break; 23440Sstevel@tonic-gate 23450Sstevel@tonic-gate case SMEDIA_CNUM_CHECK_FORMAT_STATUS: 23460Sstevel@tonic-gate 23470Sstevel@tonic-gate (void) memset((void *) &cdb, 0, sizeof (union scsi_cdb)); 23480Sstevel@tonic-gate (void) memset((void *) &ucmd, 0, sizeof (ucmd)); 23490Sstevel@tonic-gate (void) memset((void *) &data, 0, sizeof (data)); 23500Sstevel@tonic-gate cdb.scc_cmd = SCMD_REQUEST_SENSE; 23510Sstevel@tonic-gate cdb.g0_count0 = sizeof (data); 23520Sstevel@tonic-gate ucmd.uscsi_cdb = (caddr_t)&cdb; 23530Sstevel@tonic-gate ucmd.uscsi_cdblen = CDB_GROUP0; 23540Sstevel@tonic-gate ucmd.uscsi_bufaddr = (caddr_t)&data; 23550Sstevel@tonic-gate ucmd.uscsi_buflen = sizeof (data); 23560Sstevel@tonic-gate ucmd.uscsi_timeout = 120; /* If 0, HBA hangs forever */ 23570Sstevel@tonic-gate ucmd.uscsi_rqlen = RQ_LEN; 23580Sstevel@tonic-gate ucmd.uscsi_rqbuf = rq_data; 23590Sstevel@tonic-gate ret_val = do_uscsi_cmd(door_dp->dd_fd, 23600Sstevel@tonic-gate &ucmd, USCSI_READ|USCSI_RQENABLE); 23610Sstevel@tonic-gate if (ret_val || ucmd.uscsi_status) { 23620Sstevel@tonic-gate debug(5, "Request sense failed: %d - %d errno = %d\n", 23630Sstevel@tonic-gate ret_val, ucmd.uscsi_status, errno); 23640Sstevel@tonic-gate door_ret_err(&reterror, errno); 23650Sstevel@tonic-gate } 23660Sstevel@tonic-gate 23670Sstevel@tonic-gate if ((data[0] & 0x7F) == DEFERRED_ERROR) { 23680Sstevel@tonic-gate /* Deffered error. The format must have failed */ 23690Sstevel@tonic-gate debug(5, "format failed!\n"); 23700Sstevel@tonic-gate door_ret_err(&reterror, EIO); 23710Sstevel@tonic-gate } 23720Sstevel@tonic-gate 23730Sstevel@tonic-gate if (data[SKSV_OFFSET] & SKSV_FIELD) { 23740Sstevel@tonic-gate completed = 23750Sstevel@tonic-gate (data[FORMAT_PROGRESS_INDICATOR_OFFSET_0] << 8) 23760Sstevel@tonic-gate | data[FORMAT_PROGRESS_INDICATOR_OFFSET_1]; 23770Sstevel@tonic-gate completed = (completed*100/65536); 23780Sstevel@tonic-gate } else { 23790Sstevel@tonic-gate completed = (100); 23800Sstevel@tonic-gate } 23810Sstevel@tonic-gate rmsvc.retcheck_format_status.percent_complete = completed; 23820Sstevel@tonic-gate my_door_return((char *)&rmsvc.retcheck_format_status, 23830Sstevel@tonic-gate sizeof (smedia_retcheck_format_status_t), 0, 0); 23840Sstevel@tonic-gate break; 23850Sstevel@tonic-gate 23860Sstevel@tonic-gate case SMEDIA_CNUM_REASSIGN_BLOCK: 23870Sstevel@tonic-gate 23880Sstevel@tonic-gate ret_val = reassign_block(door_dp, req); 23890Sstevel@tonic-gate if (ret_val == -1) 23900Sstevel@tonic-gate door_ret_err(&reterror, errno); 23910Sstevel@tonic-gate my_door_return((char *)&rmsvc.retreassign_block, 23920Sstevel@tonic-gate sizeof (smedia_retreassign_block_t), 0, 0); 23930Sstevel@tonic-gate break; 23940Sstevel@tonic-gate 23950Sstevel@tonic-gate } /* end of switch */ 23960Sstevel@tonic-gate 23970Sstevel@tonic-gate debug(10, "Exiting client server...\n"); 23980Sstevel@tonic-gate my_door_return((char *)&reterror, sizeof (smedia_reterror_t), 0, 0); 23990Sstevel@tonic-gate } 24000Sstevel@tonic-gate 2401*1137Sarutz /* 2402*1137Sarutz * This is the service procedure for the door that is associated with 2403*1137Sarutz * the (doorfs) filesystem Door that is created at 'smedia_service'. 2404*1137Sarutz */ 24050Sstevel@tonic-gate /*ARGSUSED*/ 24060Sstevel@tonic-gate static void 2407*1137Sarutz main_servproc(void *server_data, char *argp, size_t arg_size, 24080Sstevel@tonic-gate door_desc_t *dp, uint_t ndesc) 24090Sstevel@tonic-gate { 24100Sstevel@tonic-gate smedia_services_t *req; 24110Sstevel@tonic-gate door_cred_t door_credentials; 24120Sstevel@tonic-gate int ret_val; 24130Sstevel@tonic-gate door_data_t *ddata; 24140Sstevel@tonic-gate smedia_reterror_t reterror; 24150Sstevel@tonic-gate smedia_reterror_t retok; 24160Sstevel@tonic-gate struct stat stat; 24170Sstevel@tonic-gate door_desc_t *didpp; 24180Sstevel@tonic-gate struct dk_cinfo dkinfo; 2419*1137Sarutz uint_t nexpected_desc; 2420*1137Sarutz 2421*1137Sarutz debug(10, "Entering main_servproc[%d].\n", pthread_self()); 24220Sstevel@tonic-gate 24230Sstevel@tonic-gate didpp = dp; 24240Sstevel@tonic-gate (void) mutex_lock(&svcstate_lock); 24250Sstevel@tonic-gate svcstate = _SERVED; 24260Sstevel@tonic-gate (void) mutex_unlock(&svcstate_lock); 24270Sstevel@tonic-gate 24280Sstevel@tonic-gate reterror.cnum = SMEDIA_CNUM_ERROR; 24290Sstevel@tonic-gate reterror.errnum = SMEDIA_FAILURE; 2430*1137Sarutz 24310Sstevel@tonic-gate if (argp == NULL) { 24320Sstevel@tonic-gate debug(5, "argp is NULL\n"); 24330Sstevel@tonic-gate if (ndesc > 0) 24340Sstevel@tonic-gate close_door_descs(dp, ndesc); 24350Sstevel@tonic-gate my_door_return((char *)&reterror, 24360Sstevel@tonic-gate sizeof (smedia_reterror_t), 0, 0); 24370Sstevel@tonic-gate } 24380Sstevel@tonic-gate 24390Sstevel@tonic-gate req = (smedia_services_t *)((void *)argp); 2440*1137Sarutz 24410Sstevel@tonic-gate retok.cnum = req->in.cnum; 24420Sstevel@tonic-gate retok.errnum = 0; 24430Sstevel@tonic-gate 24440Sstevel@tonic-gate debug(5, "req = %s arg_size = 0x%x \n", 2445*1137Sarutz xlate_cnum(req->reqopen.cnum), arg_size); 24460Sstevel@tonic-gate 24470Sstevel@tonic-gate /* 24480Sstevel@tonic-gate * Our caller may have passed more descriptors than we expected. 24490Sstevel@tonic-gate * If so, we silently close (and ignore) them. 24500Sstevel@tonic-gate */ 2451*1137Sarutz nexpected_desc = (req->in.cnum == SMEDIA_CNUM_OPEN_FD) ? 1 : 0; 2452*1137Sarutz if (ndesc > nexpected_desc) { 2453*1137Sarutz close_door_descs(dp + nexpected_desc, ndesc - nexpected_desc); 2454*1137Sarutz } 24550Sstevel@tonic-gate 24560Sstevel@tonic-gate switch (req->in.cnum) { 24570Sstevel@tonic-gate default: 2458*1137Sarutz debug(5, "main_servproc: unknown command 0x%x\n", 2459*1137Sarutz req->reqopen.cnum); 24600Sstevel@tonic-gate break; 24610Sstevel@tonic-gate 2462*1137Sarutz case SMEDIA_CNUM_PING: 24630Sstevel@tonic-gate /* 24640Sstevel@tonic-gate * This service is to indicate that server is up and 24650Sstevel@tonic-gate * running. It is usually called from another instance of 24660Sstevel@tonic-gate * server that is started. 24670Sstevel@tonic-gate */ 24680Sstevel@tonic-gate reterror.cnum = SMEDIA_CNUM_PING; 24690Sstevel@tonic-gate reterror.errnum = 0; 24700Sstevel@tonic-gate my_door_return((char *)&reterror, 2471*1137Sarutz sizeof (smedia_reterror_t), 0, 0); 24720Sstevel@tonic-gate break; 24730Sstevel@tonic-gate 24740Sstevel@tonic-gate 2475*1137Sarutz case SMEDIA_CNUM_OPEN_FD: 24760Sstevel@tonic-gate 24770Sstevel@tonic-gate debug(5, "ndesc = %d\n", ndesc); 24780Sstevel@tonic-gate if (ndesc == 0) { 24790Sstevel@tonic-gate my_door_return((char *)&reterror, 2480*1137Sarutz sizeof (smedia_reterror_t), 0, 0); 24810Sstevel@tonic-gate } 2482*1137Sarutz debug(5, "Checking file descriptor of target device\n"); 24830Sstevel@tonic-gate if (fstat(didpp->d_data.d_desc.d_descriptor, &stat) < 0) { 2484*1137Sarutz warning(gettext("main_servproc:fstat failed. " 2485*1137Sarutz "errno = %d\n"), errno); 24860Sstevel@tonic-gate (void) close(didpp->d_data.d_desc.d_descriptor); 24870Sstevel@tonic-gate my_door_return((char *)&reterror, 2488*1137Sarutz sizeof (smedia_reterror_t), 0, 0); 24890Sstevel@tonic-gate } 24900Sstevel@tonic-gate debug(5, "descriptor = %d st_mode = 0x%lx\n", 2491*1137Sarutz didpp->d_data.d_desc.d_descriptor, 2492*1137Sarutz stat.st_mode); 24930Sstevel@tonic-gate 24940Sstevel@tonic-gate /* Obtain the credentials of the user */ 24950Sstevel@tonic-gate ret_val = door_cred(&door_credentials); 24960Sstevel@tonic-gate if (ret_val < 0) { 2497*1137Sarutz warning(gettext("main_servproc:door_cred " 2498*1137Sarutz "failed. errno = %d\n"), errno); 24990Sstevel@tonic-gate (void) close(didpp->d_data.d_desc.d_descriptor); 25000Sstevel@tonic-gate my_door_return((char *)&reterror, 2501*1137Sarutz sizeof (smedia_reterror_t), 0, 0); 25020Sstevel@tonic-gate } 25030Sstevel@tonic-gate if (ioctl(didpp->d_data.d_desc.d_descriptor, DKIOCINFO, 25040Sstevel@tonic-gate &dkinfo) == -1) { 2505*1137Sarutz warning(gettext("main_servproc:DKIOCINFO failed. " 2506*1137Sarutz "errno = %d\n"), errno); 25070Sstevel@tonic-gate (void) close(didpp->d_data.d_desc.d_descriptor); 25080Sstevel@tonic-gate my_door_return((char *)&reterror, 2509*1137Sarutz sizeof (smedia_reterror_t), 0, 0); 25100Sstevel@tonic-gate } 25110Sstevel@tonic-gate 25120Sstevel@tonic-gate ddata = (door_data_t *)calloc(1, sizeof (door_data_t)); 25130Sstevel@tonic-gate if (ddata == NULL) { 2514*1137Sarutz warning(gettext("main_servproc:calloc failed. " 2515*1137Sarutz "errno = %d\n"), errno); 25160Sstevel@tonic-gate (void) close(didpp->d_data.d_desc.d_descriptor); 25170Sstevel@tonic-gate my_door_return((char *)&reterror, 2518*1137Sarutz sizeof (smedia_reterror_t), 0, 0); 25190Sstevel@tonic-gate } 25200Sstevel@tonic-gate ddata->dd_stat = stat; 25210Sstevel@tonic-gate ddata->dd_cred = door_credentials; 25220Sstevel@tonic-gate ddata->dd_fd = didpp->d_data.d_desc.d_descriptor; 25230Sstevel@tonic-gate ddata->dd_buf = NULL; 25240Sstevel@tonic-gate ddata->dd_buf_len = 0; 25250Sstevel@tonic-gate ddata->dd_buffd = -1; 25260Sstevel@tonic-gate ddata->dd_sector_size = 0; 25270Sstevel@tonic-gate ddata->dd_dkinfo = dkinfo; 2528*1137Sarutz debug(5, "ddata = 0x%p \n", (void *)ddata); 2529*1137Sarutz 2530*1137Sarutz /* specify a function that'll customize our door threads */ 2531*1137Sarutz (void) door_server_create(sm_door_server_create); 25320Sstevel@tonic-gate debug(5, "door_server_create called.\n"); 25330Sstevel@tonic-gate 25340Sstevel@tonic-gate (void) mutex_lock(&ddata->dd_lock); 25350Sstevel@tonic-gate 2536*1137Sarutz /* create Client Door */ 2537*1137Sarutz ddata->dd_cdoor_descriptor = 2538*1137Sarutz door_create(client_servproc, 2539*1137Sarutz (void *)ddata, DOOR_PRIVATE | DOOR_NO_CANCEL | DOOR_UNREF); 2540*1137Sarutz 2541*1137Sarutz if (ddata->dd_cdoor_descriptor < 0) { 2542*1137Sarutz /* then door_create() failed */ 2543*1137Sarutz int err = errno; 2544*1137Sarutz 2545*1137Sarutz (void) mutex_unlock(&ddata->dd_lock); 2546*1137Sarutz 2547*1137Sarutz warning(gettext("main_servproc: door_create of Client " 2548*1137Sarutz "Door failed = %d\n"), err); 25490Sstevel@tonic-gate free(ddata); 2550*1137Sarutz 2551*1137Sarutz /* close target device */ 25520Sstevel@tonic-gate (void) close(didpp->d_data.d_desc.d_descriptor); 2553*1137Sarutz my_door_return((char *)&reterror, 2554*1137Sarutz sizeof (smedia_reterror_t), 0, 0); 25550Sstevel@tonic-gate } 2556*1137Sarutz 2557*1137Sarutz /* create Death Door */ 2558*1137Sarutz ddata->dd_ddoor_descriptor = 2559*1137Sarutz door_create(death_servproc, (void *)ddata, 2560*1137Sarutz DOOR_REFUSE_DESC | DOOR_NO_CANCEL); 2561*1137Sarutz if (ddata->dd_ddoor_descriptor < 0) { 2562*1137Sarutz warning(gettext("main_servproc: door_create of Death " 2563*1137Sarutz "Door failed = %d\n"), errno); 2564*1137Sarutz } else { 2565*1137Sarutz (void) door_setparam(ddata->dd_ddoor_descriptor, 2566*1137Sarutz DOOR_PARAM_DATA_MAX, 0); 25670Sstevel@tonic-gate } 2568*1137Sarutz 2569*1137Sarutz debug(5, "main_servproc[%d]: Client Door = %d, " 2570*1137Sarutz "Death Door = %d", pthread_self(), 2571*1137Sarutz ddata->dd_cdoor_descriptor, ddata->dd_ddoor_descriptor); 25720Sstevel@tonic-gate 25730Sstevel@tonic-gate audit_init(ddata); 25740Sstevel@tonic-gate 2575*1137Sarutz /* wait until sm_server_thread does door_bind() */ 25760Sstevel@tonic-gate (void) cond_wait(&ddata->dd_cv_bind, &ddata->dd_lock); 2577*1137Sarutz 25780Sstevel@tonic-gate (void) mutex_unlock(&ddata->dd_lock); 25790Sstevel@tonic-gate 25800Sstevel@tonic-gate (void) mutex_lock(&svcstate_lock); 25810Sstevel@tonic-gate svccount++; 25820Sstevel@tonic-gate (void) mutex_unlock(&svcstate_lock); 2583*1137Sarutz 2584*1137Sarutz if (ddata->dd_ddoor_descriptor < 0) { 2585*1137Sarutz /* Return only the Client Door to the client. */ 2586*1137Sarutz ddata->dd_cdoor.d_attributes = (DOOR_DESCRIPTOR); 2587*1137Sarutz my_door_return((char *)&reterror, 2588*1137Sarutz sizeof (smedia_reterror_t), &ddata->dd_desc[0], 1); 2589*1137Sarutz } else { 2590*1137Sarutz /* 2591*1137Sarutz * Return the Client Door and Death Door 2592*1137Sarutz * to the client. 2593*1137Sarutz */ 2594*1137Sarutz debug(5, "retok.cnum = 0x%x\n", retok.cnum); 2595*1137Sarutz ddata->dd_cdoor.d_attributes = (DOOR_DESCRIPTOR); 2596*1137Sarutz ddata->dd_ddoor.d_attributes = (DOOR_DESCRIPTOR); 2597*1137Sarutz my_door_return((char *)&retok, 2598*1137Sarutz sizeof (smedia_reterror_t), &ddata->dd_desc[0], 2); 2599*1137Sarutz } 26000Sstevel@tonic-gate break; 26010Sstevel@tonic-gate } 26020Sstevel@tonic-gate 2603*1137Sarutz debug(10, "exiting main_servproc. \n"); 26040Sstevel@tonic-gate my_door_return((char *)&reterror, sizeof (smedia_reterror_t), 0, 0); 26050Sstevel@tonic-gate } 26060Sstevel@tonic-gate 26070Sstevel@tonic-gate /* ARGSUSED */ 26080Sstevel@tonic-gate static void 26090Sstevel@tonic-gate term_handler(int sig, siginfo_t *siginfo, void *sigctx) 26100Sstevel@tonic-gate { 26110Sstevel@tonic-gate warning(gettext("thread[%d]: Received signal %d. Ignoring it.\n"), 2612*1137Sarutz pthread_self(), 2613*1137Sarutz sig); 26140Sstevel@tonic-gate } 26150Sstevel@tonic-gate 26160Sstevel@tonic-gate /* ARGSUSED */ 26170Sstevel@tonic-gate static void 26180Sstevel@tonic-gate hup_handler(int sig, siginfo_t *siginfo, void *sigctx) 26190Sstevel@tonic-gate { 26200Sstevel@tonic-gate warning(gettext("thread[%d]: Received signal %d. Ignoring it.\n"), 2621*1137Sarutz pthread_self(), 2622*1137Sarutz sig); 26230Sstevel@tonic-gate } 26240Sstevel@tonic-gate 26250Sstevel@tonic-gate /*ARGSUSED*/ 26260Sstevel@tonic-gate static void 26270Sstevel@tonic-gate sig_handler(int sig, siginfo_t *siginfo, void *sigctx) 26280Sstevel@tonic-gate { 26290Sstevel@tonic-gate warning(gettext("thread[%d]: Received signal %d. Ignoring it.\n"), 2630*1137Sarutz pthread_self(), 2631*1137Sarutz sig); 26320Sstevel@tonic-gate } 26330Sstevel@tonic-gate 26340Sstevel@tonic-gate /*ARGSUSED*/ 26350Sstevel@tonic-gate static void 26360Sstevel@tonic-gate badsig_handler(int sig, siginfo_t *siginfo, void *sigctx) 26370Sstevel@tonic-gate { 26380Sstevel@tonic-gate fatal(BADSIG_MSG, pthread_self(), sig, siginfo->si_addr, 2639*1137Sarutz siginfo->si_trapno, 2640*1137Sarutz siginfo->si_pc); 26410Sstevel@tonic-gate } 26420Sstevel@tonic-gate 26430Sstevel@tonic-gate /*ARGSUSED*/ 2644*1137Sarutz static void * 26450Sstevel@tonic-gate init_server(void *argp) 26460Sstevel@tonic-gate { 26470Sstevel@tonic-gate int i, fd; 26480Sstevel@tonic-gate struct sigaction act; 26490Sstevel@tonic-gate struct rlimit rlim; 26500Sstevel@tonic-gate 26510Sstevel@tonic-gate debug(10, "init_server running\n"); 26520Sstevel@tonic-gate 26530Sstevel@tonic-gate (void) setlocale(LC_ALL, ""); 26540Sstevel@tonic-gate #if !defined(TEXT_DOMAIN) 26550Sstevel@tonic-gate #define TEXT_DOMAIN "SYS_TEST" 26560Sstevel@tonic-gate #endif 26570Sstevel@tonic-gate (void) textdomain(TEXT_DOMAIN); 26580Sstevel@tonic-gate 26590Sstevel@tonic-gate 26600Sstevel@tonic-gate if (geteuid() != 0) fatal("Must be root to execute smserverd\n"); 26610Sstevel@tonic-gate 26620Sstevel@tonic-gate 26630Sstevel@tonic-gate /* 26640Sstevel@tonic-gate * setup signal handlers. 26650Sstevel@tonic-gate */ 26660Sstevel@tonic-gate 26670Sstevel@tonic-gate for (i = 0; i < N_BADSIGS; i++) { 26680Sstevel@tonic-gate act.sa_sigaction = badsig_handler; 26690Sstevel@tonic-gate (void) sigemptyset(&act.sa_mask); 26700Sstevel@tonic-gate act.sa_flags = SA_SIGINFO; 26710Sstevel@tonic-gate if (sigaction(badsigs[i], &act, NULL) == -1) 26720Sstevel@tonic-gate warning(gettext(SIGACT_FAILED), strsignal(badsigs[i]), 26730Sstevel@tonic-gate strerror(errno)); 26740Sstevel@tonic-gate } 26750Sstevel@tonic-gate 26760Sstevel@tonic-gate /* 26770Sstevel@tonic-gate * Ignore SIGHUP until all the initialization is done. 26780Sstevel@tonic-gate */ 26790Sstevel@tonic-gate act.sa_handler = SIG_IGN; 26800Sstevel@tonic-gate (void) sigemptyset(&act.sa_mask); 26810Sstevel@tonic-gate act.sa_flags = 0; 26820Sstevel@tonic-gate if (sigaction(SIGHUP, &act, NULL) == -1) 26830Sstevel@tonic-gate warning(gettext(SIGACT_FAILED), strsignal(SIGHUP), 26840Sstevel@tonic-gate strerror(errno)); 26850Sstevel@tonic-gate /* 26860Sstevel@tonic-gate * Increase file descriptor limit to the most it can possibly 26870Sstevel@tonic-gate * be. 26880Sstevel@tonic-gate */ 26890Sstevel@tonic-gate if (getrlimit(RLIMIT_NOFILE, &rlim) < 0) { 26900Sstevel@tonic-gate warning(gettext("getrlimit for fd's failed; %m\n")); 26910Sstevel@tonic-gate } 26920Sstevel@tonic-gate 26930Sstevel@tonic-gate rlim.rlim_cur = rlim.rlim_max; 26940Sstevel@tonic-gate 26950Sstevel@tonic-gate if (setrlimit(RLIMIT_NOFILE, &rlim) < 0) { 26960Sstevel@tonic-gate warning(gettext("setrlimit for fd's failed; %m\n")); 26970Sstevel@tonic-gate } 26980Sstevel@tonic-gate 2699*1137Sarutz server_door = door_create(main_servproc, (void *)&server_data, 0); 27000Sstevel@tonic-gate if (server_door == -1) { 27010Sstevel@tonic-gate debug(1, "main door_create"); 27020Sstevel@tonic-gate exit(1); 27030Sstevel@tonic-gate } 27040Sstevel@tonic-gate 27050Sstevel@tonic-gate (void) unlink(smedia_service); 27060Sstevel@tonic-gate fd = open(smedia_service, O_RDWR|O_CREAT|O_EXCL, 0644); 27070Sstevel@tonic-gate if (fd < 0) { 27080Sstevel@tonic-gate debug(5, "could not open %s.\n", smedia_service); 27090Sstevel@tonic-gate exit(1); 27100Sstevel@tonic-gate } 27110Sstevel@tonic-gate (void) close(fd); 27120Sstevel@tonic-gate server_fd = fattach(server_door, smedia_service); 27130Sstevel@tonic-gate if (server_fd == -1) { 27140Sstevel@tonic-gate debug(1, "main fattach"); 27150Sstevel@tonic-gate exit(1); 27160Sstevel@tonic-gate } 27170Sstevel@tonic-gate server_data.sd_door = server_door; 27180Sstevel@tonic-gate server_data.sd_fd = server_fd; 27190Sstevel@tonic-gate 27200Sstevel@tonic-gate /* 27210Sstevel@tonic-gate * setup signal handlers for post-init 27220Sstevel@tonic-gate */ 27230Sstevel@tonic-gate 27240Sstevel@tonic-gate act.sa_sigaction = hup_handler; 27250Sstevel@tonic-gate (void) sigemptyset(&act.sa_mask); 27260Sstevel@tonic-gate act.sa_flags = SA_SIGINFO; 27270Sstevel@tonic-gate if (sigaction(SIGHUP, &act, NULL) == -1) 27280Sstevel@tonic-gate warning(gettext(SIGACT_FAILED), strsignal(SIGHUP), 27290Sstevel@tonic-gate strerror(errno)); 27300Sstevel@tonic-gate 27310Sstevel@tonic-gate act.sa_sigaction = term_handler; 27320Sstevel@tonic-gate (void) sigemptyset(&act.sa_mask); 27330Sstevel@tonic-gate act.sa_flags = SA_SIGINFO; 27340Sstevel@tonic-gate if (sigaction(SIGTERM, &act, NULL) == -1) 27350Sstevel@tonic-gate warning(gettext(SIGACT_FAILED), strsignal(SIGTERM), 27360Sstevel@tonic-gate strerror(errno)); 27370Sstevel@tonic-gate 27380Sstevel@tonic-gate act.sa_sigaction = sig_handler; 27390Sstevel@tonic-gate (void) sigemptyset(&act.sa_mask); 27400Sstevel@tonic-gate act.sa_flags = SA_SIGINFO; 27410Sstevel@tonic-gate if (sigaction(SIGINT, &act, NULL) == -1) 27420Sstevel@tonic-gate warning(gettext(SIGACT_FAILED), strsignal(SIGHUP), 27430Sstevel@tonic-gate strerror(errno)); 27440Sstevel@tonic-gate 27450Sstevel@tonic-gate act.sa_sigaction = sig_handler; 27460Sstevel@tonic-gate (void) sigemptyset(&act.sa_mask); 27470Sstevel@tonic-gate act.sa_flags = SA_SIGINFO; 27480Sstevel@tonic-gate if (sigaction(SIGQUIT, &act, NULL) == -1) 27490Sstevel@tonic-gate warning(gettext(SIGACT_FAILED), strsignal(SIGHUP), 27500Sstevel@tonic-gate strerror(errno)); 27510Sstevel@tonic-gate debug(10, "init_server completed successfully\n"); 27520Sstevel@tonic-gate 27530Sstevel@tonic-gate server_data.sd_init_state = INIT_DONE; 27540Sstevel@tonic-gate return (NULL); 27550Sstevel@tonic-gate } 27560Sstevel@tonic-gate 27570Sstevel@tonic-gate static int 27580Sstevel@tonic-gate server_exists() 27590Sstevel@tonic-gate { 27600Sstevel@tonic-gate door_arg_t darg; 27610Sstevel@tonic-gate smedia_reqping_t req_ping; 27620Sstevel@tonic-gate smedia_retping_t *ret_ping; 27630Sstevel@tonic-gate int doorh; 27640Sstevel@tonic-gate door_info_t dinfo; 27650Sstevel@tonic-gate char rbuf[sizeof (smedia_services_t) + sizeof (door_desc_t)]; 27660Sstevel@tonic-gate 27670Sstevel@tonic-gate doorh = open(smedia_service, O_RDONLY); 27680Sstevel@tonic-gate if (doorh < 0) 27690Sstevel@tonic-gate return (0); 27700Sstevel@tonic-gate if (door_info(doorh, &dinfo) < 0) { 27710Sstevel@tonic-gate (void) close(doorh); 27720Sstevel@tonic-gate return (0); 27730Sstevel@tonic-gate } 27740Sstevel@tonic-gate if (dinfo.di_attributes & DOOR_REVOKED) { 27750Sstevel@tonic-gate (void) close(doorh); 27760Sstevel@tonic-gate return (0); 27770Sstevel@tonic-gate } 27780Sstevel@tonic-gate 27790Sstevel@tonic-gate req_ping.cnum = SMEDIA_CNUM_PING; 27800Sstevel@tonic-gate 27810Sstevel@tonic-gate darg.data_ptr = (char *)&req_ping; 27820Sstevel@tonic-gate darg.data_size = sizeof (smedia_reqping_t); 27830Sstevel@tonic-gate darg.desc_ptr = NULL; 27840Sstevel@tonic-gate darg.desc_num = 0; 27850Sstevel@tonic-gate darg.rbuf = rbuf; 27860Sstevel@tonic-gate darg.rsize = sizeof (rbuf); 27870Sstevel@tonic-gate 27880Sstevel@tonic-gate if (door_call(doorh, &darg) < 0) { 27890Sstevel@tonic-gate (void) close(doorh); 27900Sstevel@tonic-gate return (0); 27910Sstevel@tonic-gate } 27920Sstevel@tonic-gate ret_ping = (smedia_retping_t *)((void *)darg.data_ptr); 27930Sstevel@tonic-gate if (ret_ping->cnum != SMEDIA_CNUM_PING) { 27940Sstevel@tonic-gate (void) close(doorh); 27950Sstevel@tonic-gate return (0); 27960Sstevel@tonic-gate } 27970Sstevel@tonic-gate 27980Sstevel@tonic-gate (void) close(doorh); 27990Sstevel@tonic-gate return (1); 28000Sstevel@tonic-gate } 28010Sstevel@tonic-gate 28020Sstevel@tonic-gate static int 28030Sstevel@tonic-gate get_run_level() 28040Sstevel@tonic-gate { 28050Sstevel@tonic-gate int run_level; 28060Sstevel@tonic-gate struct utmpx *utmpp; 28070Sstevel@tonic-gate 28080Sstevel@tonic-gate setutxent(); 28090Sstevel@tonic-gate while ((utmpp = getutxent()) != NULL) { 28100Sstevel@tonic-gate if (utmpp->ut_type == RUN_LVL) { 28110Sstevel@tonic-gate run_level = atoi( 28120Sstevel@tonic-gate &utmpp->ut_line[strlen("run-level ")]); 28130Sstevel@tonic-gate } 28140Sstevel@tonic-gate } 28150Sstevel@tonic-gate return (run_level); 28160Sstevel@tonic-gate } 28170Sstevel@tonic-gate 28180Sstevel@tonic-gate /*ARGSUSED*/ 28190Sstevel@tonic-gate static void * 28200Sstevel@tonic-gate closedown(void *arg) 28210Sstevel@tonic-gate { 28220Sstevel@tonic-gate 28230Sstevel@tonic-gate int current_run_level; 28240Sstevel@tonic-gate 28250Sstevel@tonic-gate /*CONSTCOND*/ 28260Sstevel@tonic-gate #ifndef lint 28270Sstevel@tonic-gate while (1) { 28280Sstevel@tonic-gate #endif 28290Sstevel@tonic-gate (void) sleep(SVC_CLOSEDOWN/2); 28300Sstevel@tonic-gate 28310Sstevel@tonic-gate /* 28320Sstevel@tonic-gate * If the server was started at init level 1 28330Sstevel@tonic-gate * and the current init level is 1 then 28340Sstevel@tonic-gate * do not exit from server. This server will run 28350Sstevel@tonic-gate * until it is explicitly stopped by the user. 28360Sstevel@tonic-gate */ 28370Sstevel@tonic-gate if (svcstart_level == 1) { 28380Sstevel@tonic-gate current_run_level = get_run_level(); 28390Sstevel@tonic-gate if (current_run_level == 1) 28400Sstevel@tonic-gate #ifndef lint 28410Sstevel@tonic-gate continue; 28420Sstevel@tonic-gate #else 28430Sstevel@tonic-gate return (NULL); 28440Sstevel@tonic-gate #endif 28450Sstevel@tonic-gate /* 28460Sstevel@tonic-gate * who ever started the server at level 1 has 28470Sstevel@tonic-gate * forgotten to stop the server. we will kill ourself. 28480Sstevel@tonic-gate */ 28490Sstevel@tonic-gate debug(5, 28500Sstevel@tonic-gate "Terminating the server started at init level 1\n"); 28510Sstevel@tonic-gate exit(0); 28520Sstevel@tonic-gate } 28530Sstevel@tonic-gate 28540Sstevel@tonic-gate if (mutex_trylock(&svcstate_lock) != 0) 28550Sstevel@tonic-gate #ifndef lint 28560Sstevel@tonic-gate continue; 28570Sstevel@tonic-gate #else 28580Sstevel@tonic-gate return (NULL); 28590Sstevel@tonic-gate #endif 28600Sstevel@tonic-gate if (svcstate == _IDLE && svccount == 0) { 28610Sstevel@tonic-gate int size; 28620Sstevel@tonic-gate int i, openfd = 0; 28630Sstevel@tonic-gate 28640Sstevel@tonic-gate size = svc_max_pollfd; 28650Sstevel@tonic-gate for (i = 0; i < size && openfd < 2; i++) 28660Sstevel@tonic-gate if (svc_pollfd[i].fd >= 0) 28670Sstevel@tonic-gate openfd++; 28680Sstevel@tonic-gate if (openfd <= 1) { 28690Sstevel@tonic-gate debug(5, 28700Sstevel@tonic-gate "Exiting the server from closedown routine.\n"); 28710Sstevel@tonic-gate exit(0); 28720Sstevel@tonic-gate } 28730Sstevel@tonic-gate } else 28740Sstevel@tonic-gate svcstate = _IDLE; 28750Sstevel@tonic-gate 28760Sstevel@tonic-gate (void) mutex_unlock(&svcstate_lock); 28770Sstevel@tonic-gate #ifndef lint 28780Sstevel@tonic-gate } 28790Sstevel@tonic-gate #else 28800Sstevel@tonic-gate return (NULL); 28810Sstevel@tonic-gate #endif 28820Sstevel@tonic-gate 28830Sstevel@tonic-gate } 28840Sstevel@tonic-gate 28850Sstevel@tonic-gate static void 28860Sstevel@tonic-gate usage() 28870Sstevel@tonic-gate { 28880Sstevel@tonic-gate warning(gettext("usage: %s [-L loglevel] level of debug information\n"), 28890Sstevel@tonic-gate prog_name); 28900Sstevel@tonic-gate } 28910Sstevel@tonic-gate 28920Sstevel@tonic-gate 28930Sstevel@tonic-gate /*ARGSUSED*/ 2894796Smathue int 28950Sstevel@tonic-gate main(int argc, char **argv) 28960Sstevel@tonic-gate { 28970Sstevel@tonic-gate int c; 28980Sstevel@tonic-gate pthread_attr_t attr; 28990Sstevel@tonic-gate 29000Sstevel@tonic-gate (void) setlocale(LC_ALL, ""); 29010Sstevel@tonic-gate #if !defined(TEXT_DOMAIN) 29020Sstevel@tonic-gate #define TEXT_DOMAIN "SYS_TEST" 29030Sstevel@tonic-gate #endif 29040Sstevel@tonic-gate (void) textdomain(TEXT_DOMAIN); 29050Sstevel@tonic-gate 29060Sstevel@tonic-gate prog_name = argv[0]; 29070Sstevel@tonic-gate 29080Sstevel@tonic-gate (void) sigset(SIGPIPE, SIG_IGN); 29090Sstevel@tonic-gate 29100Sstevel@tonic-gate while ((c = getopt(argc, argv, "L:")) != -1) { 29110Sstevel@tonic-gate switch (c) { 29120Sstevel@tonic-gate case 'L': 29130Sstevel@tonic-gate debug_level = atoi((char *)optarg); 29140Sstevel@tonic-gate break; 29150Sstevel@tonic-gate default: 29160Sstevel@tonic-gate usage(); 29170Sstevel@tonic-gate break; 29180Sstevel@tonic-gate } 29190Sstevel@tonic-gate } 29200Sstevel@tonic-gate 29210Sstevel@tonic-gate /* 29220Sstevel@tonic-gate * If stdin looks like a TLI endpoint, we assume 29230Sstevel@tonic-gate * that we were started by a port monitor. If 29240Sstevel@tonic-gate * t_getstate fails with TBADF, this is not a 29250Sstevel@tonic-gate * TLI endpoint. 29260Sstevel@tonic-gate */ 29270Sstevel@tonic-gate if (t_getstate(0) != -1 || t_errno != TBADF) { 29280Sstevel@tonic-gate char *netid; 29290Sstevel@tonic-gate struct netconfig *nconf = NULL; 29300Sstevel@tonic-gate SVCXPRT *transp; 29310Sstevel@tonic-gate int pmclose; 29320Sstevel@tonic-gate 29330Sstevel@tonic-gate openlog(prog_name, LOG_PID, LOG_DAEMON); 29340Sstevel@tonic-gate 29350Sstevel@tonic-gate debug(1, gettext("server started by port monitor.\n")); 29360Sstevel@tonic-gate if ((netid = getenv("NLSPROVIDER")) == NULL) { 29370Sstevel@tonic-gate /* started from inetd */ 29380Sstevel@tonic-gate pmclose = 1; 29390Sstevel@tonic-gate } else { 29400Sstevel@tonic-gate if ((nconf = getnetconfigent(netid)) == NULL) 29410Sstevel@tonic-gate syslog(LOG_ERR, gettext( 29420Sstevel@tonic-gate "cannot get transport info")); 29430Sstevel@tonic-gate 29440Sstevel@tonic-gate pmclose = (t_getstate(0) != T_DATAXFER); 29450Sstevel@tonic-gate } 29460Sstevel@tonic-gate if ((transp = svc_tli_create(0, nconf, NULL, 0, 0)) == NULL) { 29470Sstevel@tonic-gate syslog(LOG_ERR, gettext("cannot create server handle")); 29480Sstevel@tonic-gate exit(1); 29490Sstevel@tonic-gate } 29500Sstevel@tonic-gate if (nconf) 29510Sstevel@tonic-gate freenetconfigent(nconf); 29520Sstevel@tonic-gate if (!svc_reg(transp, SMSERVERPROG, SMSERVERVERS, 29530Sstevel@tonic-gate smserverprog_1, 0)) { 29540Sstevel@tonic-gate syslog(LOG_ERR, gettext( 29550Sstevel@tonic-gate "unable to register (SMSERVERPROG, SMSERVERVERS).")); 29560Sstevel@tonic-gate exit(1); 29570Sstevel@tonic-gate } 29580Sstevel@tonic-gate svcstart_level = get_run_level(); 29590Sstevel@tonic-gate if (pmclose) { 29600Sstevel@tonic-gate (void) pthread_attr_init(&attr); 29610Sstevel@tonic-gate (void) pthread_attr_setscope(&attr, 29620Sstevel@tonic-gate PTHREAD_SCOPE_SYSTEM | PTHREAD_CREATE_DETACHED); 29630Sstevel@tonic-gate if (pthread_create(NULL, &attr, closedown, NULL) != 0) { 29640Sstevel@tonic-gate syslog(LOG_ERR, gettext( 29650Sstevel@tonic-gate "cannot create closedown thread")); 29660Sstevel@tonic-gate exit(1); 29670Sstevel@tonic-gate } 29680Sstevel@tonic-gate (void) pthread_attr_destroy(&attr); 29690Sstevel@tonic-gate } 29700Sstevel@tonic-gate svc_run(); 29710Sstevel@tonic-gate exit(1); 29720Sstevel@tonic-gate /* NOTREACHED */ 29730Sstevel@tonic-gate } else { 29740Sstevel@tonic-gate /* 29750Sstevel@tonic-gate * Started by library or manually. 29760Sstevel@tonic-gate */ 29770Sstevel@tonic-gate /* 29780Sstevel@tonic-gate * Check to see if the server is already running. 29790Sstevel@tonic-gate * There is no need to log messages in the syslog file 29800Sstevel@tonic-gate * because server will get launched each time libsmedia 29810Sstevel@tonic-gate * library calls are made at init 1 level. 29820Sstevel@tonic-gate * We ensure that only one copy will run. 29830Sstevel@tonic-gate */ 29840Sstevel@tonic-gate debug(1, gettext("server started manually.\n")); 29850Sstevel@tonic-gate if (server_exists()) { 29860Sstevel@tonic-gate exit(0); 29870Sstevel@tonic-gate } 29880Sstevel@tonic-gate svcstart_level = get_run_level(); 29890Sstevel@tonic-gate (void) pthread_attr_init(&attr); 29900Sstevel@tonic-gate (void) pthread_attr_setscope(&attr, 29910Sstevel@tonic-gate PTHREAD_SCOPE_SYSTEM | PTHREAD_CREATE_DETACHED); 29920Sstevel@tonic-gate if (pthread_create(NULL, &attr, closedown, NULL) != 0) { 29930Sstevel@tonic-gate syslog(LOG_ERR, gettext( 29940Sstevel@tonic-gate "cannot create closedown thread")); 29950Sstevel@tonic-gate exit(1); 29960Sstevel@tonic-gate } 29970Sstevel@tonic-gate (void) pthread_attr_destroy(&attr); 29980Sstevel@tonic-gate (void) init_server(NULL); 29990Sstevel@tonic-gate for (;;) (void) pause(); 30000Sstevel@tonic-gate } 3001796Smathue return (0); 30020Sstevel@tonic-gate } 30030Sstevel@tonic-gate 30040Sstevel@tonic-gate 30050Sstevel@tonic-gate /*ARGSUSED*/ 30060Sstevel@tonic-gate static int32_t 30070Sstevel@tonic-gate scsi_floppy_write_protect(int32_t fd, smwp_state_t *wp) 30080Sstevel@tonic-gate { 30090Sstevel@tonic-gate debug(5, "Invalid mode\n"); 30100Sstevel@tonic-gate errno = ENOTSUP; 30110Sstevel@tonic-gate 30120Sstevel@tonic-gate return (-1); 30130Sstevel@tonic-gate } 30140Sstevel@tonic-gate 30150Sstevel@tonic-gate /* 30160Sstevel@tonic-gate * Generate standard geometry information for SCSI floppy devices. And 30170Sstevel@tonic-gate * register the geometry with the SCSI driver. This will expand as more 30180Sstevel@tonic-gate * formats are added. 30190Sstevel@tonic-gate */ 30200Sstevel@tonic-gate 30210Sstevel@tonic-gate /*ARGSUSED*/ 30220Sstevel@tonic-gate static int32_t 30230Sstevel@tonic-gate get_floppy_geom(int32_t fd, uint32_t capacity, struct dk_geom *dkgeom) 30240Sstevel@tonic-gate { 30250Sstevel@tonic-gate 30260Sstevel@tonic-gate 30270Sstevel@tonic-gate debug(5, "get_floppy_geom: capacity = 0x%x\n", capacity); 30280Sstevel@tonic-gate 30290Sstevel@tonic-gate switch (capacity) { 30300Sstevel@tonic-gate 30310Sstevel@tonic-gate case 0x5A0: 30320Sstevel@tonic-gate /* Double Density 720K */ 30330Sstevel@tonic-gate dkgeom->dkg_pcyl = 80; 30340Sstevel@tonic-gate dkgeom->dkg_ncyl = 80; 30350Sstevel@tonic-gate dkgeom->dkg_nhead = 2; 30360Sstevel@tonic-gate dkgeom->dkg_nsect = 9; 30370Sstevel@tonic-gate break; 30380Sstevel@tonic-gate case 0x4D0: 30390Sstevel@tonic-gate /* High Density 1.25MB */ 30400Sstevel@tonic-gate dkgeom->dkg_pcyl = 77; 30410Sstevel@tonic-gate dkgeom->dkg_ncyl = 77; 30420Sstevel@tonic-gate dkgeom->dkg_nhead = 2; 30430Sstevel@tonic-gate dkgeom->dkg_nsect = 9; 30440Sstevel@tonic-gate break; 30450Sstevel@tonic-gate case 0xB40: 30460Sstevel@tonic-gate /* High Density 1.44MB */ 30470Sstevel@tonic-gate 30480Sstevel@tonic-gate dkgeom->dkg_pcyl = 80; 30490Sstevel@tonic-gate dkgeom->dkg_ncyl = 80; 30500Sstevel@tonic-gate dkgeom->dkg_nhead = 2; 30510Sstevel@tonic-gate dkgeom->dkg_nsect = 18; 30520Sstevel@tonic-gate break; 30530Sstevel@tonic-gate case 0x3C300: 30540Sstevel@tonic-gate /* Ultra High density ls-120 120MB */ 30550Sstevel@tonic-gate dkgeom->dkg_pcyl = 963; 30560Sstevel@tonic-gate dkgeom->dkg_ncyl = 963; 30570Sstevel@tonic-gate dkgeom->dkg_nhead = 8; 30580Sstevel@tonic-gate dkgeom->dkg_nsect = 32; 30590Sstevel@tonic-gate break; 30600Sstevel@tonic-gate default: 30610Sstevel@tonic-gate debug(5, "unknown capacity type %d\n", capacity); 30620Sstevel@tonic-gate return (-1); 30630Sstevel@tonic-gate 30640Sstevel@tonic-gate } 30650Sstevel@tonic-gate debug(5, "get_floppy_geom: setting cyl = %d, nsect = %d, head = %d", 30660Sstevel@tonic-gate dkgeom->dkg_pcyl, dkgeom->dkg_nhead, dkgeom->dkg_nsect); 30670Sstevel@tonic-gate return (0); 30680Sstevel@tonic-gate 30690Sstevel@tonic-gate } 30700Sstevel@tonic-gate /* ARGSUSED */ 3071*1137Sarutz static int32_t 30720Sstevel@tonic-gate scsi_floppy_format(int32_t fd, uint_t flavor, uint_t mode) 30730Sstevel@tonic-gate { 30740Sstevel@tonic-gate struct uscsi_cmd ucmd; 30750Sstevel@tonic-gate uchar_t cdb[12]; 30760Sstevel@tonic-gate int32_t ret_val; 30770Sstevel@tonic-gate uint32_t capacity, blocksize; 30780Sstevel@tonic-gate uchar_t data[12]; 30790Sstevel@tonic-gate char rq_data[RQ_LEN]; 30800Sstevel@tonic-gate int i; 30810Sstevel@tonic-gate struct dk_geom dkgeom; 30820Sstevel@tonic-gate 30830Sstevel@tonic-gate debug(5, "scsi_floppy_format:\n"); 30840Sstevel@tonic-gate 30850Sstevel@tonic-gate if ((mode != SM_FORMAT_IMMEDIATE) && (mode != SM_FORMAT_BLOCKED)) { 30860Sstevel@tonic-gate errno = ENOTSUP; 30870Sstevel@tonic-gate 30880Sstevel@tonic-gate return (-1); 30890Sstevel@tonic-gate } 30900Sstevel@tonic-gate 30910Sstevel@tonic-gate switch (flavor) { 30920Sstevel@tonic-gate case SM_FORMAT_QUICK : 30930Sstevel@tonic-gate debug(1, "Format not supported\n"); 30940Sstevel@tonic-gate errno = ENOTSUP; 30950Sstevel@tonic-gate return (-1); 30960Sstevel@tonic-gate case SM_FORMAT_FORCE : 30970Sstevel@tonic-gate break; 30980Sstevel@tonic-gate case SM_FORMAT_LONG : 30990Sstevel@tonic-gate break; 31000Sstevel@tonic-gate 31010Sstevel@tonic-gate default : 31020Sstevel@tonic-gate debug(1, "Format option not specified!!\n"); 31030Sstevel@tonic-gate errno = ENOTSUP; 31040Sstevel@tonic-gate return (-1); 31050Sstevel@tonic-gate } 31060Sstevel@tonic-gate 31070Sstevel@tonic-gate ret_val = get_media_capacity(fd, &capacity, &blocksize); 31080Sstevel@tonic-gate 31090Sstevel@tonic-gate if (capacity >= 0x3C300) { 31100Sstevel@tonic-gate /* 31110Sstevel@tonic-gate * It's an LS-120 media, it does not support track 31120Sstevel@tonic-gate * formatting. 31130Sstevel@tonic-gate */ 31140Sstevel@tonic-gate return (scsi_ls120_format(fd, flavor, capacity, blocksize)); 31150Sstevel@tonic-gate } 31160Sstevel@tonic-gate 31170Sstevel@tonic-gate ret_val = get_floppy_geom(fd, capacity, &dkgeom); 31180Sstevel@tonic-gate if (ret_val) { 31190Sstevel@tonic-gate errno = ENOTSUP; 31200Sstevel@tonic-gate return (-1); 31210Sstevel@tonic-gate } 31220Sstevel@tonic-gate 31230Sstevel@tonic-gate (void) memset((void *)&data, 0, sizeof (data)); 31240Sstevel@tonic-gate (void) memset((void *)&ucmd, 0, sizeof (ucmd)); 31250Sstevel@tonic-gate (void) memset((void *)&cdb, 0, sizeof (cdb)); 31260Sstevel@tonic-gate 31270Sstevel@tonic-gate /* retrieve size discriptor of inserted media */ 31280Sstevel@tonic-gate cdb[0] = SCMD_FORMAT; /* format */ 31290Sstevel@tonic-gate 31300Sstevel@tonic-gate /* 31310Sstevel@tonic-gate * Defect list sent by initiator is a complete list of defects. 31320Sstevel@tonic-gate */ 31330Sstevel@tonic-gate 31340Sstevel@tonic-gate cdb[1] = (FMTDATA | 0x7); 31350Sstevel@tonic-gate 31360Sstevel@tonic-gate cdb[8] = 0xC; /* parameter list length */ 31370Sstevel@tonic-gate data[3] = 0x8; /* should be always 8 */ 31380Sstevel@tonic-gate 31390Sstevel@tonic-gate data[4] = (uchar_t)(capacity >> 24); 31400Sstevel@tonic-gate data[5] = (uchar_t)(capacity >> 16); 31410Sstevel@tonic-gate data[6] = (uchar_t)(capacity >> 8); 31420Sstevel@tonic-gate data[7] = (uchar_t)capacity; 31430Sstevel@tonic-gate 31440Sstevel@tonic-gate data[9] = (uchar_t)(blocksize >> 16); 31450Sstevel@tonic-gate data[10] = (uchar_t)(blocksize >> 8); 31460Sstevel@tonic-gate data[11] = (uchar_t)blocksize; 31470Sstevel@tonic-gate 31480Sstevel@tonic-gate ucmd.uscsi_cdb = (caddr_t)&cdb; 31490Sstevel@tonic-gate ucmd.uscsi_cdblen = CDB_GROUP5; 31500Sstevel@tonic-gate ucmd.uscsi_bufaddr = (caddr_t)data; 31510Sstevel@tonic-gate ucmd.uscsi_buflen = sizeof (data); 31520Sstevel@tonic-gate ucmd.uscsi_timeout = 0x15; 31530Sstevel@tonic-gate ucmd.uscsi_rqlen = RQ_LEN; 31540Sstevel@tonic-gate ucmd.uscsi_rqbuf = rq_data; 31550Sstevel@tonic-gate 31560Sstevel@tonic-gate debug(5, "cdb: %x %x %x ... %x", cdb[0], cdb[1], cdb[2], cdb[8]); 31570Sstevel@tonic-gate debug(5, "data: %x %x %x %x\n", data[0], data[1], data[2], data[3]); 31580Sstevel@tonic-gate debug(5, " : %x %x %x %x\n", data[4], data[5], data[6], data[7]); 31590Sstevel@tonic-gate debug(5, " : %x %x %x %x\n", data[8], data[9], data[10], data[11]); 31600Sstevel@tonic-gate 31610Sstevel@tonic-gate for (i = 0; i < dkgeom.dkg_pcyl; i++) { /* number of tracks */ 31620Sstevel@tonic-gate data[1] = (0xb0 | FOV); 31630Sstevel@tonic-gate cdb[2] = i; 31640Sstevel@tonic-gate 31650Sstevel@tonic-gate (void) fflush(stdout); 31660Sstevel@tonic-gate ret_val = do_uscsi_cmd(fd, &ucmd, USCSI_WRITE|USCSI_RQENABLE); 31670Sstevel@tonic-gate info("format side 0 returned : 0x%x\n", ret_val); 31680Sstevel@tonic-gate 31690Sstevel@tonic-gate if (ret_val || ucmd.uscsi_status) { 31700Sstevel@tonic-gate debug(5, "Retrieving media info failed: %d - %d\n", 31710Sstevel@tonic-gate ret_val, ucmd.uscsi_status); 31720Sstevel@tonic-gate if ((rq_data[2] == KEY_DATA_PROTECT) && 31730Sstevel@tonic-gate (rq_data[12] == 0x30) && (rq_data[13] == 0)) { 31740Sstevel@tonic-gate debug(5, "Invalid command for media\n"); 31750Sstevel@tonic-gate errno = EINVAL; 31760Sstevel@tonic-gate } 31770Sstevel@tonic-gate 31780Sstevel@tonic-gate if ((rq_data[2] == KEY_NOT_READY) && 31790Sstevel@tonic-gate (rq_data[12] == 0x30)) { 31800Sstevel@tonic-gate debug(5, "Incompatible media.\n"); 31810Sstevel@tonic-gate errno = EINVAL; 31820Sstevel@tonic-gate } 31830Sstevel@tonic-gate 31840Sstevel@tonic-gate return (-1); 31850Sstevel@tonic-gate } 31860Sstevel@tonic-gate data[1] = (0xb0 | FOV) + 1; 31870Sstevel@tonic-gate ret_val = do_uscsi_cmd(fd, &ucmd, USCSI_WRITE|USCSI_RQENABLE); 31880Sstevel@tonic-gate info("format side 1 returned : 0x%x\n", ret_val); 31890Sstevel@tonic-gate 31900Sstevel@tonic-gate if (ret_val || ucmd.uscsi_status) { 31910Sstevel@tonic-gate debug(5, "Retrieving media info failed: %d - %d\n", 31920Sstevel@tonic-gate ret_val, ucmd.uscsi_status); 31930Sstevel@tonic-gate if ((rq_data[2] == KEY_DATA_PROTECT) && 31940Sstevel@tonic-gate (rq_data[12] == 0x30) && (rq_data[13] == 0)) { 31950Sstevel@tonic-gate (void) info("Invalid command for media\n"); 31960Sstevel@tonic-gate errno = EINVAL; 31970Sstevel@tonic-gate } 31980Sstevel@tonic-gate 31990Sstevel@tonic-gate if ((rq_data[2] == KEY_NOT_READY) && 32000Sstevel@tonic-gate (rq_data[12] == 0x30)) { 32010Sstevel@tonic-gate debug(5, "Incompatible media.\n"); 32020Sstevel@tonic-gate errno = EINVAL; 32030Sstevel@tonic-gate } 32040Sstevel@tonic-gate 32050Sstevel@tonic-gate return (-1); 32060Sstevel@tonic-gate } 32070Sstevel@tonic-gate } 32080Sstevel@tonic-gate 32090Sstevel@tonic-gate debug(5, "formatting done!"); 32100Sstevel@tonic-gate return (0); 32110Sstevel@tonic-gate } 32120Sstevel@tonic-gate 32130Sstevel@tonic-gate 32140Sstevel@tonic-gate /* ARGSUSED */ 3215*1137Sarutz static int32_t 32160Sstevel@tonic-gate scsi_floppy_media_status(int32_t fd) 32170Sstevel@tonic-gate { 32180Sstevel@tonic-gate struct mode_header_g1 modeh; 32190Sstevel@tonic-gate struct uscsi_cmd ucmd; 32200Sstevel@tonic-gate uchar_t cdb[10]; 32210Sstevel@tonic-gate int32_t ret_val; 32220Sstevel@tonic-gate int32_t cur_status; 32230Sstevel@tonic-gate char rq_data[RQ_LEN]; 32240Sstevel@tonic-gate 32250Sstevel@tonic-gate debug(5, "SCSI MEDIA STATUS CALLED \n"); 32260Sstevel@tonic-gate 32270Sstevel@tonic-gate (void) memset((void *) &modeh, 0, sizeof (modeh)); 32280Sstevel@tonic-gate (void) memset((void *) &ucmd, 0, sizeof (ucmd)); 32290Sstevel@tonic-gate (void) memset(cdb, 0, sizeof (cdb)); 32300Sstevel@tonic-gate /* 32310Sstevel@tonic-gate * issue 10 byte mode sense (0x5A) 32320Sstevel@tonic-gate */ 32330Sstevel@tonic-gate cdb[0] = SCMD_MODE_SENSE_G1; 32340Sstevel@tonic-gate cdb[7] = sizeof (modeh) >> 8; 32350Sstevel@tonic-gate cdb[8] = sizeof (modeh) & 0xff; 32360Sstevel@tonic-gate 32370Sstevel@tonic-gate ucmd.uscsi_cdb = (caddr_t)cdb; 32380Sstevel@tonic-gate ucmd.uscsi_cdblen = CDB_GROUP1; 32390Sstevel@tonic-gate ucmd.uscsi_bufaddr = (caddr_t)&modeh; 32400Sstevel@tonic-gate ucmd.uscsi_buflen = sizeof (modeh); 32410Sstevel@tonic-gate ucmd.uscsi_timeout = 120; /* If 0, HBA hangs forever */ 32420Sstevel@tonic-gate ucmd.uscsi_rqlen = RQ_LEN; 32430Sstevel@tonic-gate ucmd.uscsi_rqbuf = rq_data; 32440Sstevel@tonic-gate ret_val = do_uscsi_cmd(fd, &ucmd, USCSI_READ|USCSI_RQENABLE); 32450Sstevel@tonic-gate if (ret_val || ucmd.uscsi_status) { 32460Sstevel@tonic-gate /* 32470Sstevel@tonic-gate * UFI devices may not respond to the 0 mode page. 32480Sstevel@tonic-gate * retry with the error recovery page(0x01) 32490Sstevel@tonic-gate */ 32500Sstevel@tonic-gate if (ucmd.uscsi_status & STATUS_CHECK) { 32510Sstevel@tonic-gate cdb[2] = 0x1; /* page code */ 32520Sstevel@tonic-gate ret_val = do_uscsi_cmd(fd, &ucmd, 32530Sstevel@tonic-gate USCSI_READ|USCSI_RQENABLE); 32540Sstevel@tonic-gate } 32550Sstevel@tonic-gate if (ret_val || ucmd.uscsi_status) { 32560Sstevel@tonic-gate debug(1, "Modesense failed: %d - %d\n", 32570Sstevel@tonic-gate ret_val, ucmd.uscsi_status); 32580Sstevel@tonic-gate return (-1); 32590Sstevel@tonic-gate } 32600Sstevel@tonic-gate } 32610Sstevel@tonic-gate debug(5, "Modesense succeeded: 0x%x\n", modeh.device_specific); 32620Sstevel@tonic-gate 32630Sstevel@tonic-gate if (modeh.device_specific & 0x80) { 32640Sstevel@tonic-gate cur_status = SM_WRITE_PROTECT_NOPASSWD; 32650Sstevel@tonic-gate } else { 32660Sstevel@tonic-gate cur_status = SM_WRITE_PROTECT_DISABLE; 32670Sstevel@tonic-gate } 32680Sstevel@tonic-gate return (cur_status); 32690Sstevel@tonic-gate } 3270