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