17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 57c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 67c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 77c478bd9Sstevel@tonic-gate * with the License. 87c478bd9Sstevel@tonic-gate * 97c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 107c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 117c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 127c478bd9Sstevel@tonic-gate * and limitations under the License. 137c478bd9Sstevel@tonic-gate * 147c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 157c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 167c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 177c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 187c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 197c478bd9Sstevel@tonic-gate * 207c478bd9Sstevel@tonic-gate * CDDL HEADER END 217c478bd9Sstevel@tonic-gate */ 227c478bd9Sstevel@tonic-gate /* 237c478bd9Sstevel@tonic-gate * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 247c478bd9Sstevel@tonic-gate * Use is subject to license terms. 257c478bd9Sstevel@tonic-gate */ 267c478bd9Sstevel@tonic-gate 277c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 287c478bd9Sstevel@tonic-gate 297c478bd9Sstevel@tonic-gate #include <stdio.h> 307c478bd9Sstevel@tonic-gate #include <errno.h> 317c478bd9Sstevel@tonic-gate #include <ctype.h> 327c478bd9Sstevel@tonic-gate #include <syslog.h> 337c478bd9Sstevel@tonic-gate #include <signal.h> 347c478bd9Sstevel@tonic-gate #include <limits.h> 357c478bd9Sstevel@tonic-gate #include <unistd.h> 367c478bd9Sstevel@tonic-gate #include <sys/types.h> 377c478bd9Sstevel@tonic-gate #include <sys/mman.h> 387c478bd9Sstevel@tonic-gate #include <stdlib.h> 397c478bd9Sstevel@tonic-gate #include <sys/stat.h> 407c478bd9Sstevel@tonic-gate #include <sys/mkdev.h> 417c478bd9Sstevel@tonic-gate #include <fcntl.h> 427c478bd9Sstevel@tonic-gate #include <sys/scsi/scsi.h> 437c478bd9Sstevel@tonic-gate #include <sys/scsi/generic/commands.h> 447c478bd9Sstevel@tonic-gate #include <string.h> 457c478bd9Sstevel@tonic-gate #include <door.h> 467c478bd9Sstevel@tonic-gate #include <pwd.h> 477c478bd9Sstevel@tonic-gate #include <thread.h> 487c478bd9Sstevel@tonic-gate #include <synch.h> 497c478bd9Sstevel@tonic-gate #include <pthread.h> 507c478bd9Sstevel@tonic-gate #include <locale.h> 517c478bd9Sstevel@tonic-gate #include <sys/resource.h> 527c478bd9Sstevel@tonic-gate #include <netconfig.h> 537c478bd9Sstevel@tonic-gate #include <sys/smedia.h> 547c478bd9Sstevel@tonic-gate #include "smserver.h" 557c478bd9Sstevel@tonic-gate #include <rpc/rpc.h> 567c478bd9Sstevel@tonic-gate #include "smed.h" 577c478bd9Sstevel@tonic-gate #include "myaudit.h" 587c478bd9Sstevel@tonic-gate #include <bsm/libbsm.h> 597c478bd9Sstevel@tonic-gate #include <bsm/audit_uevents.h> 607c478bd9Sstevel@tonic-gate #include <utmpx.h> 617c478bd9Sstevel@tonic-gate 627c478bd9Sstevel@tonic-gate 637c478bd9Sstevel@tonic-gate /* 647c478bd9Sstevel@tonic-gate * The comments below would help in understanding what is being attempted 657c478bd9Sstevel@tonic-gate * in the server. 667c478bd9Sstevel@tonic-gate * 677c478bd9Sstevel@tonic-gate * The server can be started either by inetd or by the client directly. 687c478bd9Sstevel@tonic-gate * Normally the server is started by inetd when the client invokes the 697c478bd9Sstevel@tonic-gate * appropriate libsmedia library call(smedia_get_handle). 707c478bd9Sstevel@tonic-gate * However since the inetd runs only at init level 2 and above a mechanism 717c478bd9Sstevel@tonic-gate * is provided for the server to be started if an attempt is made to use 727c478bd9Sstevel@tonic-gate * the libsmedia calls in maintenence mode(init level 1). 737c478bd9Sstevel@tonic-gate * The main() routine determines how the server was invoked and takes 747c478bd9Sstevel@tonic-gate * the necessary action. 757c478bd9Sstevel@tonic-gate * When started by inetd it registers itself as an RPC program. 767c478bd9Sstevel@tonic-gate * The server also implements a mechanism by which it removes itself 777c478bd9Sstevel@tonic-gate * after a period of inactivity. The period of inactivity is specified 787c478bd9Sstevel@tonic-gate * by SVC_CLOSEDOWN which is set at 180 secs. 797c478bd9Sstevel@tonic-gate * The logic of detecting inactivity is as follows: 807c478bd9Sstevel@tonic-gate * 817c478bd9Sstevel@tonic-gate * Two variables svcstate and svccount are used to determine if the server 827c478bd9Sstevel@tonic-gate * is IDLE. 837c478bd9Sstevel@tonic-gate * The svcstate is set to 1(_SERVED) when ever the server does any operation 847c478bd9Sstevel@tonic-gate * on behalf of the client. 857c478bd9Sstevel@tonic-gate * The svccount indicates the number of active clients who have established 867c478bd9Sstevel@tonic-gate * a connection with the server. A connection is established when the 877c478bd9Sstevel@tonic-gate * libsmedia call smedia_get_handle() succeeds. 887c478bd9Sstevel@tonic-gate * The connection is broken when the client calls smedia_free_handle() OR 897c478bd9Sstevel@tonic-gate * exits. 907c478bd9Sstevel@tonic-gate * A thread called closedown is started up when server is started. 917c478bd9Sstevel@tonic-gate * This thread runs periodically and monitors both svcstate and svccount. 927c478bd9Sstevel@tonic-gate * If svcstate is IDLE and svccount is 0 then server exits. 937c478bd9Sstevel@tonic-gate * The svcstate is set to IDLE by the closedown thread. It is set to _SERVED 947c478bd9Sstevel@tonic-gate * by server. It is possible for the state to be _SERVED and the svccount 957c478bd9Sstevel@tonic-gate * to be 0. The server could be kept busy by client calls of smedia_get_handle 967c478bd9Sstevel@tonic-gate * that do not succeed. This is the reason for using both svcstate and svccount 977c478bd9Sstevel@tonic-gate * to determine the true server state. 987c478bd9Sstevel@tonic-gate * 997c478bd9Sstevel@tonic-gate * The communication between client and server is thru door calls. 1007c478bd9Sstevel@tonic-gate * Below are the door descriptors available to communicate to the server. 1017c478bd9Sstevel@tonic-gate * 1027c478bd9Sstevel@tonic-gate * main_door_descriptor: 1037c478bd9Sstevel@tonic-gate * --------------------- 1047c478bd9Sstevel@tonic-gate * This is a predefined descriptor used by client to establish a 1057c478bd9Sstevel@tonic-gate * connection with the server. This descriptor is available to the client 1067c478bd9Sstevel@tonic-gate * as /var/adm/smedia_svc 107*5363f09cSarutz * The client uses the main_door_descriptor to obtain a dedicated 1087c478bd9Sstevel@tonic-gate * client_door_descriptor for itself. The smedia_get_handle call communicates 1097c478bd9Sstevel@tonic-gate * to the server using the main_door_descriptor and obtains the 1107c478bd9Sstevel@tonic-gate * client_door_descriptor which is stored in the handle structure. 1117c478bd9Sstevel@tonic-gate * All other libsmedia calls use the client_door_descriptor to communicate 1127c478bd9Sstevel@tonic-gate * with the server. 1137c478bd9Sstevel@tonic-gate * 1147c478bd9Sstevel@tonic-gate * client_door_descriptor: 1157c478bd9Sstevel@tonic-gate * ----------------------- 1167c478bd9Sstevel@tonic-gate * This is the door descriptor that is used by the clients to 1177c478bd9Sstevel@tonic-gate * request server to perform the necessary tasks. This door descriptor is 1187c478bd9Sstevel@tonic-gate * available only to the client for whom it was created. 1197c478bd9Sstevel@tonic-gate * 1207c478bd9Sstevel@tonic-gate * death_door_descriptor: 1217c478bd9Sstevel@tonic-gate * ---------------------- 122*5363f09cSarutz * The sole function of this descriptor HAD been to inform the server of 123*5363f09cSarutz * the untimely death of the client. This descriptor is no longer used, though 124*5363f09cSarutz * it is still created, as libsmedia expects to use it. This descriptor's 125*5363f09cSarutz * service procedure had used pthread cancellation(5) to terminate the thread of 126*5363f09cSarutz * the associated client_door_descriptor. The client_door_descriptor now 127*5363f09cSarutz * handles the scenarios where a door_call/client are aborted/terminated. 1287c478bd9Sstevel@tonic-gate * 129*5363f09cSarutz * main_servproc() 1307c478bd9Sstevel@tonic-gate * ------------- 1317c478bd9Sstevel@tonic-gate * This is the routine associated with the main_door_descriptor. 1327c478bd9Sstevel@tonic-gate * This is the routine that handles the smedia_get_handle() call 1337c478bd9Sstevel@tonic-gate * of the client. If the door call to this routine succeeds it creates a 1347c478bd9Sstevel@tonic-gate * client_door_descriptor that is used by the client in subsequent library 1357c478bd9Sstevel@tonic-gate * calls. 1367c478bd9Sstevel@tonic-gate * This client_door_descriptor is passed to the client thru the door_return 1377c478bd9Sstevel@tonic-gate * call. This client_door_descriptor cannot be used by any other process other 1387c478bd9Sstevel@tonic-gate * than the client process that obtained it. 1397c478bd9Sstevel@tonic-gate * In addition to the client_door_descriptor a death_door_descriptor is also 1407c478bd9Sstevel@tonic-gate * created by the main server and passed on to the client. The client does not 141*5363f09cSarutz * use the death_door_descriptor. 1427c478bd9Sstevel@tonic-gate * 143*5363f09cSarutz * client_servproc() 1447c478bd9Sstevel@tonic-gate * --------------- 1457c478bd9Sstevel@tonic-gate * This is the routine that handles the libsmedia calls of the 1467c478bd9Sstevel@tonic-gate * client. In the current implementation the server takes control of the 1477c478bd9Sstevel@tonic-gate * number of threads that handle the door calls. This is done by creating the 1487c478bd9Sstevel@tonic-gate * door descriptor as DOOR_PRIVATE. 1497c478bd9Sstevel@tonic-gate * The server runs only one thread per handle. This makes the implementation 1507c478bd9Sstevel@tonic-gate * simple as we do not have to use mutex to make the code MT safe. 151*5363f09cSarutz * The server thread has a data structure door_data_t associated with it. 1527c478bd9Sstevel@tonic-gate * 1537c478bd9Sstevel@tonic-gate * door_data_t 1547c478bd9Sstevel@tonic-gate * ----------- 155*5363f09cSarutz * This is the data structure that is created by the main_servproc when it 1567c478bd9Sstevel@tonic-gate * creates the client_door_descriptor. The door mechanism has a way to associate 1577c478bd9Sstevel@tonic-gate * a cookie with the door descriptor. door_data_t is the cookie for the 158*5363f09cSarutz * client_door_descriptor. This cookie is passed to the server function that 159*5363f09cSarutz * handles the client_door_descriptor calls. In our case it is the 160*5363f09cSarutz * client_servproc routine. 1617c478bd9Sstevel@tonic-gate * The key elements of the door_data_t are the following: 1627c478bd9Sstevel@tonic-gate * 1637c478bd9Sstevel@tonic-gate * dd_fd file descriptor for the device. 1647c478bd9Sstevel@tonic-gate * dd_buf The shared memory buffer between client-server. 1657c478bd9Sstevel@tonic-gate * dd_thread The thread that handles the door_calls. 1667c478bd9Sstevel@tonic-gate * 1677c478bd9Sstevel@tonic-gate * signal handling: 1687c478bd9Sstevel@tonic-gate * ---------------- 1697c478bd9Sstevel@tonic-gate * The main purpose of trapping the signals is to exit gracefully 1707c478bd9Sstevel@tonic-gate * from the server after recording the appropriate message in the syslog. 1717c478bd9Sstevel@tonic-gate * This will help the administrator to determine the cause of failure of the 1727c478bd9Sstevel@tonic-gate * server by examining the log file. 1737c478bd9Sstevel@tonic-gate * 1747c478bd9Sstevel@tonic-gate * cleanup() 1757c478bd9Sstevel@tonic-gate * --------- 1767c478bd9Sstevel@tonic-gate * This routine frees up all the resources allocated for the client. 177*5363f09cSarutz * Resources include the file descriptor, shared memory, threads. 1787c478bd9Sstevel@tonic-gate * 1797c478bd9Sstevel@tonic-gate * shared memory 1807c478bd9Sstevel@tonic-gate * ------------- 1817c478bd9Sstevel@tonic-gate * In order to reduce the overheads of moving large amounts of data 1827c478bd9Sstevel@tonic-gate * during raw read/write operations, the server uses the mmapped data of 1837c478bd9Sstevel@tonic-gate * client. The smedia_raw_read, smedia_raw_write library calls mmap the 1847c478bd9Sstevel@tonic-gate * memory and pass on the file descriptor that maps the memory to the server. 1857c478bd9Sstevel@tonic-gate * The server subsequently uses this mmapped memory during the IO. 1867c478bd9Sstevel@tonic-gate * If the mmapped memory changes in size, the server is informed and it 1877c478bd9Sstevel@tonic-gate * remaps the memory to the changed size. 1887c478bd9Sstevel@tonic-gate */ 1897c478bd9Sstevel@tonic-gate #ifdef DEBUG 1907c478bd9Sstevel@tonic-gate #define DEFAULT_VERBOSE 1 1917c478bd9Sstevel@tonic-gate #define DEFAULT_DEBUG 1 1927c478bd9Sstevel@tonic-gate #else 1937c478bd9Sstevel@tonic-gate #define DEFAULT_VERBOSE 0 1947c478bd9Sstevel@tonic-gate #define DEFAULT_DEBUG 0 1957c478bd9Sstevel@tonic-gate #endif 1967c478bd9Sstevel@tonic-gate 1977c478bd9Sstevel@tonic-gate #define N_BADSIGS (sizeof (badsigs)/sizeof (badsigs[0])) 1987c478bd9Sstevel@tonic-gate #define MD_LEN 30 1997c478bd9Sstevel@tonic-gate #define MAXUGNAME 10 2007c478bd9Sstevel@tonic-gate #define SVC_CLOSEDOWN 180 2017c478bd9Sstevel@tonic-gate 2027c478bd9Sstevel@tonic-gate /* 2037c478bd9Sstevel@tonic-gate * We will NOT be permitting the following USCI cmd options. 2047c478bd9Sstevel@tonic-gate * 2057c478bd9Sstevel@tonic-gate * RESET of target 2067c478bd9Sstevel@tonic-gate * RESET of Bus. 2077c478bd9Sstevel@tonic-gate * Tagged commands to device 2087c478bd9Sstevel@tonic-gate * Explicitly setting SYNC/ASYNC mode of operations. 2097c478bd9Sstevel@tonic-gate * POLLED MODE of operation. 2107c478bd9Sstevel@tonic-gate * Explicitly setting NO DISCONNECT features. 2117c478bd9Sstevel@tonic-gate * use of RESERVED flags. 2127c478bd9Sstevel@tonic-gate */ 2137c478bd9Sstevel@tonic-gate #define FORBIDDEN_FLAGS (USCSI_RESET | USCSI_RESET_ALL | USCSI_RENEGOT \ 2147c478bd9Sstevel@tonic-gate | USCSI_ASYNC | USCSI_SYNC | USCSI_NOINTR | \ 2157c478bd9Sstevel@tonic-gate USCSI_NOTAG | USCSI_NOPARITY | USCSI_NODISCON \ 2167c478bd9Sstevel@tonic-gate | USCSI_RESERVED) 2177c478bd9Sstevel@tonic-gate 2187c478bd9Sstevel@tonic-gate /* States a server can be in wrt request */ 2197c478bd9Sstevel@tonic-gate 2207c478bd9Sstevel@tonic-gate #define _IDLE 0 2217c478bd9Sstevel@tonic-gate #define _SERVED 1 2227c478bd9Sstevel@tonic-gate 2237c478bd9Sstevel@tonic-gate static char *prog_name; 2247c478bd9Sstevel@tonic-gate static int svcstate = _IDLE; /* Set when a request is serviced */ 2257c478bd9Sstevel@tonic-gate static int svccount = 0; /* Number of requests being serviced */ 2267c478bd9Sstevel@tonic-gate static int svcstart_level = 0; /* init level when server was started */ 2277c478bd9Sstevel@tonic-gate static mutex_t svcstate_lock; /* lock for svcstate, svccount */ 2287c478bd9Sstevel@tonic-gate 2297c478bd9Sstevel@tonic-gate extern void smserverprog_1(struct svc_req *, SVCXPRT *); 2307c478bd9Sstevel@tonic-gate 2317c478bd9Sstevel@tonic-gate /* 2327c478bd9Sstevel@tonic-gate * Log messages 2337c478bd9Sstevel@tonic-gate */ 2347c478bd9Sstevel@tonic-gate #define SIGACT_FAILED "Failed to install signal handler for %s: %s" 2357c478bd9Sstevel@tonic-gate #define BADSIG_MSG "Thread %d Caught signal %d addr=%p trapno=%d pc=%p" 2367c478bd9Sstevel@tonic-gate 2377c478bd9Sstevel@tonic-gate static int badsigs[] = {SIGSEGV, SIGBUS, SIGFPE, SIGILL}; 2387c478bd9Sstevel@tonic-gate 2397c478bd9Sstevel@tonic-gate /* global variables */ 2407c478bd9Sstevel@tonic-gate int verbose = DEFAULT_VERBOSE; 2417c478bd9Sstevel@tonic-gate int debug_level = DEFAULT_DEBUG; 2427c478bd9Sstevel@tonic-gate char *smediad_devdir = DEFAULT_SMEDIAD_DEVDIR; 2437c478bd9Sstevel@tonic-gate 2447c478bd9Sstevel@tonic-gate thread_key_t door_key; 2457c478bd9Sstevel@tonic-gate 2467c478bd9Sstevel@tonic-gate server_data_t server_data; 2477c478bd9Sstevel@tonic-gate 2487c478bd9Sstevel@tonic-gate static int server_door, server_fd; 2497c478bd9Sstevel@tonic-gate 2507c478bd9Sstevel@tonic-gate static int32_t do_uscsi_cmd(int32_t file, struct uscsi_cmd *uscsi_cmd, 2517c478bd9Sstevel@tonic-gate int32_t flag); 252*5363f09cSarutz static void client_servproc(void *cookie, char *argp, size_t arg_size, 2537c478bd9Sstevel@tonic-gate door_desc_t *dp, uint_t ndesc); 2547c478bd9Sstevel@tonic-gate static void cleanup(door_data_t *); 2557c478bd9Sstevel@tonic-gate static void *init_server(void *); 2567c478bd9Sstevel@tonic-gate static int32_t scsi_reassign_block(int32_t fd, diskaddr_t); 2577c478bd9Sstevel@tonic-gate static int32_t get_mode_page(int32_t fd, uchar_t pc, uchar_t page_code, 2587c478bd9Sstevel@tonic-gate uchar_t *md_data, uchar_t data_len); 2597c478bd9Sstevel@tonic-gate static int32_t get_device_type(char *v_name); 2607c478bd9Sstevel@tonic-gate static int32_t get_device_type_scsi(int32_t fd, struct scsi_inquiry *inq); 2617c478bd9Sstevel@tonic-gate 2627c478bd9Sstevel@tonic-gate static int32_t scsi_format(int32_t fd, uint_t flavor, uint_t mode); 2637c478bd9Sstevel@tonic-gate static int32_t scsi_media_status(int32_t fd); 2647c478bd9Sstevel@tonic-gate static int32_t scsi_write_protect(int32_t fd, smwp_state_t *wp); 2657c478bd9Sstevel@tonic-gate static int32_t scsi_floppy_media_status(int32_t fd); 2667c478bd9Sstevel@tonic-gate static int32_t scsi_floppy_write_protect(int32_t fd, smwp_state_t *wp); 2677c478bd9Sstevel@tonic-gate static int32_t scsi_floppy_format(int32_t, uint_t, uint_t); 2687c478bd9Sstevel@tonic-gate static int32_t get_floppy_geom(int32_t fd, uint32_t capacity, 2697c478bd9Sstevel@tonic-gate struct dk_geom *dkgeom); 2707c478bd9Sstevel@tonic-gate static int32_t get_media_capacity(int32_t fd, uint32_t *capacity, 2717c478bd9Sstevel@tonic-gate uint32_t *blocksize); 2727c478bd9Sstevel@tonic-gate 2737c478bd9Sstevel@tonic-gate static int32_t scsi_ls120_format(uint_t fd, uint_t flavor, uint32_t capacity, 2747c478bd9Sstevel@tonic-gate uint32_t blocksize); 2757c478bd9Sstevel@tonic-gate 276*5363f09cSarutz static void *sm_server_thread(void *arg); 277*5363f09cSarutz static void sm_door_server_create(door_info_t *dip); 2787c478bd9Sstevel@tonic-gate static void term_handler(int sig, siginfo_t *siginfo, void *sigctx); 2797c478bd9Sstevel@tonic-gate static void hup_handler(int sig, siginfo_t *siginfo, void *sigctx); 2807c478bd9Sstevel@tonic-gate static void sig_handler(int sig, siginfo_t *siginfo, void *sigctx); 2817c478bd9Sstevel@tonic-gate static void badsig_handler(int sig, siginfo_t *siginfo, void *sigctx); 2827c478bd9Sstevel@tonic-gate static void server_badsig_handler(int sig, siginfo_t *siginfo, void *sigctx); 2837c478bd9Sstevel@tonic-gate static char *xlate_state(int32_t); 2847c478bd9Sstevel@tonic-gate static uint32_t get_sector_size(int fd); 2857c478bd9Sstevel@tonic-gate static int32_t raw_read(door_data_t *door_dp, smedia_services_t *req); 2867c478bd9Sstevel@tonic-gate static int32_t raw_write(door_data_t *door_dp, smedia_services_t *req); 2877c478bd9Sstevel@tonic-gate static int32_t reassign_block(door_data_t *door_dp, smedia_services_t *req); 2887c478bd9Sstevel@tonic-gate static int32_t set_protection_status(door_data_t *door_dp, 2897c478bd9Sstevel@tonic-gate smedia_services_t *req); 2907c478bd9Sstevel@tonic-gate static int32_t set_shfd(door_data_t *door_dp, int32_t fd, 2917c478bd9Sstevel@tonic-gate smedia_services_t *req); 2927c478bd9Sstevel@tonic-gate 2937c478bd9Sstevel@tonic-gate static void door_ret_err(smedia_reterror_t *reterror, int32_t err); 2947c478bd9Sstevel@tonic-gate static void my_door_return(char *data_ptr, size_t data_size, 2957c478bd9Sstevel@tonic-gate door_desc_t *desc_ptr, uint_t num_desc); 2967c478bd9Sstevel@tonic-gate static int32_t invalid_uscsi_operation(door_data_t *, struct uscsi_cmd *); 2977c478bd9Sstevel@tonic-gate 2987c478bd9Sstevel@tonic-gate #define W_E_MASK 0x80 2997c478bd9Sstevel@tonic-gate 3007c478bd9Sstevel@tonic-gate static smserver_info server_info; 3017c478bd9Sstevel@tonic-gate 3027c478bd9Sstevel@tonic-gate static int32_t 3037c478bd9Sstevel@tonic-gate invalid_uscsi_operation(door_data_t *door_dp, struct uscsi_cmd *ucmd) 3047c478bd9Sstevel@tonic-gate { 3057c478bd9Sstevel@tonic-gate 3067c478bd9Sstevel@tonic-gate if (door_dp->dd_dkinfo.dki_ctype != DKC_CDROM) { 3077c478bd9Sstevel@tonic-gate debug(5, 3087c478bd9Sstevel@tonic-gate "Invalid device type(0x%x) found for uscsi cmd.\n", 3097c478bd9Sstevel@tonic-gate door_dp->dd_dkinfo.dki_ctype); 3107c478bd9Sstevel@tonic-gate errno = EINVAL; 3117c478bd9Sstevel@tonic-gate return (EINVAL); 3127c478bd9Sstevel@tonic-gate } 3137c478bd9Sstevel@tonic-gate if (ucmd->uscsi_flags & FORBIDDEN_FLAGS) { 3147c478bd9Sstevel@tonic-gate debug(5, 3157c478bd9Sstevel@tonic-gate "Invalid flags(0x%x) set in uscsi cmd. cdb[0]=0x%x\n", 3167c478bd9Sstevel@tonic-gate ucmd->uscsi_flags, ucmd->uscsi_cdb[0]); 3177c478bd9Sstevel@tonic-gate errno = EINVAL; 3187c478bd9Sstevel@tonic-gate return (EINVAL); 3197c478bd9Sstevel@tonic-gate } 3207c478bd9Sstevel@tonic-gate if (ucmd->uscsi_cdb[0] == SCMD_COPY || 3217c478bd9Sstevel@tonic-gate ucmd->uscsi_cdb[0] == SCMD_COPY_VERIFY || 3227c478bd9Sstevel@tonic-gate ucmd->uscsi_cdb[0] == SCMD_COMPARE || 3237c478bd9Sstevel@tonic-gate ucmd->uscsi_cdb[0] == SCMD_WRITE_BUFFER) { 3247c478bd9Sstevel@tonic-gate debug(5, 3257c478bd9Sstevel@tonic-gate "Invalid command(0x%x) found in cdb.\n", 3267c478bd9Sstevel@tonic-gate ucmd->uscsi_cdb[0]); 3277c478bd9Sstevel@tonic-gate errno = EINVAL; 3287c478bd9Sstevel@tonic-gate return (EINVAL); 3297c478bd9Sstevel@tonic-gate } 3307c478bd9Sstevel@tonic-gate return (0); 3317c478bd9Sstevel@tonic-gate } 3327c478bd9Sstevel@tonic-gate 3337c478bd9Sstevel@tonic-gate static uint32_t 3347c478bd9Sstevel@tonic-gate get_sector_size(int fd) 3357c478bd9Sstevel@tonic-gate { 3367c478bd9Sstevel@tonic-gate uint32_t sector_size; 3377c478bd9Sstevel@tonic-gate struct uscsi_cmd ucmd; 3387c478bd9Sstevel@tonic-gate union scsi_cdb cdb; 3397c478bd9Sstevel@tonic-gate int32_t ret_val; 3407c478bd9Sstevel@tonic-gate uint32_t rc_data[2]; 3417c478bd9Sstevel@tonic-gate char rq_data[RQ_LEN]; 3427c478bd9Sstevel@tonic-gate 3437c478bd9Sstevel@tonic-gate cdb.scc_cmd = SCMD_READ_CAPACITY; 3447c478bd9Sstevel@tonic-gate ucmd.uscsi_cdb = (caddr_t)&cdb; 3457c478bd9Sstevel@tonic-gate ucmd.uscsi_cdblen = CDB_GROUP1; 3467c478bd9Sstevel@tonic-gate ucmd.uscsi_bufaddr = (caddr_t)&rc_data; 3477c478bd9Sstevel@tonic-gate ucmd.uscsi_buflen = sizeof (rc_data); 3487c478bd9Sstevel@tonic-gate ucmd.uscsi_timeout = 120; /* If 0, HBA hangs forever */ 3497c478bd9Sstevel@tonic-gate ucmd.uscsi_rqlen = RQ_LEN; 3507c478bd9Sstevel@tonic-gate ucmd.uscsi_rqbuf = rq_data; 3517c478bd9Sstevel@tonic-gate 3527c478bd9Sstevel@tonic-gate ret_val = do_uscsi_cmd(fd, 3537c478bd9Sstevel@tonic-gate &ucmd, USCSI_READ|USCSI_RQENABLE); 3547c478bd9Sstevel@tonic-gate if (ret_val || ucmd.uscsi_status) { 3557c478bd9Sstevel@tonic-gate debug(5, "Read capacity : %d - %d errno = %d\n", 3567c478bd9Sstevel@tonic-gate ret_val, ucmd.uscsi_status, errno); 3577c478bd9Sstevel@tonic-gate sector_size = 512; 3587c478bd9Sstevel@tonic-gate } else { 3597c478bd9Sstevel@tonic-gate sector_size = ntohl(rc_data[1]); 3607c478bd9Sstevel@tonic-gate } 3617c478bd9Sstevel@tonic-gate debug(5, "sector size = 0x%x(%d)\n", 3627c478bd9Sstevel@tonic-gate sector_size, sector_size); 3637c478bd9Sstevel@tonic-gate return (sector_size); 3647c478bd9Sstevel@tonic-gate } 3657c478bd9Sstevel@tonic-gate 3667c478bd9Sstevel@tonic-gate static char * 3677c478bd9Sstevel@tonic-gate xlate_state(int32_t state) 3687c478bd9Sstevel@tonic-gate { 3697c478bd9Sstevel@tonic-gate switch (state) { 3707c478bd9Sstevel@tonic-gate 3717c478bd9Sstevel@tonic-gate case SM_WRITE_PROTECT_DISABLE: 3727c478bd9Sstevel@tonic-gate return ("PROTECTION_DISABLED"); 3737c478bd9Sstevel@tonic-gate case SM_WRITE_PROTECT_PASSWD: 3747c478bd9Sstevel@tonic-gate return ("WRITE_PROTECT_PASSWD"); 3757c478bd9Sstevel@tonic-gate case SM_WRITE_PROTECT_NOPASSWD: 3767c478bd9Sstevel@tonic-gate return ("WRITE_PROTECT_NOPASSWD"); 3777c478bd9Sstevel@tonic-gate case SM_READ_WRITE_PROTECT: 3787c478bd9Sstevel@tonic-gate return ("READ_WRITE_PROTECT"); 3797c478bd9Sstevel@tonic-gate case SM_TEMP_UNLOCK_MODE: 3807c478bd9Sstevel@tonic-gate return ("PROTECTION DISABLED"); 3817c478bd9Sstevel@tonic-gate default: 3827c478bd9Sstevel@tonic-gate return ("UNKNOWN_STATE"); 3837c478bd9Sstevel@tonic-gate } 3847c478bd9Sstevel@tonic-gate } 3857c478bd9Sstevel@tonic-gate 3867c478bd9Sstevel@tonic-gate static char * 3877c478bd9Sstevel@tonic-gate xlate_cnum(smedia_callnumber_t cnum) 3887c478bd9Sstevel@tonic-gate { 3897c478bd9Sstevel@tonic-gate switch (cnum) { 3907c478bd9Sstevel@tonic-gate 3917c478bd9Sstevel@tonic-gate case SMEDIA_CNUM_OPEN_FD: 3927c478bd9Sstevel@tonic-gate return ("SMEDIA_CNUM_OPEN_FD"); 3937c478bd9Sstevel@tonic-gate case SMEDIA_CNUM_GET_DEVICE_INFO: 3947c478bd9Sstevel@tonic-gate return ("SMEDIA_CNUM_GET_DEVICE_INFO"); 3957c478bd9Sstevel@tonic-gate case SMEDIA_CNUM_GET_MEDIUM_PROPERTY: 3967c478bd9Sstevel@tonic-gate return ("SMEDIA_CNUM_GET_MEDIUM_PROPERTY"); 3977c478bd9Sstevel@tonic-gate case SMEDIA_CNUM_GET_PROTECTION_STATUS: 3987c478bd9Sstevel@tonic-gate return ("SMEDIA_CNUM_GET_PROTECTION_STATUS"); 3997c478bd9Sstevel@tonic-gate case SMEDIA_CNUM_SET_PROTECTION_STATUS: 4007c478bd9Sstevel@tonic-gate return ("SMEDIA_CNUM_SET_PROTECTION_STATUS"); 4017c478bd9Sstevel@tonic-gate case SMEDIA_CNUM_RAW_READ: 4027c478bd9Sstevel@tonic-gate return ("SMEDIA_CNUM_RAW_READ"); 4037c478bd9Sstevel@tonic-gate case SMEDIA_CNUM_RAW_WRITE: 4047c478bd9Sstevel@tonic-gate return (" SMEDIA_CNUM_RAW_WRITE"); 4057c478bd9Sstevel@tonic-gate case SMEDIA_CNUM_FORMAT: 4067c478bd9Sstevel@tonic-gate return ("SMEDIA_CNUM_FORMAT"); 4077c478bd9Sstevel@tonic-gate case SMEDIA_CNUM_CHECK_FORMAT_STATUS: 4087c478bd9Sstevel@tonic-gate return ("SMEDIA_CNUM_CHECK_FORMAT_STATUS"); 4097c478bd9Sstevel@tonic-gate case SMEDIA_CNUM_EJECT: 4107c478bd9Sstevel@tonic-gate return ("SMEDIA_CNUM_EJECT"); 4117c478bd9Sstevel@tonic-gate case SMEDIA_CNUM_REASSIGN_BLOCK: 4127c478bd9Sstevel@tonic-gate return ("SMEDIA_CNUM_REASSIGN_BLOCK"); 4137c478bd9Sstevel@tonic-gate case SMEDIA_CNUM_SET_SHFD: 4147c478bd9Sstevel@tonic-gate return ("SMEDIA_CNUM_SET_SHFD"); 4157c478bd9Sstevel@tonic-gate case SMEDIA_CNUM_PING: 4167c478bd9Sstevel@tonic-gate return ("SMEDIA_CNUM_PING"); 4177c478bd9Sstevel@tonic-gate case SMEDIA_CNUM_USCSI_CMD: 4187c478bd9Sstevel@tonic-gate return ("SMEDIA_CNUM_USCSI_CMD"); 4197c478bd9Sstevel@tonic-gate default: 4207c478bd9Sstevel@tonic-gate return ("UNKNOWN_CNUM"); 4217c478bd9Sstevel@tonic-gate } 4227c478bd9Sstevel@tonic-gate } 4237c478bd9Sstevel@tonic-gate 4247c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 4257c478bd9Sstevel@tonic-gate smserver_info * 4267c478bd9Sstevel@tonic-gate smserverproc_get_serverinfo_1(void *argp, CLIENT *clnt) 4277c478bd9Sstevel@tonic-gate { 4287c478bd9Sstevel@tonic-gate (void) mutex_lock(&svcstate_lock); 4297c478bd9Sstevel@tonic-gate svcstate = _SERVED; 4307c478bd9Sstevel@tonic-gate (void) mutex_unlock(&svcstate_lock); 4317c478bd9Sstevel@tonic-gate server_info.vernum = SMSERVERVERS; 4327c478bd9Sstevel@tonic-gate server_info.status = 0; 4337c478bd9Sstevel@tonic-gate (void) mutex_lock(&server_data.sd_init_lock); 4347c478bd9Sstevel@tonic-gate if (server_data.sd_init_state == INIT_NOT_DONE) { 4357c478bd9Sstevel@tonic-gate server_data.sd_init_state = INIT_IN_PROGRESS; 4367c478bd9Sstevel@tonic-gate debug(5, "Initialising server\n"); 4377c478bd9Sstevel@tonic-gate (void) init_server(NULL); 4387c478bd9Sstevel@tonic-gate } 4397c478bd9Sstevel@tonic-gate if (server_data.sd_init_state != INIT_DONE) { 440*5363f09cSarutz debug(1, "init_server did not do the job. " 441*5363f09cSarutz "init_state=%d\n", server_data.sd_init_state); 4427c478bd9Sstevel@tonic-gate server_data.sd_init_state = INIT_NOT_DONE; 4437c478bd9Sstevel@tonic-gate (void) mutex_unlock(&server_data.sd_init_lock); 4447c478bd9Sstevel@tonic-gate server_info.status = -1; 4457c478bd9Sstevel@tonic-gate return (&server_info); 4467c478bd9Sstevel@tonic-gate } 4477c478bd9Sstevel@tonic-gate (void) mutex_unlock(&server_data.sd_init_lock); 4487c478bd9Sstevel@tonic-gate 4497c478bd9Sstevel@tonic-gate debug(5, "smserverproc thread %d running....\n", pthread_self()); 4507c478bd9Sstevel@tonic-gate return (&server_info); 4517c478bd9Sstevel@tonic-gate } 4527c478bd9Sstevel@tonic-gate 4537c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 4547c478bd9Sstevel@tonic-gate static void 4557c478bd9Sstevel@tonic-gate server_badsig_handler(int sig, siginfo_t *siginfo, void *sigctx) 4567c478bd9Sstevel@tonic-gate { 4577c478bd9Sstevel@tonic-gate 4587c478bd9Sstevel@tonic-gate fatal(gettext(BADSIG_MSG), pthread_self(), sig, siginfo->si_addr, 4597c478bd9Sstevel@tonic-gate siginfo->si_trapno, 4607c478bd9Sstevel@tonic-gate siginfo->si_pc); 4617c478bd9Sstevel@tonic-gate } 4627c478bd9Sstevel@tonic-gate 4637c478bd9Sstevel@tonic-gate static int32_t 4647c478bd9Sstevel@tonic-gate do_uscsi_cmd(int32_t file, struct uscsi_cmd *uscsi_cmd, int32_t flag) 4657c478bd9Sstevel@tonic-gate { 4667c478bd9Sstevel@tonic-gate int32_t ret_val; 4677c478bd9Sstevel@tonic-gate 4687c478bd9Sstevel@tonic-gate /* 4697c478bd9Sstevel@tonic-gate * Set function flags for driver. 4707c478bd9Sstevel@tonic-gate */ 4717c478bd9Sstevel@tonic-gate uscsi_cmd->uscsi_flags = USCSI_ISOLATE; 4727c478bd9Sstevel@tonic-gate 4737c478bd9Sstevel@tonic-gate #ifdef DEBUG 4747c478bd9Sstevel@tonic-gate uscsi_cmd->uscsi_flags |= USCSI_DIAGNOSE; 4757c478bd9Sstevel@tonic-gate #else 4767c478bd9Sstevel@tonic-gate uscsi_cmd->uscsi_flags |= USCSI_SILENT; 4777c478bd9Sstevel@tonic-gate #endif /* DEBUG */ 4787c478bd9Sstevel@tonic-gate 4797c478bd9Sstevel@tonic-gate uscsi_cmd->uscsi_flags |= flag; 4807c478bd9Sstevel@tonic-gate 4817c478bd9Sstevel@tonic-gate errno = 0; 4827c478bd9Sstevel@tonic-gate ret_val = ioctl(file, USCSICMD, uscsi_cmd); 4837c478bd9Sstevel@tonic-gate if (ret_val == 0 && uscsi_cmd->uscsi_status == 0) { 4847c478bd9Sstevel@tonic-gate return (ret_val); 4857c478bd9Sstevel@tonic-gate } 4867c478bd9Sstevel@tonic-gate if (!errno) 4877c478bd9Sstevel@tonic-gate errno = EIO; 4887c478bd9Sstevel@tonic-gate return (-1); 4897c478bd9Sstevel@tonic-gate } 4907c478bd9Sstevel@tonic-gate 4917c478bd9Sstevel@tonic-gate static int32_t 4927c478bd9Sstevel@tonic-gate get_device_type(char *v_name) 4937c478bd9Sstevel@tonic-gate { 4947c478bd9Sstevel@tonic-gate int32_t i; 4957c478bd9Sstevel@tonic-gate 4967c478bd9Sstevel@tonic-gate for (i = 0; i < 8; i++) { 4977c478bd9Sstevel@tonic-gate v_name[i] = toupper(v_name[i]); 4987c478bd9Sstevel@tonic-gate } 4997c478bd9Sstevel@tonic-gate if (strstr(v_name, "IOMEGA")) { 5007c478bd9Sstevel@tonic-gate return (SCSI_IOMEGA); 5017c478bd9Sstevel@tonic-gate } 5027c478bd9Sstevel@tonic-gate if (strstr(v_name, "FD") || 5037c478bd9Sstevel@tonic-gate strstr(v_name, "LS-120")) { 5047c478bd9Sstevel@tonic-gate return (SCSI_FLOPPY); 5057c478bd9Sstevel@tonic-gate } 5067c478bd9Sstevel@tonic-gate return (SCSI_GENERIC); 5077c478bd9Sstevel@tonic-gate 5087c478bd9Sstevel@tonic-gate } 5097c478bd9Sstevel@tonic-gate 5107c478bd9Sstevel@tonic-gate static int32_t 5117c478bd9Sstevel@tonic-gate get_device_type_scsi(int32_t fd, struct scsi_inquiry *inq) 5127c478bd9Sstevel@tonic-gate { 5137c478bd9Sstevel@tonic-gate int32_t dev_type; 5147c478bd9Sstevel@tonic-gate struct uscsi_cmd ucmd; 5157c478bd9Sstevel@tonic-gate union scsi_cdb cdb; 5167c478bd9Sstevel@tonic-gate int32_t ret_val; 5177c478bd9Sstevel@tonic-gate char rq_data[RQ_LEN]; 5187c478bd9Sstevel@tonic-gate 5197c478bd9Sstevel@tonic-gate (void) memset((void *) inq, 0, sizeof (struct scsi_inquiry)); 5207c478bd9Sstevel@tonic-gate (void) memset((void *) &ucmd, 0, sizeof (ucmd)); 5217c478bd9Sstevel@tonic-gate (void) memset((void *) &cdb, 0, sizeof (union scsi_cdb)); 5227c478bd9Sstevel@tonic-gate cdb.scc_cmd = SCMD_INQUIRY; 5237c478bd9Sstevel@tonic-gate FORMG0COUNT(&cdb, sizeof (struct scsi_inquiry)); 5247c478bd9Sstevel@tonic-gate ucmd.uscsi_cdb = (caddr_t)&cdb; 5257c478bd9Sstevel@tonic-gate ucmd.uscsi_cdblen = CDB_GROUP0; 5267c478bd9Sstevel@tonic-gate ucmd.uscsi_bufaddr = (caddr_t)inq; 5277c478bd9Sstevel@tonic-gate ucmd.uscsi_buflen = sizeof (struct scsi_inquiry); 5287c478bd9Sstevel@tonic-gate ucmd.uscsi_timeout = 120; /* If 0, HBA hangs forever */ 5297c478bd9Sstevel@tonic-gate ucmd.uscsi_rqlen = RQ_LEN; 5307c478bd9Sstevel@tonic-gate ucmd.uscsi_rqbuf = rq_data; 5317c478bd9Sstevel@tonic-gate ret_val = do_uscsi_cmd(fd, &ucmd, USCSI_READ|USCSI_RQENABLE); 5327c478bd9Sstevel@tonic-gate if (ret_val || ucmd.uscsi_status) { 533*5363f09cSarutz debug(5, "INQUIRY failed: rv = %d uscsi_status = " 534*5363f09cSarutz "%d errno = %d\n", ret_val, ucmd.uscsi_status, errno); 5357c478bd9Sstevel@tonic-gate return (-1); 5367c478bd9Sstevel@tonic-gate } 5377c478bd9Sstevel@tonic-gate 5387c478bd9Sstevel@tonic-gate dev_type = get_device_type(inq->inq_vid); 5397c478bd9Sstevel@tonic-gate 5407c478bd9Sstevel@tonic-gate debug(5, "dev_type %d\n", dev_type); 5417c478bd9Sstevel@tonic-gate return (dev_type); 5427c478bd9Sstevel@tonic-gate 5437c478bd9Sstevel@tonic-gate } 5447c478bd9Sstevel@tonic-gate 5457c478bd9Sstevel@tonic-gate static int32_t 5467c478bd9Sstevel@tonic-gate get_media_capacity(int32_t fd, uint32_t *capacity, uint32_t *blocksize) 5477c478bd9Sstevel@tonic-gate { 5487c478bd9Sstevel@tonic-gate struct uscsi_cmd ucmd; 5497c478bd9Sstevel@tonic-gate uchar_t cdb[12]; 5507c478bd9Sstevel@tonic-gate int32_t ret_val; 5517c478bd9Sstevel@tonic-gate uchar_t data[20]; 5527c478bd9Sstevel@tonic-gate char rq_data[RQ_LEN]; 5537c478bd9Sstevel@tonic-gate 5547c478bd9Sstevel@tonic-gate debug(5, "get_media_capacity:\n"); 5557c478bd9Sstevel@tonic-gate 5567c478bd9Sstevel@tonic-gate (void) memset((void *)&data, 0, sizeof (data)); 5577c478bd9Sstevel@tonic-gate (void) memset((void *)&ucmd, 0, sizeof (ucmd)); 5587c478bd9Sstevel@tonic-gate (void) memset((void *)&cdb, 0, sizeof (cdb)); 5597c478bd9Sstevel@tonic-gate 5607c478bd9Sstevel@tonic-gate /* retrieve size discriptor of inserted media */ 5617c478bd9Sstevel@tonic-gate cdb[0] = SCMD_READ_FORMAT_CAP; 5627c478bd9Sstevel@tonic-gate cdb[8] = 0x14; /* data size */ 5637c478bd9Sstevel@tonic-gate 5647c478bd9Sstevel@tonic-gate /* Fill in the USCSI fields */ 5657c478bd9Sstevel@tonic-gate ucmd.uscsi_cdb = (caddr_t)&cdb; 5667c478bd9Sstevel@tonic-gate ucmd.uscsi_cdblen = CDB_GROUP5; 5677c478bd9Sstevel@tonic-gate ucmd.uscsi_bufaddr = (caddr_t)data; 5687c478bd9Sstevel@tonic-gate ucmd.uscsi_buflen = sizeof (data); 5697c478bd9Sstevel@tonic-gate ucmd.uscsi_timeout = 120; 5707c478bd9Sstevel@tonic-gate ucmd.uscsi_rqlen = RQ_LEN; 5717c478bd9Sstevel@tonic-gate ucmd.uscsi_rqbuf = rq_data; 5727c478bd9Sstevel@tonic-gate ret_val = do_uscsi_cmd(fd, &ucmd, USCSI_READ|USCSI_RQENABLE); 5737c478bd9Sstevel@tonic-gate 5747c478bd9Sstevel@tonic-gate if (ret_val || ucmd.uscsi_status) { 5757c478bd9Sstevel@tonic-gate debug(5, "Retrieving media info failed: %d - %d\n", ret_val, 5767c478bd9Sstevel@tonic-gate ucmd.uscsi_status); 5777c478bd9Sstevel@tonic-gate 5787c478bd9Sstevel@tonic-gate if ((rq_data[2] == KEY_DATA_PROTECT) && (rq_data[12] == 0x30) && 5797c478bd9Sstevel@tonic-gate (rq_data[13] == 0)) { 5807c478bd9Sstevel@tonic-gate (void) debug(1, "Invalid command for media\n"); 5817c478bd9Sstevel@tonic-gate errno = EINVAL; 5827c478bd9Sstevel@tonic-gate } 5837c478bd9Sstevel@tonic-gate return (-1); 5847c478bd9Sstevel@tonic-gate } 5857c478bd9Sstevel@tonic-gate 5867c478bd9Sstevel@tonic-gate /* No media, bail out */ 5877c478bd9Sstevel@tonic-gate if (data[8] == 0x3) { 5887c478bd9Sstevel@tonic-gate (void) debug(5, "no media in drive\n"); 5897c478bd9Sstevel@tonic-gate return (-1); 5907c478bd9Sstevel@tonic-gate } 5917c478bd9Sstevel@tonic-gate 5927c478bd9Sstevel@tonic-gate /* 5937c478bd9Sstevel@tonic-gate * Generate capacity and blocksize information 5947c478bd9Sstevel@tonic-gate */ 5957c478bd9Sstevel@tonic-gate 5967c478bd9Sstevel@tonic-gate *capacity = (uint32_t)((data[4] << 24) + (data[5] << 16) + 5977c478bd9Sstevel@tonic-gate (data[6] << 8) + data[7]); 5987c478bd9Sstevel@tonic-gate 5997c478bd9Sstevel@tonic-gate debug(1, "capacity is %x %x %x %x = %x", data[4], data[5], data[6], 6007c478bd9Sstevel@tonic-gate data[7], *capacity); 6017c478bd9Sstevel@tonic-gate 6027c478bd9Sstevel@tonic-gate *blocksize = (uint32_t)((data[9] << 16) + (data[10] << 8) + data[11]); 6037c478bd9Sstevel@tonic-gate 6047c478bd9Sstevel@tonic-gate return (0); 6057c478bd9Sstevel@tonic-gate } 6067c478bd9Sstevel@tonic-gate 6077c478bd9Sstevel@tonic-gate static int32_t 6087c478bd9Sstevel@tonic-gate scsi_zip_format(int32_t fd, uint_t flavor, uint_t mode) 6097c478bd9Sstevel@tonic-gate { 6107c478bd9Sstevel@tonic-gate struct uscsi_cmd ucmd; 6117c478bd9Sstevel@tonic-gate struct scsi_inquiry inq; 6127c478bd9Sstevel@tonic-gate uchar_t cdb[12]; 6137c478bd9Sstevel@tonic-gate int32_t ret_val; 6147c478bd9Sstevel@tonic-gate uchar_t data[4]; 6157c478bd9Sstevel@tonic-gate uint32_t rc_data[2]; 6167c478bd9Sstevel@tonic-gate char rq_data[RQ_LEN]; 6177c478bd9Sstevel@tonic-gate uint32_t capacity; 6187c478bd9Sstevel@tonic-gate 6197c478bd9Sstevel@tonic-gate 6207c478bd9Sstevel@tonic-gate if ((mode != SM_FORMAT_IMMEDIATE) && 6217c478bd9Sstevel@tonic-gate (mode != SM_FORMAT_BLOCKED)) { 6227c478bd9Sstevel@tonic-gate errno = ENOTSUP; 6237c478bd9Sstevel@tonic-gate return (ENOTSUP); 6247c478bd9Sstevel@tonic-gate } 6257c478bd9Sstevel@tonic-gate /* 6267c478bd9Sstevel@tonic-gate * Do an inquiry and try to figure out if it an 6277c478bd9Sstevel@tonic-gate * IOMEGA JAZ 2GB device. 6287c478bd9Sstevel@tonic-gate */ 6297c478bd9Sstevel@tonic-gate 6307c478bd9Sstevel@tonic-gate (void) memset((void *) &inq, 0, sizeof (inq)); 6317c478bd9Sstevel@tonic-gate (void) memset((void *) &ucmd, 0, sizeof (ucmd)); 6327c478bd9Sstevel@tonic-gate (void) memset((void *) &cdb, 0, sizeof (cdb)); 6337c478bd9Sstevel@tonic-gate (void) memset((void *) &rq_data, 0, sizeof (rq_data)); 6347c478bd9Sstevel@tonic-gate cdb[0] = SCMD_INQUIRY; 6357c478bd9Sstevel@tonic-gate cdb[4] = sizeof (inq); 6367c478bd9Sstevel@tonic-gate ucmd.uscsi_cdb = (caddr_t)&cdb; 6377c478bd9Sstevel@tonic-gate ucmd.uscsi_cdblen = CDB_GROUP0; 6387c478bd9Sstevel@tonic-gate ucmd.uscsi_bufaddr = (caddr_t)&inq; 6397c478bd9Sstevel@tonic-gate ucmd.uscsi_buflen = sizeof (inq); 6407c478bd9Sstevel@tonic-gate ucmd.uscsi_timeout = 120; /* If 0, HBA hangs forever */ 6417c478bd9Sstevel@tonic-gate ucmd.uscsi_rqlen = RQ_LEN; 6427c478bd9Sstevel@tonic-gate ucmd.uscsi_rqbuf = rq_data; 6437c478bd9Sstevel@tonic-gate ret_val = do_uscsi_cmd(fd, &ucmd, USCSI_READ|USCSI_RQENABLE); 6447c478bd9Sstevel@tonic-gate if (ret_val || ucmd.uscsi_status) { 6457c478bd9Sstevel@tonic-gate debug(5, "inquiry failed: %d - %d errno = %d\n", 6467c478bd9Sstevel@tonic-gate ret_val, ucmd.uscsi_status, errno); 6477c478bd9Sstevel@tonic-gate return (ucmd.uscsi_status); 6487c478bd9Sstevel@tonic-gate } 6497c478bd9Sstevel@tonic-gate 6507c478bd9Sstevel@tonic-gate (void) memset((void *) &rc_data, 0, sizeof (rc_data)); 6517c478bd9Sstevel@tonic-gate (void) memset((void *) &ucmd, 0, sizeof (ucmd)); 6527c478bd9Sstevel@tonic-gate (void) memset((void *) &cdb, 0, sizeof (cdb)); 6537c478bd9Sstevel@tonic-gate cdb[0] = SCMD_READ_CAPACITY; 6547c478bd9Sstevel@tonic-gate ucmd.uscsi_cdb = (caddr_t)&cdb; 6557c478bd9Sstevel@tonic-gate ucmd.uscsi_cdblen = CDB_GROUP1; 6567c478bd9Sstevel@tonic-gate ucmd.uscsi_bufaddr = (caddr_t)&rc_data; 6577c478bd9Sstevel@tonic-gate ucmd.uscsi_buflen = sizeof (rc_data); 6587c478bd9Sstevel@tonic-gate ucmd.uscsi_timeout = 120; /* If 0, HBA hangs forever */ 6597c478bd9Sstevel@tonic-gate 6607c478bd9Sstevel@tonic-gate ret_val = do_uscsi_cmd(fd, &ucmd, USCSI_READ); 6617c478bd9Sstevel@tonic-gate if (ret_val || ucmd.uscsi_status) { 6627c478bd9Sstevel@tonic-gate debug(5, "Read capacity : %d - %d errno = %d\n", 6637c478bd9Sstevel@tonic-gate ret_val, ucmd.uscsi_status, errno); 6647c478bd9Sstevel@tonic-gate return (ucmd.uscsi_status); 6657c478bd9Sstevel@tonic-gate } 6667c478bd9Sstevel@tonic-gate 6677c478bd9Sstevel@tonic-gate capacity = ntohl(rc_data[0]); 6687c478bd9Sstevel@tonic-gate 6697c478bd9Sstevel@tonic-gate (void) memset((void *)&data, 0, sizeof (data)); 6707c478bd9Sstevel@tonic-gate (void) memset((void *)&ucmd, 0, sizeof (ucmd)); 6717c478bd9Sstevel@tonic-gate (void) memset((void *)&cdb, 0, sizeof (cdb)); 6727c478bd9Sstevel@tonic-gate cdb[0] = SCMD_FORMAT; 6737c478bd9Sstevel@tonic-gate /* 6747c478bd9Sstevel@tonic-gate * Defect list sent by initiator is a complete list of defects. 6757c478bd9Sstevel@tonic-gate */ 6767c478bd9Sstevel@tonic-gate cdb[1] = (FMTDATA | CMPLIST); 6777c478bd9Sstevel@tonic-gate /* 6787c478bd9Sstevel@tonic-gate * Target should examine the setting of the DPRY, DCRT, STPF, IP 6797c478bd9Sstevel@tonic-gate * and DSP bits. 6807c478bd9Sstevel@tonic-gate */ 6817c478bd9Sstevel@tonic-gate data[1] = FOV; 6827c478bd9Sstevel@tonic-gate 6837c478bd9Sstevel@tonic-gate switch (flavor) { 6847c478bd9Sstevel@tonic-gate case SM_FORMAT_QUICK : 6857c478bd9Sstevel@tonic-gate /* 6867c478bd9Sstevel@tonic-gate * Target should not perform any vendor specific 6877c478bd9Sstevel@tonic-gate * medium certification process or format verification 6887c478bd9Sstevel@tonic-gate */ 6897c478bd9Sstevel@tonic-gate data[1] = (FOV | DCRT); 6907c478bd9Sstevel@tonic-gate /* 6917c478bd9Sstevel@tonic-gate * Defect list sent is an addition to the existing 6927c478bd9Sstevel@tonic-gate * list of defects. 6937c478bd9Sstevel@tonic-gate */ 6947c478bd9Sstevel@tonic-gate cdb[1] = FMTDATA; 6957c478bd9Sstevel@tonic-gate break; 6967c478bd9Sstevel@tonic-gate case SM_FORMAT_FORCE : 6977c478bd9Sstevel@tonic-gate if (strstr(inq.inq_pid, "jaz")) { 6987c478bd9Sstevel@tonic-gate debug(1, 6997c478bd9Sstevel@tonic-gate "LONG Format of JAZ media not supported\n"); 7007c478bd9Sstevel@tonic-gate errno = ENOTSUP; 7017c478bd9Sstevel@tonic-gate return (ENOTSUP); 7027c478bd9Sstevel@tonic-gate } 7037c478bd9Sstevel@tonic-gate /* 7047c478bd9Sstevel@tonic-gate * Formatting a write-protected or read/write 7057c478bd9Sstevel@tonic-gate * protected cartridge is allowed. 7067c478bd9Sstevel@tonic-gate * This is a vendor specific Format Option. 7077c478bd9Sstevel@tonic-gate */ 7087c478bd9Sstevel@tonic-gate cdb[2] = 0x20; 7097c478bd9Sstevel@tonic-gate break; 7107c478bd9Sstevel@tonic-gate case SM_FORMAT_LONG : 7117c478bd9Sstevel@tonic-gate if (strstr(inq.inq_pid, "jaz")) { 7127c478bd9Sstevel@tonic-gate debug(1, 7137c478bd9Sstevel@tonic-gate "LONG Format of JAZ media not supported\n"); 7147c478bd9Sstevel@tonic-gate errno = ENOTSUP; 7157c478bd9Sstevel@tonic-gate return (ENOTSUP); 7167c478bd9Sstevel@tonic-gate } 7177c478bd9Sstevel@tonic-gate /* 7187c478bd9Sstevel@tonic-gate * Defect list sent is an addition to the existing 7197c478bd9Sstevel@tonic-gate * list of defects. 7207c478bd9Sstevel@tonic-gate */ 7217c478bd9Sstevel@tonic-gate cdb[1] = FMTDATA; 7227c478bd9Sstevel@tonic-gate break; 7237c478bd9Sstevel@tonic-gate default : 7247c478bd9Sstevel@tonic-gate debug(1, "Format option %d not supported!!\n", 7257c478bd9Sstevel@tonic-gate flavor); 7267c478bd9Sstevel@tonic-gate errno = ENOTSUP; 7277c478bd9Sstevel@tonic-gate return (ENOTSUP); 7287c478bd9Sstevel@tonic-gate } 7297c478bd9Sstevel@tonic-gate 7307c478bd9Sstevel@tonic-gate if (mode == SM_FORMAT_IMMEDIATE) { 7317c478bd9Sstevel@tonic-gate data[1] |= IMMED; 7327c478bd9Sstevel@tonic-gate debug(5, "immediate_flag set\n"); 7337c478bd9Sstevel@tonic-gate } 7347c478bd9Sstevel@tonic-gate 7357c478bd9Sstevel@tonic-gate ucmd.uscsi_cdb = (caddr_t)&cdb; 7367c478bd9Sstevel@tonic-gate debug(5, "cdb: %x ", cdb[0]); 7377c478bd9Sstevel@tonic-gate debug(5, "%x %x ", cdb[1], cdb[2]); 7387c478bd9Sstevel@tonic-gate debug(5, "%x %x %x\n", cdb[3], cdb[4], cdb[5]); 7397c478bd9Sstevel@tonic-gate debug(5, "data: %x %x %x %x\n", data[0], data[1], data[2], data[3]); 7407c478bd9Sstevel@tonic-gate 7417c478bd9Sstevel@tonic-gate ucmd.uscsi_cdblen = CDB_GROUP0; 7427c478bd9Sstevel@tonic-gate ucmd.uscsi_bufaddr = (caddr_t)data; 7437c478bd9Sstevel@tonic-gate ucmd.uscsi_buflen = sizeof (data); 7447c478bd9Sstevel@tonic-gate ucmd.uscsi_timeout = FORMAT_TIMEOUT(capacity); 7457c478bd9Sstevel@tonic-gate ucmd.uscsi_rqlen = RQ_LEN; 7467c478bd9Sstevel@tonic-gate ucmd.uscsi_rqbuf = rq_data; 7477c478bd9Sstevel@tonic-gate ret_val = do_uscsi_cmd(fd, &ucmd, USCSI_WRITE|USCSI_RQENABLE); 7487c478bd9Sstevel@tonic-gate if (ret_val || ucmd.uscsi_status) { 7497c478bd9Sstevel@tonic-gate debug(5, "Format failed : %d - uscsi_status = %d errno = %d\n", 7507c478bd9Sstevel@tonic-gate ret_val, 7517c478bd9Sstevel@tonic-gate ucmd.uscsi_status, errno); 7527c478bd9Sstevel@tonic-gate if ((rq_data[2] == KEY_DATA_PROTECT) || 7537c478bd9Sstevel@tonic-gate (rq_data[2] == KEY_ILLEGAL_REQUEST)) 7547c478bd9Sstevel@tonic-gate errno = EINVAL; 7557c478bd9Sstevel@tonic-gate if ((rq_data[2] == KEY_MEDIUM_ERROR) || 7567c478bd9Sstevel@tonic-gate (rq_data[2] == KEY_HARDWARE_ERROR)) 7577c478bd9Sstevel@tonic-gate errno = EIO; 7587c478bd9Sstevel@tonic-gate return (errno); 7597c478bd9Sstevel@tonic-gate } 7607c478bd9Sstevel@tonic-gate 7617c478bd9Sstevel@tonic-gate return (0); 7627c478bd9Sstevel@tonic-gate } 7637c478bd9Sstevel@tonic-gate 7647c478bd9Sstevel@tonic-gate static int32_t 7657c478bd9Sstevel@tonic-gate scsi_ls120_format(uint_t fd, uint_t flavor, uint32_t capacity, 7667c478bd9Sstevel@tonic-gate uint32_t blocksize) 7677c478bd9Sstevel@tonic-gate { 7687c478bd9Sstevel@tonic-gate struct uscsi_cmd ucmd; 7697c478bd9Sstevel@tonic-gate uchar_t cdb[12]; 7707c478bd9Sstevel@tonic-gate int32_t ret_val; 7717c478bd9Sstevel@tonic-gate uchar_t data[12]; 7727c478bd9Sstevel@tonic-gate char rq_data[RQ_LEN]; 7737c478bd9Sstevel@tonic-gate 7747c478bd9Sstevel@tonic-gate debug(5, "scsi_ls120_format:\n"); 7757c478bd9Sstevel@tonic-gate 7767c478bd9Sstevel@tonic-gate (void) memset((void *) &ucmd, 0, sizeof (ucmd)); 7777c478bd9Sstevel@tonic-gate (void) memset((void *) &cdb, 0, sizeof (cdb)); 7787c478bd9Sstevel@tonic-gate (void) memset((void *) &rq_data, 0, sizeof (rq_data)); 7797c478bd9Sstevel@tonic-gate 7807c478bd9Sstevel@tonic-gate cdb[0] = SCMD_FORMAT; 7817c478bd9Sstevel@tonic-gate cdb[1] = (FMTDATA | 0x7); 7827c478bd9Sstevel@tonic-gate cdb[8] = 0x0C; /* parameter list length */ 7837c478bd9Sstevel@tonic-gate 7847c478bd9Sstevel@tonic-gate data[1] = 0x80; 7857c478bd9Sstevel@tonic-gate data[3] = 0x08; 7867c478bd9Sstevel@tonic-gate 7877c478bd9Sstevel@tonic-gate 7887c478bd9Sstevel@tonic-gate data[4] = (capacity >> 24) & 0xff; 7897c478bd9Sstevel@tonic-gate data[5] = (capacity >> 16) & 0xff; 7907c478bd9Sstevel@tonic-gate data[6] = (capacity >> 8) & 0xff; 7917c478bd9Sstevel@tonic-gate data[7] = capacity & 0xff; 7927c478bd9Sstevel@tonic-gate 7937c478bd9Sstevel@tonic-gate 7947c478bd9Sstevel@tonic-gate data[9] = (blocksize >> 16) & 0xff; 7957c478bd9Sstevel@tonic-gate data[10] = (blocksize >> 8) & 0xff; 7967c478bd9Sstevel@tonic-gate data[11] = blocksize & 0xff; 7977c478bd9Sstevel@tonic-gate 7987c478bd9Sstevel@tonic-gate debug(5, "cdb: %x %x %x ... %x", cdb[0], cdb[1], cdb[2], cdb[8]); 7997c478bd9Sstevel@tonic-gate debug(5, "data: %x %x %x %x\n", data[0], data[1], data[2], data[3]); 8007c478bd9Sstevel@tonic-gate debug(5, " : %x %x %x %x\n", data[4], data[5], data[6], data[7]); 8017c478bd9Sstevel@tonic-gate debug(5, " : %x %x %x %x\n", data[8], data[9], data[10], data[11]); 8027c478bd9Sstevel@tonic-gate 8037c478bd9Sstevel@tonic-gate switch (flavor) { 8047c478bd9Sstevel@tonic-gate case SM_FORMAT_QUICK : 8057c478bd9Sstevel@tonic-gate debug(1, "Format not supported\n"); 8067c478bd9Sstevel@tonic-gate errno = ENOTSUP; 8077c478bd9Sstevel@tonic-gate return (-1); 8087c478bd9Sstevel@tonic-gate case SM_FORMAT_FORCE : 8097c478bd9Sstevel@tonic-gate break; 8107c478bd9Sstevel@tonic-gate case SM_FORMAT_LONG : 8117c478bd9Sstevel@tonic-gate break; 8127c478bd9Sstevel@tonic-gate default : 8137c478bd9Sstevel@tonic-gate debug(1, "Format option not specified!!\n"); 8147c478bd9Sstevel@tonic-gate errno = ENOTSUP; 8157c478bd9Sstevel@tonic-gate return (-1); 8167c478bd9Sstevel@tonic-gate } 8177c478bd9Sstevel@tonic-gate 8187c478bd9Sstevel@tonic-gate ucmd.uscsi_cdb = (caddr_t)&cdb; 8197c478bd9Sstevel@tonic-gate 8207c478bd9Sstevel@tonic-gate 8217c478bd9Sstevel@tonic-gate ucmd.uscsi_cdblen = CDB_GROUP5; 8227c478bd9Sstevel@tonic-gate ucmd.uscsi_bufaddr = (caddr_t)data; 8237c478bd9Sstevel@tonic-gate ucmd.uscsi_buflen = sizeof (data); 8247c478bd9Sstevel@tonic-gate ucmd.uscsi_timeout = 0x12c0; 8257c478bd9Sstevel@tonic-gate ucmd.uscsi_rqlen = RQ_LEN; 8267c478bd9Sstevel@tonic-gate ucmd.uscsi_rqbuf = rq_data; 8277c478bd9Sstevel@tonic-gate (void) fflush(stdout); 8287c478bd9Sstevel@tonic-gate 8297c478bd9Sstevel@tonic-gate ret_val = do_uscsi_cmd(fd, &ucmd, USCSI_WRITE|USCSI_RQENABLE); 8307c478bd9Sstevel@tonic-gate if (ret_val || ucmd.uscsi_status) { 8317c478bd9Sstevel@tonic-gate debug(1, "Format failed failed: %d - %d\n", ret_val, 8327c478bd9Sstevel@tonic-gate ucmd.uscsi_status); 8337c478bd9Sstevel@tonic-gate 8347c478bd9Sstevel@tonic-gate if ((rq_data[2] == KEY_DATA_PROTECT) && 8357c478bd9Sstevel@tonic-gate (rq_data[12] == 0x30) && (rq_data[13] == 0)) { 8367c478bd9Sstevel@tonic-gate 8377c478bd9Sstevel@tonic-gate debug(1, "Invalid command for media\n"); 8387c478bd9Sstevel@tonic-gate errno = EINVAL; 8397c478bd9Sstevel@tonic-gate } 8407c478bd9Sstevel@tonic-gate 8417c478bd9Sstevel@tonic-gate if ((rq_data[2] == KEY_NOT_READY) && (rq_data[12] == 0x30)) { 8427c478bd9Sstevel@tonic-gate debug(1, "Incompatible media.\n"); 8437c478bd9Sstevel@tonic-gate errno = EINVAL; 8447c478bd9Sstevel@tonic-gate } 8457c478bd9Sstevel@tonic-gate 8467c478bd9Sstevel@tonic-gate return (-1); 8477c478bd9Sstevel@tonic-gate } 8487c478bd9Sstevel@tonic-gate 8497c478bd9Sstevel@tonic-gate return (0); 8507c478bd9Sstevel@tonic-gate } 8517c478bd9Sstevel@tonic-gate 8527c478bd9Sstevel@tonic-gate static int32_t 8537c478bd9Sstevel@tonic-gate scsi_format(int32_t fd, uint_t flavor, uint_t mode) 8547c478bd9Sstevel@tonic-gate { 8557c478bd9Sstevel@tonic-gate struct uscsi_cmd ucmd; 8567c478bd9Sstevel@tonic-gate struct scsi_inquiry inq; 8577c478bd9Sstevel@tonic-gate uchar_t cdb[12]; 8587c478bd9Sstevel@tonic-gate int32_t ret_val; 8597c478bd9Sstevel@tonic-gate uchar_t data[4]; 8607c478bd9Sstevel@tonic-gate char rq_data[RQ_LEN]; 8617c478bd9Sstevel@tonic-gate uint32_t rc_data[2]; 8627c478bd9Sstevel@tonic-gate uint32_t capacity; 8637c478bd9Sstevel@tonic-gate 8647c478bd9Sstevel@tonic-gate 8657c478bd9Sstevel@tonic-gate 8667c478bd9Sstevel@tonic-gate if ((mode != SM_FORMAT_IMMEDIATE) && 8677c478bd9Sstevel@tonic-gate (mode != SM_FORMAT_BLOCKED)) { 8687c478bd9Sstevel@tonic-gate errno = ENOTSUP; 8697c478bd9Sstevel@tonic-gate return (-1); 8707c478bd9Sstevel@tonic-gate } 8717c478bd9Sstevel@tonic-gate 8727c478bd9Sstevel@tonic-gate /* 8737c478bd9Sstevel@tonic-gate * Do an inquiry and try to figure out if it an 8747c478bd9Sstevel@tonic-gate * IOMEGA JAZ 2GB device. 8757c478bd9Sstevel@tonic-gate */ 8767c478bd9Sstevel@tonic-gate 8777c478bd9Sstevel@tonic-gate (void) memset((void *) &inq, 0, sizeof (inq)); 8787c478bd9Sstevel@tonic-gate (void) memset((void *) &ucmd, 0, sizeof (ucmd)); 8797c478bd9Sstevel@tonic-gate (void) memset((void *) &cdb, 0, sizeof (cdb)); 8807c478bd9Sstevel@tonic-gate (void) memset((void *) &rq_data, 0, sizeof (rq_data)); 8817c478bd9Sstevel@tonic-gate cdb[0] = SCMD_INQUIRY; 8827c478bd9Sstevel@tonic-gate cdb[4] = sizeof (inq); 8837c478bd9Sstevel@tonic-gate ucmd.uscsi_cdb = (caddr_t)&cdb; 8847c478bd9Sstevel@tonic-gate ucmd.uscsi_cdblen = CDB_GROUP0; 8857c478bd9Sstevel@tonic-gate ucmd.uscsi_bufaddr = (caddr_t)&inq; 8867c478bd9Sstevel@tonic-gate ucmd.uscsi_buflen = sizeof (inq); 8877c478bd9Sstevel@tonic-gate ucmd.uscsi_timeout = 120; /* If 0, HBA hangs forever */ 8887c478bd9Sstevel@tonic-gate ucmd.uscsi_rqlen = RQ_LEN; 8897c478bd9Sstevel@tonic-gate ucmd.uscsi_rqbuf = rq_data; 8907c478bd9Sstevel@tonic-gate ret_val = do_uscsi_cmd(fd, &ucmd, USCSI_READ|USCSI_RQENABLE); 8917c478bd9Sstevel@tonic-gate if (ret_val || ucmd.uscsi_status) { 8927c478bd9Sstevel@tonic-gate debug(5, "inquiry failed: %d - %d errno = %d\n", 8937c478bd9Sstevel@tonic-gate ret_val, ucmd.uscsi_status, errno); 8947c478bd9Sstevel@tonic-gate return (ucmd.uscsi_status); 8957c478bd9Sstevel@tonic-gate } 8967c478bd9Sstevel@tonic-gate 8977c478bd9Sstevel@tonic-gate (void) memset((void *) &rc_data, 0, sizeof (rc_data)); 8987c478bd9Sstevel@tonic-gate (void) memset((void *) &ucmd, 0, sizeof (ucmd)); 8997c478bd9Sstevel@tonic-gate (void) memset((void *) &cdb, 0, sizeof (cdb)); 9007c478bd9Sstevel@tonic-gate cdb[0] = SCMD_READ_CAPACITY; 9017c478bd9Sstevel@tonic-gate ucmd.uscsi_cdb = (caddr_t)&cdb; 9027c478bd9Sstevel@tonic-gate ucmd.uscsi_cdblen = CDB_GROUP1; 9037c478bd9Sstevel@tonic-gate ucmd.uscsi_bufaddr = (caddr_t)&rc_data; 9047c478bd9Sstevel@tonic-gate ucmd.uscsi_buflen = sizeof (rc_data); 9057c478bd9Sstevel@tonic-gate ucmd.uscsi_timeout = 120; /* If 0, HBA hangs forever */ 9067c478bd9Sstevel@tonic-gate 9077c478bd9Sstevel@tonic-gate ret_val = do_uscsi_cmd(fd, &ucmd, USCSI_READ); 9087c478bd9Sstevel@tonic-gate if (ret_val || ucmd.uscsi_status) { 9097c478bd9Sstevel@tonic-gate debug(5, "Read capacity : %d - %d errno = %d\n", 9107c478bd9Sstevel@tonic-gate ret_val, ucmd.uscsi_status, errno); 9117c478bd9Sstevel@tonic-gate return (ucmd.uscsi_status); 9127c478bd9Sstevel@tonic-gate } 9137c478bd9Sstevel@tonic-gate 9147c478bd9Sstevel@tonic-gate capacity = ntohl(rc_data[0]); 9157c478bd9Sstevel@tonic-gate 9167c478bd9Sstevel@tonic-gate (void) memset((void *)&data, 0, sizeof (data)); 9177c478bd9Sstevel@tonic-gate (void) memset((void *)&ucmd, 0, sizeof (ucmd)); 9187c478bd9Sstevel@tonic-gate (void) memset((void *)&cdb, 0, sizeof (cdb)); 9197c478bd9Sstevel@tonic-gate cdb[0] = SCMD_FORMAT; 9207c478bd9Sstevel@tonic-gate /* 9217c478bd9Sstevel@tonic-gate * Defect list sent is an addition to the existing 9227c478bd9Sstevel@tonic-gate * list of defects. 9237c478bd9Sstevel@tonic-gate */ 9247c478bd9Sstevel@tonic-gate cdb[1] = FMTDATA; 9257c478bd9Sstevel@tonic-gate /* 9267c478bd9Sstevel@tonic-gate * Target should examine the setting of the DPRY, DCRT, STPF, IP 9277c478bd9Sstevel@tonic-gate * and DSP bits. 9287c478bd9Sstevel@tonic-gate */ 9297c478bd9Sstevel@tonic-gate data[1] = FOV; 9307c478bd9Sstevel@tonic-gate 9317c478bd9Sstevel@tonic-gate if (mode == SM_FORMAT_IMMEDIATE) { 9327c478bd9Sstevel@tonic-gate debug(5, 9337c478bd9Sstevel@tonic-gate "SM_FORMAT_IMMEDIATE specified ignored. Performing a long format!\n"); 9347c478bd9Sstevel@tonic-gate } 9357c478bd9Sstevel@tonic-gate 9367c478bd9Sstevel@tonic-gate switch (flavor) { 9377c478bd9Sstevel@tonic-gate case SM_FORMAT_LONG : 9387c478bd9Sstevel@tonic-gate if (strstr(inq.inq_pid, "jaz")) { 9397c478bd9Sstevel@tonic-gate debug(1, 9407c478bd9Sstevel@tonic-gate "LONG Format of JAZ media not supported\n"); 9417c478bd9Sstevel@tonic-gate errno = ENOTSUP; 9427c478bd9Sstevel@tonic-gate return (ENOTSUP); 9437c478bd9Sstevel@tonic-gate } 9447c478bd9Sstevel@tonic-gate /* 9457c478bd9Sstevel@tonic-gate * Defect list sent is an addition to the existing 9467c478bd9Sstevel@tonic-gate * list of defects. 9477c478bd9Sstevel@tonic-gate */ 9487c478bd9Sstevel@tonic-gate cdb[1] = FMTDATA; 9497c478bd9Sstevel@tonic-gate break; 9507c478bd9Sstevel@tonic-gate default : 9517c478bd9Sstevel@tonic-gate debug(1, "Format option %d not supported!!\n", 9527c478bd9Sstevel@tonic-gate flavor); 9537c478bd9Sstevel@tonic-gate errno = ENOTSUP; 9547c478bd9Sstevel@tonic-gate return (ENOTSUP); 9557c478bd9Sstevel@tonic-gate } 9567c478bd9Sstevel@tonic-gate 9577c478bd9Sstevel@tonic-gate 9587c478bd9Sstevel@tonic-gate ucmd.uscsi_cdb = (caddr_t)&cdb; 9597c478bd9Sstevel@tonic-gate ucmd.uscsi_cdblen = CDB_GROUP0; 9607c478bd9Sstevel@tonic-gate ucmd.uscsi_bufaddr = (caddr_t)data; 9617c478bd9Sstevel@tonic-gate ucmd.uscsi_buflen = sizeof (data); 9627c478bd9Sstevel@tonic-gate ucmd.uscsi_timeout = FORMAT_TIMEOUT(capacity); 9637c478bd9Sstevel@tonic-gate ucmd.uscsi_rqlen = RQ_LEN; 9647c478bd9Sstevel@tonic-gate ucmd.uscsi_rqbuf = rq_data; 9657c478bd9Sstevel@tonic-gate ret_val = do_uscsi_cmd(fd, &ucmd, USCSI_WRITE|USCSI_RQENABLE); 9667c478bd9Sstevel@tonic-gate if (ret_val || ucmd.uscsi_status) { 9677c478bd9Sstevel@tonic-gate debug(5, "Format failed failed: %d - %d errno = %d\n", 9687c478bd9Sstevel@tonic-gate ret_val, ucmd.uscsi_status, errno); 9697c478bd9Sstevel@tonic-gate return (ucmd.uscsi_status); 9707c478bd9Sstevel@tonic-gate } 9717c478bd9Sstevel@tonic-gate 9727c478bd9Sstevel@tonic-gate return (0); 9737c478bd9Sstevel@tonic-gate } 9747c478bd9Sstevel@tonic-gate 9757c478bd9Sstevel@tonic-gate static int32_t 9767c478bd9Sstevel@tonic-gate scsi_media_status(int32_t fd) 9777c478bd9Sstevel@tonic-gate { 9787c478bd9Sstevel@tonic-gate struct mode_header modeh; 9797c478bd9Sstevel@tonic-gate struct uscsi_cmd ucmd; 9807c478bd9Sstevel@tonic-gate union scsi_cdb cdb; 9817c478bd9Sstevel@tonic-gate int32_t ret_val; 9827c478bd9Sstevel@tonic-gate int32_t cur_status; 9837c478bd9Sstevel@tonic-gate char rq_data[RQ_LEN]; 9847c478bd9Sstevel@tonic-gate 9857c478bd9Sstevel@tonic-gate debug(10, "SCSI MEDIA STATUS CALLED \n"); 9867c478bd9Sstevel@tonic-gate 9877c478bd9Sstevel@tonic-gate (void) memset((void *) &modeh, 0, sizeof (modeh)); 9887c478bd9Sstevel@tonic-gate (void) memset((void *) &ucmd, 0, sizeof (ucmd)); 9897c478bd9Sstevel@tonic-gate (void) memset((void *) &cdb, 0, sizeof (union scsi_cdb)); 9907c478bd9Sstevel@tonic-gate cdb.scc_cmd = SCMD_MODE_SENSE; 9917c478bd9Sstevel@tonic-gate FORMG0COUNT(&cdb, sizeof (modeh)); 9927c478bd9Sstevel@tonic-gate ucmd.uscsi_cdb = (caddr_t)&cdb; 9937c478bd9Sstevel@tonic-gate ucmd.uscsi_cdblen = CDB_GROUP0; 9947c478bd9Sstevel@tonic-gate ucmd.uscsi_bufaddr = (caddr_t)&modeh; 9957c478bd9Sstevel@tonic-gate ucmd.uscsi_buflen = sizeof (modeh); 9967c478bd9Sstevel@tonic-gate ucmd.uscsi_timeout = 120; /* If 0, HBA hangs forever */ 9977c478bd9Sstevel@tonic-gate ucmd.uscsi_rqlen = RQ_LEN; 9987c478bd9Sstevel@tonic-gate ucmd.uscsi_rqbuf = rq_data; 9997c478bd9Sstevel@tonic-gate ret_val = do_uscsi_cmd(fd, &ucmd, USCSI_READ|USCSI_RQENABLE); 10007c478bd9Sstevel@tonic-gate if (ret_val || ucmd.uscsi_status) { 10017c478bd9Sstevel@tonic-gate debug(5, "Modesense failed: %d - %d errno = %d\n", 10027c478bd9Sstevel@tonic-gate ret_val, ucmd.uscsi_status, errno); 10037c478bd9Sstevel@tonic-gate return (-1); 10047c478bd9Sstevel@tonic-gate } 10057c478bd9Sstevel@tonic-gate 10067c478bd9Sstevel@tonic-gate 10077c478bd9Sstevel@tonic-gate if (modeh.device_specific & W_E_MASK) { 10087c478bd9Sstevel@tonic-gate cur_status = SM_WRITE_PROTECT_NOPASSWD; 10097c478bd9Sstevel@tonic-gate } else { 10107c478bd9Sstevel@tonic-gate cur_status = SM_WRITE_PROTECT_DISABLE; 10117c478bd9Sstevel@tonic-gate } 10127c478bd9Sstevel@tonic-gate debug(5, "cur status %d\n", cur_status); 10137c478bd9Sstevel@tonic-gate 10147c478bd9Sstevel@tonic-gate return (cur_status); 10157c478bd9Sstevel@tonic-gate } 10167c478bd9Sstevel@tonic-gate 10177c478bd9Sstevel@tonic-gate static int32_t 10187c478bd9Sstevel@tonic-gate scsi_zip_media_status(int32_t fd) 10197c478bd9Sstevel@tonic-gate { 10207c478bd9Sstevel@tonic-gate struct uscsi_cmd ucmd; 10217c478bd9Sstevel@tonic-gate uchar_t cdb[12]; 10227c478bd9Sstevel@tonic-gate int32_t status; 10237c478bd9Sstevel@tonic-gate int32_t mode; 10247c478bd9Sstevel@tonic-gate uchar_t data[64]; 10257c478bd9Sstevel@tonic-gate char rq_data[RQ_LEN]; 10267c478bd9Sstevel@tonic-gate 10277c478bd9Sstevel@tonic-gate debug(10, "Getting media status\n"); 10287c478bd9Sstevel@tonic-gate 10297c478bd9Sstevel@tonic-gate (void) memset((void *)&ucmd, 0, sizeof (ucmd)); 10307c478bd9Sstevel@tonic-gate (void) memset((void *)&cdb, 0, sizeof (cdb)); 10317c478bd9Sstevel@tonic-gate 10327c478bd9Sstevel@tonic-gate cdb[0] = IOMEGA_NONSENSE_CMD; 10337c478bd9Sstevel@tonic-gate cdb[2] = CARTRIDGE_STATUS_PAGE; 10347c478bd9Sstevel@tonic-gate cdb[4] = ND_LENGTH; 10357c478bd9Sstevel@tonic-gate ucmd.uscsi_cdb = (caddr_t)&cdb; 10367c478bd9Sstevel@tonic-gate ucmd.uscsi_cdblen = CDB_GROUP0; 10377c478bd9Sstevel@tonic-gate ucmd.uscsi_bufaddr = (caddr_t)data; 10387c478bd9Sstevel@tonic-gate ucmd.uscsi_buflen = 64; 10397c478bd9Sstevel@tonic-gate ucmd.uscsi_timeout = 120; /* If 0, HBA hangs forever */ 10407c478bd9Sstevel@tonic-gate ucmd.uscsi_rqlen = RQ_LEN; 10417c478bd9Sstevel@tonic-gate ucmd.uscsi_rqbuf = rq_data; 10427c478bd9Sstevel@tonic-gate status = do_uscsi_cmd(fd, &ucmd, USCSI_READ|USCSI_RQENABLE); 10437c478bd9Sstevel@tonic-gate if (status || ucmd.uscsi_status) { 1044*5363f09cSarutz debug(5, "Cartridge protect operation failed: " 1045*5363f09cSarutz "rv = %d uscsi_status = %d errno = %d\n", 10467c478bd9Sstevel@tonic-gate status, ucmd.uscsi_status, errno); 10477c478bd9Sstevel@tonic-gate return (-1); 10487c478bd9Sstevel@tonic-gate } 10497c478bd9Sstevel@tonic-gate 10507c478bd9Sstevel@tonic-gate if (data[DISK_STATUS_OFFSET + NON_SENSE_HDR_LEN] == 4) { 10517c478bd9Sstevel@tonic-gate debug(1, "Disk not present. \n"); 10527c478bd9Sstevel@tonic-gate return (-1); 10537c478bd9Sstevel@tonic-gate } 10547c478bd9Sstevel@tonic-gate mode = data[PROTECT_MODE_OFFSET + NON_SENSE_HDR_LEN] & 0xF; 10557c478bd9Sstevel@tonic-gate 1056*5363f09cSarutz debug(5, "MODE 0x%x / %d.\n", mode, mode); 10577c478bd9Sstevel@tonic-gate 10587c478bd9Sstevel@tonic-gate switch (mode) { 10597c478bd9Sstevel@tonic-gate case UNLOCK_MODE: 10607c478bd9Sstevel@tonic-gate status = SM_WRITE_PROTECT_DISABLE; 10617c478bd9Sstevel@tonic-gate break; 10627c478bd9Sstevel@tonic-gate case WRITE_PROTECT_MODE: 10637c478bd9Sstevel@tonic-gate status = SM_WRITE_PROTECT_NOPASSWD; 10647c478bd9Sstevel@tonic-gate break; 10657c478bd9Sstevel@tonic-gate case PASSWD_WRITE_PROTECT_MODE: 10667c478bd9Sstevel@tonic-gate status = SM_WRITE_PROTECT_PASSWD; 10677c478bd9Sstevel@tonic-gate break; 10687c478bd9Sstevel@tonic-gate case READ_WRITE_PROTECT_MODE: 10697c478bd9Sstevel@tonic-gate status = SM_READ_WRITE_PROTECT; 10707c478bd9Sstevel@tonic-gate break; 10717c478bd9Sstevel@tonic-gate default : 10727c478bd9Sstevel@tonic-gate if (mode & TEMP_UNLOCK_MODE) 10737c478bd9Sstevel@tonic-gate status = SM_TEMP_UNLOCK_MODE; 10747c478bd9Sstevel@tonic-gate else 10757c478bd9Sstevel@tonic-gate status = SM_STATUS_UNKNOWN; 10767c478bd9Sstevel@tonic-gate break; 10777c478bd9Sstevel@tonic-gate } 10787c478bd9Sstevel@tonic-gate 10797c478bd9Sstevel@tonic-gate debug(5, "status %d \n", status); 10807c478bd9Sstevel@tonic-gate return (status); 10817c478bd9Sstevel@tonic-gate } 10827c478bd9Sstevel@tonic-gate 1083*5363f09cSarutz static int32_t 10847c478bd9Sstevel@tonic-gate scsi_reassign_block(int32_t fd, diskaddr_t block) 10857c478bd9Sstevel@tonic-gate { 10867c478bd9Sstevel@tonic-gate uchar_t data[8]; 10877c478bd9Sstevel@tonic-gate struct uscsi_cmd ucmd; 10887c478bd9Sstevel@tonic-gate char cdb[12]; 10897c478bd9Sstevel@tonic-gate int32_t ret_val; 10907c478bd9Sstevel@tonic-gate char rq_data[RQ_LEN]; 10917c478bd9Sstevel@tonic-gate 10927c478bd9Sstevel@tonic-gate debug(5, "SCSI REASSIGN CALLED block = %lld\n", block); 10937c478bd9Sstevel@tonic-gate 10947c478bd9Sstevel@tonic-gate (void) memset((void *) &data, 0, sizeof (data)); 10957c478bd9Sstevel@tonic-gate (void) memset((void *) &ucmd, 0, sizeof (ucmd)); 10967c478bd9Sstevel@tonic-gate (void) memset((void *) &cdb, 0, sizeof (cdb)); 10977c478bd9Sstevel@tonic-gate cdb[0] = SCMD_REASSIGN_BLOCK; 10987c478bd9Sstevel@tonic-gate data[3] = 4; 10997c478bd9Sstevel@tonic-gate data[4] = ((block & 0xFF000000) >> 24); 11007c478bd9Sstevel@tonic-gate data[5] = ((block & 0xFF0000) >> 16); 11017c478bd9Sstevel@tonic-gate data[6] = ((block & 0xFF00) >> 8); 11027c478bd9Sstevel@tonic-gate data[7] = block & 0xFF; 11037c478bd9Sstevel@tonic-gate 11047c478bd9Sstevel@tonic-gate ucmd.uscsi_cdb = (caddr_t)&cdb; 11057c478bd9Sstevel@tonic-gate ucmd.uscsi_cdblen = CDB_GROUP0; 11067c478bd9Sstevel@tonic-gate ucmd.uscsi_bufaddr = (caddr_t)data; 11077c478bd9Sstevel@tonic-gate ucmd.uscsi_buflen = sizeof (data); 11087c478bd9Sstevel@tonic-gate ucmd.uscsi_timeout = 120; /* If 0, HBA hangs forever */ 11097c478bd9Sstevel@tonic-gate ucmd.uscsi_rqlen = RQ_LEN; 11107c478bd9Sstevel@tonic-gate ucmd.uscsi_rqbuf = rq_data; 11117c478bd9Sstevel@tonic-gate ret_val = do_uscsi_cmd(fd, &ucmd, USCSI_WRITE|USCSI_RQENABLE); 11127c478bd9Sstevel@tonic-gate if (ret_val || ucmd.uscsi_status) { 11137c478bd9Sstevel@tonic-gate debug(5, "Reassign block failed: %d - %d errno = %d\n", 11147c478bd9Sstevel@tonic-gate ret_val, ucmd.uscsi_status, errno); 11157c478bd9Sstevel@tonic-gate return (-1); 11167c478bd9Sstevel@tonic-gate } 11177c478bd9Sstevel@tonic-gate 11187c478bd9Sstevel@tonic-gate return (0); 11197c478bd9Sstevel@tonic-gate } 11207c478bd9Sstevel@tonic-gate 1121*5363f09cSarutz static int32_t 11227c478bd9Sstevel@tonic-gate get_mode_page(int32_t fd, uchar_t pc, uchar_t page_code, 11237c478bd9Sstevel@tonic-gate uchar_t *md_data, uchar_t data_len) 11247c478bd9Sstevel@tonic-gate { 11257c478bd9Sstevel@tonic-gate struct uscsi_cmd ucmd; 11267c478bd9Sstevel@tonic-gate uchar_t cdb[12]; 11277c478bd9Sstevel@tonic-gate int32_t ret_val; 11287c478bd9Sstevel@tonic-gate char rq_data[RQ_LEN]; 11297c478bd9Sstevel@tonic-gate 1130*5363f09cSarutz debug(10, "MODE SENSE(6) - page_code = 0x%x\n", page_code); 11317c478bd9Sstevel@tonic-gate 11327c478bd9Sstevel@tonic-gate (void) memset((void *) md_data, 0, sizeof (data_len)); 11337c478bd9Sstevel@tonic-gate (void) memset((void *) &ucmd, 0, sizeof (ucmd)); 11347c478bd9Sstevel@tonic-gate (void) memset((void *) &cdb, 0, sizeof (cdb)); 11357c478bd9Sstevel@tonic-gate cdb[0] = SCMD_MODE_SENSE; 11367c478bd9Sstevel@tonic-gate cdb[2] = (pc << 6) | page_code; 11377c478bd9Sstevel@tonic-gate cdb[4] = data_len; 11387c478bd9Sstevel@tonic-gate 11397c478bd9Sstevel@tonic-gate ucmd.uscsi_cdb = (caddr_t)&cdb; 11407c478bd9Sstevel@tonic-gate ucmd.uscsi_cdblen = CDB_GROUP0; 11417c478bd9Sstevel@tonic-gate ucmd.uscsi_bufaddr = (caddr_t)md_data; 11427c478bd9Sstevel@tonic-gate ucmd.uscsi_buflen = data_len; 11437c478bd9Sstevel@tonic-gate ucmd.uscsi_timeout = 120; /* If 0, HBA hangs forever */ 11447c478bd9Sstevel@tonic-gate ucmd.uscsi_rqlen = RQ_LEN; 11457c478bd9Sstevel@tonic-gate ucmd.uscsi_rqbuf = rq_data; 11467c478bd9Sstevel@tonic-gate ret_val = do_uscsi_cmd(fd, &ucmd, USCSI_READ|USCSI_RQENABLE); 11477c478bd9Sstevel@tonic-gate if (ret_val || ucmd.uscsi_status) { 11487c478bd9Sstevel@tonic-gate debug(5, "Modesense failed: %d - %d errno = %d\n", 11497c478bd9Sstevel@tonic-gate ret_val, ucmd.uscsi_status, errno); 11507c478bd9Sstevel@tonic-gate return (-2); 11517c478bd9Sstevel@tonic-gate } 11527c478bd9Sstevel@tonic-gate 11537c478bd9Sstevel@tonic-gate return (0); 11547c478bd9Sstevel@tonic-gate } 11557c478bd9Sstevel@tonic-gate 11567c478bd9Sstevel@tonic-gate static int32_t 11577c478bd9Sstevel@tonic-gate scsi_zip_write_protect(int32_t fd, smwp_state_t *wp) 11587c478bd9Sstevel@tonic-gate { 11597c478bd9Sstevel@tonic-gate struct uscsi_cmd ucmd; 11607c478bd9Sstevel@tonic-gate struct scsi_inquiry inq; 11617c478bd9Sstevel@tonic-gate uchar_t cdb[12]; 11627c478bd9Sstevel@tonic-gate int32_t status; 11637c478bd9Sstevel@tonic-gate int32_t new_mode; 11647c478bd9Sstevel@tonic-gate char rq_data[RQ_LEN]; 11657c478bd9Sstevel@tonic-gate int32_t wa_bit; 11667c478bd9Sstevel@tonic-gate char *tmp_passwd = NULL; 11677c478bd9Sstevel@tonic-gate 11687c478bd9Sstevel@tonic-gate debug(10, "SCSI ZIP WRITE PROTECT CALLED \n"); 11697c478bd9Sstevel@tonic-gate 11707c478bd9Sstevel@tonic-gate /* 11717c478bd9Sstevel@tonic-gate * Do an inquiry and try to figure out if it an 11727c478bd9Sstevel@tonic-gate * ATAPI or SCSI device. 11737c478bd9Sstevel@tonic-gate */ 11747c478bd9Sstevel@tonic-gate 11757c478bd9Sstevel@tonic-gate (void) memset((void *) &inq, 0, sizeof (inq)); 11767c478bd9Sstevel@tonic-gate (void) memset((void *) &ucmd, 0, sizeof (ucmd)); 11777c478bd9Sstevel@tonic-gate (void) memset((void *) &cdb, 0, sizeof (cdb)); 11787c478bd9Sstevel@tonic-gate (void) memset((void *) &rq_data, 0, sizeof (rq_data)); 11797c478bd9Sstevel@tonic-gate cdb[0] = SCMD_INQUIRY; 11807c478bd9Sstevel@tonic-gate cdb[4] = sizeof (inq); 11817c478bd9Sstevel@tonic-gate ucmd.uscsi_cdb = (caddr_t)&cdb; 11827c478bd9Sstevel@tonic-gate ucmd.uscsi_cdblen = CDB_GROUP0; 11837c478bd9Sstevel@tonic-gate ucmd.uscsi_bufaddr = (caddr_t)&inq; 11847c478bd9Sstevel@tonic-gate ucmd.uscsi_buflen = sizeof (inq); 11857c478bd9Sstevel@tonic-gate ucmd.uscsi_timeout = 120; /* If 0, HBA hangs forever */ 11867c478bd9Sstevel@tonic-gate ucmd.uscsi_rqlen = RQ_LEN; 11877c478bd9Sstevel@tonic-gate ucmd.uscsi_rqbuf = rq_data; 11887c478bd9Sstevel@tonic-gate status = do_uscsi_cmd(fd, &ucmd, USCSI_READ|USCSI_RQENABLE); 11897c478bd9Sstevel@tonic-gate if (status || ucmd.uscsi_status) { 11907c478bd9Sstevel@tonic-gate debug(5, "inquiry failed: %d - %d errno = %d\n", 11917c478bd9Sstevel@tonic-gate status, ucmd.uscsi_status, errno); 11927c478bd9Sstevel@tonic-gate return (-1); 11937c478bd9Sstevel@tonic-gate } 11947c478bd9Sstevel@tonic-gate 11957c478bd9Sstevel@tonic-gate if (inq.inq_ansi > 0) { 11967c478bd9Sstevel@tonic-gate wa_bit = 0; 11977c478bd9Sstevel@tonic-gate debug(5, "SCSI device\n"); 11987c478bd9Sstevel@tonic-gate } else { 11997c478bd9Sstevel@tonic-gate wa_bit = 1; 12007c478bd9Sstevel@tonic-gate debug(5, "ATAPI device\n"); 12017c478bd9Sstevel@tonic-gate } 12027c478bd9Sstevel@tonic-gate 12037c478bd9Sstevel@tonic-gate switch (wp->sm_new_state) { 12047c478bd9Sstevel@tonic-gate case SM_WRITE_PROTECT_DISABLE : 12057c478bd9Sstevel@tonic-gate new_mode = 0x0; 12067c478bd9Sstevel@tonic-gate break; 12077c478bd9Sstevel@tonic-gate case SM_WRITE_PROTECT_NOPASSWD : 12087c478bd9Sstevel@tonic-gate new_mode = 0x2; 12097c478bd9Sstevel@tonic-gate break; 12107c478bd9Sstevel@tonic-gate case SM_WRITE_PROTECT_PASSWD : 12117c478bd9Sstevel@tonic-gate new_mode = 0x3; 12127c478bd9Sstevel@tonic-gate break; 12137c478bd9Sstevel@tonic-gate case SM_READ_WRITE_PROTECT : 12147c478bd9Sstevel@tonic-gate new_mode = 0x5; 12157c478bd9Sstevel@tonic-gate break; 12167c478bd9Sstevel@tonic-gate case SM_TEMP_UNLOCK_MODE : 12177c478bd9Sstevel@tonic-gate new_mode = 0x8; 12187c478bd9Sstevel@tonic-gate break; 12197c478bd9Sstevel@tonic-gate default : 12207c478bd9Sstevel@tonic-gate debug(1, "Invalid mode 0x%x specified\n", 12217c478bd9Sstevel@tonic-gate wp->sm_new_state); 12227c478bd9Sstevel@tonic-gate errno = ENOTSUP; 12237c478bd9Sstevel@tonic-gate return (-1); 12247c478bd9Sstevel@tonic-gate } 12257c478bd9Sstevel@tonic-gate 12267c478bd9Sstevel@tonic-gate 12277c478bd9Sstevel@tonic-gate (void) memset((void *)&ucmd, 0, sizeof (ucmd)); 12287c478bd9Sstevel@tonic-gate (void) memset((void *)&cdb, 0, sizeof (cdb)); 12297c478bd9Sstevel@tonic-gate (void) memset((void *) &rq_data, 0, sizeof (rq_data)); 12307c478bd9Sstevel@tonic-gate cdb[0] = IOMEGA_CATRIDGE_PROTECT; 12317c478bd9Sstevel@tonic-gate cdb[1] |= new_mode; 12327c478bd9Sstevel@tonic-gate if (wa_bit) 12337c478bd9Sstevel@tonic-gate cdb[1] |= WA_BIT; 12347c478bd9Sstevel@tonic-gate cdb[4] = wp->sm_passwd_len; 12357c478bd9Sstevel@tonic-gate ucmd.uscsi_cdb = (caddr_t)&cdb; 12367c478bd9Sstevel@tonic-gate ucmd.uscsi_cdblen = CDB_GROUP0; 12377c478bd9Sstevel@tonic-gate if (wa_bit && (wp->sm_passwd_len & 1)) { 12387c478bd9Sstevel@tonic-gate /* 12397c478bd9Sstevel@tonic-gate * Oops, ATAPI device with an odd length passwd! 12407c478bd9Sstevel@tonic-gate * Allocate a buffer to hold one extra byte. 12417c478bd9Sstevel@tonic-gate */ 12427c478bd9Sstevel@tonic-gate debug(5, "Odd len passwd for ATAPI device!\n"); 12437c478bd9Sstevel@tonic-gate errno = 0; 12447c478bd9Sstevel@tonic-gate tmp_passwd = (char *)malloc(wp->sm_passwd_len+1); 12457c478bd9Sstevel@tonic-gate if (tmp_passwd == NULL) { 12467c478bd9Sstevel@tonic-gate if (errno == 0) 12477c478bd9Sstevel@tonic-gate errno = ENOMEM; 12487c478bd9Sstevel@tonic-gate return (-1); 12497c478bd9Sstevel@tonic-gate } 12507c478bd9Sstevel@tonic-gate (void) memset(tmp_passwd, 0, wp->sm_passwd_len+1); 12517c478bd9Sstevel@tonic-gate (void) memcpy(tmp_passwd, wp->sm_passwd, wp->sm_passwd_len); 12527c478bd9Sstevel@tonic-gate ucmd.uscsi_bufaddr = (caddr_t)tmp_passwd; 12537c478bd9Sstevel@tonic-gate ucmd.uscsi_buflen = wp->sm_passwd_len+1; 12547c478bd9Sstevel@tonic-gate } else { 12557c478bd9Sstevel@tonic-gate ucmd.uscsi_bufaddr = (caddr_t)wp->sm_passwd; 12567c478bd9Sstevel@tonic-gate ucmd.uscsi_buflen = wp->sm_passwd_len; 12577c478bd9Sstevel@tonic-gate } 12587c478bd9Sstevel@tonic-gate ucmd.uscsi_timeout = 120; /* If 0, HBA hangs forever */ 12597c478bd9Sstevel@tonic-gate ucmd.uscsi_rqlen = RQ_LEN; 12607c478bd9Sstevel@tonic-gate ucmd.uscsi_rqbuf = rq_data; 12617c478bd9Sstevel@tonic-gate status = do_uscsi_cmd(fd, &ucmd, USCSI_WRITE|USCSI_RQENABLE); 12627c478bd9Sstevel@tonic-gate if (tmp_passwd != NULL) { 12637c478bd9Sstevel@tonic-gate free(tmp_passwd); 12647c478bd9Sstevel@tonic-gate } 12657c478bd9Sstevel@tonic-gate if (status || ucmd.uscsi_status) { 1266*5363f09cSarutz debug(5, "Cartridge-protect operation failed: rv " 1267*5363f09cSarutz "= %d uscsi_status = %d errno = %d\n", status, 1268*5363f09cSarutz ucmd.uscsi_status, errno); 12697c478bd9Sstevel@tonic-gate if ((rq_data[2] & 0xF) == KEY_ILLEGAL_REQUEST) { 12707c478bd9Sstevel@tonic-gate if (rq_data[12] == 0x26) { 12717c478bd9Sstevel@tonic-gate /* Wrong passwd */ 1272*5363f09cSarutz debug(5, "Protection Request with wrong " 1273*5363f09cSarutz "passwd. errno is being set to EACCES.\n"); 12747c478bd9Sstevel@tonic-gate errno = EACCES; 12757c478bd9Sstevel@tonic-gate } 12767c478bd9Sstevel@tonic-gate } 12777c478bd9Sstevel@tonic-gate return (-1); 12787c478bd9Sstevel@tonic-gate } 12797c478bd9Sstevel@tonic-gate 12807c478bd9Sstevel@tonic-gate return (0); 12817c478bd9Sstevel@tonic-gate } 12827c478bd9Sstevel@tonic-gate 12837c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 12847c478bd9Sstevel@tonic-gate static int32_t 12857c478bd9Sstevel@tonic-gate scsi_write_protect(int32_t fd, smwp_state_t *wp) 12867c478bd9Sstevel@tonic-gate { 12877c478bd9Sstevel@tonic-gate errno = ENOTSUP; 12887c478bd9Sstevel@tonic-gate return (-1); 12897c478bd9Sstevel@tonic-gate } 12907c478bd9Sstevel@tonic-gate 1291*5363f09cSarutz /* 1292*5363f09cSarutz * This thread becomes the server-side thread used in 1293*5363f09cSarutz * the implementation of a door_call between a client 1294*5363f09cSarutz * and the Client Door. 1295*5363f09cSarutz * 1296*5363f09cSarutz * This thread is customized both by the door_server_create(3c) 1297*5363f09cSarutz * function sm_door_server_create, as well as by itself. 1298*5363f09cSarutz * 1299*5363f09cSarutz * This thread needs to synchronize with the 1300*5363f09cSarutz * main_servproc[SMEDIA_CNUM_OPEN_FD] door_call in terms of 1301*5363f09cSarutz * both successful and failure scenarios. main_servproc 1302*5363f09cSarutz * locks dd_lock before calling door_create. This thread 1303*5363f09cSarutz * then attempts to lock, but will block until main_servproc 1304*5363f09cSarutz * has either created all doors it requires, or until a 1305*5363f09cSarutz * door_create has failed (door_create's return and the 1306*5363f09cSarutz * creation of an associated thread are asynchronous). 1307*5363f09cSarutz * 1308*5363f09cSarutz * If door_create failed, this thread will be able to obtain 1309*5363f09cSarutz * dd_lock and call pthread_exit. If all door_create's succeed, 1310*5363f09cSarutz * this thread will obtain dd_lock and commence with 1311*5363f09cSarutz * customizing the thread's attributes. door_bind is called to 1312*5363f09cSarutz * bind this thread to the per-door private thread pool, and 1313*5363f09cSarutz * main_servproc is cond_signal'd to avail it of this fact. 1314*5363f09cSarutz * 1315*5363f09cSarutz * Finally, this thread calls door_return, which causes it to 1316*5363f09cSarutz * commence its lifetime as a server-side thread in implementation 1317*5363f09cSarutz * of a Client Door door_call. 1318*5363f09cSarutz */ 13197c478bd9Sstevel@tonic-gate static void * 1320*5363f09cSarutz sm_server_thread(void *arg) 13217c478bd9Sstevel@tonic-gate { 13227c478bd9Sstevel@tonic-gate door_data_t *door_dp; 13237c478bd9Sstevel@tonic-gate struct sigaction act; 1324*5363f09cSarutz int i; 1325*5363f09cSarutz int err; 13267c478bd9Sstevel@tonic-gate 13277c478bd9Sstevel@tonic-gate door_dp = (door_data_t *)arg; 13287c478bd9Sstevel@tonic-gate 13297c478bd9Sstevel@tonic-gate if (door_dp == NULL) { 1330*5363f09cSarutz fatal("sm_server_thread[%d]: argument is NULL!!\n", 13317c478bd9Sstevel@tonic-gate pthread_self()); 13327c478bd9Sstevel@tonic-gate exit(-1); 13337c478bd9Sstevel@tonic-gate } 13347c478bd9Sstevel@tonic-gate 1335*5363f09cSarutz /* Wait for Client Door to be created */ 13367c478bd9Sstevel@tonic-gate (void) mutex_lock(&door_dp->dd_lock); 1337*5363f09cSarutz if (door_dp->dd_cdoor_descriptor < 0) { 1338*5363f09cSarutz debug(5, "sm_server_thread[%d]: door_create() failed", 1339*5363f09cSarutz pthread_self()); 1340*5363f09cSarutz (void) mutex_unlock(&door_dp->dd_lock); 1341*5363f09cSarutz pthread_exit((void *)-2); 1342*5363f09cSarutz } 13437c478bd9Sstevel@tonic-gate (void) mutex_unlock(&door_dp->dd_lock); 13447c478bd9Sstevel@tonic-gate 13457c478bd9Sstevel@tonic-gate for (i = 0; i < N_BADSIGS; i++) { 13467c478bd9Sstevel@tonic-gate act.sa_sigaction = server_badsig_handler; 13477c478bd9Sstevel@tonic-gate (void) sigemptyset(&act.sa_mask); 13487c478bd9Sstevel@tonic-gate act.sa_flags = SA_SIGINFO; 13497c478bd9Sstevel@tonic-gate if (sigaction(badsigs[i], &act, NULL) == -1) 13507c478bd9Sstevel@tonic-gate warning(gettext(SIGACT_FAILED), strsignal(badsigs[i]), 13517c478bd9Sstevel@tonic-gate strerror(errno)); 13527c478bd9Sstevel@tonic-gate } 13537c478bd9Sstevel@tonic-gate if (sigemptyset(&door_dp->dd_newset) != 0) 13547c478bd9Sstevel@tonic-gate warning(gettext("sigemptyset failed. errno = %d\n"), 13557c478bd9Sstevel@tonic-gate errno); 1356*5363f09cSarutz if ((err = pthread_sigmask(SIG_BLOCK, &door_dp->dd_newset, NULL)) != 0) 1357*5363f09cSarutz warning(gettext("pthread_sigmask failed = %d\n"), err); 13587c478bd9Sstevel@tonic-gate 1359*5363f09cSarutz /* Bind thread with pool associated with Client Door */ 13607c478bd9Sstevel@tonic-gate 1361*5363f09cSarutz if (door_bind(door_dp->dd_cdoor_descriptor) < 0) { 13627c478bd9Sstevel@tonic-gate fatal("door_bind"); 13637c478bd9Sstevel@tonic-gate exit(-1); 13647c478bd9Sstevel@tonic-gate } 1365*5363f09cSarutz debug(5, "thr[%d] bound to Client Door[%d]", pthread_self(), 1366*5363f09cSarutz door_dp->dd_cdoor_descriptor); 1367*5363f09cSarutz 13687c478bd9Sstevel@tonic-gate /* 1369*5363f09cSarutz * Set these two cancellation(5) attributes. Ensure that the 1370*5363f09cSarutz * pthread we create has cancellation(5) DISABLED and DEFERRED, 1371*5363f09cSarutz * as our implementation is based on this. DEFERRED is the 1372*5363f09cSarutz * default, but set it anyways, in case the defaults change in 1373*5363f09cSarutz * the future. 13747c478bd9Sstevel@tonic-gate */ 1375*5363f09cSarutz if ((err = pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL)) != 0) 1376*5363f09cSarutz warning(gettext("pthread_setcancelstate(PTHREAD_CANCEL_DISABLE)" 1377*5363f09cSarutz " failed = %d\n"), err); 1378*5363f09cSarutz if ((err = pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, 1379*5363f09cSarutz NULL)) != 0) 1380*5363f09cSarutz warning(gettext("pthread_setcanceltype(DEFERRED) " 1381*5363f09cSarutz "failed = %d\n"), err); 1382*5363f09cSarutz 1383*5363f09cSarutz /* Inform main_servproc that door_bind() is complete. */ 13847c478bd9Sstevel@tonic-gate (void) cond_signal(&door_dp->dd_cv_bind); 1385*5363f09cSarutz 1386*5363f09cSarutz /* 1387*5363f09cSarutz * Per doors protocol, transfer control to the doors-runtime in 1388*5363f09cSarutz * order to make this thread available to answer future door_call()'s. 1389*5363f09cSarutz */ 13907c478bd9Sstevel@tonic-gate (void) door_return(NULL, 0, NULL, 0); 13917c478bd9Sstevel@tonic-gate return (NULL); 13927c478bd9Sstevel@tonic-gate } 13937c478bd9Sstevel@tonic-gate 1394*5363f09cSarutz /* 1395*5363f09cSarutz * This function cleans up all per-connection resources. 1396*5363f09cSarutz * 1397*5363f09cSarutz * This function is called when the Client Door's service procedure 1398*5363f09cSarutz * (client_servproc) is called w/ DOOR_UNREF_DATA, which is the 1399*5363f09cSarutz * doors protocol convention stating that the number of file 1400*5363f09cSarutz * descriptors referring to this door has dropped to one. 1401*5363f09cSarutz * client_servproc is passed DOOR_UNREF_DATA because the Client Door 1402*5363f09cSarutz * was door_create'd with the DOOR_UNREF bitflag. 1403*5363f09cSarutz */ 14047c478bd9Sstevel@tonic-gate static void 14057c478bd9Sstevel@tonic-gate cleanup(door_data_t *door_dp) 14067c478bd9Sstevel@tonic-gate { 1407*5363f09cSarutz /* do door_revoke() of Death Door */ 1408*5363f09cSarutz if (door_dp->dd_ddoor_descriptor >= 0) { 1409*5363f09cSarutz debug(1, "cleanup[%d]: door_revoke() Death Door[%d]", 1410*5363f09cSarutz pthread_self(), door_dp->dd_ddoor_descriptor); 14117c478bd9Sstevel@tonic-gate 1412*5363f09cSarutz if (door_revoke(door_dp->dd_ddoor_descriptor) < 0) { 1413*5363f09cSarutz warning(gettext("cleanup[%d]: door_revoke() of Death " 1414*5363f09cSarutz "Door(%d) failed = %d"), pthread_self(), 1415*5363f09cSarutz door_dp->dd_ddoor_descriptor, errno); 1416*5363f09cSarutz } else { 1417*5363f09cSarutz door_dp->dd_ddoor_descriptor = -1; 14187c478bd9Sstevel@tonic-gate } 1419*5363f09cSarutz } 1420*5363f09cSarutz 1421*5363f09cSarutz /* release memory that is shared between client and (our) server */ 1422*5363f09cSarutz if (door_dp->dd_buffd >= 0) { 1423*5363f09cSarutz debug(1, "cleanup[%d]: release shared memory", pthread_self()); 14247c478bd9Sstevel@tonic-gate (void) munmap(door_dp->dd_buf, door_dp->dd_buf_len); 14257c478bd9Sstevel@tonic-gate (void) close(door_dp->dd_buffd); 1426*5363f09cSarutz 1427*5363f09cSarutz door_dp->dd_buffd = -1; 14287c478bd9Sstevel@tonic-gate door_dp->dd_buf = NULL; 14297c478bd9Sstevel@tonic-gate door_dp->dd_buf_len = 0; 14307c478bd9Sstevel@tonic-gate } 14317c478bd9Sstevel@tonic-gate 1432*5363f09cSarutz /* close the (target) device that the Client is operating on */ 1433*5363f09cSarutz if (door_dp->dd_fd >= 0) { 1434*5363f09cSarutz debug(1, "cleanup[%d]: close(%d) target device", pthread_self(), 1435*5363f09cSarutz door_dp->dd_fd); 14367c478bd9Sstevel@tonic-gate if (close(door_dp->dd_fd) < 0) { 1437*5363f09cSarutz warning(gettext("cleanup[%d]: close() of target device" 1438*5363f09cSarutz "failed = %d\n"), pthread_self(), errno); 14397c478bd9Sstevel@tonic-gate } 14407c478bd9Sstevel@tonic-gate } 14417c478bd9Sstevel@tonic-gate 1442*5363f09cSarutz /* 1443*5363f09cSarutz * Unbind the current thread from the Client Door's private 1444*5363f09cSarutz * thread pool. 1445*5363f09cSarutz */ 1446*5363f09cSarutz debug(1, "cleanup[%d]: door_unbind() of Client Door[%d]", 1447*5363f09cSarutz pthread_self(), door_dp->dd_cdoor_descriptor); 1448*5363f09cSarutz if (door_unbind() < 0) 1449*5363f09cSarutz warning("door_unbind() of Client Door[%d] failed = " 1450*5363f09cSarutz "%d", door_dp->dd_cdoor_descriptor, errno); 1451*5363f09cSarutz 1452*5363f09cSarutz /* Disallow any future requests to the Client Door */ 1453*5363f09cSarutz if (door_dp->dd_cdoor_descriptor >= 0) { 1454*5363f09cSarutz debug(1, "cleanup[%d]: door_revoke() Client Door[%d]", 1455*5363f09cSarutz pthread_self(), door_dp->dd_cdoor_descriptor); 1456*5363f09cSarutz 1457*5363f09cSarutz if (door_revoke(door_dp->dd_cdoor_descriptor) < 0) { 1458*5363f09cSarutz warning(gettext("cleanup[%d]: door_revoke() of " 1459*5363f09cSarutz "Client Door[%d] failed = %d"), pthread_self(), 1460*5363f09cSarutz door_dp->dd_cdoor_descriptor, errno); 1461*5363f09cSarutz } 1462*5363f09cSarutz } 1463*5363f09cSarutz 1464*5363f09cSarutz free(door_dp); 1465*5363f09cSarutz debug(5, "cleanup[%d] ...exiting\n", pthread_self()); 1466*5363f09cSarutz } 1467*5363f09cSarutz 1468*5363f09cSarutz /* 1469*5363f09cSarutz * This is the door_server_create(3c) function used to customize 1470*5363f09cSarutz * creation of the threads used in the handling of our daemon's 1471*5363f09cSarutz * door_call(3c)'s. 1472*5363f09cSarutz * 1473*5363f09cSarutz * This function is called synchronously as part of door_create(3c). 1474*5363f09cSarutz * Note that door_create(), however, is not synchronous; it can return 1475*5363f09cSarutz * with the created door file descriptor before any associated 1476*5363f09cSarutz * thread has been created. As a result, synchronization is needed 1477*5363f09cSarutz * between door_create() caller and the created pthread. This is 1478*5363f09cSarutz * needed both when each activity succeeds or when either activity 1479*5363f09cSarutz * fails. 1480*5363f09cSarutz * 1481*5363f09cSarutz * Specifically, this function ensures that each "connection" 1482*5363f09cSarutz * with the client creates only one thread in the per-door, 1483*5363f09cSarutz * private thread pool. This function locks dd_threadlock and 1484*5363f09cSarutz * then calls pthread_create(). If that succeeds, dd_thread 1485*5363f09cSarutz * is assigned the thread id, and dd_threadlock is unlocked. 1486*5363f09cSarutz * Any per-connection door_create that causes control to flow 1487*5363f09cSarutz * to this function will eventually find that dd_thread is 1488*5363f09cSarutz * non-zero, and control will exit this function. 1489*5363f09cSarutz * 1490*5363f09cSarutz * In the current implementation, the door_create for the Client Door 1491*5363f09cSarutz * is called first, and the Death Door is door_create'd second. 1492*5363f09cSarutz * As a result, the following function can safely make the static 1493*5363f09cSarutz * assumption that the first door (within a connection) is the 1494*5363f09cSarutz * Client Door. A connection's Client Door and Death Door share 1495*5363f09cSarutz * the same thread as well as the same door_data_t instance. 1496*5363f09cSarutz */ 14977c478bd9Sstevel@tonic-gate static void 1498*5363f09cSarutz sm_door_server_create(door_info_t *dip) 14997c478bd9Sstevel@tonic-gate { 15007c478bd9Sstevel@tonic-gate door_data_t *door_dp; 15017c478bd9Sstevel@tonic-gate pthread_t tid; 15027c478bd9Sstevel@tonic-gate pthread_attr_t attr; 15037c478bd9Sstevel@tonic-gate int ret_val; 1504*5363f09cSarutz int err; 15057c478bd9Sstevel@tonic-gate 15067c478bd9Sstevel@tonic-gate if (dip == NULL) { 15077c478bd9Sstevel@tonic-gate return; 15087c478bd9Sstevel@tonic-gate } 1509360e6f5eSmathue door_dp = (door_data_t *)(uintptr_t)dip->di_data; 15107c478bd9Sstevel@tonic-gate 1511*5363f09cSarutz debug(10, "sm_door_server_create[%d]: entering...\n", pthread_self()); 15127c478bd9Sstevel@tonic-gate 15137c478bd9Sstevel@tonic-gate /* create one thread for this door */ 15147c478bd9Sstevel@tonic-gate 15157c478bd9Sstevel@tonic-gate (void) mutex_lock(&door_dp->dd_threadlock); 15167c478bd9Sstevel@tonic-gate 15177c478bd9Sstevel@tonic-gate if (door_dp->dd_thread != 0) { 1518*5363f09cSarutz debug(8, "sm_door_server_create[%d]: Exiting without creating " 1519*5363f09cSarutz "thread.\n", pthread_self()); 15207c478bd9Sstevel@tonic-gate (void) mutex_unlock(&door_dp->dd_threadlock); 15217c478bd9Sstevel@tonic-gate return; 15227c478bd9Sstevel@tonic-gate } 15237c478bd9Sstevel@tonic-gate 15247c478bd9Sstevel@tonic-gate (void) pthread_attr_init(&attr); 15257c478bd9Sstevel@tonic-gate 1526*5363f09cSarutz if ((err = pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM)) != 0) 1527*5363f09cSarutz warning(gettext("pthread_attr_setscope failed = %d\n"), err); 1528*5363f09cSarutz if ((err = pthread_attr_setdetachstate(&attr, 1529*5363f09cSarutz PTHREAD_CREATE_DETACHED)) != 0) 1530*5363f09cSarutz warning(gettext("pthread_attr_setdetachstate failed = %d\n"), 1531*5363f09cSarutz err); 1532*5363f09cSarutz 1533*5363f09cSarutz ret_val = pthread_create(&tid, &attr, sm_server_thread, 1534*5363f09cSarutz (void *)(uintptr_t)(dip->di_data)); 15357c478bd9Sstevel@tonic-gate if (ret_val != 0) { 1536*5363f09cSarutz warning(gettext("sm_door_server_create[%d]: pthread_create " 1537*5363f09cSarutz "failed = %d\n"), pthread_self(), ret_val); 15387c478bd9Sstevel@tonic-gate (void) mutex_unlock(&door_dp->dd_threadlock); 15397c478bd9Sstevel@tonic-gate (void) pthread_attr_destroy(&attr); 15407c478bd9Sstevel@tonic-gate return; 15417c478bd9Sstevel@tonic-gate } 15427c478bd9Sstevel@tonic-gate (void) pthread_attr_destroy(&attr); 15437c478bd9Sstevel@tonic-gate door_dp->dd_thread = tid; 15447c478bd9Sstevel@tonic-gate 15457c478bd9Sstevel@tonic-gate (void) mutex_unlock(&door_dp->dd_threadlock); 1546*5363f09cSarutz debug(5, "Exiting sm_door_server_create[%d] after creating thr[%d].\n", 1547*5363f09cSarutz pthread_self(), tid); 15487c478bd9Sstevel@tonic-gate } 15497c478bd9Sstevel@tonic-gate 15507c478bd9Sstevel@tonic-gate static void 15517c478bd9Sstevel@tonic-gate door_ret_err(smedia_reterror_t *reterror, int32_t err) 15527c478bd9Sstevel@tonic-gate { 15537c478bd9Sstevel@tonic-gate reterror->cnum = SMEDIA_CNUM_ERROR; 15547c478bd9Sstevel@tonic-gate reterror->errnum = err; 15557c478bd9Sstevel@tonic-gate (void) door_return((char *)reterror, sizeof (smedia_reterror_t), 0, 0); 15567c478bd9Sstevel@tonic-gate } 15577c478bd9Sstevel@tonic-gate 15587c478bd9Sstevel@tonic-gate static void 15597c478bd9Sstevel@tonic-gate my_door_return(char *data_ptr, size_t data_size, 15607c478bd9Sstevel@tonic-gate door_desc_t *desc_ptr, uint_t num_desc) 15617c478bd9Sstevel@tonic-gate { 15627c478bd9Sstevel@tonic-gate (void) door_return(data_ptr, data_size, desc_ptr, num_desc); 15637c478bd9Sstevel@tonic-gate } 15647c478bd9Sstevel@tonic-gate 15657c478bd9Sstevel@tonic-gate static int32_t 15667c478bd9Sstevel@tonic-gate raw_read(door_data_t *door_dp, smedia_services_t *req) 15677c478bd9Sstevel@tonic-gate { 15687c478bd9Sstevel@tonic-gate struct uscsi_cmd ucmd; 15697c478bd9Sstevel@tonic-gate union scsi_cdb cdb; 15707c478bd9Sstevel@tonic-gate int32_t ret_val; 15717c478bd9Sstevel@tonic-gate int32_t num_sectors, sector_size; 15727c478bd9Sstevel@tonic-gate int32_t rc_data[2]; 15737c478bd9Sstevel@tonic-gate char rq_data[RQ_LEN]; 15747c478bd9Sstevel@tonic-gate 15757c478bd9Sstevel@tonic-gate (void) memset((void *) &rc_data, 0, sizeof (rc_data)); 15767c478bd9Sstevel@tonic-gate (void) memset((void *) &ucmd, 0, sizeof (ucmd)); 15777c478bd9Sstevel@tonic-gate (void) memset((void *) &cdb, 0, sizeof (union scsi_cdb)); 15787c478bd9Sstevel@tonic-gate 15797c478bd9Sstevel@tonic-gate if (door_dp->dd_sector_size == 0) { 15807c478bd9Sstevel@tonic-gate sector_size = get_sector_size(door_dp->dd_fd); 15817c478bd9Sstevel@tonic-gate door_dp->dd_sector_size = sector_size; 15827c478bd9Sstevel@tonic-gate } else sector_size = door_dp->dd_sector_size; 15837c478bd9Sstevel@tonic-gate 15847c478bd9Sstevel@tonic-gate if ((req->reqraw_read.nbytes > door_dp->dd_buf_len) || 15857c478bd9Sstevel@tonic-gate (door_dp->dd_buf == NULL)) { 15867c478bd9Sstevel@tonic-gate errno = EINVAL; 15877c478bd9Sstevel@tonic-gate return (-1); 15887c478bd9Sstevel@tonic-gate } 15897c478bd9Sstevel@tonic-gate if ((!req->reqraw_read.nbytes) || 15907c478bd9Sstevel@tonic-gate (req->reqraw_read.nbytes % sector_size)) { 15917c478bd9Sstevel@tonic-gate errno = EINVAL; 15927c478bd9Sstevel@tonic-gate return (-1); 15937c478bd9Sstevel@tonic-gate } 15947c478bd9Sstevel@tonic-gate 15957c478bd9Sstevel@tonic-gate (void) memset((void *) &cdb, 0, sizeof (cdb)); 15967c478bd9Sstevel@tonic-gate num_sectors = (uint32_t)req->reqraw_read.nbytes/sector_size; 15977c478bd9Sstevel@tonic-gate 15987c478bd9Sstevel@tonic-gate cdb.scc_cmd = SCMD_READ_G1; 15997c478bd9Sstevel@tonic-gate FORMG1ADDR(&cdb, (uint32_t)req->reqraw_read.blockno); 16007c478bd9Sstevel@tonic-gate FORMG1COUNT(&cdb, num_sectors); 16017c478bd9Sstevel@tonic-gate 16027c478bd9Sstevel@tonic-gate ucmd.uscsi_cdb = (caddr_t)&cdb; 16037c478bd9Sstevel@tonic-gate ucmd.uscsi_cdblen = CDB_GROUP1; 16047c478bd9Sstevel@tonic-gate ucmd.uscsi_bufaddr = (caddr_t)door_dp->dd_buf; 16057c478bd9Sstevel@tonic-gate ucmd.uscsi_buflen = (uint32_t)req->reqraw_read.nbytes; 16067c478bd9Sstevel@tonic-gate ucmd.uscsi_timeout = 120; /* If 0, HBA hangs forever */ 16077c478bd9Sstevel@tonic-gate ucmd.uscsi_rqlen = RQ_LEN; 16087c478bd9Sstevel@tonic-gate ucmd.uscsi_rqbuf = rq_data; 16097c478bd9Sstevel@tonic-gate ret_val = do_uscsi_cmd(door_dp->dd_fd, 16107c478bd9Sstevel@tonic-gate &ucmd, USCSI_READ|USCSI_RQENABLE); 16117c478bd9Sstevel@tonic-gate if (ret_val || ucmd.uscsi_status) { 16127c478bd9Sstevel@tonic-gate debug(5, "read failed: %d - %d errno = %d\n", 16137c478bd9Sstevel@tonic-gate ret_val, ucmd.uscsi_status, errno); 16147c478bd9Sstevel@tonic-gate debug(5, "buflen = 0x%x resid = 0x%x sector size = %d\n", 16157c478bd9Sstevel@tonic-gate ucmd.uscsi_buflen, ucmd.uscsi_resid, sector_size); 16167c478bd9Sstevel@tonic-gate debug(5, "cdb addr: %x %x %x %x \n", cdb.g1_addr3, 16177c478bd9Sstevel@tonic-gate cdb.g1_addr2, cdb.g1_addr1, cdb.g1_addr0); 16187c478bd9Sstevel@tonic-gate debug(5, "cdb count: %x %x\n", cdb.g1_count1, 16197c478bd9Sstevel@tonic-gate cdb.g1_count0); 16207c478bd9Sstevel@tonic-gate return (-1); 16217c478bd9Sstevel@tonic-gate } 16227c478bd9Sstevel@tonic-gate ret_val = ucmd.uscsi_buflen - ucmd.uscsi_resid; 16237c478bd9Sstevel@tonic-gate return (ret_val); 16247c478bd9Sstevel@tonic-gate } 16257c478bd9Sstevel@tonic-gate 16267c478bd9Sstevel@tonic-gate static int32_t 16277c478bd9Sstevel@tonic-gate raw_write(door_data_t *door_dp, smedia_services_t *req) 16287c478bd9Sstevel@tonic-gate { 16297c478bd9Sstevel@tonic-gate struct uscsi_cmd ucmd; 16307c478bd9Sstevel@tonic-gate union scsi_cdb cdb; 16317c478bd9Sstevel@tonic-gate int32_t ret_val; 16327c478bd9Sstevel@tonic-gate int32_t num_sectors, sector_size; 16337c478bd9Sstevel@tonic-gate int32_t rc_data[2]; 16347c478bd9Sstevel@tonic-gate char rq_data[RQ_LEN]; 16357c478bd9Sstevel@tonic-gate 16367c478bd9Sstevel@tonic-gate (void) memset((void *) &rc_data, 0, sizeof (rc_data)); 16377c478bd9Sstevel@tonic-gate (void) memset((void *) &ucmd, 0, sizeof (ucmd)); 16387c478bd9Sstevel@tonic-gate (void) memset((void *) &cdb, 0, sizeof (union scsi_cdb)); 16397c478bd9Sstevel@tonic-gate 16407c478bd9Sstevel@tonic-gate if (door_dp->dd_sector_size == 0) { 16417c478bd9Sstevel@tonic-gate sector_size = get_sector_size(door_dp->dd_fd); 16427c478bd9Sstevel@tonic-gate door_dp->dd_sector_size = sector_size; 16437c478bd9Sstevel@tonic-gate } else sector_size = door_dp->dd_sector_size; 16447c478bd9Sstevel@tonic-gate 16457c478bd9Sstevel@tonic-gate 16467c478bd9Sstevel@tonic-gate if ((req->reqraw_write.nbytes > door_dp->dd_buf_len) || 16477c478bd9Sstevel@tonic-gate (door_dp->dd_buf == NULL)) { 16487c478bd9Sstevel@tonic-gate errno = EINVAL; 16497c478bd9Sstevel@tonic-gate return (-1); 16507c478bd9Sstevel@tonic-gate } 16517c478bd9Sstevel@tonic-gate if ((req->reqraw_write.nbytes % sector_size)) { 16527c478bd9Sstevel@tonic-gate errno = EINVAL; 16537c478bd9Sstevel@tonic-gate return (-1); 16547c478bd9Sstevel@tonic-gate } 16557c478bd9Sstevel@tonic-gate 16567c478bd9Sstevel@tonic-gate (void) memset((void *) &cdb, 0, sizeof (cdb)); 16577c478bd9Sstevel@tonic-gate num_sectors = (uint32_t)req->reqraw_write.nbytes/sector_size; 16587c478bd9Sstevel@tonic-gate 16597c478bd9Sstevel@tonic-gate cdb.scc_cmd = SCMD_WRITE_G1; 16607c478bd9Sstevel@tonic-gate FORMG1ADDR(&cdb, (uint32_t)req->reqraw_write.blockno); 16617c478bd9Sstevel@tonic-gate FORMG1COUNT(&cdb, num_sectors); 16627c478bd9Sstevel@tonic-gate 16637c478bd9Sstevel@tonic-gate ucmd.uscsi_cdb = (caddr_t)&cdb; 16647c478bd9Sstevel@tonic-gate ucmd.uscsi_cdblen = CDB_GROUP1; 16657c478bd9Sstevel@tonic-gate ucmd.uscsi_bufaddr = (caddr_t)door_dp->dd_buf; 16667c478bd9Sstevel@tonic-gate ucmd.uscsi_buflen = (uint32_t)req->reqraw_write.nbytes; 16677c478bd9Sstevel@tonic-gate ucmd.uscsi_timeout = 120; /* If 0, HBA hangs forever */ 16687c478bd9Sstevel@tonic-gate ucmd.uscsi_rqlen = RQ_LEN; 16697c478bd9Sstevel@tonic-gate ucmd.uscsi_rqbuf = rq_data; 16707c478bd9Sstevel@tonic-gate ret_val = do_uscsi_cmd(door_dp->dd_fd, 16717c478bd9Sstevel@tonic-gate &ucmd, USCSI_WRITE|USCSI_RQENABLE); 16727c478bd9Sstevel@tonic-gate if (ret_val || ucmd.uscsi_status) { 16737c478bd9Sstevel@tonic-gate debug(5, "write failed: %d - %d errno = %d\n", 16747c478bd9Sstevel@tonic-gate ret_val, ucmd.uscsi_status, errno); 16757c478bd9Sstevel@tonic-gate debug(5, "buflen = 0x%x resid = 0x%x sector size = %d\n", 16767c478bd9Sstevel@tonic-gate ucmd.uscsi_buflen, ucmd.uscsi_resid, sector_size); 16777c478bd9Sstevel@tonic-gate debug(5, "cdb addr: %x %x %x %x \n", cdb.g1_addr3, 16787c478bd9Sstevel@tonic-gate cdb.g1_addr2, cdb.g1_addr1, cdb.g1_addr0); 16797c478bd9Sstevel@tonic-gate debug(5, "cdb count: %x %x\n", cdb.g1_count1, 16807c478bd9Sstevel@tonic-gate cdb.g1_count0); 16817c478bd9Sstevel@tonic-gate return (-1); 16827c478bd9Sstevel@tonic-gate } 16837c478bd9Sstevel@tonic-gate ret_val = ucmd.uscsi_buflen - ucmd.uscsi_resid; 16847c478bd9Sstevel@tonic-gate return (ret_val); 16857c478bd9Sstevel@tonic-gate } 16867c478bd9Sstevel@tonic-gate 16877c478bd9Sstevel@tonic-gate static int32_t 16887c478bd9Sstevel@tonic-gate set_protection_status(door_data_t *door_dp, smedia_services_t *req) 16897c478bd9Sstevel@tonic-gate { 16907c478bd9Sstevel@tonic-gate int32_t ret_val, saved_errno, status; 16917c478bd9Sstevel@tonic-gate struct scsi_inquiry inq; 16927c478bd9Sstevel@tonic-gate char vid[9]; 16937c478bd9Sstevel@tonic-gate char pid[17]; 16947c478bd9Sstevel@tonic-gate struct passwd *pwd; 16957c478bd9Sstevel@tonic-gate char uname[MAXUGNAME + 1]; 16967c478bd9Sstevel@tonic-gate char *new_state, *old_state; 16977c478bd9Sstevel@tonic-gate 16987c478bd9Sstevel@tonic-gate /* 16997c478bd9Sstevel@tonic-gate * Read the current protection state before modifiying. 17007c478bd9Sstevel@tonic-gate * Needed for audit purposes. 17017c478bd9Sstevel@tonic-gate */ 17027c478bd9Sstevel@tonic-gate switch (get_device_type_scsi(door_dp->dd_fd, &inq)) { 17037c478bd9Sstevel@tonic-gate case SCSI_IOMEGA: 17047c478bd9Sstevel@tonic-gate status = scsi_zip_media_status(door_dp->dd_fd); 17057c478bd9Sstevel@tonic-gate ret_val = scsi_zip_write_protect(door_dp->dd_fd, 17067c478bd9Sstevel@tonic-gate &req->reqset_protection_status.prot_state); 17077c478bd9Sstevel@tonic-gate break; 17087c478bd9Sstevel@tonic-gate case SCSI_FLOPPY: 17097c478bd9Sstevel@tonic-gate info("Formatting floppy"); 17107c478bd9Sstevel@tonic-gate status = scsi_floppy_media_status(door_dp->dd_fd); 17117c478bd9Sstevel@tonic-gate ret_val = scsi_floppy_write_protect(door_dp->dd_fd, 17127c478bd9Sstevel@tonic-gate &req->reqset_protection_status.prot_state); 17137c478bd9Sstevel@tonic-gate break; 17147c478bd9Sstevel@tonic-gate case SCSI_GENERIC: 17157c478bd9Sstevel@tonic-gate status = scsi_media_status(door_dp->dd_fd); 17167c478bd9Sstevel@tonic-gate ret_val = scsi_write_protect(door_dp->dd_fd, 17177c478bd9Sstevel@tonic-gate &req->reqset_protection_status.prot_state); 17187c478bd9Sstevel@tonic-gate break; 17197c478bd9Sstevel@tonic-gate } 17207c478bd9Sstevel@tonic-gate 17217c478bd9Sstevel@tonic-gate saved_errno = errno; 17227c478bd9Sstevel@tonic-gate new_state = xlate_state( 17237c478bd9Sstevel@tonic-gate req->reqset_protection_status.prot_state.sm_new_state); 17247c478bd9Sstevel@tonic-gate old_state = xlate_state(status); 17257c478bd9Sstevel@tonic-gate 17267c478bd9Sstevel@tonic-gate if (can_audit()) { 17277c478bd9Sstevel@tonic-gate (void) audit_save_me(door_dp); 17287c478bd9Sstevel@tonic-gate door_dp->audit_text[0] = 0; 17297c478bd9Sstevel@tonic-gate door_dp->audit_text1[0] = 0; 17307c478bd9Sstevel@tonic-gate door_dp->audit_event = AUE_smserverd; 17317c478bd9Sstevel@tonic-gate } 17327c478bd9Sstevel@tonic-gate (void) strlcpy(vid, inq.inq_vid, sizeof (vid)); 17337c478bd9Sstevel@tonic-gate (void) strlcpy(pid, inq.inq_pid, sizeof (pid)); 17347c478bd9Sstevel@tonic-gate if (ret_val < 0) { 17357c478bd9Sstevel@tonic-gate if (errno == EACCES) { 17367c478bd9Sstevel@tonic-gate pwd = getpwuid(door_dp->dd_cred.dc_ruid); 17377c478bd9Sstevel@tonic-gate if (pwd != NULL) { 17387c478bd9Sstevel@tonic-gate (void) strlcpy(uname, 17397c478bd9Sstevel@tonic-gate pwd->pw_name, MAXUGNAME); 17407c478bd9Sstevel@tonic-gate } else uname[0] = 0; 17417c478bd9Sstevel@tonic-gate 17427c478bd9Sstevel@tonic-gate if (can_audit()) { 17437c478bd9Sstevel@tonic-gate (void) snprintf(door_dp->audit_text, 17447c478bd9Sstevel@tonic-gate sizeof (door_dp->audit_text), 17457c478bd9Sstevel@tonic-gate dgettext(TEXT_DOMAIN, "from %s to %s"), 17467c478bd9Sstevel@tonic-gate old_state, new_state); 17477c478bd9Sstevel@tonic-gate 17487c478bd9Sstevel@tonic-gate (void) snprintf(door_dp->audit_text1, 17497c478bd9Sstevel@tonic-gate sizeof (door_dp->audit_text1), 17507c478bd9Sstevel@tonic-gate "%s %s (%d,%d)", vid, pid, 17517c478bd9Sstevel@tonic-gate (int)major(door_dp->dd_stat.st_rdev), 17527c478bd9Sstevel@tonic-gate (int)minor(door_dp->dd_stat.st_rdev)); 17537c478bd9Sstevel@tonic-gate 17547c478bd9Sstevel@tonic-gate door_dp->audit_sorf = 1; 17557c478bd9Sstevel@tonic-gate if (audit_audit(door_dp) == -1) 17567c478bd9Sstevel@tonic-gate warning("Error in writing audit info\n"); 17577c478bd9Sstevel@tonic-gate } 17587c478bd9Sstevel@tonic-gate } /* errno == EACCES */ 17597c478bd9Sstevel@tonic-gate errno = saved_errno; 17607c478bd9Sstevel@tonic-gate return (-1); 17617c478bd9Sstevel@tonic-gate } 17627c478bd9Sstevel@tonic-gate if (can_audit()) { 17637c478bd9Sstevel@tonic-gate (void) snprintf(door_dp->audit_text, 17647c478bd9Sstevel@tonic-gate sizeof (door_dp->audit_text), 17657c478bd9Sstevel@tonic-gate dgettext(TEXT_DOMAIN, "from %s to %s"), 17667c478bd9Sstevel@tonic-gate old_state, new_state); 17677c478bd9Sstevel@tonic-gate 17687c478bd9Sstevel@tonic-gate (void) snprintf(door_dp->audit_text1, 17697c478bd9Sstevel@tonic-gate sizeof (door_dp->audit_text1), 17707c478bd9Sstevel@tonic-gate "%s %s (%d,%d)", vid, pid, 17717c478bd9Sstevel@tonic-gate (int)major(door_dp->dd_stat.st_rdev), 17727c478bd9Sstevel@tonic-gate (int)minor(door_dp->dd_stat.st_rdev)); 17737c478bd9Sstevel@tonic-gate 17747c478bd9Sstevel@tonic-gate door_dp->audit_sorf = 0; 17757c478bd9Sstevel@tonic-gate if (audit_audit(door_dp) == -1) 17767c478bd9Sstevel@tonic-gate warning("Error in writing audit info\n"); 17777c478bd9Sstevel@tonic-gate } 17787c478bd9Sstevel@tonic-gate errno = saved_errno; 17797c478bd9Sstevel@tonic-gate return (0); 17807c478bd9Sstevel@tonic-gate } 17817c478bd9Sstevel@tonic-gate 17827c478bd9Sstevel@tonic-gate static int32_t 17837c478bd9Sstevel@tonic-gate set_shfd(door_data_t *door_dp, int32_t fd, smedia_services_t *req) 17847c478bd9Sstevel@tonic-gate { 17857c478bd9Sstevel@tonic-gate void *fbuf; 1786*5363f09cSarutz int32_t ret_val = 0; 17877c478bd9Sstevel@tonic-gate 1788*5363f09cSarutz if ((door_dp->dd_buffd != -1) && (door_dp->dd_buf != NULL)) { 1789*5363f09cSarutz ret_val = munmap(door_dp->dd_buf, door_dp->dd_buf_len); 17907c478bd9Sstevel@tonic-gate if (ret_val == -1) 1791*5363f09cSarutz warning(gettext("munmap failed. errno=%d\n"), 17927c478bd9Sstevel@tonic-gate errno); 17937c478bd9Sstevel@tonic-gate (void) close(door_dp->dd_buffd); 1794*5363f09cSarutz 17957c478bd9Sstevel@tonic-gate door_dp->dd_buffd = -1; 17967c478bd9Sstevel@tonic-gate door_dp->dd_buf = 0; 17977c478bd9Sstevel@tonic-gate door_dp->dd_buf_len = 0; 17987c478bd9Sstevel@tonic-gate } 1799*5363f09cSarutz 18007c478bd9Sstevel@tonic-gate fbuf = mmap(0, req->reqset_shfd.fdbuf_len, 18017c478bd9Sstevel@tonic-gate PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); 1802*5363f09cSarutz if (fbuf == MAP_FAILED) { 1803*5363f09cSarutz ret_val = errno; 18047c478bd9Sstevel@tonic-gate debug(5, "mmap failed. errno=%d\n", errno); 1805*5363f09cSarutz return (ret_val); 18067c478bd9Sstevel@tonic-gate } 18077c478bd9Sstevel@tonic-gate door_dp->dd_buffd = fd; 18087c478bd9Sstevel@tonic-gate door_dp->dd_buf = fbuf; 18097c478bd9Sstevel@tonic-gate door_dp->dd_buf_len = req->reqset_shfd.fdbuf_len; 1810*5363f09cSarutz 18117c478bd9Sstevel@tonic-gate return (0); 18127c478bd9Sstevel@tonic-gate } 18137c478bd9Sstevel@tonic-gate 18147c478bd9Sstevel@tonic-gate static int32_t 18157c478bd9Sstevel@tonic-gate reassign_block(door_data_t *door_dp, smedia_services_t *req) 18167c478bd9Sstevel@tonic-gate { 18177c478bd9Sstevel@tonic-gate struct uscsi_cmd ucmd; 18187c478bd9Sstevel@tonic-gate union scsi_cdb cdb; 18197c478bd9Sstevel@tonic-gate int32_t ret_val; 18207c478bd9Sstevel@tonic-gate int32_t sector_size; 18217c478bd9Sstevel@tonic-gate char *read_buf; 18227c478bd9Sstevel@tonic-gate uchar_t mode_data[MD_LEN]; 18237c478bd9Sstevel@tonic-gate 18247c478bd9Sstevel@tonic-gate if (get_mode_page(door_dp->dd_fd, 0, 1, 18257c478bd9Sstevel@tonic-gate mode_data, MD_LEN) < 0) { 18267c478bd9Sstevel@tonic-gate debug(5, "Mode sense failed\n"); 18277c478bd9Sstevel@tonic-gate ret_val = scsi_reassign_block(door_dp->dd_fd, 18287c478bd9Sstevel@tonic-gate req->reqreassign_block.blockno); 18297c478bd9Sstevel@tonic-gate if (ret_val != 0) 18307c478bd9Sstevel@tonic-gate return (-1); 18317c478bd9Sstevel@tonic-gate return (0); 18327c478bd9Sstevel@tonic-gate } 18337c478bd9Sstevel@tonic-gate 18347c478bd9Sstevel@tonic-gate /* 18357c478bd9Sstevel@tonic-gate * No need to check if enough data is returned for 18367c478bd9Sstevel@tonic-gate * AWRE bit or not. 18377c478bd9Sstevel@tonic-gate * It will be 0 otherwise which needs to reassign the block. 18387c478bd9Sstevel@tonic-gate */ 18397c478bd9Sstevel@tonic-gate if (!(mode_data[AWRE_OFFSET] & AWRE)) { 18407c478bd9Sstevel@tonic-gate debug(5, "AWRE bit not set\n"); 18417c478bd9Sstevel@tonic-gate ret_val = scsi_reassign_block(door_dp->dd_fd, 18427c478bd9Sstevel@tonic-gate req->reqreassign_block.blockno); 18437c478bd9Sstevel@tonic-gate if (ret_val != 0) 18447c478bd9Sstevel@tonic-gate return (-1); 18457c478bd9Sstevel@tonic-gate return (0); 18467c478bd9Sstevel@tonic-gate } 18477c478bd9Sstevel@tonic-gate sector_size = (mode_data[BLOCK_LEN_OFFSET] << 16) | 18487c478bd9Sstevel@tonic-gate (mode_data[BLOCK_LEN_OFFSET + 1] << 8) | 18497c478bd9Sstevel@tonic-gate mode_data[BLOCK_LEN_OFFSET + 2]; 18507c478bd9Sstevel@tonic-gate 18517c478bd9Sstevel@tonic-gate debug(5, "REASSIGN BLOCK: sec size = 0x%x\n", sector_size); 18527c478bd9Sstevel@tonic-gate read_buf = (char *)malloc(sector_size); 18537c478bd9Sstevel@tonic-gate if (read_buf == NULL) { 18547c478bd9Sstevel@tonic-gate /* Alloc failed. Atleast reassign the block */ 18557c478bd9Sstevel@tonic-gate ret_val = scsi_reassign_block(door_dp->dd_fd, 18567c478bd9Sstevel@tonic-gate req->reqreassign_block.blockno); 18577c478bd9Sstevel@tonic-gate if (ret_val != 0) 18587c478bd9Sstevel@tonic-gate return (-1); 18597c478bd9Sstevel@tonic-gate return (0); 18607c478bd9Sstevel@tonic-gate } 18617c478bd9Sstevel@tonic-gate 18627c478bd9Sstevel@tonic-gate (void) memset(read_buf, 0, sector_size); 18637c478bd9Sstevel@tonic-gate /* Read the sector */ 18647c478bd9Sstevel@tonic-gate debug(5, "Reading the block %d\n", 18657c478bd9Sstevel@tonic-gate (uint32_t)req->reqreassign_block.blockno); 18667c478bd9Sstevel@tonic-gate 18677c478bd9Sstevel@tonic-gate (void) memset((void *) &ucmd, 0, sizeof (ucmd)); 18687c478bd9Sstevel@tonic-gate (void) memset((void *) &cdb, 0, sizeof (union scsi_cdb)); 18697c478bd9Sstevel@tonic-gate 18707c478bd9Sstevel@tonic-gate cdb.scc_cmd = SCMD_READ_G1; 18717c478bd9Sstevel@tonic-gate FORMG1ADDR(&cdb, req->reqreassign_block.blockno); 18727c478bd9Sstevel@tonic-gate FORMG1COUNT(&cdb, 1); /* One block */ 18737c478bd9Sstevel@tonic-gate 18747c478bd9Sstevel@tonic-gate ucmd.uscsi_cdb = (caddr_t)&cdb; 18757c478bd9Sstevel@tonic-gate ucmd.uscsi_cdblen = CDB_GROUP1; 18767c478bd9Sstevel@tonic-gate ucmd.uscsi_bufaddr = (caddr_t)read_buf; 18777c478bd9Sstevel@tonic-gate ucmd.uscsi_buflen = sector_size; 18787c478bd9Sstevel@tonic-gate ucmd.uscsi_timeout = 120; /* If 0, HBA hangs forever */ 18797c478bd9Sstevel@tonic-gate (void) do_uscsi_cmd(door_dp->dd_fd, &ucmd, USCSI_READ); 18807c478bd9Sstevel@tonic-gate 18817c478bd9Sstevel@tonic-gate /* Write the data back */ 18827c478bd9Sstevel@tonic-gate 18837c478bd9Sstevel@tonic-gate debug(5, "Writing the block %d\n", 18847c478bd9Sstevel@tonic-gate (uint32_t)req->reqreassign_block.blockno); 18857c478bd9Sstevel@tonic-gate (void) memset((void *) &ucmd, 0, sizeof (ucmd)); 18867c478bd9Sstevel@tonic-gate (void) memset((void *) &cdb, 0, sizeof (cdb)); 18877c478bd9Sstevel@tonic-gate 18887c478bd9Sstevel@tonic-gate cdb.scc_cmd = SCMD_WRITE_G1; 18897c478bd9Sstevel@tonic-gate FORMG1ADDR(&cdb, req->reqreassign_block.blockno); 18907c478bd9Sstevel@tonic-gate FORMG1COUNT(&cdb, 1); /* One block */ 18917c478bd9Sstevel@tonic-gate 18927c478bd9Sstevel@tonic-gate ucmd.uscsi_cdb = (caddr_t)&cdb; 18937c478bd9Sstevel@tonic-gate ucmd.uscsi_cdblen = CDB_GROUP1; 18947c478bd9Sstevel@tonic-gate ucmd.uscsi_bufaddr = (caddr_t)read_buf; 18957c478bd9Sstevel@tonic-gate ucmd.uscsi_buflen = sector_size; 18967c478bd9Sstevel@tonic-gate ucmd.uscsi_timeout = 120; /* If 0, HBA hangs forever */ 18977c478bd9Sstevel@tonic-gate ret_val = do_uscsi_cmd(door_dp->dd_fd, &ucmd, USCSI_WRITE); 18987c478bd9Sstevel@tonic-gate free(read_buf); 18997c478bd9Sstevel@tonic-gate if (ret_val || ucmd.uscsi_status) { 19007c478bd9Sstevel@tonic-gate debug(5, "Reassign failed: %d - %d errno = %d\n", 19017c478bd9Sstevel@tonic-gate ret_val, ucmd.uscsi_status, errno); 19027c478bd9Sstevel@tonic-gate ret_val = scsi_reassign_block(door_dp->dd_fd, 19037c478bd9Sstevel@tonic-gate req->reqreassign_block.blockno); 19047c478bd9Sstevel@tonic-gate if (ret_val != 0) 19057c478bd9Sstevel@tonic-gate return (-1); 19067c478bd9Sstevel@tonic-gate return (0); 19077c478bd9Sstevel@tonic-gate } 19087c478bd9Sstevel@tonic-gate 19097c478bd9Sstevel@tonic-gate return (0); 19107c478bd9Sstevel@tonic-gate } 19117c478bd9Sstevel@tonic-gate 19127c478bd9Sstevel@tonic-gate static void 19137c478bd9Sstevel@tonic-gate close_door_descs(door_desc_t *dp, uint_t ndesc) 19147c478bd9Sstevel@tonic-gate { 19157c478bd9Sstevel@tonic-gate while (ndesc > 0) { 19167c478bd9Sstevel@tonic-gate int fd = dp->d_data.d_desc.d_descriptor; 19177c478bd9Sstevel@tonic-gate if (dp->d_attributes & DOOR_DESCRIPTOR) 19187c478bd9Sstevel@tonic-gate (void) close(fd); 19197c478bd9Sstevel@tonic-gate dp++; 19207c478bd9Sstevel@tonic-gate ndesc--; 19217c478bd9Sstevel@tonic-gate } 19227c478bd9Sstevel@tonic-gate } 19237c478bd9Sstevel@tonic-gate 1924*5363f09cSarutz /* 1925*5363f09cSarutz * This is a Death Door's service procedure. 1926*5363f09cSarutz * 1927*5363f09cSarutz * This procedure is a NOP because the Death Door functionality 1928*5363f09cSarutz * is no longer used and will be removed in the future. 1929*5363f09cSarutz */ 1930*5363f09cSarutz /*ARGSUSED*/ 19317c478bd9Sstevel@tonic-gate static void 1932*5363f09cSarutz death_servproc(void *cookie, char *argp, size_t arg_size, 1933*5363f09cSarutz door_desc_t *dp, uint_t ndesc) 1934*5363f09cSarutz { 1935*5363f09cSarutz debug(1, "death_servproc[%d]: argp = 0x%p " 1936*5363f09cSarutz "Death Door[%d]\n", pthread_self(), (void *)argp, 1937*5363f09cSarutz ((door_data_t *)cookie)->dd_ddoor_descriptor); 1938*5363f09cSarutz 1939*5363f09cSarutz (void) door_return(NULL, 0, NULL, 0); 1940*5363f09cSarutz } 1941*5363f09cSarutz 1942*5363f09cSarutz /* 1943*5363f09cSarutz * This is a Client Door's service procedure. 1944*5363f09cSarutz * 1945*5363f09cSarutz * This procedure is specified in the door_create() of a Client Door, 1946*5363f09cSarutz * and its functionality represents the bulk of services that the 1947*5363f09cSarutz * rpc.smserverd daemon offers. 1948*5363f09cSarutz */ 1949*5363f09cSarutz static void 1950*5363f09cSarutz client_servproc(void *cookie, char *argp, size_t arg_size, 19517c478bd9Sstevel@tonic-gate door_desc_t *dp, uint_t ndesc) 19527c478bd9Sstevel@tonic-gate { 19537c478bd9Sstevel@tonic-gate smedia_services_t *req; 19547c478bd9Sstevel@tonic-gate smedia_services_t rmsvc; 19557c478bd9Sstevel@tonic-gate smedia_reterror_t reterror; 19567c478bd9Sstevel@tonic-gate smedia_retraw_read_t retraw_read; 19577c478bd9Sstevel@tonic-gate struct scsi_inquiry inq; 19587c478bd9Sstevel@tonic-gate struct dk_minfo media_info; 19597c478bd9Sstevel@tonic-gate struct dk_geom dkgeom; 19607c478bd9Sstevel@tonic-gate int32_t status; 19617c478bd9Sstevel@tonic-gate uchar_t data[18]; 19627c478bd9Sstevel@tonic-gate int32_t completed = 0; 19637c478bd9Sstevel@tonic-gate door_data_t *door_dp; 19647c478bd9Sstevel@tonic-gate size_t retbuf_size; 19657c478bd9Sstevel@tonic-gate struct uscsi_cmd ucmd; 19667c478bd9Sstevel@tonic-gate union scsi_cdb cdb; 19677c478bd9Sstevel@tonic-gate int32_t ret_val, err; 19687c478bd9Sstevel@tonic-gate char rq_data[RQ_LEN]; 1969*5363f09cSarutz uint_t nexpected_desc; 19707c478bd9Sstevel@tonic-gate struct vtoc vtoc; 19717c478bd9Sstevel@tonic-gate 19727c478bd9Sstevel@tonic-gate door_dp = (door_data_t *)cookie; 19737c478bd9Sstevel@tonic-gate req = (smedia_services_t *)((void *)argp); 19747c478bd9Sstevel@tonic-gate 1975*5363f09cSarutz debug(10, "client_servproc[%d]...\n", pthread_self()); 19767c478bd9Sstevel@tonic-gate 19777c478bd9Sstevel@tonic-gate if (argp == DOOR_UNREF_DATA) { 1978*5363f09cSarutz debug(5, "client_servproc[%d]: req = DOOR_UNREF_DATA\n", 19797c478bd9Sstevel@tonic-gate pthread_self()); 19807c478bd9Sstevel@tonic-gate debug(5, "Client has exited. Cleaning up resources\n"); 1981*5363f09cSarutz 19827c478bd9Sstevel@tonic-gate (void) mutex_lock(&svcstate_lock); 19837c478bd9Sstevel@tonic-gate svccount--; 19847c478bd9Sstevel@tonic-gate (void) mutex_unlock(&svcstate_lock); 1985*5363f09cSarutz 19867c478bd9Sstevel@tonic-gate cleanup(door_dp); 1987*5363f09cSarutz return; 19887c478bd9Sstevel@tonic-gate } 1989*5363f09cSarutz 19907c478bd9Sstevel@tonic-gate (void) mutex_lock(&svcstate_lock); 19917c478bd9Sstevel@tonic-gate svcstate = _SERVED; 19927c478bd9Sstevel@tonic-gate (void) mutex_unlock(&svcstate_lock); 19937c478bd9Sstevel@tonic-gate 19947c478bd9Sstevel@tonic-gate rmsvc.in.cnum = req->in.cnum; 1995*5363f09cSarutz debug(5, "client_servproc[%d]: req = %s\n", pthread_self(), 19967c478bd9Sstevel@tonic-gate xlate_cnum(req->in.cnum)); 19977c478bd9Sstevel@tonic-gate 19987c478bd9Sstevel@tonic-gate /* 19997c478bd9Sstevel@tonic-gate * Our caller may have passed more descriptors than we expected. 20007c478bd9Sstevel@tonic-gate * If so, we silently close (and ignore) them. 20017c478bd9Sstevel@tonic-gate */ 2002*5363f09cSarutz nexpected_desc = (req->in.cnum == SMEDIA_CNUM_SET_SHFD) ? 1 : 0; 2003*5363f09cSarutz if (ndesc > nexpected_desc) { 2004*5363f09cSarutz close_door_descs(dp + nexpected_desc, ndesc - nexpected_desc); 2005*5363f09cSarutz } 20067c478bd9Sstevel@tonic-gate 20077c478bd9Sstevel@tonic-gate switch (req->in.cnum) { 20087c478bd9Sstevel@tonic-gate default: 2009*5363f09cSarutz debug(5, "client_servproc: unknown command %d\n", req->in.cnum); 20107c478bd9Sstevel@tonic-gate door_ret_err(&reterror, ENOTSUP); 20117c478bd9Sstevel@tonic-gate break; 20127c478bd9Sstevel@tonic-gate 20137c478bd9Sstevel@tonic-gate case SMEDIA_CNUM_SET_SHFD: 20147c478bd9Sstevel@tonic-gate if (ndesc == 0) 20157c478bd9Sstevel@tonic-gate door_ret_err(&reterror, EINVAL); 20167c478bd9Sstevel@tonic-gate /* 2017*5363f09cSarutz * Allocate shared memory for this connection. 2018*5363f09cSarutz * If this connection already has shared memory, 2019*5363f09cSarutz * deallocate before doing the allocation. 20207c478bd9Sstevel@tonic-gate */ 2021*5363f09cSarutz ret_val = set_shfd(door_dp, dp->d_data.d_desc.d_descriptor, 2022*5363f09cSarutz req); 20237c478bd9Sstevel@tonic-gate if (ret_val == 0) { 20247c478bd9Sstevel@tonic-gate reterror.cnum = SMEDIA_CNUM_SET_SHFD; 20257c478bd9Sstevel@tonic-gate reterror.errnum = 0; 2026*5363f09cSarutz 20277c478bd9Sstevel@tonic-gate my_door_return((char *)&reterror, 20287c478bd9Sstevel@tonic-gate sizeof (smedia_reterror_t), 0, 0); 20297c478bd9Sstevel@tonic-gate } else { 20307c478bd9Sstevel@tonic-gate (void) close(dp->d_data.d_desc.d_descriptor); 2031*5363f09cSarutz door_ret_err(&reterror, ret_val); 20327c478bd9Sstevel@tonic-gate } 20337c478bd9Sstevel@tonic-gate break; 20347c478bd9Sstevel@tonic-gate 20357c478bd9Sstevel@tonic-gate case SMEDIA_CNUM_RAW_READ: 20367c478bd9Sstevel@tonic-gate debug(10, " arg size = %d blk num=0x%x nbytes = 0x%x \n", 20377c478bd9Sstevel@tonic-gate (int)arg_size, 20387c478bd9Sstevel@tonic-gate (uint32_t)req->reqraw_read.blockno, 20397c478bd9Sstevel@tonic-gate req->reqraw_read.nbytes); 20407c478bd9Sstevel@tonic-gate retbuf_size = sizeof (smedia_retraw_read_t); 20417c478bd9Sstevel@tonic-gate if (req->reqraw_read.nbytes == 0) { 20427c478bd9Sstevel@tonic-gate /* Nothing to write */ 20437c478bd9Sstevel@tonic-gate rmsvc.retraw_write.nbytes = 0; 20447c478bd9Sstevel@tonic-gate my_door_return((char *)&rmsvc, 20457c478bd9Sstevel@tonic-gate sizeof (smedia_retraw_write_t), 0, 0); 20467c478bd9Sstevel@tonic-gate } 20477c478bd9Sstevel@tonic-gate retraw_read.cnum = SMEDIA_CNUM_RAW_READ; 20487c478bd9Sstevel@tonic-gate ret_val = raw_read(door_dp, req); 20497c478bd9Sstevel@tonic-gate if (ret_val == -1) { 20507c478bd9Sstevel@tonic-gate door_ret_err(&reterror, errno); 20517c478bd9Sstevel@tonic-gate } 20527c478bd9Sstevel@tonic-gate retraw_read.nbytes = ret_val; 20537c478bd9Sstevel@tonic-gate my_door_return((char *)&retraw_read, retbuf_size, 0, 0); 20547c478bd9Sstevel@tonic-gate break; 20557c478bd9Sstevel@tonic-gate 20567c478bd9Sstevel@tonic-gate case SMEDIA_CNUM_USCSI_CMD: 20577c478bd9Sstevel@tonic-gate retbuf_size = sizeof (smedia_retuscsi_cmd_t); 20587c478bd9Sstevel@tonic-gate rmsvc.retuscsi_cmd.cnum = SMEDIA_CNUM_USCSI_CMD; 20597c478bd9Sstevel@tonic-gate ucmd.uscsi_flags = req->requscsi_cmd.uscsi_flags; 20607c478bd9Sstevel@tonic-gate ucmd.uscsi_cdb = (caddr_t)&req->requscsi_cmd.uscsi_cdb; 20617c478bd9Sstevel@tonic-gate ucmd.uscsi_cdblen = req->requscsi_cmd.uscsi_cdblen; 20627c478bd9Sstevel@tonic-gate ucmd.uscsi_bufaddr = (caddr_t)door_dp->dd_buf; 20637c478bd9Sstevel@tonic-gate ucmd.uscsi_buflen = req->requscsi_cmd.uscsi_buflen; 20647c478bd9Sstevel@tonic-gate ucmd.uscsi_timeout = req->requscsi_cmd.uscsi_timeout; 20657c478bd9Sstevel@tonic-gate ucmd.uscsi_rqlen = req->requscsi_cmd.uscsi_rqlen; 20667c478bd9Sstevel@tonic-gate ucmd.uscsi_rqbuf = (caddr_t)&rmsvc.retuscsi_cmd.uscsi_rqbuf; 2067*5363f09cSarutz debug(5, "USCSI CMD 0x%x requested.\n", 20687c478bd9Sstevel@tonic-gate req->requscsi_cmd.uscsi_cdb[0]); 20697c478bd9Sstevel@tonic-gate /* 20707c478bd9Sstevel@tonic-gate * Check the device type and invalid flags specified. 20717c478bd9Sstevel@tonic-gate * We permit operations only on CDROM devices types. 20727c478bd9Sstevel@tonic-gate */ 2073*5363f09cSarutz errno = invalid_uscsi_operation(door_dp, &ucmd); 20747c478bd9Sstevel@tonic-gate if (errno) { 20757c478bd9Sstevel@tonic-gate door_ret_err(&reterror, errno); 20767c478bd9Sstevel@tonic-gate } 20777c478bd9Sstevel@tonic-gate 20787c478bd9Sstevel@tonic-gate if ((req->requscsi_cmd.uscsi_buflen) && 20797c478bd9Sstevel@tonic-gate ((req->requscsi_cmd.uscsi_buflen > door_dp->dd_buf_len) || 20807c478bd9Sstevel@tonic-gate (door_dp->dd_buf == NULL))) { 2081*5363f09cSarutz debug(5, "uscsi_cmd failed: uscsi_buflen=0x%x " 2082*5363f09cSarutz "dd_buf_len=0x%x dd_buf=0x%p\n", 20837c478bd9Sstevel@tonic-gate req->requscsi_cmd.uscsi_buflen, 20847c478bd9Sstevel@tonic-gate door_dp->dd_buf_len, 20857c478bd9Sstevel@tonic-gate door_dp->dd_buf); 20867c478bd9Sstevel@tonic-gate errno = EINVAL; 20877c478bd9Sstevel@tonic-gate door_ret_err(&reterror, errno); 20887c478bd9Sstevel@tonic-gate } 20897c478bd9Sstevel@tonic-gate ret_val = do_uscsi_cmd(door_dp->dd_fd, 20907c478bd9Sstevel@tonic-gate &ucmd, req->requscsi_cmd.uscsi_flags); 20917c478bd9Sstevel@tonic-gate rmsvc.retuscsi_cmd.uscsi_status = ucmd.uscsi_status; 20927c478bd9Sstevel@tonic-gate rmsvc.retuscsi_cmd.uscsi_resid = ucmd.uscsi_resid; 20937c478bd9Sstevel@tonic-gate rmsvc.retuscsi_cmd.uscsi_rqstatus = ucmd.uscsi_rqstatus; 20947c478bd9Sstevel@tonic-gate rmsvc.retuscsi_cmd.uscsi_rqresid = ucmd.uscsi_rqresid; 20957c478bd9Sstevel@tonic-gate rmsvc.retuscsi_cmd.uscsi_retval = ret_val; 20967c478bd9Sstevel@tonic-gate rmsvc.retuscsi_cmd.uscsi_errno = errno; 20977c478bd9Sstevel@tonic-gate if (ret_val || ucmd.uscsi_status) { 20987c478bd9Sstevel@tonic-gate debug(5, "uscsi_cmd failed: %d - %d errno = %d\n", 20997c478bd9Sstevel@tonic-gate ret_val, ucmd.uscsi_status, errno); 21007c478bd9Sstevel@tonic-gate } 21017c478bd9Sstevel@tonic-gate my_door_return((char *)&rmsvc, retbuf_size, 0, 0); 21027c478bd9Sstevel@tonic-gate break; 21037c478bd9Sstevel@tonic-gate 21047c478bd9Sstevel@tonic-gate case SMEDIA_CNUM_RAW_WRITE: 21057c478bd9Sstevel@tonic-gate if (req->reqraw_write.nbytes == 0) { 21067c478bd9Sstevel@tonic-gate /* Nothing to write */ 21077c478bd9Sstevel@tonic-gate rmsvc.retraw_write.nbytes = 0; 21087c478bd9Sstevel@tonic-gate my_door_return((char *)&rmsvc, 21097c478bd9Sstevel@tonic-gate sizeof (smedia_retraw_write_t), 0, 0); 21107c478bd9Sstevel@tonic-gate } 21117c478bd9Sstevel@tonic-gate ret_val = raw_write(door_dp, req); 21127c478bd9Sstevel@tonic-gate if (ret_val == -1) 21137c478bd9Sstevel@tonic-gate door_ret_err(&reterror, errno); 21147c478bd9Sstevel@tonic-gate rmsvc.retraw_write.nbytes = ret_val; 21157c478bd9Sstevel@tonic-gate my_door_return((char *)&rmsvc, sizeof (smedia_retraw_write_t), 21167c478bd9Sstevel@tonic-gate 0, 0); 21177c478bd9Sstevel@tonic-gate break; 21187c478bd9Sstevel@tonic-gate 21197c478bd9Sstevel@tonic-gate case SMEDIA_CNUM_GET_DEVICE_INFO: 21207c478bd9Sstevel@tonic-gate 21217c478bd9Sstevel@tonic-gate (void) memset((void *) &inq, 0, sizeof (inq)); 21227c478bd9Sstevel@tonic-gate (void) memset((void *) &ucmd, 0, sizeof (ucmd)); 21237c478bd9Sstevel@tonic-gate (void) memset((void *) &cdb, 0, sizeof (union scsi_cdb)); 21247c478bd9Sstevel@tonic-gate cdb.scc_cmd = SCMD_INQUIRY; 21257c478bd9Sstevel@tonic-gate FORMG0COUNT(&cdb, sizeof (inq)); 21267c478bd9Sstevel@tonic-gate ucmd.uscsi_cdb = (caddr_t)&cdb; 21277c478bd9Sstevel@tonic-gate ucmd.uscsi_cdblen = CDB_GROUP0; 21287c478bd9Sstevel@tonic-gate ucmd.uscsi_bufaddr = (caddr_t)&inq; 21297c478bd9Sstevel@tonic-gate ucmd.uscsi_buflen = sizeof (inq); 21307c478bd9Sstevel@tonic-gate ucmd.uscsi_timeout = 120; /* If 0, HBA hangs forever */ 21317c478bd9Sstevel@tonic-gate ucmd.uscsi_rqlen = RQ_LEN; 21327c478bd9Sstevel@tonic-gate ucmd.uscsi_rqbuf = rq_data; 21337c478bd9Sstevel@tonic-gate ret_val = do_uscsi_cmd(door_dp->dd_fd, 21347c478bd9Sstevel@tonic-gate &ucmd, USCSI_READ|USCSI_RQENABLE); 21357c478bd9Sstevel@tonic-gate if (ret_val || ucmd.uscsi_status) { 21367c478bd9Sstevel@tonic-gate debug(5, "inquiry failed: %d - %d errno = %d\n", 21377c478bd9Sstevel@tonic-gate ret_val, ucmd.uscsi_status, errno); 21387c478bd9Sstevel@tonic-gate door_ret_err(&reterror, errno); 21397c478bd9Sstevel@tonic-gate } 21407c478bd9Sstevel@tonic-gate 21417c478bd9Sstevel@tonic-gate debug(5, "%s\n", inq.inq_vid); 21427c478bd9Sstevel@tonic-gate debug(5, "%s\n", rmsvc.retget_device_info.sm_vendor_name); 21437c478bd9Sstevel@tonic-gate 21447c478bd9Sstevel@tonic-gate (void) strlcpy(rmsvc.retget_device_info.sm_vendor_name, 21457c478bd9Sstevel@tonic-gate inq.inq_vid, 8); 21467c478bd9Sstevel@tonic-gate rmsvc.retget_device_info.sm_vendor_name[8] = 0; 21477c478bd9Sstevel@tonic-gate (void) strlcpy(rmsvc.retget_device_info.sm_product_name, 21487c478bd9Sstevel@tonic-gate inq.inq_pid, 16); 21497c478bd9Sstevel@tonic-gate rmsvc.retget_device_info.sm_product_name[16] = 0; 21507c478bd9Sstevel@tonic-gate (void) strlcpy(rmsvc.retget_device_info.sm_firmware_version, 21517c478bd9Sstevel@tonic-gate inq.inq_revision, 4); 21527c478bd9Sstevel@tonic-gate rmsvc.retget_device_info.sm_firmware_version[4] = ' '; 21537c478bd9Sstevel@tonic-gate (void) strlcpy( 21547c478bd9Sstevel@tonic-gate &rmsvc.retget_device_info.sm_firmware_version[5], 21557c478bd9Sstevel@tonic-gate inq.inq_serial, 12); 21567c478bd9Sstevel@tonic-gate rmsvc.retget_device_info.sm_product_name[17] = 0; 21577c478bd9Sstevel@tonic-gate 21587c478bd9Sstevel@tonic-gate rmsvc.retget_device_info.sm_interface_type = IF_SCSI; 21597c478bd9Sstevel@tonic-gate 2160*5363f09cSarutz debug(5, "Vendor name = %s\n", 2161*5363f09cSarutz rmsvc.retget_device_info.sm_vendor_name); 2162*5363f09cSarutz debug(5, "product name = %s\n", 2163*5363f09cSarutz rmsvc.retget_device_info.sm_product_name); 2164*5363f09cSarutz debug(5, "Firmware revision = %s\n", 2165*5363f09cSarutz rmsvc.retget_device_info.sm_firmware_version); 2166*5363f09cSarutz 21677c478bd9Sstevel@tonic-gate my_door_return((char *)&rmsvc.retget_device_info, 21687c478bd9Sstevel@tonic-gate sizeof (smedia_retget_device_info_t), 0, 0); 21697c478bd9Sstevel@tonic-gate break; 21707c478bd9Sstevel@tonic-gate 21717c478bd9Sstevel@tonic-gate case SMEDIA_CNUM_GET_MEDIUM_PROPERTY: 21727c478bd9Sstevel@tonic-gate 21737c478bd9Sstevel@tonic-gate (void) memset((void *)&rmsvc.retget_medium_property.smprop, 21747c478bd9Sstevel@tonic-gate 0, sizeof (smmedium_prop_t)); 21757c478bd9Sstevel@tonic-gate 21767c478bd9Sstevel@tonic-gate ret_val = ioctl(door_dp->dd_fd, DKIOCGMEDIAINFO, &media_info); 21777c478bd9Sstevel@tonic-gate 21787c478bd9Sstevel@tonic-gate if (ret_val < 0) { 21797c478bd9Sstevel@tonic-gate uint32_t capacity; 21807c478bd9Sstevel@tonic-gate uint32_t blocksize; 21817c478bd9Sstevel@tonic-gate /* 21827c478bd9Sstevel@tonic-gate * Devices may fail DKIOCGMEDIAINFO if an unformed 21837c478bd9Sstevel@tonic-gate * media is inserted. We can get the capacity 21847c478bd9Sstevel@tonic-gate * information from the SCMD_READ_FORMAT_CAP command. 21857c478bd9Sstevel@tonic-gate */ 21867c478bd9Sstevel@tonic-gate 2187*5363f09cSarutz debug(5, "DKIOCGMEDIAINFO failed; using " 2188*5363f09cSarutz "SCMD_READ_FORMAT_CAP"); 21897c478bd9Sstevel@tonic-gate ret_val = get_media_capacity(door_dp->dd_fd, 21907c478bd9Sstevel@tonic-gate &capacity, &blocksize); 21917c478bd9Sstevel@tonic-gate 21927c478bd9Sstevel@tonic-gate if (ret_val >= 0) { 21937c478bd9Sstevel@tonic-gate media_info.dki_lbsize = blocksize; 21947c478bd9Sstevel@tonic-gate media_info.dki_capacity = capacity; 21957c478bd9Sstevel@tonic-gate } else { 21967c478bd9Sstevel@tonic-gate debug(5, "SCMD_READ_FORMAT_CAP failed"); 21977c478bd9Sstevel@tonic-gate door_ret_err(&reterror, errno); 21987c478bd9Sstevel@tonic-gate } 21997c478bd9Sstevel@tonic-gate } 22007c478bd9Sstevel@tonic-gate rmsvc.retget_medium_property.smprop.sm_blocksize = 22017c478bd9Sstevel@tonic-gate media_info.dki_lbsize; 22027c478bd9Sstevel@tonic-gate rmsvc.retget_medium_property.smprop.sm_capacity = 22037c478bd9Sstevel@tonic-gate media_info.dki_capacity; 22047c478bd9Sstevel@tonic-gate 22057c478bd9Sstevel@tonic-gate rmsvc.retget_medium_property.smprop.sm_media_type = 22067c478bd9Sstevel@tonic-gate media_info.dki_media_type; 22077c478bd9Sstevel@tonic-gate /* 22087c478bd9Sstevel@tonic-gate * These devices show as SCSI devices but we need to treat it 22097c478bd9Sstevel@tonic-gate * differently. so we need a seperate class. 22107c478bd9Sstevel@tonic-gate */ 22117c478bd9Sstevel@tonic-gate if (get_device_type_scsi(door_dp->dd_fd, &inq) == SCSI_FLOPPY) { 22127c478bd9Sstevel@tonic-gate rmsvc.retget_medium_property.smprop.sm_media_type = 22137c478bd9Sstevel@tonic-gate SM_SCSI_FLOPPY; 22147c478bd9Sstevel@tonic-gate } 22157c478bd9Sstevel@tonic-gate 22167c478bd9Sstevel@tonic-gate /* Check for EFI type because DKIOCGGEOM does not support EFI */ 22177c478bd9Sstevel@tonic-gate ret_val = ioctl(door_dp->dd_fd, DKIOCGVTOC, &vtoc); 22187c478bd9Sstevel@tonic-gate if (!((ret_val < 0) && (errno == ENOTSUP))) { 22197c478bd9Sstevel@tonic-gate ret_val = ioctl(door_dp->dd_fd, DKIOCGGEOM, &dkgeom); 22207c478bd9Sstevel@tonic-gate if (ret_val < 0) { 22217c478bd9Sstevel@tonic-gate /* 22227c478bd9Sstevel@tonic-gate * DKIOCGGEOM may fail for unformed floppies. 22237c478bd9Sstevel@tonic-gate * We need to generate the appropriate geometry 22247c478bd9Sstevel@tonic-gate * information. 22257c478bd9Sstevel@tonic-gate */ 22267c478bd9Sstevel@tonic-gate if (rmsvc.retget_medium_property.smprop. 22277c478bd9Sstevel@tonic-gate sm_media_type == SM_SCSI_FLOPPY) { 22287c478bd9Sstevel@tonic-gate ret_val = get_floppy_geom( 22297c478bd9Sstevel@tonic-gate door_dp->dd_fd, 22307c478bd9Sstevel@tonic-gate media_info.dki_capacity, &dkgeom); 22317c478bd9Sstevel@tonic-gate 22327c478bd9Sstevel@tonic-gate if (ret_val < 0) { 22337c478bd9Sstevel@tonic-gate debug(5, "Cannot determine " 22347c478bd9Sstevel@tonic-gate "media size"); 22357c478bd9Sstevel@tonic-gate door_ret_err(&reterror, errno); 22367c478bd9Sstevel@tonic-gate } 22377c478bd9Sstevel@tonic-gate } else { 22387c478bd9Sstevel@tonic-gate #ifdef sparc 22397c478bd9Sstevel@tonic-gate debug(5, "DKIOCGGEOM ioctl failed"); 22407c478bd9Sstevel@tonic-gate door_ret_err(&reterror, errno); 22417c478bd9Sstevel@tonic-gate #else /* !sparc */ 22427c478bd9Sstevel@tonic-gate /* 22437c478bd9Sstevel@tonic-gate * Try getting Physical geometry on x86. 22447c478bd9Sstevel@tonic-gate */ 22457c478bd9Sstevel@tonic-gate ret_val = ioctl(door_dp->dd_fd, 22467c478bd9Sstevel@tonic-gate DKIOCG_PHYGEOM, &dkgeom); 22477c478bd9Sstevel@tonic-gate if (ret_val < 0) { 22487c478bd9Sstevel@tonic-gate debug(5, "DKIOCG_PHYGEOM " 22497c478bd9Sstevel@tonic-gate "ioctl failed"); 22507c478bd9Sstevel@tonic-gate door_ret_err(&reterror, errno); 22517c478bd9Sstevel@tonic-gate } 22527c478bd9Sstevel@tonic-gate #endif /* sparc */ 22537c478bd9Sstevel@tonic-gate } 22547c478bd9Sstevel@tonic-gate } 22557c478bd9Sstevel@tonic-gate 22567c478bd9Sstevel@tonic-gate 22577c478bd9Sstevel@tonic-gate /* 22587c478bd9Sstevel@tonic-gate * Some faked geometry may not have pcyl filled in so 22597c478bd9Sstevel@tonic-gate * later calculations using this field will be 22607c478bd9Sstevel@tonic-gate * incorrect. We will substitute it with the number of 22617c478bd9Sstevel@tonic-gate * available cylinders. 22627c478bd9Sstevel@tonic-gate */ 22637c478bd9Sstevel@tonic-gate if (dkgeom.dkg_pcyl == 0) 22647c478bd9Sstevel@tonic-gate rmsvc.retget_medium_property.smprop.sm_pcyl = 22657c478bd9Sstevel@tonic-gate dkgeom.dkg_ncyl; 22667c478bd9Sstevel@tonic-gate else 22677c478bd9Sstevel@tonic-gate rmsvc.retget_medium_property.smprop.sm_pcyl = 22687c478bd9Sstevel@tonic-gate dkgeom.dkg_pcyl; 22697c478bd9Sstevel@tonic-gate 22707c478bd9Sstevel@tonic-gate rmsvc.retget_medium_property.smprop.sm_nhead = 22717c478bd9Sstevel@tonic-gate dkgeom.dkg_nhead; 22727c478bd9Sstevel@tonic-gate rmsvc.retget_medium_property.smprop.sm_nsect = 22737c478bd9Sstevel@tonic-gate dkgeom.dkg_nsect; 22747c478bd9Sstevel@tonic-gate } 22757c478bd9Sstevel@tonic-gate 22767c478bd9Sstevel@tonic-gate debug(1, "properties are: lbasize = %d, cap = %llu", 22777c478bd9Sstevel@tonic-gate media_info.dki_lbsize, media_info.dki_capacity); 22787c478bd9Sstevel@tonic-gate 22797c478bd9Sstevel@tonic-gate my_door_return((char *)&rmsvc.retget_medium_property, 22807c478bd9Sstevel@tonic-gate sizeof (smedia_retget_medium_property_t), 0, 0); 22817c478bd9Sstevel@tonic-gate break; 22827c478bd9Sstevel@tonic-gate 22837c478bd9Sstevel@tonic-gate case SMEDIA_CNUM_GET_PROTECTION_STATUS: 22847c478bd9Sstevel@tonic-gate switch (get_device_type_scsi(door_dp->dd_fd, &inq)) { 22857c478bd9Sstevel@tonic-gate case SCSI_FLOPPY: 22867c478bd9Sstevel@tonic-gate status = scsi_floppy_media_status(door_dp->dd_fd); 22877c478bd9Sstevel@tonic-gate break; 22887c478bd9Sstevel@tonic-gate case SCSI_IOMEGA: 22897c478bd9Sstevel@tonic-gate status = scsi_zip_media_status(door_dp->dd_fd); 22907c478bd9Sstevel@tonic-gate break; 22917c478bd9Sstevel@tonic-gate case SCSI_GENERIC: 22927c478bd9Sstevel@tonic-gate status = scsi_media_status(door_dp->dd_fd); 22937c478bd9Sstevel@tonic-gate break; 22947c478bd9Sstevel@tonic-gate default: 22957c478bd9Sstevel@tonic-gate door_ret_err(&reterror, errno); 22967c478bd9Sstevel@tonic-gate } 22977c478bd9Sstevel@tonic-gate if (status < 0) 22987c478bd9Sstevel@tonic-gate door_ret_err(&reterror, errno); 22997c478bd9Sstevel@tonic-gate 23007c478bd9Sstevel@tonic-gate rmsvc.retget_protection_status.prot_state.sm_new_state = 23017c478bd9Sstevel@tonic-gate status; 23027c478bd9Sstevel@tonic-gate 23037c478bd9Sstevel@tonic-gate my_door_return((char *)&rmsvc.retget_protection_status, 23047c478bd9Sstevel@tonic-gate sizeof (smedia_retget_protection_status_t), 0, 0); 23057c478bd9Sstevel@tonic-gate break; 23067c478bd9Sstevel@tonic-gate 23077c478bd9Sstevel@tonic-gate case SMEDIA_CNUM_SET_PROTECTION_STATUS: 23087c478bd9Sstevel@tonic-gate 23097c478bd9Sstevel@tonic-gate ret_val = set_protection_status(door_dp, req); 23107c478bd9Sstevel@tonic-gate if (ret_val == -1) 23117c478bd9Sstevel@tonic-gate door_ret_err(&reterror, errno); 23127c478bd9Sstevel@tonic-gate else 23137c478bd9Sstevel@tonic-gate my_door_return((char *)&rmsvc.retset_protection_status, 23147c478bd9Sstevel@tonic-gate sizeof (smedia_retset_protection_status_t), 23157c478bd9Sstevel@tonic-gate 0, 0); 23167c478bd9Sstevel@tonic-gate break; 23177c478bd9Sstevel@tonic-gate 23187c478bd9Sstevel@tonic-gate case SMEDIA_CNUM_FORMAT: 23197c478bd9Sstevel@tonic-gate switch (get_device_type_scsi(door_dp->dd_fd, &inq)) { 23207c478bd9Sstevel@tonic-gate case SCSI_FLOPPY: 23217c478bd9Sstevel@tonic-gate info("formatting floppy"); 23227c478bd9Sstevel@tonic-gate err = scsi_floppy_format(door_dp->dd_fd, 23237c478bd9Sstevel@tonic-gate req->reqformat.flavor, req->reqformat.mode); 23247c478bd9Sstevel@tonic-gate 23257c478bd9Sstevel@tonic-gate break; 23267c478bd9Sstevel@tonic-gate case SCSI_IOMEGA: 23277c478bd9Sstevel@tonic-gate err = scsi_zip_format(door_dp->dd_fd, 23287c478bd9Sstevel@tonic-gate req->reqformat.flavor, req->reqformat.mode); 23297c478bd9Sstevel@tonic-gate break; 23307c478bd9Sstevel@tonic-gate case SCSI_GENERIC: 23317c478bd9Sstevel@tonic-gate err = scsi_format(door_dp->dd_fd, 23327c478bd9Sstevel@tonic-gate req->reqformat.flavor, req->reqformat.mode); 23337c478bd9Sstevel@tonic-gate break; 23347c478bd9Sstevel@tonic-gate default: 23357c478bd9Sstevel@tonic-gate door_ret_err(&reterror, ENOTSUP); 23367c478bd9Sstevel@tonic-gate } 23377c478bd9Sstevel@tonic-gate 23387c478bd9Sstevel@tonic-gate if (err) 23397c478bd9Sstevel@tonic-gate door_ret_err(&reterror, errno); 23407c478bd9Sstevel@tonic-gate my_door_return((char *)&rmsvc.retformat, 23417c478bd9Sstevel@tonic-gate sizeof (smedia_retformat_t), 0, 0); 23427c478bd9Sstevel@tonic-gate 23437c478bd9Sstevel@tonic-gate break; 23447c478bd9Sstevel@tonic-gate 23457c478bd9Sstevel@tonic-gate case SMEDIA_CNUM_CHECK_FORMAT_STATUS: 23467c478bd9Sstevel@tonic-gate 23477c478bd9Sstevel@tonic-gate (void) memset((void *) &cdb, 0, sizeof (union scsi_cdb)); 23487c478bd9Sstevel@tonic-gate (void) memset((void *) &ucmd, 0, sizeof (ucmd)); 23497c478bd9Sstevel@tonic-gate (void) memset((void *) &data, 0, sizeof (data)); 23507c478bd9Sstevel@tonic-gate cdb.scc_cmd = SCMD_REQUEST_SENSE; 23517c478bd9Sstevel@tonic-gate cdb.g0_count0 = sizeof (data); 23527c478bd9Sstevel@tonic-gate ucmd.uscsi_cdb = (caddr_t)&cdb; 23537c478bd9Sstevel@tonic-gate ucmd.uscsi_cdblen = CDB_GROUP0; 23547c478bd9Sstevel@tonic-gate ucmd.uscsi_bufaddr = (caddr_t)&data; 23557c478bd9Sstevel@tonic-gate ucmd.uscsi_buflen = sizeof (data); 23567c478bd9Sstevel@tonic-gate ucmd.uscsi_timeout = 120; /* If 0, HBA hangs forever */ 23577c478bd9Sstevel@tonic-gate ucmd.uscsi_rqlen = RQ_LEN; 23587c478bd9Sstevel@tonic-gate ucmd.uscsi_rqbuf = rq_data; 23597c478bd9Sstevel@tonic-gate ret_val = do_uscsi_cmd(door_dp->dd_fd, 23607c478bd9Sstevel@tonic-gate &ucmd, USCSI_READ|USCSI_RQENABLE); 23617c478bd9Sstevel@tonic-gate if (ret_val || ucmd.uscsi_status) { 23627c478bd9Sstevel@tonic-gate debug(5, "Request sense failed: %d - %d errno = %d\n", 23637c478bd9Sstevel@tonic-gate ret_val, ucmd.uscsi_status, errno); 23647c478bd9Sstevel@tonic-gate door_ret_err(&reterror, errno); 23657c478bd9Sstevel@tonic-gate } 23667c478bd9Sstevel@tonic-gate 23677c478bd9Sstevel@tonic-gate if ((data[0] & 0x7F) == DEFERRED_ERROR) { 23687c478bd9Sstevel@tonic-gate /* Deffered error. The format must have failed */ 23697c478bd9Sstevel@tonic-gate debug(5, "format failed!\n"); 23707c478bd9Sstevel@tonic-gate door_ret_err(&reterror, EIO); 23717c478bd9Sstevel@tonic-gate } 23727c478bd9Sstevel@tonic-gate 23737c478bd9Sstevel@tonic-gate if (data[SKSV_OFFSET] & SKSV_FIELD) { 23747c478bd9Sstevel@tonic-gate completed = 23757c478bd9Sstevel@tonic-gate (data[FORMAT_PROGRESS_INDICATOR_OFFSET_0] << 8) 23767c478bd9Sstevel@tonic-gate | data[FORMAT_PROGRESS_INDICATOR_OFFSET_1]; 23777c478bd9Sstevel@tonic-gate completed = (completed*100/65536); 23787c478bd9Sstevel@tonic-gate } else { 23797c478bd9Sstevel@tonic-gate completed = (100); 23807c478bd9Sstevel@tonic-gate } 23817c478bd9Sstevel@tonic-gate rmsvc.retcheck_format_status.percent_complete = completed; 23827c478bd9Sstevel@tonic-gate my_door_return((char *)&rmsvc.retcheck_format_status, 23837c478bd9Sstevel@tonic-gate sizeof (smedia_retcheck_format_status_t), 0, 0); 23847c478bd9Sstevel@tonic-gate break; 23857c478bd9Sstevel@tonic-gate 23867c478bd9Sstevel@tonic-gate case SMEDIA_CNUM_REASSIGN_BLOCK: 23877c478bd9Sstevel@tonic-gate 23887c478bd9Sstevel@tonic-gate ret_val = reassign_block(door_dp, req); 23897c478bd9Sstevel@tonic-gate if (ret_val == -1) 23907c478bd9Sstevel@tonic-gate door_ret_err(&reterror, errno); 23917c478bd9Sstevel@tonic-gate my_door_return((char *)&rmsvc.retreassign_block, 23927c478bd9Sstevel@tonic-gate sizeof (smedia_retreassign_block_t), 0, 0); 23937c478bd9Sstevel@tonic-gate break; 23947c478bd9Sstevel@tonic-gate 23957c478bd9Sstevel@tonic-gate } /* end of switch */ 23967c478bd9Sstevel@tonic-gate 23977c478bd9Sstevel@tonic-gate debug(10, "Exiting client server...\n"); 23987c478bd9Sstevel@tonic-gate my_door_return((char *)&reterror, sizeof (smedia_reterror_t), 0, 0); 23997c478bd9Sstevel@tonic-gate } 24007c478bd9Sstevel@tonic-gate 2401*5363f09cSarutz /* 2402*5363f09cSarutz * This is the service procedure for the door that is associated with 2403*5363f09cSarutz * the (doorfs) filesystem Door that is created at 'smedia_service'. 2404*5363f09cSarutz */ 24057c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 24067c478bd9Sstevel@tonic-gate static void 2407*5363f09cSarutz main_servproc(void *server_data, char *argp, size_t arg_size, 24087c478bd9Sstevel@tonic-gate door_desc_t *dp, uint_t ndesc) 24097c478bd9Sstevel@tonic-gate { 24107c478bd9Sstevel@tonic-gate smedia_services_t *req; 24117c478bd9Sstevel@tonic-gate door_cred_t door_credentials; 24127c478bd9Sstevel@tonic-gate int ret_val; 24137c478bd9Sstevel@tonic-gate door_data_t *ddata; 24147c478bd9Sstevel@tonic-gate smedia_reterror_t reterror; 24157c478bd9Sstevel@tonic-gate smedia_reterror_t retok; 24167c478bd9Sstevel@tonic-gate struct stat stat; 24177c478bd9Sstevel@tonic-gate door_desc_t *didpp; 24187c478bd9Sstevel@tonic-gate struct dk_cinfo dkinfo; 2419*5363f09cSarutz uint_t nexpected_desc; 24207c478bd9Sstevel@tonic-gate 2421*5363f09cSarutz debug(10, "Entering main_servproc[%d].\n", pthread_self()); 24227c478bd9Sstevel@tonic-gate 24237c478bd9Sstevel@tonic-gate didpp = dp; 24247c478bd9Sstevel@tonic-gate (void) mutex_lock(&svcstate_lock); 24257c478bd9Sstevel@tonic-gate svcstate = _SERVED; 24267c478bd9Sstevel@tonic-gate (void) mutex_unlock(&svcstate_lock); 24277c478bd9Sstevel@tonic-gate 24287c478bd9Sstevel@tonic-gate reterror.cnum = SMEDIA_CNUM_ERROR; 24297c478bd9Sstevel@tonic-gate reterror.errnum = SMEDIA_FAILURE; 2430*5363f09cSarutz 24317c478bd9Sstevel@tonic-gate if (argp == NULL) { 24327c478bd9Sstevel@tonic-gate debug(5, "argp is NULL\n"); 24337c478bd9Sstevel@tonic-gate if (ndesc > 0) 24347c478bd9Sstevel@tonic-gate close_door_descs(dp, ndesc); 24357c478bd9Sstevel@tonic-gate my_door_return((char *)&reterror, 24367c478bd9Sstevel@tonic-gate sizeof (smedia_reterror_t), 0, 0); 24377c478bd9Sstevel@tonic-gate } 24387c478bd9Sstevel@tonic-gate 24397c478bd9Sstevel@tonic-gate req = (smedia_services_t *)((void *)argp); 2440*5363f09cSarutz 24417c478bd9Sstevel@tonic-gate retok.cnum = req->in.cnum; 24427c478bd9Sstevel@tonic-gate retok.errnum = 0; 24437c478bd9Sstevel@tonic-gate 24447c478bd9Sstevel@tonic-gate debug(5, "req = %s arg_size = 0x%x \n", 24457c478bd9Sstevel@tonic-gate xlate_cnum(req->reqopen.cnum), arg_size); 24467c478bd9Sstevel@tonic-gate 24477c478bd9Sstevel@tonic-gate /* 24487c478bd9Sstevel@tonic-gate * Our caller may have passed more descriptors than we expected. 24497c478bd9Sstevel@tonic-gate * If so, we silently close (and ignore) them. 24507c478bd9Sstevel@tonic-gate */ 2451*5363f09cSarutz nexpected_desc = (req->in.cnum == SMEDIA_CNUM_OPEN_FD) ? 1 : 0; 2452*5363f09cSarutz if (ndesc > nexpected_desc) { 2453*5363f09cSarutz close_door_descs(dp + nexpected_desc, ndesc - nexpected_desc); 2454*5363f09cSarutz } 24557c478bd9Sstevel@tonic-gate 24567c478bd9Sstevel@tonic-gate switch (req->in.cnum) { 24577c478bd9Sstevel@tonic-gate default: 2458*5363f09cSarutz debug(5, "main_servproc: unknown command 0x%x\n", 2459*5363f09cSarutz req->reqopen.cnum); 24607c478bd9Sstevel@tonic-gate break; 24617c478bd9Sstevel@tonic-gate 24627c478bd9Sstevel@tonic-gate case SMEDIA_CNUM_PING: 24637c478bd9Sstevel@tonic-gate /* 24647c478bd9Sstevel@tonic-gate * This service is to indicate that server is up and 24657c478bd9Sstevel@tonic-gate * running. It is usually called from another instance of 24667c478bd9Sstevel@tonic-gate * server that is started. 24677c478bd9Sstevel@tonic-gate */ 24687c478bd9Sstevel@tonic-gate reterror.cnum = SMEDIA_CNUM_PING; 24697c478bd9Sstevel@tonic-gate reterror.errnum = 0; 24707c478bd9Sstevel@tonic-gate my_door_return((char *)&reterror, 24717c478bd9Sstevel@tonic-gate sizeof (smedia_reterror_t), 0, 0); 24727c478bd9Sstevel@tonic-gate break; 24737c478bd9Sstevel@tonic-gate 24747c478bd9Sstevel@tonic-gate 24757c478bd9Sstevel@tonic-gate case SMEDIA_CNUM_OPEN_FD: 24767c478bd9Sstevel@tonic-gate 24777c478bd9Sstevel@tonic-gate debug(5, "ndesc = %d\n", ndesc); 24787c478bd9Sstevel@tonic-gate if (ndesc == 0) { 24797c478bd9Sstevel@tonic-gate my_door_return((char *)&reterror, 24807c478bd9Sstevel@tonic-gate sizeof (smedia_reterror_t), 0, 0); 24817c478bd9Sstevel@tonic-gate } 2482*5363f09cSarutz debug(5, "Checking file descriptor of target device\n"); 24837c478bd9Sstevel@tonic-gate if (fstat(didpp->d_data.d_desc.d_descriptor, &stat) < 0) { 2484*5363f09cSarutz warning(gettext("main_servproc:fstat failed. " 2485*5363f09cSarutz "errno = %d\n"), errno); 24867c478bd9Sstevel@tonic-gate (void) close(didpp->d_data.d_desc.d_descriptor); 24877c478bd9Sstevel@tonic-gate my_door_return((char *)&reterror, 24887c478bd9Sstevel@tonic-gate sizeof (smedia_reterror_t), 0, 0); 24897c478bd9Sstevel@tonic-gate } 24907c478bd9Sstevel@tonic-gate debug(5, "descriptor = %d st_mode = 0x%lx\n", 24917c478bd9Sstevel@tonic-gate didpp->d_data.d_desc.d_descriptor, 24927c478bd9Sstevel@tonic-gate stat.st_mode); 24937c478bd9Sstevel@tonic-gate 24947c478bd9Sstevel@tonic-gate /* Obtain the credentials of the user */ 24957c478bd9Sstevel@tonic-gate ret_val = door_cred(&door_credentials); 24967c478bd9Sstevel@tonic-gate if (ret_val < 0) { 2497*5363f09cSarutz warning(gettext("main_servproc:door_cred " 2498*5363f09cSarutz "failed. errno = %d\n"), errno); 24997c478bd9Sstevel@tonic-gate (void) close(didpp->d_data.d_desc.d_descriptor); 25007c478bd9Sstevel@tonic-gate my_door_return((char *)&reterror, 25017c478bd9Sstevel@tonic-gate sizeof (smedia_reterror_t), 0, 0); 25027c478bd9Sstevel@tonic-gate } 25037c478bd9Sstevel@tonic-gate if (ioctl(didpp->d_data.d_desc.d_descriptor, DKIOCINFO, 25047c478bd9Sstevel@tonic-gate &dkinfo) == -1) { 2505*5363f09cSarutz warning(gettext("main_servproc:DKIOCINFO failed. " 2506*5363f09cSarutz "errno = %d\n"), errno); 25077c478bd9Sstevel@tonic-gate (void) close(didpp->d_data.d_desc.d_descriptor); 25087c478bd9Sstevel@tonic-gate my_door_return((char *)&reterror, 25097c478bd9Sstevel@tonic-gate sizeof (smedia_reterror_t), 0, 0); 25107c478bd9Sstevel@tonic-gate } 25117c478bd9Sstevel@tonic-gate 25127c478bd9Sstevel@tonic-gate ddata = (door_data_t *)calloc(1, sizeof (door_data_t)); 25137c478bd9Sstevel@tonic-gate if (ddata == NULL) { 2514*5363f09cSarutz warning(gettext("main_servproc:calloc failed. " 2515*5363f09cSarutz "errno = %d\n"), errno); 25167c478bd9Sstevel@tonic-gate (void) close(didpp->d_data.d_desc.d_descriptor); 25177c478bd9Sstevel@tonic-gate my_door_return((char *)&reterror, 25187c478bd9Sstevel@tonic-gate sizeof (smedia_reterror_t), 0, 0); 25197c478bd9Sstevel@tonic-gate } 25207c478bd9Sstevel@tonic-gate ddata->dd_stat = stat; 25217c478bd9Sstevel@tonic-gate ddata->dd_cred = door_credentials; 25227c478bd9Sstevel@tonic-gate ddata->dd_fd = didpp->d_data.d_desc.d_descriptor; 25237c478bd9Sstevel@tonic-gate ddata->dd_buf = NULL; 25247c478bd9Sstevel@tonic-gate ddata->dd_buf_len = 0; 25257c478bd9Sstevel@tonic-gate ddata->dd_buffd = -1; 25267c478bd9Sstevel@tonic-gate ddata->dd_sector_size = 0; 25277c478bd9Sstevel@tonic-gate ddata->dd_dkinfo = dkinfo; 2528*5363f09cSarutz debug(5, "ddata = 0x%p \n", (void *)ddata); 25297c478bd9Sstevel@tonic-gate 2530*5363f09cSarutz /* specify a function that'll customize our door threads */ 2531*5363f09cSarutz (void) door_server_create(sm_door_server_create); 25327c478bd9Sstevel@tonic-gate debug(5, "door_server_create called.\n"); 25337c478bd9Sstevel@tonic-gate 25347c478bd9Sstevel@tonic-gate (void) mutex_lock(&ddata->dd_lock); 25357c478bd9Sstevel@tonic-gate 2536*5363f09cSarutz /* create Client Door */ 2537*5363f09cSarutz ddata->dd_cdoor_descriptor = 2538*5363f09cSarutz door_create(client_servproc, 2539*5363f09cSarutz (void *)ddata, DOOR_PRIVATE | DOOR_NO_CANCEL | DOOR_UNREF); 2540*5363f09cSarutz 2541*5363f09cSarutz if (ddata->dd_cdoor_descriptor < 0) { 2542*5363f09cSarutz /* then door_create() failed */ 2543*5363f09cSarutz int err = errno; 2544*5363f09cSarutz 2545*5363f09cSarutz (void) mutex_unlock(&ddata->dd_lock); 2546*5363f09cSarutz 2547*5363f09cSarutz warning(gettext("main_servproc: door_create of Client " 2548*5363f09cSarutz "Door failed = %d\n"), err); 25497c478bd9Sstevel@tonic-gate free(ddata); 2550*5363f09cSarutz 2551*5363f09cSarutz /* close target device */ 25527c478bd9Sstevel@tonic-gate (void) close(didpp->d_data.d_desc.d_descriptor); 2553*5363f09cSarutz my_door_return((char *)&reterror, 2554*5363f09cSarutz sizeof (smedia_reterror_t), 0, 0); 25557c478bd9Sstevel@tonic-gate } 2556*5363f09cSarutz 2557*5363f09cSarutz /* create Death Door */ 2558*5363f09cSarutz ddata->dd_ddoor_descriptor = 2559*5363f09cSarutz door_create(death_servproc, (void *)ddata, 2560*5363f09cSarutz DOOR_REFUSE_DESC | DOOR_NO_CANCEL); 2561*5363f09cSarutz if (ddata->dd_ddoor_descriptor < 0) { 2562*5363f09cSarutz warning(gettext("main_servproc: door_create of Death " 2563*5363f09cSarutz "Door failed = %d\n"), errno); 2564*5363f09cSarutz } else { 2565*5363f09cSarutz (void) door_setparam(ddata->dd_ddoor_descriptor, 2566*5363f09cSarutz DOOR_PARAM_DATA_MAX, 0); 25677c478bd9Sstevel@tonic-gate } 2568*5363f09cSarutz 2569*5363f09cSarutz debug(5, "main_servproc[%d]: Client Door = %d, " 2570*5363f09cSarutz "Death Door = %d", pthread_self(), 2571*5363f09cSarutz ddata->dd_cdoor_descriptor, ddata->dd_ddoor_descriptor); 25727c478bd9Sstevel@tonic-gate 25737c478bd9Sstevel@tonic-gate audit_init(ddata); 25747c478bd9Sstevel@tonic-gate 2575*5363f09cSarutz /* wait until sm_server_thread does door_bind() */ 25767c478bd9Sstevel@tonic-gate (void) cond_wait(&ddata->dd_cv_bind, &ddata->dd_lock); 2577*5363f09cSarutz 25787c478bd9Sstevel@tonic-gate (void) mutex_unlock(&ddata->dd_lock); 25797c478bd9Sstevel@tonic-gate 25807c478bd9Sstevel@tonic-gate (void) mutex_lock(&svcstate_lock); 25817c478bd9Sstevel@tonic-gate svccount++; 25827c478bd9Sstevel@tonic-gate (void) mutex_unlock(&svcstate_lock); 25837c478bd9Sstevel@tonic-gate 2584*5363f09cSarutz if (ddata->dd_ddoor_descriptor < 0) { 2585*5363f09cSarutz /* Return only the Client Door to the client. */ 2586*5363f09cSarutz ddata->dd_cdoor.d_attributes = (DOOR_DESCRIPTOR); 2587*5363f09cSarutz my_door_return((char *)&reterror, 2588*5363f09cSarutz sizeof (smedia_reterror_t), &ddata->dd_desc[0], 1); 2589*5363f09cSarutz } else { 2590*5363f09cSarutz /* 2591*5363f09cSarutz * Return the Client Door and Death Door 2592*5363f09cSarutz * to the client. 2593*5363f09cSarutz */ 2594*5363f09cSarutz debug(5, "retok.cnum = 0x%x\n", retok.cnum); 2595*5363f09cSarutz ddata->dd_cdoor.d_attributes = (DOOR_DESCRIPTOR); 2596*5363f09cSarutz ddata->dd_ddoor.d_attributes = (DOOR_DESCRIPTOR); 2597*5363f09cSarutz my_door_return((char *)&retok, 2598*5363f09cSarutz sizeof (smedia_reterror_t), &ddata->dd_desc[0], 2); 2599*5363f09cSarutz } 26007c478bd9Sstevel@tonic-gate break; 26017c478bd9Sstevel@tonic-gate } 26027c478bd9Sstevel@tonic-gate 2603*5363f09cSarutz debug(10, "exiting main_servproc. \n"); 26047c478bd9Sstevel@tonic-gate my_door_return((char *)&reterror, sizeof (smedia_reterror_t), 0, 0); 26057c478bd9Sstevel@tonic-gate } 26067c478bd9Sstevel@tonic-gate 26077c478bd9Sstevel@tonic-gate /* ARGSUSED */ 26087c478bd9Sstevel@tonic-gate static void 26097c478bd9Sstevel@tonic-gate term_handler(int sig, siginfo_t *siginfo, void *sigctx) 26107c478bd9Sstevel@tonic-gate { 26117c478bd9Sstevel@tonic-gate warning(gettext("thread[%d]: Received signal %d. Ignoring it.\n"), 26127c478bd9Sstevel@tonic-gate pthread_self(), 26137c478bd9Sstevel@tonic-gate sig); 26147c478bd9Sstevel@tonic-gate } 26157c478bd9Sstevel@tonic-gate 26167c478bd9Sstevel@tonic-gate /* ARGSUSED */ 26177c478bd9Sstevel@tonic-gate static void 26187c478bd9Sstevel@tonic-gate hup_handler(int sig, siginfo_t *siginfo, void *sigctx) 26197c478bd9Sstevel@tonic-gate { 26207c478bd9Sstevel@tonic-gate warning(gettext("thread[%d]: Received signal %d. Ignoring it.\n"), 26217c478bd9Sstevel@tonic-gate pthread_self(), 26227c478bd9Sstevel@tonic-gate sig); 26237c478bd9Sstevel@tonic-gate } 26247c478bd9Sstevel@tonic-gate 26257c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 26267c478bd9Sstevel@tonic-gate static void 26277c478bd9Sstevel@tonic-gate sig_handler(int sig, siginfo_t *siginfo, void *sigctx) 26287c478bd9Sstevel@tonic-gate { 26297c478bd9Sstevel@tonic-gate warning(gettext("thread[%d]: Received signal %d. Ignoring it.\n"), 26307c478bd9Sstevel@tonic-gate pthread_self(), 26317c478bd9Sstevel@tonic-gate sig); 26327c478bd9Sstevel@tonic-gate } 26337c478bd9Sstevel@tonic-gate 26347c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 26357c478bd9Sstevel@tonic-gate static void 26367c478bd9Sstevel@tonic-gate badsig_handler(int sig, siginfo_t *siginfo, void *sigctx) 26377c478bd9Sstevel@tonic-gate { 26387c478bd9Sstevel@tonic-gate fatal(BADSIG_MSG, pthread_self(), sig, siginfo->si_addr, 26397c478bd9Sstevel@tonic-gate siginfo->si_trapno, 26407c478bd9Sstevel@tonic-gate siginfo->si_pc); 26417c478bd9Sstevel@tonic-gate } 26427c478bd9Sstevel@tonic-gate 26437c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 2644*5363f09cSarutz static void * 26457c478bd9Sstevel@tonic-gate init_server(void *argp) 26467c478bd9Sstevel@tonic-gate { 26477c478bd9Sstevel@tonic-gate int i, fd; 26487c478bd9Sstevel@tonic-gate struct sigaction act; 26497c478bd9Sstevel@tonic-gate struct rlimit rlim; 26507c478bd9Sstevel@tonic-gate 26517c478bd9Sstevel@tonic-gate debug(10, "init_server running\n"); 26527c478bd9Sstevel@tonic-gate 26537c478bd9Sstevel@tonic-gate (void) setlocale(LC_ALL, ""); 26547c478bd9Sstevel@tonic-gate #if !defined(TEXT_DOMAIN) 26557c478bd9Sstevel@tonic-gate #define TEXT_DOMAIN "SYS_TEST" 26567c478bd9Sstevel@tonic-gate #endif 26577c478bd9Sstevel@tonic-gate (void) textdomain(TEXT_DOMAIN); 26587c478bd9Sstevel@tonic-gate 26597c478bd9Sstevel@tonic-gate 26607c478bd9Sstevel@tonic-gate if (geteuid() != 0) fatal("Must be root to execute smserverd\n"); 26617c478bd9Sstevel@tonic-gate 26627c478bd9Sstevel@tonic-gate 26637c478bd9Sstevel@tonic-gate /* 26647c478bd9Sstevel@tonic-gate * setup signal handlers. 26657c478bd9Sstevel@tonic-gate */ 26667c478bd9Sstevel@tonic-gate 26677c478bd9Sstevel@tonic-gate for (i = 0; i < N_BADSIGS; i++) { 26687c478bd9Sstevel@tonic-gate act.sa_sigaction = badsig_handler; 26697c478bd9Sstevel@tonic-gate (void) sigemptyset(&act.sa_mask); 26707c478bd9Sstevel@tonic-gate act.sa_flags = SA_SIGINFO; 26717c478bd9Sstevel@tonic-gate if (sigaction(badsigs[i], &act, NULL) == -1) 26727c478bd9Sstevel@tonic-gate warning(gettext(SIGACT_FAILED), strsignal(badsigs[i]), 26737c478bd9Sstevel@tonic-gate strerror(errno)); 26747c478bd9Sstevel@tonic-gate } 26757c478bd9Sstevel@tonic-gate 26767c478bd9Sstevel@tonic-gate /* 26777c478bd9Sstevel@tonic-gate * Ignore SIGHUP until all the initialization is done. 26787c478bd9Sstevel@tonic-gate */ 26797c478bd9Sstevel@tonic-gate act.sa_handler = SIG_IGN; 26807c478bd9Sstevel@tonic-gate (void) sigemptyset(&act.sa_mask); 26817c478bd9Sstevel@tonic-gate act.sa_flags = 0; 26827c478bd9Sstevel@tonic-gate if (sigaction(SIGHUP, &act, NULL) == -1) 26837c478bd9Sstevel@tonic-gate warning(gettext(SIGACT_FAILED), strsignal(SIGHUP), 26847c478bd9Sstevel@tonic-gate strerror(errno)); 26857c478bd9Sstevel@tonic-gate /* 26867c478bd9Sstevel@tonic-gate * Increase file descriptor limit to the most it can possibly 26877c478bd9Sstevel@tonic-gate * be. 26887c478bd9Sstevel@tonic-gate */ 26897c478bd9Sstevel@tonic-gate if (getrlimit(RLIMIT_NOFILE, &rlim) < 0) { 26907c478bd9Sstevel@tonic-gate warning(gettext("getrlimit for fd's failed; %m\n")); 26917c478bd9Sstevel@tonic-gate } 26927c478bd9Sstevel@tonic-gate 26937c478bd9Sstevel@tonic-gate rlim.rlim_cur = rlim.rlim_max; 26947c478bd9Sstevel@tonic-gate 26957c478bd9Sstevel@tonic-gate if (setrlimit(RLIMIT_NOFILE, &rlim) < 0) { 26967c478bd9Sstevel@tonic-gate warning(gettext("setrlimit for fd's failed; %m\n")); 26977c478bd9Sstevel@tonic-gate } 26987c478bd9Sstevel@tonic-gate 2699*5363f09cSarutz server_door = door_create(main_servproc, (void *)&server_data, 0); 27007c478bd9Sstevel@tonic-gate if (server_door == -1) { 27017c478bd9Sstevel@tonic-gate debug(1, "main door_create"); 27027c478bd9Sstevel@tonic-gate exit(1); 27037c478bd9Sstevel@tonic-gate } 27047c478bd9Sstevel@tonic-gate 27057c478bd9Sstevel@tonic-gate (void) unlink(smedia_service); 27067c478bd9Sstevel@tonic-gate fd = open(smedia_service, O_RDWR|O_CREAT|O_EXCL, 0644); 27077c478bd9Sstevel@tonic-gate if (fd < 0) { 27087c478bd9Sstevel@tonic-gate debug(5, "could not open %s.\n", smedia_service); 27097c478bd9Sstevel@tonic-gate exit(1); 27107c478bd9Sstevel@tonic-gate } 27117c478bd9Sstevel@tonic-gate (void) close(fd); 27127c478bd9Sstevel@tonic-gate server_fd = fattach(server_door, smedia_service); 27137c478bd9Sstevel@tonic-gate if (server_fd == -1) { 27147c478bd9Sstevel@tonic-gate debug(1, "main fattach"); 27157c478bd9Sstevel@tonic-gate exit(1); 27167c478bd9Sstevel@tonic-gate } 27177c478bd9Sstevel@tonic-gate server_data.sd_door = server_door; 27187c478bd9Sstevel@tonic-gate server_data.sd_fd = server_fd; 27197c478bd9Sstevel@tonic-gate 27207c478bd9Sstevel@tonic-gate /* 27217c478bd9Sstevel@tonic-gate * setup signal handlers for post-init 27227c478bd9Sstevel@tonic-gate */ 27237c478bd9Sstevel@tonic-gate 27247c478bd9Sstevel@tonic-gate act.sa_sigaction = hup_handler; 27257c478bd9Sstevel@tonic-gate (void) sigemptyset(&act.sa_mask); 27267c478bd9Sstevel@tonic-gate act.sa_flags = SA_SIGINFO; 27277c478bd9Sstevel@tonic-gate if (sigaction(SIGHUP, &act, NULL) == -1) 27287c478bd9Sstevel@tonic-gate warning(gettext(SIGACT_FAILED), strsignal(SIGHUP), 27297c478bd9Sstevel@tonic-gate strerror(errno)); 27307c478bd9Sstevel@tonic-gate 27317c478bd9Sstevel@tonic-gate act.sa_sigaction = term_handler; 27327c478bd9Sstevel@tonic-gate (void) sigemptyset(&act.sa_mask); 27337c478bd9Sstevel@tonic-gate act.sa_flags = SA_SIGINFO; 27347c478bd9Sstevel@tonic-gate if (sigaction(SIGTERM, &act, NULL) == -1) 27357c478bd9Sstevel@tonic-gate warning(gettext(SIGACT_FAILED), strsignal(SIGTERM), 27367c478bd9Sstevel@tonic-gate strerror(errno)); 27377c478bd9Sstevel@tonic-gate 27387c478bd9Sstevel@tonic-gate act.sa_sigaction = sig_handler; 27397c478bd9Sstevel@tonic-gate (void) sigemptyset(&act.sa_mask); 27407c478bd9Sstevel@tonic-gate act.sa_flags = SA_SIGINFO; 27417c478bd9Sstevel@tonic-gate if (sigaction(SIGINT, &act, NULL) == -1) 27427c478bd9Sstevel@tonic-gate warning(gettext(SIGACT_FAILED), strsignal(SIGHUP), 27437c478bd9Sstevel@tonic-gate strerror(errno)); 27447c478bd9Sstevel@tonic-gate 27457c478bd9Sstevel@tonic-gate act.sa_sigaction = sig_handler; 27467c478bd9Sstevel@tonic-gate (void) sigemptyset(&act.sa_mask); 27477c478bd9Sstevel@tonic-gate act.sa_flags = SA_SIGINFO; 27487c478bd9Sstevel@tonic-gate if (sigaction(SIGQUIT, &act, NULL) == -1) 27497c478bd9Sstevel@tonic-gate warning(gettext(SIGACT_FAILED), strsignal(SIGHUP), 27507c478bd9Sstevel@tonic-gate strerror(errno)); 27517c478bd9Sstevel@tonic-gate debug(10, "init_server completed successfully\n"); 27527c478bd9Sstevel@tonic-gate 27537c478bd9Sstevel@tonic-gate server_data.sd_init_state = INIT_DONE; 27547c478bd9Sstevel@tonic-gate return (NULL); 27557c478bd9Sstevel@tonic-gate } 27567c478bd9Sstevel@tonic-gate 27577c478bd9Sstevel@tonic-gate static int 27587c478bd9Sstevel@tonic-gate server_exists() 27597c478bd9Sstevel@tonic-gate { 27607c478bd9Sstevel@tonic-gate door_arg_t darg; 27617c478bd9Sstevel@tonic-gate smedia_reqping_t req_ping; 27627c478bd9Sstevel@tonic-gate smedia_retping_t *ret_ping; 27637c478bd9Sstevel@tonic-gate int doorh; 27647c478bd9Sstevel@tonic-gate door_info_t dinfo; 27657c478bd9Sstevel@tonic-gate char rbuf[sizeof (smedia_services_t) + sizeof (door_desc_t)]; 27667c478bd9Sstevel@tonic-gate 27677c478bd9Sstevel@tonic-gate doorh = open(smedia_service, O_RDONLY); 27687c478bd9Sstevel@tonic-gate if (doorh < 0) 27697c478bd9Sstevel@tonic-gate return (0); 27707c478bd9Sstevel@tonic-gate if (door_info(doorh, &dinfo) < 0) { 27717c478bd9Sstevel@tonic-gate (void) close(doorh); 27727c478bd9Sstevel@tonic-gate return (0); 27737c478bd9Sstevel@tonic-gate } 27747c478bd9Sstevel@tonic-gate if (dinfo.di_attributes & DOOR_REVOKED) { 27757c478bd9Sstevel@tonic-gate (void) close(doorh); 27767c478bd9Sstevel@tonic-gate return (0); 27777c478bd9Sstevel@tonic-gate } 27787c478bd9Sstevel@tonic-gate 27797c478bd9Sstevel@tonic-gate req_ping.cnum = SMEDIA_CNUM_PING; 27807c478bd9Sstevel@tonic-gate 27817c478bd9Sstevel@tonic-gate darg.data_ptr = (char *)&req_ping; 27827c478bd9Sstevel@tonic-gate darg.data_size = sizeof (smedia_reqping_t); 27837c478bd9Sstevel@tonic-gate darg.desc_ptr = NULL; 27847c478bd9Sstevel@tonic-gate darg.desc_num = 0; 27857c478bd9Sstevel@tonic-gate darg.rbuf = rbuf; 27867c478bd9Sstevel@tonic-gate darg.rsize = sizeof (rbuf); 27877c478bd9Sstevel@tonic-gate 27887c478bd9Sstevel@tonic-gate if (door_call(doorh, &darg) < 0) { 27897c478bd9Sstevel@tonic-gate (void) close(doorh); 27907c478bd9Sstevel@tonic-gate return (0); 27917c478bd9Sstevel@tonic-gate } 27927c478bd9Sstevel@tonic-gate ret_ping = (smedia_retping_t *)((void *)darg.data_ptr); 27937c478bd9Sstevel@tonic-gate if (ret_ping->cnum != SMEDIA_CNUM_PING) { 27947c478bd9Sstevel@tonic-gate (void) close(doorh); 27957c478bd9Sstevel@tonic-gate return (0); 27967c478bd9Sstevel@tonic-gate } 27977c478bd9Sstevel@tonic-gate 27987c478bd9Sstevel@tonic-gate (void) close(doorh); 27997c478bd9Sstevel@tonic-gate return (1); 28007c478bd9Sstevel@tonic-gate } 28017c478bd9Sstevel@tonic-gate 28027c478bd9Sstevel@tonic-gate static int 28037c478bd9Sstevel@tonic-gate get_run_level() 28047c478bd9Sstevel@tonic-gate { 28057c478bd9Sstevel@tonic-gate int run_level; 28067c478bd9Sstevel@tonic-gate struct utmpx *utmpp; 28077c478bd9Sstevel@tonic-gate 28087c478bd9Sstevel@tonic-gate setutxent(); 28097c478bd9Sstevel@tonic-gate while ((utmpp = getutxent()) != NULL) { 28107c478bd9Sstevel@tonic-gate if (utmpp->ut_type == RUN_LVL) { 28117c478bd9Sstevel@tonic-gate run_level = atoi( 28127c478bd9Sstevel@tonic-gate &utmpp->ut_line[strlen("run-level ")]); 28137c478bd9Sstevel@tonic-gate } 28147c478bd9Sstevel@tonic-gate } 28157c478bd9Sstevel@tonic-gate return (run_level); 28167c478bd9Sstevel@tonic-gate } 28177c478bd9Sstevel@tonic-gate 28187c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 28197c478bd9Sstevel@tonic-gate static void * 28207c478bd9Sstevel@tonic-gate closedown(void *arg) 28217c478bd9Sstevel@tonic-gate { 28227c478bd9Sstevel@tonic-gate 28237c478bd9Sstevel@tonic-gate int current_run_level; 28247c478bd9Sstevel@tonic-gate 28257c478bd9Sstevel@tonic-gate /*CONSTCOND*/ 28267c478bd9Sstevel@tonic-gate #ifndef lint 28277c478bd9Sstevel@tonic-gate while (1) { 28287c478bd9Sstevel@tonic-gate #endif 28297c478bd9Sstevel@tonic-gate (void) sleep(SVC_CLOSEDOWN/2); 28307c478bd9Sstevel@tonic-gate 28317c478bd9Sstevel@tonic-gate /* 28327c478bd9Sstevel@tonic-gate * If the server was started at init level 1 28337c478bd9Sstevel@tonic-gate * and the current init level is 1 then 28347c478bd9Sstevel@tonic-gate * do not exit from server. This server will run 28357c478bd9Sstevel@tonic-gate * until it is explicitly stopped by the user. 28367c478bd9Sstevel@tonic-gate */ 28377c478bd9Sstevel@tonic-gate if (svcstart_level == 1) { 28387c478bd9Sstevel@tonic-gate current_run_level = get_run_level(); 28397c478bd9Sstevel@tonic-gate if (current_run_level == 1) 28407c478bd9Sstevel@tonic-gate #ifndef lint 28417c478bd9Sstevel@tonic-gate continue; 28427c478bd9Sstevel@tonic-gate #else 28437c478bd9Sstevel@tonic-gate return (NULL); 28447c478bd9Sstevel@tonic-gate #endif 28457c478bd9Sstevel@tonic-gate /* 28467c478bd9Sstevel@tonic-gate * who ever started the server at level 1 has 28477c478bd9Sstevel@tonic-gate * forgotten to stop the server. we will kill ourself. 28487c478bd9Sstevel@tonic-gate */ 28497c478bd9Sstevel@tonic-gate debug(5, 28507c478bd9Sstevel@tonic-gate "Terminating the server started at init level 1\n"); 28517c478bd9Sstevel@tonic-gate exit(0); 28527c478bd9Sstevel@tonic-gate } 28537c478bd9Sstevel@tonic-gate 28547c478bd9Sstevel@tonic-gate if (mutex_trylock(&svcstate_lock) != 0) 28557c478bd9Sstevel@tonic-gate #ifndef lint 28567c478bd9Sstevel@tonic-gate continue; 28577c478bd9Sstevel@tonic-gate #else 28587c478bd9Sstevel@tonic-gate return (NULL); 28597c478bd9Sstevel@tonic-gate #endif 28607c478bd9Sstevel@tonic-gate if (svcstate == _IDLE && svccount == 0) { 28617c478bd9Sstevel@tonic-gate int size; 28627c478bd9Sstevel@tonic-gate int i, openfd = 0; 28637c478bd9Sstevel@tonic-gate 28647c478bd9Sstevel@tonic-gate size = svc_max_pollfd; 28657c478bd9Sstevel@tonic-gate for (i = 0; i < size && openfd < 2; i++) 28667c478bd9Sstevel@tonic-gate if (svc_pollfd[i].fd >= 0) 28677c478bd9Sstevel@tonic-gate openfd++; 28687c478bd9Sstevel@tonic-gate if (openfd <= 1) { 28697c478bd9Sstevel@tonic-gate debug(5, 28707c478bd9Sstevel@tonic-gate "Exiting the server from closedown routine.\n"); 28717c478bd9Sstevel@tonic-gate exit(0); 28727c478bd9Sstevel@tonic-gate } 28737c478bd9Sstevel@tonic-gate } else 28747c478bd9Sstevel@tonic-gate svcstate = _IDLE; 28757c478bd9Sstevel@tonic-gate 28767c478bd9Sstevel@tonic-gate (void) mutex_unlock(&svcstate_lock); 28777c478bd9Sstevel@tonic-gate #ifndef lint 28787c478bd9Sstevel@tonic-gate } 28797c478bd9Sstevel@tonic-gate #else 28807c478bd9Sstevel@tonic-gate return (NULL); 28817c478bd9Sstevel@tonic-gate #endif 28827c478bd9Sstevel@tonic-gate 28837c478bd9Sstevel@tonic-gate } 28847c478bd9Sstevel@tonic-gate 28857c478bd9Sstevel@tonic-gate static void 28867c478bd9Sstevel@tonic-gate usage() 28877c478bd9Sstevel@tonic-gate { 28887c478bd9Sstevel@tonic-gate warning(gettext("usage: %s [-L loglevel] level of debug information\n"), 28897c478bd9Sstevel@tonic-gate prog_name); 28907c478bd9Sstevel@tonic-gate } 28917c478bd9Sstevel@tonic-gate 28927c478bd9Sstevel@tonic-gate 28937c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 2894360e6f5eSmathue int 28957c478bd9Sstevel@tonic-gate main(int argc, char **argv) 28967c478bd9Sstevel@tonic-gate { 28977c478bd9Sstevel@tonic-gate int c; 28987c478bd9Sstevel@tonic-gate pthread_attr_t attr; 28997c478bd9Sstevel@tonic-gate 29007c478bd9Sstevel@tonic-gate (void) setlocale(LC_ALL, ""); 29017c478bd9Sstevel@tonic-gate #if !defined(TEXT_DOMAIN) 29027c478bd9Sstevel@tonic-gate #define TEXT_DOMAIN "SYS_TEST" 29037c478bd9Sstevel@tonic-gate #endif 29047c478bd9Sstevel@tonic-gate (void) textdomain(TEXT_DOMAIN); 29057c478bd9Sstevel@tonic-gate 29067c478bd9Sstevel@tonic-gate prog_name = argv[0]; 29077c478bd9Sstevel@tonic-gate 29087c478bd9Sstevel@tonic-gate (void) sigset(SIGPIPE, SIG_IGN); 29097c478bd9Sstevel@tonic-gate 29107c478bd9Sstevel@tonic-gate while ((c = getopt(argc, argv, "L:")) != -1) { 29117c478bd9Sstevel@tonic-gate switch (c) { 29127c478bd9Sstevel@tonic-gate case 'L': 29137c478bd9Sstevel@tonic-gate debug_level = atoi((char *)optarg); 29147c478bd9Sstevel@tonic-gate break; 29157c478bd9Sstevel@tonic-gate default: 29167c478bd9Sstevel@tonic-gate usage(); 29177c478bd9Sstevel@tonic-gate break; 29187c478bd9Sstevel@tonic-gate } 29197c478bd9Sstevel@tonic-gate } 29207c478bd9Sstevel@tonic-gate 29217c478bd9Sstevel@tonic-gate /* 29227c478bd9Sstevel@tonic-gate * If stdin looks like a TLI endpoint, we assume 29237c478bd9Sstevel@tonic-gate * that we were started by a port monitor. If 29247c478bd9Sstevel@tonic-gate * t_getstate fails with TBADF, this is not a 29257c478bd9Sstevel@tonic-gate * TLI endpoint. 29267c478bd9Sstevel@tonic-gate */ 29277c478bd9Sstevel@tonic-gate if (t_getstate(0) != -1 || t_errno != TBADF) { 29287c478bd9Sstevel@tonic-gate char *netid; 29297c478bd9Sstevel@tonic-gate struct netconfig *nconf = NULL; 29307c478bd9Sstevel@tonic-gate SVCXPRT *transp; 29317c478bd9Sstevel@tonic-gate int pmclose; 29327c478bd9Sstevel@tonic-gate 29337c478bd9Sstevel@tonic-gate openlog(prog_name, LOG_PID, LOG_DAEMON); 29347c478bd9Sstevel@tonic-gate 29357c478bd9Sstevel@tonic-gate debug(1, gettext("server started by port monitor.\n")); 29367c478bd9Sstevel@tonic-gate if ((netid = getenv("NLSPROVIDER")) == NULL) { 29377c478bd9Sstevel@tonic-gate /* started from inetd */ 29387c478bd9Sstevel@tonic-gate pmclose = 1; 29397c478bd9Sstevel@tonic-gate } else { 29407c478bd9Sstevel@tonic-gate if ((nconf = getnetconfigent(netid)) == NULL) 29417c478bd9Sstevel@tonic-gate syslog(LOG_ERR, gettext( 29427c478bd9Sstevel@tonic-gate "cannot get transport info")); 29437c478bd9Sstevel@tonic-gate 29447c478bd9Sstevel@tonic-gate pmclose = (t_getstate(0) != T_DATAXFER); 29457c478bd9Sstevel@tonic-gate } 29467c478bd9Sstevel@tonic-gate if ((transp = svc_tli_create(0, nconf, NULL, 0, 0)) == NULL) { 29477c478bd9Sstevel@tonic-gate syslog(LOG_ERR, gettext("cannot create server handle")); 29487c478bd9Sstevel@tonic-gate exit(1); 29497c478bd9Sstevel@tonic-gate } 29507c478bd9Sstevel@tonic-gate if (nconf) 29517c478bd9Sstevel@tonic-gate freenetconfigent(nconf); 29527c478bd9Sstevel@tonic-gate if (!svc_reg(transp, SMSERVERPROG, SMSERVERVERS, 29537c478bd9Sstevel@tonic-gate smserverprog_1, 0)) { 29547c478bd9Sstevel@tonic-gate syslog(LOG_ERR, gettext( 29557c478bd9Sstevel@tonic-gate "unable to register (SMSERVERPROG, SMSERVERVERS).")); 29567c478bd9Sstevel@tonic-gate exit(1); 29577c478bd9Sstevel@tonic-gate } 29587c478bd9Sstevel@tonic-gate svcstart_level = get_run_level(); 29597c478bd9Sstevel@tonic-gate if (pmclose) { 29607c478bd9Sstevel@tonic-gate (void) pthread_attr_init(&attr); 29617c478bd9Sstevel@tonic-gate (void) pthread_attr_setscope(&attr, 29627c478bd9Sstevel@tonic-gate PTHREAD_SCOPE_SYSTEM | PTHREAD_CREATE_DETACHED); 29637c478bd9Sstevel@tonic-gate if (pthread_create(NULL, &attr, closedown, NULL) != 0) { 29647c478bd9Sstevel@tonic-gate syslog(LOG_ERR, gettext( 29657c478bd9Sstevel@tonic-gate "cannot create closedown thread")); 29667c478bd9Sstevel@tonic-gate exit(1); 29677c478bd9Sstevel@tonic-gate } 29687c478bd9Sstevel@tonic-gate (void) pthread_attr_destroy(&attr); 29697c478bd9Sstevel@tonic-gate } 29707c478bd9Sstevel@tonic-gate svc_run(); 29717c478bd9Sstevel@tonic-gate exit(1); 29727c478bd9Sstevel@tonic-gate /* NOTREACHED */ 29737c478bd9Sstevel@tonic-gate } else { 29747c478bd9Sstevel@tonic-gate /* 29757c478bd9Sstevel@tonic-gate * Started by library or manually. 29767c478bd9Sstevel@tonic-gate */ 29777c478bd9Sstevel@tonic-gate /* 29787c478bd9Sstevel@tonic-gate * Check to see if the server is already running. 29797c478bd9Sstevel@tonic-gate * There is no need to log messages in the syslog file 29807c478bd9Sstevel@tonic-gate * because server will get launched each time libsmedia 29817c478bd9Sstevel@tonic-gate * library calls are made at init 1 level. 29827c478bd9Sstevel@tonic-gate * We ensure that only one copy will run. 29837c478bd9Sstevel@tonic-gate */ 29847c478bd9Sstevel@tonic-gate debug(1, gettext("server started manually.\n")); 29857c478bd9Sstevel@tonic-gate if (server_exists()) { 29867c478bd9Sstevel@tonic-gate exit(0); 29877c478bd9Sstevel@tonic-gate } 29887c478bd9Sstevel@tonic-gate svcstart_level = get_run_level(); 29897c478bd9Sstevel@tonic-gate (void) pthread_attr_init(&attr); 29907c478bd9Sstevel@tonic-gate (void) pthread_attr_setscope(&attr, 29917c478bd9Sstevel@tonic-gate PTHREAD_SCOPE_SYSTEM | PTHREAD_CREATE_DETACHED); 29927c478bd9Sstevel@tonic-gate if (pthread_create(NULL, &attr, closedown, NULL) != 0) { 29937c478bd9Sstevel@tonic-gate syslog(LOG_ERR, gettext( 29947c478bd9Sstevel@tonic-gate "cannot create closedown thread")); 29957c478bd9Sstevel@tonic-gate exit(1); 29967c478bd9Sstevel@tonic-gate } 29977c478bd9Sstevel@tonic-gate (void) pthread_attr_destroy(&attr); 29987c478bd9Sstevel@tonic-gate (void) init_server(NULL); 29997c478bd9Sstevel@tonic-gate for (;;) (void) pause(); 30007c478bd9Sstevel@tonic-gate } 3001360e6f5eSmathue return (0); 30027c478bd9Sstevel@tonic-gate } 30037c478bd9Sstevel@tonic-gate 30047c478bd9Sstevel@tonic-gate 30057c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 30067c478bd9Sstevel@tonic-gate static int32_t 30077c478bd9Sstevel@tonic-gate scsi_floppy_write_protect(int32_t fd, smwp_state_t *wp) 30087c478bd9Sstevel@tonic-gate { 30097c478bd9Sstevel@tonic-gate debug(5, "Invalid mode\n"); 30107c478bd9Sstevel@tonic-gate errno = ENOTSUP; 30117c478bd9Sstevel@tonic-gate 30127c478bd9Sstevel@tonic-gate return (-1); 30137c478bd9Sstevel@tonic-gate } 30147c478bd9Sstevel@tonic-gate 30157c478bd9Sstevel@tonic-gate /* 30167c478bd9Sstevel@tonic-gate * Generate standard geometry information for SCSI floppy devices. And 30177c478bd9Sstevel@tonic-gate * register the geometry with the SCSI driver. This will expand as more 30187c478bd9Sstevel@tonic-gate * formats are added. 30197c478bd9Sstevel@tonic-gate */ 30207c478bd9Sstevel@tonic-gate 30217c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 30227c478bd9Sstevel@tonic-gate static int32_t 30237c478bd9Sstevel@tonic-gate get_floppy_geom(int32_t fd, uint32_t capacity, struct dk_geom *dkgeom) 30247c478bd9Sstevel@tonic-gate { 30257c478bd9Sstevel@tonic-gate 30267c478bd9Sstevel@tonic-gate 30277c478bd9Sstevel@tonic-gate debug(5, "get_floppy_geom: capacity = 0x%x\n", capacity); 30287c478bd9Sstevel@tonic-gate 30297c478bd9Sstevel@tonic-gate switch (capacity) { 30307c478bd9Sstevel@tonic-gate 30317c478bd9Sstevel@tonic-gate case 0x5A0: 30327c478bd9Sstevel@tonic-gate /* Double Density 720K */ 30337c478bd9Sstevel@tonic-gate dkgeom->dkg_pcyl = 80; 30347c478bd9Sstevel@tonic-gate dkgeom->dkg_ncyl = 80; 30357c478bd9Sstevel@tonic-gate dkgeom->dkg_nhead = 2; 30367c478bd9Sstevel@tonic-gate dkgeom->dkg_nsect = 9; 30377c478bd9Sstevel@tonic-gate break; 30387c478bd9Sstevel@tonic-gate case 0x4D0: 30397c478bd9Sstevel@tonic-gate /* High Density 1.25MB */ 30407c478bd9Sstevel@tonic-gate dkgeom->dkg_pcyl = 77; 30417c478bd9Sstevel@tonic-gate dkgeom->dkg_ncyl = 77; 30427c478bd9Sstevel@tonic-gate dkgeom->dkg_nhead = 2; 30437c478bd9Sstevel@tonic-gate dkgeom->dkg_nsect = 9; 30447c478bd9Sstevel@tonic-gate break; 30457c478bd9Sstevel@tonic-gate case 0xB40: 30467c478bd9Sstevel@tonic-gate /* High Density 1.44MB */ 30477c478bd9Sstevel@tonic-gate 30487c478bd9Sstevel@tonic-gate dkgeom->dkg_pcyl = 80; 30497c478bd9Sstevel@tonic-gate dkgeom->dkg_ncyl = 80; 30507c478bd9Sstevel@tonic-gate dkgeom->dkg_nhead = 2; 30517c478bd9Sstevel@tonic-gate dkgeom->dkg_nsect = 18; 30527c478bd9Sstevel@tonic-gate break; 30537c478bd9Sstevel@tonic-gate case 0x3C300: 30547c478bd9Sstevel@tonic-gate /* Ultra High density ls-120 120MB */ 30557c478bd9Sstevel@tonic-gate dkgeom->dkg_pcyl = 963; 30567c478bd9Sstevel@tonic-gate dkgeom->dkg_ncyl = 963; 30577c478bd9Sstevel@tonic-gate dkgeom->dkg_nhead = 8; 30587c478bd9Sstevel@tonic-gate dkgeom->dkg_nsect = 32; 30597c478bd9Sstevel@tonic-gate break; 30607c478bd9Sstevel@tonic-gate default: 30617c478bd9Sstevel@tonic-gate debug(5, "unknown capacity type %d\n", capacity); 30627c478bd9Sstevel@tonic-gate return (-1); 30637c478bd9Sstevel@tonic-gate 30647c478bd9Sstevel@tonic-gate } 30657c478bd9Sstevel@tonic-gate debug(5, "get_floppy_geom: setting cyl = %d, nsect = %d, head = %d", 30667c478bd9Sstevel@tonic-gate dkgeom->dkg_pcyl, dkgeom->dkg_nhead, dkgeom->dkg_nsect); 30677c478bd9Sstevel@tonic-gate return (0); 30687c478bd9Sstevel@tonic-gate 30697c478bd9Sstevel@tonic-gate } 30707c478bd9Sstevel@tonic-gate /* ARGSUSED */ 3071*5363f09cSarutz static int32_t 30727c478bd9Sstevel@tonic-gate scsi_floppy_format(int32_t fd, uint_t flavor, uint_t mode) 30737c478bd9Sstevel@tonic-gate { 30747c478bd9Sstevel@tonic-gate struct uscsi_cmd ucmd; 30757c478bd9Sstevel@tonic-gate uchar_t cdb[12]; 30767c478bd9Sstevel@tonic-gate int32_t ret_val; 30777c478bd9Sstevel@tonic-gate uint32_t capacity, blocksize; 30787c478bd9Sstevel@tonic-gate uchar_t data[12]; 30797c478bd9Sstevel@tonic-gate char rq_data[RQ_LEN]; 30807c478bd9Sstevel@tonic-gate int i; 30817c478bd9Sstevel@tonic-gate struct dk_geom dkgeom; 30827c478bd9Sstevel@tonic-gate 30837c478bd9Sstevel@tonic-gate debug(5, "scsi_floppy_format:\n"); 30847c478bd9Sstevel@tonic-gate 30857c478bd9Sstevel@tonic-gate if ((mode != SM_FORMAT_IMMEDIATE) && (mode != SM_FORMAT_BLOCKED)) { 30867c478bd9Sstevel@tonic-gate errno = ENOTSUP; 30877c478bd9Sstevel@tonic-gate 30887c478bd9Sstevel@tonic-gate return (-1); 30897c478bd9Sstevel@tonic-gate } 30907c478bd9Sstevel@tonic-gate 30917c478bd9Sstevel@tonic-gate switch (flavor) { 30927c478bd9Sstevel@tonic-gate case SM_FORMAT_QUICK : 30937c478bd9Sstevel@tonic-gate debug(1, "Format not supported\n"); 30947c478bd9Sstevel@tonic-gate errno = ENOTSUP; 30957c478bd9Sstevel@tonic-gate return (-1); 30967c478bd9Sstevel@tonic-gate case SM_FORMAT_FORCE : 30977c478bd9Sstevel@tonic-gate break; 30987c478bd9Sstevel@tonic-gate case SM_FORMAT_LONG : 30997c478bd9Sstevel@tonic-gate break; 31007c478bd9Sstevel@tonic-gate 31017c478bd9Sstevel@tonic-gate default : 31027c478bd9Sstevel@tonic-gate debug(1, "Format option not specified!!\n"); 31037c478bd9Sstevel@tonic-gate errno = ENOTSUP; 31047c478bd9Sstevel@tonic-gate return (-1); 31057c478bd9Sstevel@tonic-gate } 31067c478bd9Sstevel@tonic-gate 31077c478bd9Sstevel@tonic-gate ret_val = get_media_capacity(fd, &capacity, &blocksize); 31087c478bd9Sstevel@tonic-gate 31097c478bd9Sstevel@tonic-gate if (capacity >= 0x3C300) { 31107c478bd9Sstevel@tonic-gate /* 31117c478bd9Sstevel@tonic-gate * It's an LS-120 media, it does not support track 31127c478bd9Sstevel@tonic-gate * formatting. 31137c478bd9Sstevel@tonic-gate */ 31147c478bd9Sstevel@tonic-gate return (scsi_ls120_format(fd, flavor, capacity, blocksize)); 31157c478bd9Sstevel@tonic-gate } 31167c478bd9Sstevel@tonic-gate 31177c478bd9Sstevel@tonic-gate ret_val = get_floppy_geom(fd, capacity, &dkgeom); 31187c478bd9Sstevel@tonic-gate if (ret_val) { 31197c478bd9Sstevel@tonic-gate errno = ENOTSUP; 31207c478bd9Sstevel@tonic-gate return (-1); 31217c478bd9Sstevel@tonic-gate } 31227c478bd9Sstevel@tonic-gate 31237c478bd9Sstevel@tonic-gate (void) memset((void *)&data, 0, sizeof (data)); 31247c478bd9Sstevel@tonic-gate (void) memset((void *)&ucmd, 0, sizeof (ucmd)); 31257c478bd9Sstevel@tonic-gate (void) memset((void *)&cdb, 0, sizeof (cdb)); 31267c478bd9Sstevel@tonic-gate 31277c478bd9Sstevel@tonic-gate /* retrieve size discriptor of inserted media */ 31287c478bd9Sstevel@tonic-gate cdb[0] = SCMD_FORMAT; /* format */ 31297c478bd9Sstevel@tonic-gate 31307c478bd9Sstevel@tonic-gate /* 31317c478bd9Sstevel@tonic-gate * Defect list sent by initiator is a complete list of defects. 31327c478bd9Sstevel@tonic-gate */ 31337c478bd9Sstevel@tonic-gate 31347c478bd9Sstevel@tonic-gate cdb[1] = (FMTDATA | 0x7); 31357c478bd9Sstevel@tonic-gate 31367c478bd9Sstevel@tonic-gate cdb[8] = 0xC; /* parameter list length */ 31377c478bd9Sstevel@tonic-gate data[3] = 0x8; /* should be always 8 */ 31387c478bd9Sstevel@tonic-gate 31397c478bd9Sstevel@tonic-gate data[4] = (uchar_t)(capacity >> 24); 31407c478bd9Sstevel@tonic-gate data[5] = (uchar_t)(capacity >> 16); 31417c478bd9Sstevel@tonic-gate data[6] = (uchar_t)(capacity >> 8); 31427c478bd9Sstevel@tonic-gate data[7] = (uchar_t)capacity; 31437c478bd9Sstevel@tonic-gate 31447c478bd9Sstevel@tonic-gate data[9] = (uchar_t)(blocksize >> 16); 31457c478bd9Sstevel@tonic-gate data[10] = (uchar_t)(blocksize >> 8); 31467c478bd9Sstevel@tonic-gate data[11] = (uchar_t)blocksize; 31477c478bd9Sstevel@tonic-gate 31487c478bd9Sstevel@tonic-gate ucmd.uscsi_cdb = (caddr_t)&cdb; 31497c478bd9Sstevel@tonic-gate ucmd.uscsi_cdblen = CDB_GROUP5; 31507c478bd9Sstevel@tonic-gate ucmd.uscsi_bufaddr = (caddr_t)data; 31517c478bd9Sstevel@tonic-gate ucmd.uscsi_buflen = sizeof (data); 31527c478bd9Sstevel@tonic-gate ucmd.uscsi_timeout = 0x15; 31537c478bd9Sstevel@tonic-gate ucmd.uscsi_rqlen = RQ_LEN; 31547c478bd9Sstevel@tonic-gate ucmd.uscsi_rqbuf = rq_data; 31557c478bd9Sstevel@tonic-gate 31567c478bd9Sstevel@tonic-gate debug(5, "cdb: %x %x %x ... %x", cdb[0], cdb[1], cdb[2], cdb[8]); 31577c478bd9Sstevel@tonic-gate debug(5, "data: %x %x %x %x\n", data[0], data[1], data[2], data[3]); 31587c478bd9Sstevel@tonic-gate debug(5, " : %x %x %x %x\n", data[4], data[5], data[6], data[7]); 31597c478bd9Sstevel@tonic-gate debug(5, " : %x %x %x %x\n", data[8], data[9], data[10], data[11]); 31607c478bd9Sstevel@tonic-gate 31617c478bd9Sstevel@tonic-gate for (i = 0; i < dkgeom.dkg_pcyl; i++) { /* number of tracks */ 31627c478bd9Sstevel@tonic-gate data[1] = (0xb0 | FOV); 31637c478bd9Sstevel@tonic-gate cdb[2] = i; 31647c478bd9Sstevel@tonic-gate 31657c478bd9Sstevel@tonic-gate (void) fflush(stdout); 31667c478bd9Sstevel@tonic-gate ret_val = do_uscsi_cmd(fd, &ucmd, USCSI_WRITE|USCSI_RQENABLE); 31677c478bd9Sstevel@tonic-gate info("format side 0 returned : 0x%x\n", ret_val); 31687c478bd9Sstevel@tonic-gate 31697c478bd9Sstevel@tonic-gate if (ret_val || ucmd.uscsi_status) { 31707c478bd9Sstevel@tonic-gate debug(5, "Retrieving media info failed: %d - %d\n", 31717c478bd9Sstevel@tonic-gate ret_val, ucmd.uscsi_status); 31727c478bd9Sstevel@tonic-gate if ((rq_data[2] == KEY_DATA_PROTECT) && 31737c478bd9Sstevel@tonic-gate (rq_data[12] == 0x30) && (rq_data[13] == 0)) { 31747c478bd9Sstevel@tonic-gate debug(5, "Invalid command for media\n"); 31757c478bd9Sstevel@tonic-gate errno = EINVAL; 31767c478bd9Sstevel@tonic-gate } 31777c478bd9Sstevel@tonic-gate 31787c478bd9Sstevel@tonic-gate if ((rq_data[2] == KEY_NOT_READY) && 31797c478bd9Sstevel@tonic-gate (rq_data[12] == 0x30)) { 31807c478bd9Sstevel@tonic-gate debug(5, "Incompatible media.\n"); 31817c478bd9Sstevel@tonic-gate errno = EINVAL; 31827c478bd9Sstevel@tonic-gate } 31837c478bd9Sstevel@tonic-gate 31847c478bd9Sstevel@tonic-gate return (-1); 31857c478bd9Sstevel@tonic-gate } 31867c478bd9Sstevel@tonic-gate data[1] = (0xb0 | FOV) + 1; 31877c478bd9Sstevel@tonic-gate ret_val = do_uscsi_cmd(fd, &ucmd, USCSI_WRITE|USCSI_RQENABLE); 31887c478bd9Sstevel@tonic-gate info("format side 1 returned : 0x%x\n", ret_val); 31897c478bd9Sstevel@tonic-gate 31907c478bd9Sstevel@tonic-gate if (ret_val || ucmd.uscsi_status) { 31917c478bd9Sstevel@tonic-gate debug(5, "Retrieving media info failed: %d - %d\n", 31927c478bd9Sstevel@tonic-gate ret_val, ucmd.uscsi_status); 31937c478bd9Sstevel@tonic-gate if ((rq_data[2] == KEY_DATA_PROTECT) && 31947c478bd9Sstevel@tonic-gate (rq_data[12] == 0x30) && (rq_data[13] == 0)) { 31957c478bd9Sstevel@tonic-gate (void) info("Invalid command for media\n"); 31967c478bd9Sstevel@tonic-gate errno = EINVAL; 31977c478bd9Sstevel@tonic-gate } 31987c478bd9Sstevel@tonic-gate 31997c478bd9Sstevel@tonic-gate if ((rq_data[2] == KEY_NOT_READY) && 32007c478bd9Sstevel@tonic-gate (rq_data[12] == 0x30)) { 32017c478bd9Sstevel@tonic-gate debug(5, "Incompatible media.\n"); 32027c478bd9Sstevel@tonic-gate errno = EINVAL; 32037c478bd9Sstevel@tonic-gate } 32047c478bd9Sstevel@tonic-gate 32057c478bd9Sstevel@tonic-gate return (-1); 32067c478bd9Sstevel@tonic-gate } 32077c478bd9Sstevel@tonic-gate } 32087c478bd9Sstevel@tonic-gate 32097c478bd9Sstevel@tonic-gate debug(5, "formatting done!"); 32107c478bd9Sstevel@tonic-gate return (0); 32117c478bd9Sstevel@tonic-gate } 32127c478bd9Sstevel@tonic-gate 32137c478bd9Sstevel@tonic-gate 32147c478bd9Sstevel@tonic-gate /* ARGSUSED */ 3215*5363f09cSarutz static int32_t 32167c478bd9Sstevel@tonic-gate scsi_floppy_media_status(int32_t fd) 32177c478bd9Sstevel@tonic-gate { 32187c478bd9Sstevel@tonic-gate struct mode_header_g1 modeh; 32197c478bd9Sstevel@tonic-gate struct uscsi_cmd ucmd; 32207c478bd9Sstevel@tonic-gate uchar_t cdb[10]; 32217c478bd9Sstevel@tonic-gate int32_t ret_val; 32227c478bd9Sstevel@tonic-gate int32_t cur_status; 32237c478bd9Sstevel@tonic-gate char rq_data[RQ_LEN]; 32247c478bd9Sstevel@tonic-gate 32257c478bd9Sstevel@tonic-gate debug(5, "SCSI MEDIA STATUS CALLED \n"); 32267c478bd9Sstevel@tonic-gate 32277c478bd9Sstevel@tonic-gate (void) memset((void *) &modeh, 0, sizeof (modeh)); 32287c478bd9Sstevel@tonic-gate (void) memset((void *) &ucmd, 0, sizeof (ucmd)); 32297c478bd9Sstevel@tonic-gate (void) memset(cdb, 0, sizeof (cdb)); 32307c478bd9Sstevel@tonic-gate /* 32317c478bd9Sstevel@tonic-gate * issue 10 byte mode sense (0x5A) 32327c478bd9Sstevel@tonic-gate */ 32337c478bd9Sstevel@tonic-gate cdb[0] = SCMD_MODE_SENSE_G1; 32347c478bd9Sstevel@tonic-gate cdb[7] = sizeof (modeh) >> 8; 32357c478bd9Sstevel@tonic-gate cdb[8] = sizeof (modeh) & 0xff; 32367c478bd9Sstevel@tonic-gate 32377c478bd9Sstevel@tonic-gate ucmd.uscsi_cdb = (caddr_t)cdb; 32387c478bd9Sstevel@tonic-gate ucmd.uscsi_cdblen = CDB_GROUP1; 32397c478bd9Sstevel@tonic-gate ucmd.uscsi_bufaddr = (caddr_t)&modeh; 32407c478bd9Sstevel@tonic-gate ucmd.uscsi_buflen = sizeof (modeh); 32417c478bd9Sstevel@tonic-gate ucmd.uscsi_timeout = 120; /* If 0, HBA hangs forever */ 32427c478bd9Sstevel@tonic-gate ucmd.uscsi_rqlen = RQ_LEN; 32437c478bd9Sstevel@tonic-gate ucmd.uscsi_rqbuf = rq_data; 32447c478bd9Sstevel@tonic-gate ret_val = do_uscsi_cmd(fd, &ucmd, USCSI_READ|USCSI_RQENABLE); 32457c478bd9Sstevel@tonic-gate if (ret_val || ucmd.uscsi_status) { 32467c478bd9Sstevel@tonic-gate /* 32477c478bd9Sstevel@tonic-gate * UFI devices may not respond to the 0 mode page. 32487c478bd9Sstevel@tonic-gate * retry with the error recovery page(0x01) 32497c478bd9Sstevel@tonic-gate */ 32507c478bd9Sstevel@tonic-gate if (ucmd.uscsi_status & STATUS_CHECK) { 32517c478bd9Sstevel@tonic-gate cdb[2] = 0x1; /* page code */ 32527c478bd9Sstevel@tonic-gate ret_val = do_uscsi_cmd(fd, &ucmd, 32537c478bd9Sstevel@tonic-gate USCSI_READ|USCSI_RQENABLE); 32547c478bd9Sstevel@tonic-gate } 32557c478bd9Sstevel@tonic-gate if (ret_val || ucmd.uscsi_status) { 32567c478bd9Sstevel@tonic-gate debug(1, "Modesense failed: %d - %d\n", 32577c478bd9Sstevel@tonic-gate ret_val, ucmd.uscsi_status); 32587c478bd9Sstevel@tonic-gate return (-1); 32597c478bd9Sstevel@tonic-gate } 32607c478bd9Sstevel@tonic-gate } 32617c478bd9Sstevel@tonic-gate debug(5, "Modesense succeeded: 0x%x\n", modeh.device_specific); 32627c478bd9Sstevel@tonic-gate 32637c478bd9Sstevel@tonic-gate if (modeh.device_specific & 0x80) { 32647c478bd9Sstevel@tonic-gate cur_status = SM_WRITE_PROTECT_NOPASSWD; 32657c478bd9Sstevel@tonic-gate } else { 32667c478bd9Sstevel@tonic-gate cur_status = SM_WRITE_PROTECT_DISABLE; 32677c478bd9Sstevel@tonic-gate } 32687c478bd9Sstevel@tonic-gate return (cur_status); 32697c478bd9Sstevel@tonic-gate } 3270