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 5004388ebScasper * Common Development and Distribution License (the "License"). 6004388ebScasper * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 21d4204c85Sraf 227c478bd9Sstevel@tonic-gate /* 23d4204c85Sraf * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 247c478bd9Sstevel@tonic-gate * Use is subject to license terms. 257c478bd9Sstevel@tonic-gate */ 267c478bd9Sstevel@tonic-gate 277c478bd9Sstevel@tonic-gate #include <stdio.h> 28004388ebScasper #include <stdio_ext.h> 297c478bd9Sstevel@tonic-gate #include <errno.h> 307c478bd9Sstevel@tonic-gate #include <ctype.h> 317c478bd9Sstevel@tonic-gate #include <syslog.h> 327c478bd9Sstevel@tonic-gate #include <signal.h> 337c478bd9Sstevel@tonic-gate #include <limits.h> 347c478bd9Sstevel@tonic-gate #include <unistd.h> 357c478bd9Sstevel@tonic-gate #include <sys/types.h> 367c478bd9Sstevel@tonic-gate #include <sys/mman.h> 377c478bd9Sstevel@tonic-gate #include <stdlib.h> 387c478bd9Sstevel@tonic-gate #include <sys/stat.h> 397c478bd9Sstevel@tonic-gate #include <sys/mkdev.h> 407c478bd9Sstevel@tonic-gate #include <fcntl.h> 417c478bd9Sstevel@tonic-gate #include <sys/scsi/scsi.h> 427c478bd9Sstevel@tonic-gate #include <sys/scsi/generic/commands.h> 437c478bd9Sstevel@tonic-gate #include <string.h> 447c478bd9Sstevel@tonic-gate #include <door.h> 457c478bd9Sstevel@tonic-gate #include <pwd.h> 467c478bd9Sstevel@tonic-gate #include <thread.h> 477c478bd9Sstevel@tonic-gate #include <synch.h> 487c478bd9Sstevel@tonic-gate #include <pthread.h> 497c478bd9Sstevel@tonic-gate #include <locale.h> 507c478bd9Sstevel@tonic-gate #include <sys/resource.h> 517c478bd9Sstevel@tonic-gate #include <netconfig.h> 527c478bd9Sstevel@tonic-gate #include <sys/smedia.h> 537c478bd9Sstevel@tonic-gate #include "smserver.h" 547c478bd9Sstevel@tonic-gate #include <rpc/rpc.h> 557c478bd9Sstevel@tonic-gate #include "smed.h" 567c478bd9Sstevel@tonic-gate #include "myaudit.h" 577c478bd9Sstevel@tonic-gate #include <bsm/libbsm.h> 587c478bd9Sstevel@tonic-gate #include <bsm/audit_uevents.h> 597c478bd9Sstevel@tonic-gate #include <utmpx.h> 607c478bd9Sstevel@tonic-gate 617c478bd9Sstevel@tonic-gate 627c478bd9Sstevel@tonic-gate /* 637c478bd9Sstevel@tonic-gate * The comments below would help in understanding what is being attempted 647c478bd9Sstevel@tonic-gate * in the server. 657c478bd9Sstevel@tonic-gate * 667c478bd9Sstevel@tonic-gate * The server can be started either by inetd or by the client directly. 677c478bd9Sstevel@tonic-gate * Normally the server is started by inetd when the client invokes the 687c478bd9Sstevel@tonic-gate * appropriate libsmedia library call(smedia_get_handle). 697c478bd9Sstevel@tonic-gate * However since the inetd runs only at init level 2 and above a mechanism 707c478bd9Sstevel@tonic-gate * is provided for the server to be started if an attempt is made to use 717c478bd9Sstevel@tonic-gate * the libsmedia calls in maintenence mode(init level 1). 727c478bd9Sstevel@tonic-gate * The main() routine determines how the server was invoked and takes 737c478bd9Sstevel@tonic-gate * the necessary action. 747c478bd9Sstevel@tonic-gate * When started by inetd it registers itself as an RPC program. 757c478bd9Sstevel@tonic-gate * The server also implements a mechanism by which it removes itself 767c478bd9Sstevel@tonic-gate * after a period of inactivity. The period of inactivity is specified 777c478bd9Sstevel@tonic-gate * by SVC_CLOSEDOWN which is set at 180 secs. 787c478bd9Sstevel@tonic-gate * The logic of detecting inactivity is as follows: 797c478bd9Sstevel@tonic-gate * 807c478bd9Sstevel@tonic-gate * Two variables svcstate and svccount are used to determine if the server 817c478bd9Sstevel@tonic-gate * is IDLE. 827c478bd9Sstevel@tonic-gate * The svcstate is set to 1(_SERVED) when ever the server does any operation 837c478bd9Sstevel@tonic-gate * on behalf of the client. 847c478bd9Sstevel@tonic-gate * The svccount indicates the number of active clients who have established 857c478bd9Sstevel@tonic-gate * a connection with the server. A connection is established when the 867c478bd9Sstevel@tonic-gate * libsmedia call smedia_get_handle() succeeds. 877c478bd9Sstevel@tonic-gate * The connection is broken when the client calls smedia_free_handle() OR 887c478bd9Sstevel@tonic-gate * exits. 897c478bd9Sstevel@tonic-gate * A thread called closedown is started up when server is started. 907c478bd9Sstevel@tonic-gate * This thread runs periodically and monitors both svcstate and svccount. 917c478bd9Sstevel@tonic-gate * If svcstate is IDLE and svccount is 0 then server exits. 927c478bd9Sstevel@tonic-gate * The svcstate is set to IDLE by the closedown thread. It is set to _SERVED 937c478bd9Sstevel@tonic-gate * by server. It is possible for the state to be _SERVED and the svccount 947c478bd9Sstevel@tonic-gate * to be 0. The server could be kept busy by client calls of smedia_get_handle 957c478bd9Sstevel@tonic-gate * that do not succeed. This is the reason for using both svcstate and svccount 967c478bd9Sstevel@tonic-gate * to determine the true server state. 977c478bd9Sstevel@tonic-gate * 987c478bd9Sstevel@tonic-gate * The communication between client and server is thru door calls. 997c478bd9Sstevel@tonic-gate * Below are the door descriptors available to communicate to the server. 1007c478bd9Sstevel@tonic-gate * 1017c478bd9Sstevel@tonic-gate * main_door_descriptor: 1027c478bd9Sstevel@tonic-gate * --------------------- 1037c478bd9Sstevel@tonic-gate * This is a predefined descriptor used by client to establish a 1047c478bd9Sstevel@tonic-gate * connection with the server. This descriptor is available to the client 1057c478bd9Sstevel@tonic-gate * as /var/adm/smedia_svc 1065363f09cSarutz * The client uses the main_door_descriptor to obtain a dedicated 1077c478bd9Sstevel@tonic-gate * client_door_descriptor for itself. The smedia_get_handle call communicates 1087c478bd9Sstevel@tonic-gate * to the server using the main_door_descriptor and obtains the 1097c478bd9Sstevel@tonic-gate * client_door_descriptor which is stored in the handle structure. 1107c478bd9Sstevel@tonic-gate * All other libsmedia calls use the client_door_descriptor to communicate 1117c478bd9Sstevel@tonic-gate * with the server. 1127c478bd9Sstevel@tonic-gate * 1137c478bd9Sstevel@tonic-gate * client_door_descriptor: 1147c478bd9Sstevel@tonic-gate * ----------------------- 1157c478bd9Sstevel@tonic-gate * This is the door descriptor that is used by the clients to 1167c478bd9Sstevel@tonic-gate * request server to perform the necessary tasks. This door descriptor is 1177c478bd9Sstevel@tonic-gate * available only to the client for whom it was created. 1187c478bd9Sstevel@tonic-gate * 1197c478bd9Sstevel@tonic-gate * death_door_descriptor: 1207c478bd9Sstevel@tonic-gate * ---------------------- 1215363f09cSarutz * The sole function of this descriptor HAD been to inform the server of 1225363f09cSarutz * the untimely death of the client. This descriptor is no longer used, though 1235363f09cSarutz * it is still created, as libsmedia expects to use it. This descriptor's 1245363f09cSarutz * service procedure had used pthread cancellation(5) to terminate the thread of 1255363f09cSarutz * the associated client_door_descriptor. The client_door_descriptor now 1265363f09cSarutz * handles the scenarios where a door_call/client are aborted/terminated. 1277c478bd9Sstevel@tonic-gate * 1285363f09cSarutz * main_servproc() 1297c478bd9Sstevel@tonic-gate * ------------- 1307c478bd9Sstevel@tonic-gate * This is the routine associated with the main_door_descriptor. 1317c478bd9Sstevel@tonic-gate * This is the routine that handles the smedia_get_handle() call 1327c478bd9Sstevel@tonic-gate * of the client. If the door call to this routine succeeds it creates a 1337c478bd9Sstevel@tonic-gate * client_door_descriptor that is used by the client in subsequent library 1347c478bd9Sstevel@tonic-gate * calls. 1357c478bd9Sstevel@tonic-gate * This client_door_descriptor is passed to the client thru the door_return 1367c478bd9Sstevel@tonic-gate * call. This client_door_descriptor cannot be used by any other process other 1377c478bd9Sstevel@tonic-gate * than the client process that obtained it. 1387c478bd9Sstevel@tonic-gate * In addition to the client_door_descriptor a death_door_descriptor is also 1397c478bd9Sstevel@tonic-gate * created by the main server and passed on to the client. The client does not 1405363f09cSarutz * use the death_door_descriptor. 1417c478bd9Sstevel@tonic-gate * 1425363f09cSarutz * client_servproc() 1437c478bd9Sstevel@tonic-gate * --------------- 1447c478bd9Sstevel@tonic-gate * This is the routine that handles the libsmedia calls of the 1457c478bd9Sstevel@tonic-gate * client. In the current implementation the server takes control of the 1467c478bd9Sstevel@tonic-gate * number of threads that handle the door calls. This is done by creating the 1477c478bd9Sstevel@tonic-gate * door descriptor as DOOR_PRIVATE. 1487c478bd9Sstevel@tonic-gate * The server runs only one thread per handle. This makes the implementation 1497c478bd9Sstevel@tonic-gate * simple as we do not have to use mutex to make the code MT safe. 1505363f09cSarutz * The server thread has a data structure door_data_t associated with it. 1517c478bd9Sstevel@tonic-gate * 1527c478bd9Sstevel@tonic-gate * door_data_t 1537c478bd9Sstevel@tonic-gate * ----------- 1545363f09cSarutz * This is the data structure that is created by the main_servproc when it 1557c478bd9Sstevel@tonic-gate * creates the client_door_descriptor. The door mechanism has a way to associate 1567c478bd9Sstevel@tonic-gate * a cookie with the door descriptor. door_data_t is the cookie for the 1575363f09cSarutz * client_door_descriptor. This cookie is passed to the server function that 1585363f09cSarutz * handles the client_door_descriptor calls. In our case it is the 1595363f09cSarutz * client_servproc routine. 1607c478bd9Sstevel@tonic-gate * The key elements of the door_data_t are the following: 1617c478bd9Sstevel@tonic-gate * 1627c478bd9Sstevel@tonic-gate * dd_fd file descriptor for the device. 1637c478bd9Sstevel@tonic-gate * dd_buf The shared memory buffer between client-server. 1647c478bd9Sstevel@tonic-gate * dd_thread The thread that handles the door_calls. 1657c478bd9Sstevel@tonic-gate * 1667c478bd9Sstevel@tonic-gate * signal handling: 1677c478bd9Sstevel@tonic-gate * ---------------- 1687c478bd9Sstevel@tonic-gate * The main purpose of trapping the signals is to exit gracefully 1697c478bd9Sstevel@tonic-gate * from the server after recording the appropriate message in the syslog. 1707c478bd9Sstevel@tonic-gate * This will help the administrator to determine the cause of failure of the 1717c478bd9Sstevel@tonic-gate * server by examining the log file. 1727c478bd9Sstevel@tonic-gate * 1737c478bd9Sstevel@tonic-gate * cleanup() 1747c478bd9Sstevel@tonic-gate * --------- 1757c478bd9Sstevel@tonic-gate * This routine frees up all the resources allocated for the client. 1765363f09cSarutz * Resources include the file descriptor, shared memory, threads. 1777c478bd9Sstevel@tonic-gate * 1787c478bd9Sstevel@tonic-gate * shared memory 1797c478bd9Sstevel@tonic-gate * ------------- 1807c478bd9Sstevel@tonic-gate * In order to reduce the overheads of moving large amounts of data 1817c478bd9Sstevel@tonic-gate * during raw read/write operations, the server uses the mmapped data of 1827c478bd9Sstevel@tonic-gate * client. The smedia_raw_read, smedia_raw_write library calls mmap the 1837c478bd9Sstevel@tonic-gate * memory and pass on the file descriptor that maps the memory to the server. 1847c478bd9Sstevel@tonic-gate * The server subsequently uses this mmapped memory during the IO. 1857c478bd9Sstevel@tonic-gate * If the mmapped memory changes in size, the server is informed and it 1867c478bd9Sstevel@tonic-gate * remaps the memory to the changed size. 1877c478bd9Sstevel@tonic-gate */ 1887c478bd9Sstevel@tonic-gate #ifdef DEBUG 1897c478bd9Sstevel@tonic-gate #define DEFAULT_VERBOSE 1 1907c478bd9Sstevel@tonic-gate #define DEFAULT_DEBUG 1 1917c478bd9Sstevel@tonic-gate #else 1927c478bd9Sstevel@tonic-gate #define DEFAULT_VERBOSE 0 1937c478bd9Sstevel@tonic-gate #define DEFAULT_DEBUG 0 1947c478bd9Sstevel@tonic-gate #endif 1957c478bd9Sstevel@tonic-gate 1967c478bd9Sstevel@tonic-gate #define N_BADSIGS (sizeof (badsigs)/sizeof (badsigs[0])) 1977c478bd9Sstevel@tonic-gate #define MD_LEN 30 1987c478bd9Sstevel@tonic-gate #define MAXUGNAME 10 1997c478bd9Sstevel@tonic-gate #define SVC_CLOSEDOWN 180 2007c478bd9Sstevel@tonic-gate 2017c478bd9Sstevel@tonic-gate /* 2027c478bd9Sstevel@tonic-gate * We will NOT be permitting the following USCI cmd options. 2037c478bd9Sstevel@tonic-gate * 2047c478bd9Sstevel@tonic-gate * RESET of target 2057c478bd9Sstevel@tonic-gate * RESET of Bus. 2067c478bd9Sstevel@tonic-gate * Tagged commands to device 2077c478bd9Sstevel@tonic-gate * Explicitly setting SYNC/ASYNC mode of operations. 2087c478bd9Sstevel@tonic-gate * POLLED MODE of operation. 2097c478bd9Sstevel@tonic-gate * Explicitly setting NO DISCONNECT features. 2107c478bd9Sstevel@tonic-gate * use of RESERVED flags. 2117c478bd9Sstevel@tonic-gate */ 2127c478bd9Sstevel@tonic-gate #define FORBIDDEN_FLAGS (USCSI_RESET | USCSI_RESET_ALL | USCSI_RENEGOT \ 2137c478bd9Sstevel@tonic-gate | USCSI_ASYNC | USCSI_SYNC | USCSI_NOINTR | \ 2147c478bd9Sstevel@tonic-gate USCSI_NOTAG | USCSI_NOPARITY | USCSI_NODISCON \ 2157c478bd9Sstevel@tonic-gate | USCSI_RESERVED) 2167c478bd9Sstevel@tonic-gate 2177c478bd9Sstevel@tonic-gate /* States a server can be in wrt request */ 2187c478bd9Sstevel@tonic-gate 2197c478bd9Sstevel@tonic-gate #define _IDLE 0 2207c478bd9Sstevel@tonic-gate #define _SERVED 1 2217c478bd9Sstevel@tonic-gate 2227c478bd9Sstevel@tonic-gate static char *prog_name; 2237c478bd9Sstevel@tonic-gate static int svcstate = _IDLE; /* Set when a request is serviced */ 2247c478bd9Sstevel@tonic-gate static int svccount = 0; /* Number of requests being serviced */ 2257c478bd9Sstevel@tonic-gate static int svcstart_level = 0; /* init level when server was started */ 2267c478bd9Sstevel@tonic-gate static mutex_t svcstate_lock; /* lock for svcstate, svccount */ 2277c478bd9Sstevel@tonic-gate 2287c478bd9Sstevel@tonic-gate extern void smserverprog_1(struct svc_req *, SVCXPRT *); 2297c478bd9Sstevel@tonic-gate 2307c478bd9Sstevel@tonic-gate /* 2317c478bd9Sstevel@tonic-gate * Log messages 2327c478bd9Sstevel@tonic-gate */ 2337c478bd9Sstevel@tonic-gate #define SIGACT_FAILED "Failed to install signal handler for %s: %s" 2347c478bd9Sstevel@tonic-gate #define BADSIG_MSG "Thread %d Caught signal %d addr=%p trapno=%d pc=%p" 2357c478bd9Sstevel@tonic-gate 2367c478bd9Sstevel@tonic-gate static int badsigs[] = {SIGSEGV, SIGBUS, SIGFPE, SIGILL}; 2377c478bd9Sstevel@tonic-gate 2387c478bd9Sstevel@tonic-gate /* global variables */ 2397c478bd9Sstevel@tonic-gate int verbose = DEFAULT_VERBOSE; 2407c478bd9Sstevel@tonic-gate int debug_level = DEFAULT_DEBUG; 2417c478bd9Sstevel@tonic-gate char *smediad_devdir = DEFAULT_SMEDIAD_DEVDIR; 2427c478bd9Sstevel@tonic-gate 2437c478bd9Sstevel@tonic-gate thread_key_t door_key; 2447c478bd9Sstevel@tonic-gate 2457c478bd9Sstevel@tonic-gate server_data_t server_data; 2467c478bd9Sstevel@tonic-gate 2477c478bd9Sstevel@tonic-gate static int server_door, server_fd; 2487c478bd9Sstevel@tonic-gate 2497c478bd9Sstevel@tonic-gate static int32_t do_uscsi_cmd(int32_t file, struct uscsi_cmd *uscsi_cmd, 2507c478bd9Sstevel@tonic-gate int32_t flag); 2515363f09cSarutz static void client_servproc(void *cookie, char *argp, size_t arg_size, 2527c478bd9Sstevel@tonic-gate door_desc_t *dp, uint_t ndesc); 2537c478bd9Sstevel@tonic-gate static void cleanup(door_data_t *); 2547c478bd9Sstevel@tonic-gate static void *init_server(void *); 2557c478bd9Sstevel@tonic-gate static int32_t scsi_reassign_block(int32_t fd, diskaddr_t); 2567c478bd9Sstevel@tonic-gate static int32_t get_mode_page(int32_t fd, uchar_t pc, uchar_t page_code, 2577c478bd9Sstevel@tonic-gate uchar_t *md_data, uchar_t data_len); 2587c478bd9Sstevel@tonic-gate static int32_t get_device_type(char *v_name); 2597c478bd9Sstevel@tonic-gate static int32_t get_device_type_scsi(int32_t fd, struct scsi_inquiry *inq); 2607c478bd9Sstevel@tonic-gate 2617c478bd9Sstevel@tonic-gate static int32_t scsi_format(int32_t fd, uint_t flavor, uint_t mode); 2627c478bd9Sstevel@tonic-gate static int32_t scsi_media_status(int32_t fd); 2637c478bd9Sstevel@tonic-gate static int32_t scsi_write_protect(int32_t fd, smwp_state_t *wp); 2647c478bd9Sstevel@tonic-gate static int32_t scsi_floppy_media_status(int32_t fd); 2657c478bd9Sstevel@tonic-gate static int32_t scsi_floppy_write_protect(int32_t fd, smwp_state_t *wp); 2667c478bd9Sstevel@tonic-gate static int32_t scsi_floppy_format(int32_t, uint_t, uint_t); 2677c478bd9Sstevel@tonic-gate static int32_t get_floppy_geom(int32_t fd, uint32_t capacity, 2687c478bd9Sstevel@tonic-gate struct dk_geom *dkgeom); 2697c478bd9Sstevel@tonic-gate static int32_t get_media_capacity(int32_t fd, uint32_t *capacity, 2707c478bd9Sstevel@tonic-gate uint32_t *blocksize); 2717c478bd9Sstevel@tonic-gate 2727c478bd9Sstevel@tonic-gate static int32_t scsi_ls120_format(uint_t fd, uint_t flavor, uint32_t capacity, 2737c478bd9Sstevel@tonic-gate uint32_t blocksize); 2747c478bd9Sstevel@tonic-gate 2755363f09cSarutz static void *sm_server_thread(void *arg); 2765363f09cSarutz static void sm_door_server_create(door_info_t *dip); 2777c478bd9Sstevel@tonic-gate static void term_handler(int sig, siginfo_t *siginfo, void *sigctx); 2787c478bd9Sstevel@tonic-gate static void hup_handler(int sig, siginfo_t *siginfo, void *sigctx); 2797c478bd9Sstevel@tonic-gate static void sig_handler(int sig, siginfo_t *siginfo, void *sigctx); 2807c478bd9Sstevel@tonic-gate static void badsig_handler(int sig, siginfo_t *siginfo, void *sigctx); 2817c478bd9Sstevel@tonic-gate static void server_badsig_handler(int sig, siginfo_t *siginfo, void *sigctx); 2827c478bd9Sstevel@tonic-gate static char *xlate_state(int32_t); 2837c478bd9Sstevel@tonic-gate static uint32_t get_sector_size(int fd); 2847c478bd9Sstevel@tonic-gate static int32_t raw_read(door_data_t *door_dp, smedia_services_t *req); 2857c478bd9Sstevel@tonic-gate static int32_t raw_write(door_data_t *door_dp, smedia_services_t *req); 2867c478bd9Sstevel@tonic-gate static int32_t reassign_block(door_data_t *door_dp, smedia_services_t *req); 2877c478bd9Sstevel@tonic-gate static int32_t set_protection_status(door_data_t *door_dp, 2887c478bd9Sstevel@tonic-gate smedia_services_t *req); 2897c478bd9Sstevel@tonic-gate static int32_t set_shfd(door_data_t *door_dp, int32_t fd, 2907c478bd9Sstevel@tonic-gate smedia_services_t *req); 2917c478bd9Sstevel@tonic-gate 2927c478bd9Sstevel@tonic-gate static void door_ret_err(smedia_reterror_t *reterror, int32_t err); 2937c478bd9Sstevel@tonic-gate static void my_door_return(char *data_ptr, size_t data_size, 2947c478bd9Sstevel@tonic-gate door_desc_t *desc_ptr, uint_t num_desc); 2957c478bd9Sstevel@tonic-gate static int32_t invalid_uscsi_operation(door_data_t *, struct uscsi_cmd *); 2967c478bd9Sstevel@tonic-gate 2977c478bd9Sstevel@tonic-gate #define W_E_MASK 0x80 2987c478bd9Sstevel@tonic-gate 2997c478bd9Sstevel@tonic-gate static smserver_info server_info; 3007c478bd9Sstevel@tonic-gate 3017c478bd9Sstevel@tonic-gate static int32_t 3027c478bd9Sstevel@tonic-gate invalid_uscsi_operation(door_data_t *door_dp, struct uscsi_cmd *ucmd) 3037c478bd9Sstevel@tonic-gate { 3047c478bd9Sstevel@tonic-gate 3057c478bd9Sstevel@tonic-gate if (door_dp->dd_dkinfo.dki_ctype != DKC_CDROM) { 3067c478bd9Sstevel@tonic-gate debug(5, 3077c478bd9Sstevel@tonic-gate "Invalid device type(0x%x) found for uscsi cmd.\n", 3087c478bd9Sstevel@tonic-gate door_dp->dd_dkinfo.dki_ctype); 3097c478bd9Sstevel@tonic-gate errno = EINVAL; 3107c478bd9Sstevel@tonic-gate return (EINVAL); 3117c478bd9Sstevel@tonic-gate } 3127c478bd9Sstevel@tonic-gate if (ucmd->uscsi_flags & FORBIDDEN_FLAGS) { 3137c478bd9Sstevel@tonic-gate debug(5, 3147c478bd9Sstevel@tonic-gate "Invalid flags(0x%x) set in uscsi cmd. cdb[0]=0x%x\n", 3157c478bd9Sstevel@tonic-gate ucmd->uscsi_flags, ucmd->uscsi_cdb[0]); 3167c478bd9Sstevel@tonic-gate errno = EINVAL; 3177c478bd9Sstevel@tonic-gate return (EINVAL); 3187c478bd9Sstevel@tonic-gate } 3197c478bd9Sstevel@tonic-gate if (ucmd->uscsi_cdb[0] == SCMD_COPY || 3207c478bd9Sstevel@tonic-gate ucmd->uscsi_cdb[0] == SCMD_COPY_VERIFY || 3217c478bd9Sstevel@tonic-gate ucmd->uscsi_cdb[0] == SCMD_COMPARE || 3227c478bd9Sstevel@tonic-gate ucmd->uscsi_cdb[0] == SCMD_WRITE_BUFFER) { 3237c478bd9Sstevel@tonic-gate debug(5, 3247c478bd9Sstevel@tonic-gate "Invalid command(0x%x) found in cdb.\n", 3257c478bd9Sstevel@tonic-gate ucmd->uscsi_cdb[0]); 3267c478bd9Sstevel@tonic-gate errno = EINVAL; 3277c478bd9Sstevel@tonic-gate return (EINVAL); 3287c478bd9Sstevel@tonic-gate } 3297c478bd9Sstevel@tonic-gate return (0); 3307c478bd9Sstevel@tonic-gate } 3317c478bd9Sstevel@tonic-gate 3327c478bd9Sstevel@tonic-gate static uint32_t 3337c478bd9Sstevel@tonic-gate get_sector_size(int fd) 3347c478bd9Sstevel@tonic-gate { 3357c478bd9Sstevel@tonic-gate uint32_t sector_size; 3367c478bd9Sstevel@tonic-gate struct uscsi_cmd ucmd; 3377c478bd9Sstevel@tonic-gate union scsi_cdb cdb; 3387c478bd9Sstevel@tonic-gate int32_t ret_val; 3397c478bd9Sstevel@tonic-gate uint32_t rc_data[2]; 3407c478bd9Sstevel@tonic-gate char rq_data[RQ_LEN]; 3417c478bd9Sstevel@tonic-gate 3427c478bd9Sstevel@tonic-gate cdb.scc_cmd = SCMD_READ_CAPACITY; 3437c478bd9Sstevel@tonic-gate ucmd.uscsi_cdb = (caddr_t)&cdb; 3447c478bd9Sstevel@tonic-gate ucmd.uscsi_cdblen = CDB_GROUP1; 3457c478bd9Sstevel@tonic-gate ucmd.uscsi_bufaddr = (caddr_t)&rc_data; 3467c478bd9Sstevel@tonic-gate ucmd.uscsi_buflen = sizeof (rc_data); 3477c478bd9Sstevel@tonic-gate ucmd.uscsi_timeout = 120; /* If 0, HBA hangs forever */ 3487c478bd9Sstevel@tonic-gate ucmd.uscsi_rqlen = RQ_LEN; 3497c478bd9Sstevel@tonic-gate ucmd.uscsi_rqbuf = rq_data; 3507c478bd9Sstevel@tonic-gate 3517c478bd9Sstevel@tonic-gate ret_val = do_uscsi_cmd(fd, 3527c478bd9Sstevel@tonic-gate &ucmd, USCSI_READ|USCSI_RQENABLE); 3537c478bd9Sstevel@tonic-gate if (ret_val || ucmd.uscsi_status) { 3547c478bd9Sstevel@tonic-gate debug(5, "Read capacity : %d - %d errno = %d\n", 3557c478bd9Sstevel@tonic-gate ret_val, ucmd.uscsi_status, errno); 3567c478bd9Sstevel@tonic-gate sector_size = 512; 3577c478bd9Sstevel@tonic-gate } else { 3587c478bd9Sstevel@tonic-gate sector_size = ntohl(rc_data[1]); 3597c478bd9Sstevel@tonic-gate } 3607c478bd9Sstevel@tonic-gate debug(5, "sector size = 0x%x(%d)\n", 3617c478bd9Sstevel@tonic-gate sector_size, sector_size); 3627c478bd9Sstevel@tonic-gate return (sector_size); 3637c478bd9Sstevel@tonic-gate } 3647c478bd9Sstevel@tonic-gate 3657c478bd9Sstevel@tonic-gate static char * 3667c478bd9Sstevel@tonic-gate xlate_state(int32_t state) 3677c478bd9Sstevel@tonic-gate { 3687c478bd9Sstevel@tonic-gate switch (state) { 3697c478bd9Sstevel@tonic-gate 3707c478bd9Sstevel@tonic-gate case SM_WRITE_PROTECT_DISABLE: 3717c478bd9Sstevel@tonic-gate return ("PROTECTION_DISABLED"); 3727c478bd9Sstevel@tonic-gate case SM_WRITE_PROTECT_PASSWD: 3737c478bd9Sstevel@tonic-gate return ("WRITE_PROTECT_PASSWD"); 3747c478bd9Sstevel@tonic-gate case SM_WRITE_PROTECT_NOPASSWD: 3757c478bd9Sstevel@tonic-gate return ("WRITE_PROTECT_NOPASSWD"); 3767c478bd9Sstevel@tonic-gate case SM_READ_WRITE_PROTECT: 3777c478bd9Sstevel@tonic-gate return ("READ_WRITE_PROTECT"); 3787c478bd9Sstevel@tonic-gate case SM_TEMP_UNLOCK_MODE: 3797c478bd9Sstevel@tonic-gate return ("PROTECTION DISABLED"); 3807c478bd9Sstevel@tonic-gate default: 3817c478bd9Sstevel@tonic-gate return ("UNKNOWN_STATE"); 3827c478bd9Sstevel@tonic-gate } 3837c478bd9Sstevel@tonic-gate } 3847c478bd9Sstevel@tonic-gate 3857c478bd9Sstevel@tonic-gate static char * 3867c478bd9Sstevel@tonic-gate xlate_cnum(smedia_callnumber_t cnum) 3877c478bd9Sstevel@tonic-gate { 3887c478bd9Sstevel@tonic-gate switch (cnum) { 3897c478bd9Sstevel@tonic-gate 3907c478bd9Sstevel@tonic-gate case SMEDIA_CNUM_OPEN_FD: 3917c478bd9Sstevel@tonic-gate return ("SMEDIA_CNUM_OPEN_FD"); 3927c478bd9Sstevel@tonic-gate case SMEDIA_CNUM_GET_DEVICE_INFO: 3937c478bd9Sstevel@tonic-gate return ("SMEDIA_CNUM_GET_DEVICE_INFO"); 3947c478bd9Sstevel@tonic-gate case SMEDIA_CNUM_GET_MEDIUM_PROPERTY: 3957c478bd9Sstevel@tonic-gate return ("SMEDIA_CNUM_GET_MEDIUM_PROPERTY"); 3967c478bd9Sstevel@tonic-gate case SMEDIA_CNUM_GET_PROTECTION_STATUS: 3977c478bd9Sstevel@tonic-gate return ("SMEDIA_CNUM_GET_PROTECTION_STATUS"); 3987c478bd9Sstevel@tonic-gate case SMEDIA_CNUM_SET_PROTECTION_STATUS: 3997c478bd9Sstevel@tonic-gate return ("SMEDIA_CNUM_SET_PROTECTION_STATUS"); 4007c478bd9Sstevel@tonic-gate case SMEDIA_CNUM_RAW_READ: 4017c478bd9Sstevel@tonic-gate return ("SMEDIA_CNUM_RAW_READ"); 4027c478bd9Sstevel@tonic-gate case SMEDIA_CNUM_RAW_WRITE: 4037c478bd9Sstevel@tonic-gate return (" SMEDIA_CNUM_RAW_WRITE"); 4047c478bd9Sstevel@tonic-gate case SMEDIA_CNUM_FORMAT: 4057c478bd9Sstevel@tonic-gate return ("SMEDIA_CNUM_FORMAT"); 4067c478bd9Sstevel@tonic-gate case SMEDIA_CNUM_CHECK_FORMAT_STATUS: 4077c478bd9Sstevel@tonic-gate return ("SMEDIA_CNUM_CHECK_FORMAT_STATUS"); 4087c478bd9Sstevel@tonic-gate case SMEDIA_CNUM_EJECT: 4097c478bd9Sstevel@tonic-gate return ("SMEDIA_CNUM_EJECT"); 4107c478bd9Sstevel@tonic-gate case SMEDIA_CNUM_REASSIGN_BLOCK: 4117c478bd9Sstevel@tonic-gate return ("SMEDIA_CNUM_REASSIGN_BLOCK"); 4127c478bd9Sstevel@tonic-gate case SMEDIA_CNUM_SET_SHFD: 4137c478bd9Sstevel@tonic-gate return ("SMEDIA_CNUM_SET_SHFD"); 4147c478bd9Sstevel@tonic-gate case SMEDIA_CNUM_PING: 4157c478bd9Sstevel@tonic-gate return ("SMEDIA_CNUM_PING"); 4167c478bd9Sstevel@tonic-gate case SMEDIA_CNUM_USCSI_CMD: 4177c478bd9Sstevel@tonic-gate return ("SMEDIA_CNUM_USCSI_CMD"); 4187c478bd9Sstevel@tonic-gate default: 4197c478bd9Sstevel@tonic-gate return ("UNKNOWN_CNUM"); 4207c478bd9Sstevel@tonic-gate } 4217c478bd9Sstevel@tonic-gate } 4227c478bd9Sstevel@tonic-gate 4237c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 4247c478bd9Sstevel@tonic-gate smserver_info * 4257c478bd9Sstevel@tonic-gate smserverproc_get_serverinfo_1(void *argp, CLIENT *clnt) 4267c478bd9Sstevel@tonic-gate { 4277c478bd9Sstevel@tonic-gate (void) mutex_lock(&svcstate_lock); 4287c478bd9Sstevel@tonic-gate svcstate = _SERVED; 4297c478bd9Sstevel@tonic-gate (void) mutex_unlock(&svcstate_lock); 4307c478bd9Sstevel@tonic-gate server_info.vernum = SMSERVERVERS; 4317c478bd9Sstevel@tonic-gate server_info.status = 0; 4327c478bd9Sstevel@tonic-gate (void) mutex_lock(&server_data.sd_init_lock); 4337c478bd9Sstevel@tonic-gate if (server_data.sd_init_state == INIT_NOT_DONE) { 4347c478bd9Sstevel@tonic-gate server_data.sd_init_state = INIT_IN_PROGRESS; 4357c478bd9Sstevel@tonic-gate debug(5, "Initialising server\n"); 4367c478bd9Sstevel@tonic-gate (void) init_server(NULL); 4377c478bd9Sstevel@tonic-gate } 4387c478bd9Sstevel@tonic-gate if (server_data.sd_init_state != INIT_DONE) { 4395363f09cSarutz debug(1, "init_server did not do the job. " 4405363f09cSarutz "init_state=%d\n", server_data.sd_init_state); 4417c478bd9Sstevel@tonic-gate server_data.sd_init_state = INIT_NOT_DONE; 4427c478bd9Sstevel@tonic-gate (void) mutex_unlock(&server_data.sd_init_lock); 4437c478bd9Sstevel@tonic-gate server_info.status = -1; 4447c478bd9Sstevel@tonic-gate return (&server_info); 4457c478bd9Sstevel@tonic-gate } 4467c478bd9Sstevel@tonic-gate (void) mutex_unlock(&server_data.sd_init_lock); 4477c478bd9Sstevel@tonic-gate 4487c478bd9Sstevel@tonic-gate debug(5, "smserverproc thread %d running....\n", pthread_self()); 4497c478bd9Sstevel@tonic-gate return (&server_info); 4507c478bd9Sstevel@tonic-gate } 4517c478bd9Sstevel@tonic-gate 4527c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 4537c478bd9Sstevel@tonic-gate static void 4547c478bd9Sstevel@tonic-gate server_badsig_handler(int sig, siginfo_t *siginfo, void *sigctx) 4557c478bd9Sstevel@tonic-gate { 4567c478bd9Sstevel@tonic-gate 4577c478bd9Sstevel@tonic-gate fatal(gettext(BADSIG_MSG), pthread_self(), sig, siginfo->si_addr, 4587c478bd9Sstevel@tonic-gate siginfo->si_trapno, 4597c478bd9Sstevel@tonic-gate siginfo->si_pc); 4607c478bd9Sstevel@tonic-gate } 4617c478bd9Sstevel@tonic-gate 4627c478bd9Sstevel@tonic-gate static int32_t 4637c478bd9Sstevel@tonic-gate do_uscsi_cmd(int32_t file, struct uscsi_cmd *uscsi_cmd, int32_t flag) 4647c478bd9Sstevel@tonic-gate { 4657c478bd9Sstevel@tonic-gate int32_t ret_val; 4667c478bd9Sstevel@tonic-gate 4677c478bd9Sstevel@tonic-gate /* 4687c478bd9Sstevel@tonic-gate * Set function flags for driver. 4697c478bd9Sstevel@tonic-gate */ 4707c478bd9Sstevel@tonic-gate uscsi_cmd->uscsi_flags = USCSI_ISOLATE; 4717c478bd9Sstevel@tonic-gate 4727c478bd9Sstevel@tonic-gate #ifdef DEBUG 4737c478bd9Sstevel@tonic-gate uscsi_cmd->uscsi_flags |= USCSI_DIAGNOSE; 4747c478bd9Sstevel@tonic-gate #else 4757c478bd9Sstevel@tonic-gate uscsi_cmd->uscsi_flags |= USCSI_SILENT; 4767c478bd9Sstevel@tonic-gate #endif /* DEBUG */ 4777c478bd9Sstevel@tonic-gate 4787c478bd9Sstevel@tonic-gate uscsi_cmd->uscsi_flags |= flag; 4797c478bd9Sstevel@tonic-gate 4807c478bd9Sstevel@tonic-gate errno = 0; 4817c478bd9Sstevel@tonic-gate ret_val = ioctl(file, USCSICMD, uscsi_cmd); 4827c478bd9Sstevel@tonic-gate if (ret_val == 0 && uscsi_cmd->uscsi_status == 0) { 4837c478bd9Sstevel@tonic-gate return (ret_val); 4847c478bd9Sstevel@tonic-gate } 4857c478bd9Sstevel@tonic-gate if (!errno) 4867c478bd9Sstevel@tonic-gate errno = EIO; 4877c478bd9Sstevel@tonic-gate return (-1); 4887c478bd9Sstevel@tonic-gate } 4897c478bd9Sstevel@tonic-gate 4907c478bd9Sstevel@tonic-gate static int32_t 4917c478bd9Sstevel@tonic-gate get_device_type(char *v_name) 4927c478bd9Sstevel@tonic-gate { 4937c478bd9Sstevel@tonic-gate int32_t i; 4947c478bd9Sstevel@tonic-gate 4957c478bd9Sstevel@tonic-gate for (i = 0; i < 8; i++) { 4967c478bd9Sstevel@tonic-gate v_name[i] = toupper(v_name[i]); 4977c478bd9Sstevel@tonic-gate } 4987c478bd9Sstevel@tonic-gate if (strstr(v_name, "IOMEGA")) { 4997c478bd9Sstevel@tonic-gate return (SCSI_IOMEGA); 5007c478bd9Sstevel@tonic-gate } 5017c478bd9Sstevel@tonic-gate if (strstr(v_name, "FD") || 5027c478bd9Sstevel@tonic-gate strstr(v_name, "LS-120")) { 5037c478bd9Sstevel@tonic-gate return (SCSI_FLOPPY); 5047c478bd9Sstevel@tonic-gate } 5057c478bd9Sstevel@tonic-gate return (SCSI_GENERIC); 5067c478bd9Sstevel@tonic-gate 5077c478bd9Sstevel@tonic-gate } 5087c478bd9Sstevel@tonic-gate 5097c478bd9Sstevel@tonic-gate static int32_t 5107c478bd9Sstevel@tonic-gate get_device_type_scsi(int32_t fd, struct scsi_inquiry *inq) 5117c478bd9Sstevel@tonic-gate { 5127c478bd9Sstevel@tonic-gate int32_t dev_type; 5137c478bd9Sstevel@tonic-gate struct uscsi_cmd ucmd; 5147c478bd9Sstevel@tonic-gate union scsi_cdb cdb; 5157c478bd9Sstevel@tonic-gate int32_t ret_val; 5167c478bd9Sstevel@tonic-gate char rq_data[RQ_LEN]; 5177c478bd9Sstevel@tonic-gate 5187c478bd9Sstevel@tonic-gate (void) memset((void *) inq, 0, sizeof (struct scsi_inquiry)); 5197c478bd9Sstevel@tonic-gate (void) memset((void *) &ucmd, 0, sizeof (ucmd)); 5207c478bd9Sstevel@tonic-gate (void) memset((void *) &cdb, 0, sizeof (union scsi_cdb)); 5217c478bd9Sstevel@tonic-gate cdb.scc_cmd = SCMD_INQUIRY; 5227c478bd9Sstevel@tonic-gate FORMG0COUNT(&cdb, sizeof (struct scsi_inquiry)); 5237c478bd9Sstevel@tonic-gate ucmd.uscsi_cdb = (caddr_t)&cdb; 5247c478bd9Sstevel@tonic-gate ucmd.uscsi_cdblen = CDB_GROUP0; 5257c478bd9Sstevel@tonic-gate ucmd.uscsi_bufaddr = (caddr_t)inq; 5267c478bd9Sstevel@tonic-gate ucmd.uscsi_buflen = sizeof (struct scsi_inquiry); 5277c478bd9Sstevel@tonic-gate ucmd.uscsi_timeout = 120; /* If 0, HBA hangs forever */ 5287c478bd9Sstevel@tonic-gate ucmd.uscsi_rqlen = RQ_LEN; 5297c478bd9Sstevel@tonic-gate ucmd.uscsi_rqbuf = rq_data; 5307c478bd9Sstevel@tonic-gate ret_val = do_uscsi_cmd(fd, &ucmd, USCSI_READ|USCSI_RQENABLE); 5317c478bd9Sstevel@tonic-gate if (ret_val || ucmd.uscsi_status) { 5325363f09cSarutz debug(5, "INQUIRY failed: rv = %d uscsi_status = " 5335363f09cSarutz "%d errno = %d\n", ret_val, ucmd.uscsi_status, errno); 5347c478bd9Sstevel@tonic-gate return (-1); 5357c478bd9Sstevel@tonic-gate } 5367c478bd9Sstevel@tonic-gate 5377c478bd9Sstevel@tonic-gate dev_type = get_device_type(inq->inq_vid); 5387c478bd9Sstevel@tonic-gate 5397c478bd9Sstevel@tonic-gate debug(5, "dev_type %d\n", dev_type); 5407c478bd9Sstevel@tonic-gate return (dev_type); 5417c478bd9Sstevel@tonic-gate 5427c478bd9Sstevel@tonic-gate } 5437c478bd9Sstevel@tonic-gate 5447c478bd9Sstevel@tonic-gate static int32_t 5457c478bd9Sstevel@tonic-gate get_media_capacity(int32_t fd, uint32_t *capacity, uint32_t *blocksize) 5467c478bd9Sstevel@tonic-gate { 5477c478bd9Sstevel@tonic-gate struct uscsi_cmd ucmd; 5487c478bd9Sstevel@tonic-gate uchar_t cdb[12]; 5497c478bd9Sstevel@tonic-gate int32_t ret_val; 5507c478bd9Sstevel@tonic-gate uchar_t data[20]; 5517c478bd9Sstevel@tonic-gate char rq_data[RQ_LEN]; 5527c478bd9Sstevel@tonic-gate 5537c478bd9Sstevel@tonic-gate debug(5, "get_media_capacity:\n"); 5547c478bd9Sstevel@tonic-gate 5557c478bd9Sstevel@tonic-gate (void) memset((void *)&data, 0, sizeof (data)); 5567c478bd9Sstevel@tonic-gate (void) memset((void *)&ucmd, 0, sizeof (ucmd)); 5577c478bd9Sstevel@tonic-gate (void) memset((void *)&cdb, 0, sizeof (cdb)); 5587c478bd9Sstevel@tonic-gate 5597c478bd9Sstevel@tonic-gate /* retrieve size discriptor of inserted media */ 5607c478bd9Sstevel@tonic-gate cdb[0] = SCMD_READ_FORMAT_CAP; 5617c478bd9Sstevel@tonic-gate cdb[8] = 0x14; /* data size */ 5627c478bd9Sstevel@tonic-gate 5637c478bd9Sstevel@tonic-gate /* Fill in the USCSI fields */ 5647c478bd9Sstevel@tonic-gate ucmd.uscsi_cdb = (caddr_t)&cdb; 5657c478bd9Sstevel@tonic-gate ucmd.uscsi_cdblen = CDB_GROUP5; 5667c478bd9Sstevel@tonic-gate ucmd.uscsi_bufaddr = (caddr_t)data; 5677c478bd9Sstevel@tonic-gate ucmd.uscsi_buflen = sizeof (data); 5687c478bd9Sstevel@tonic-gate ucmd.uscsi_timeout = 120; 5697c478bd9Sstevel@tonic-gate ucmd.uscsi_rqlen = RQ_LEN; 5707c478bd9Sstevel@tonic-gate ucmd.uscsi_rqbuf = rq_data; 5717c478bd9Sstevel@tonic-gate ret_val = do_uscsi_cmd(fd, &ucmd, USCSI_READ|USCSI_RQENABLE); 5727c478bd9Sstevel@tonic-gate 5737c478bd9Sstevel@tonic-gate if (ret_val || ucmd.uscsi_status) { 5747c478bd9Sstevel@tonic-gate debug(5, "Retrieving media info failed: %d - %d\n", ret_val, 5757c478bd9Sstevel@tonic-gate ucmd.uscsi_status); 5767c478bd9Sstevel@tonic-gate 5777c478bd9Sstevel@tonic-gate if ((rq_data[2] == KEY_DATA_PROTECT) && (rq_data[12] == 0x30) && 5787c478bd9Sstevel@tonic-gate (rq_data[13] == 0)) { 5797c478bd9Sstevel@tonic-gate (void) debug(1, "Invalid command for media\n"); 5807c478bd9Sstevel@tonic-gate errno = EINVAL; 5817c478bd9Sstevel@tonic-gate } 5827c478bd9Sstevel@tonic-gate return (-1); 5837c478bd9Sstevel@tonic-gate } 5847c478bd9Sstevel@tonic-gate 5857c478bd9Sstevel@tonic-gate /* No media, bail out */ 5867c478bd9Sstevel@tonic-gate if (data[8] == 0x3) { 5877c478bd9Sstevel@tonic-gate (void) debug(5, "no media in drive\n"); 5887c478bd9Sstevel@tonic-gate return (-1); 5897c478bd9Sstevel@tonic-gate } 5907c478bd9Sstevel@tonic-gate 5917c478bd9Sstevel@tonic-gate /* 5927c478bd9Sstevel@tonic-gate * Generate capacity and blocksize information 5937c478bd9Sstevel@tonic-gate */ 5947c478bd9Sstevel@tonic-gate 5957c478bd9Sstevel@tonic-gate *capacity = (uint32_t)((data[4] << 24) + (data[5] << 16) + 5967c478bd9Sstevel@tonic-gate (data[6] << 8) + data[7]); 5977c478bd9Sstevel@tonic-gate 5987c478bd9Sstevel@tonic-gate debug(1, "capacity is %x %x %x %x = %x", data[4], data[5], data[6], 5997c478bd9Sstevel@tonic-gate data[7], *capacity); 6007c478bd9Sstevel@tonic-gate 6017c478bd9Sstevel@tonic-gate *blocksize = (uint32_t)((data[9] << 16) + (data[10] << 8) + data[11]); 6027c478bd9Sstevel@tonic-gate 6037c478bd9Sstevel@tonic-gate return (0); 6047c478bd9Sstevel@tonic-gate } 6057c478bd9Sstevel@tonic-gate 6067c478bd9Sstevel@tonic-gate static int32_t 6077c478bd9Sstevel@tonic-gate scsi_zip_format(int32_t fd, uint_t flavor, uint_t mode) 6087c478bd9Sstevel@tonic-gate { 6097c478bd9Sstevel@tonic-gate struct uscsi_cmd ucmd; 6107c478bd9Sstevel@tonic-gate struct scsi_inquiry inq; 6117c478bd9Sstevel@tonic-gate uchar_t cdb[12]; 6127c478bd9Sstevel@tonic-gate int32_t ret_val; 6137c478bd9Sstevel@tonic-gate uchar_t data[4]; 6147c478bd9Sstevel@tonic-gate uint32_t rc_data[2]; 6157c478bd9Sstevel@tonic-gate char rq_data[RQ_LEN]; 6167c478bd9Sstevel@tonic-gate uint32_t capacity; 6177c478bd9Sstevel@tonic-gate 6187c478bd9Sstevel@tonic-gate 6197c478bd9Sstevel@tonic-gate if ((mode != SM_FORMAT_IMMEDIATE) && 6207c478bd9Sstevel@tonic-gate (mode != SM_FORMAT_BLOCKED)) { 6217c478bd9Sstevel@tonic-gate errno = ENOTSUP; 6227c478bd9Sstevel@tonic-gate return (ENOTSUP); 6237c478bd9Sstevel@tonic-gate } 6247c478bd9Sstevel@tonic-gate /* 6257c478bd9Sstevel@tonic-gate * Do an inquiry and try to figure out if it an 6267c478bd9Sstevel@tonic-gate * IOMEGA JAZ 2GB device. 6277c478bd9Sstevel@tonic-gate */ 6287c478bd9Sstevel@tonic-gate 6297c478bd9Sstevel@tonic-gate (void) memset((void *) &inq, 0, sizeof (inq)); 6307c478bd9Sstevel@tonic-gate (void) memset((void *) &ucmd, 0, sizeof (ucmd)); 6317c478bd9Sstevel@tonic-gate (void) memset((void *) &cdb, 0, sizeof (cdb)); 6327c478bd9Sstevel@tonic-gate (void) memset((void *) &rq_data, 0, sizeof (rq_data)); 6337c478bd9Sstevel@tonic-gate cdb[0] = SCMD_INQUIRY; 6347c478bd9Sstevel@tonic-gate cdb[4] = sizeof (inq); 6357c478bd9Sstevel@tonic-gate ucmd.uscsi_cdb = (caddr_t)&cdb; 6367c478bd9Sstevel@tonic-gate ucmd.uscsi_cdblen = CDB_GROUP0; 6377c478bd9Sstevel@tonic-gate ucmd.uscsi_bufaddr = (caddr_t)&inq; 6387c478bd9Sstevel@tonic-gate ucmd.uscsi_buflen = sizeof (inq); 6397c478bd9Sstevel@tonic-gate ucmd.uscsi_timeout = 120; /* If 0, HBA hangs forever */ 6407c478bd9Sstevel@tonic-gate ucmd.uscsi_rqlen = RQ_LEN; 6417c478bd9Sstevel@tonic-gate ucmd.uscsi_rqbuf = rq_data; 6427c478bd9Sstevel@tonic-gate ret_val = do_uscsi_cmd(fd, &ucmd, USCSI_READ|USCSI_RQENABLE); 6437c478bd9Sstevel@tonic-gate if (ret_val || ucmd.uscsi_status) { 6447c478bd9Sstevel@tonic-gate debug(5, "inquiry failed: %d - %d errno = %d\n", 6457c478bd9Sstevel@tonic-gate ret_val, ucmd.uscsi_status, errno); 6467c478bd9Sstevel@tonic-gate return (ucmd.uscsi_status); 6477c478bd9Sstevel@tonic-gate } 6487c478bd9Sstevel@tonic-gate 6497c478bd9Sstevel@tonic-gate (void) memset((void *) &rc_data, 0, sizeof (rc_data)); 6507c478bd9Sstevel@tonic-gate (void) memset((void *) &ucmd, 0, sizeof (ucmd)); 6517c478bd9Sstevel@tonic-gate (void) memset((void *) &cdb, 0, sizeof (cdb)); 6527c478bd9Sstevel@tonic-gate cdb[0] = SCMD_READ_CAPACITY; 6537c478bd9Sstevel@tonic-gate ucmd.uscsi_cdb = (caddr_t)&cdb; 6547c478bd9Sstevel@tonic-gate ucmd.uscsi_cdblen = CDB_GROUP1; 6557c478bd9Sstevel@tonic-gate ucmd.uscsi_bufaddr = (caddr_t)&rc_data; 6567c478bd9Sstevel@tonic-gate ucmd.uscsi_buflen = sizeof (rc_data); 6577c478bd9Sstevel@tonic-gate ucmd.uscsi_timeout = 120; /* If 0, HBA hangs forever */ 6587c478bd9Sstevel@tonic-gate 6597c478bd9Sstevel@tonic-gate ret_val = do_uscsi_cmd(fd, &ucmd, USCSI_READ); 6607c478bd9Sstevel@tonic-gate if (ret_val || ucmd.uscsi_status) { 6617c478bd9Sstevel@tonic-gate debug(5, "Read capacity : %d - %d errno = %d\n", 6627c478bd9Sstevel@tonic-gate ret_val, ucmd.uscsi_status, errno); 6637c478bd9Sstevel@tonic-gate return (ucmd.uscsi_status); 6647c478bd9Sstevel@tonic-gate } 6657c478bd9Sstevel@tonic-gate 6667c478bd9Sstevel@tonic-gate capacity = ntohl(rc_data[0]); 6677c478bd9Sstevel@tonic-gate 6687c478bd9Sstevel@tonic-gate (void) memset((void *)&data, 0, sizeof (data)); 6697c478bd9Sstevel@tonic-gate (void) memset((void *)&ucmd, 0, sizeof (ucmd)); 6707c478bd9Sstevel@tonic-gate (void) memset((void *)&cdb, 0, sizeof (cdb)); 6717c478bd9Sstevel@tonic-gate cdb[0] = SCMD_FORMAT; 6727c478bd9Sstevel@tonic-gate /* 6737c478bd9Sstevel@tonic-gate * Defect list sent by initiator is a complete list of defects. 6747c478bd9Sstevel@tonic-gate */ 6757c478bd9Sstevel@tonic-gate cdb[1] = (FMTDATA | CMPLIST); 6767c478bd9Sstevel@tonic-gate /* 6777c478bd9Sstevel@tonic-gate * Target should examine the setting of the DPRY, DCRT, STPF, IP 6787c478bd9Sstevel@tonic-gate * and DSP bits. 6797c478bd9Sstevel@tonic-gate */ 6807c478bd9Sstevel@tonic-gate data[1] = FOV; 6817c478bd9Sstevel@tonic-gate 6827c478bd9Sstevel@tonic-gate switch (flavor) { 6837c478bd9Sstevel@tonic-gate case SM_FORMAT_QUICK : 6847c478bd9Sstevel@tonic-gate /* 6857c478bd9Sstevel@tonic-gate * Target should not perform any vendor specific 6867c478bd9Sstevel@tonic-gate * medium certification process or format verification 6877c478bd9Sstevel@tonic-gate */ 6887c478bd9Sstevel@tonic-gate data[1] = (FOV | DCRT); 6897c478bd9Sstevel@tonic-gate /* 6907c478bd9Sstevel@tonic-gate * Defect list sent is an addition to the existing 6917c478bd9Sstevel@tonic-gate * list of defects. 6927c478bd9Sstevel@tonic-gate */ 6937c478bd9Sstevel@tonic-gate cdb[1] = FMTDATA; 6947c478bd9Sstevel@tonic-gate break; 6957c478bd9Sstevel@tonic-gate case SM_FORMAT_FORCE : 6967c478bd9Sstevel@tonic-gate if (strstr(inq.inq_pid, "jaz")) { 6977c478bd9Sstevel@tonic-gate debug(1, 6987c478bd9Sstevel@tonic-gate "LONG Format of JAZ media not supported\n"); 6997c478bd9Sstevel@tonic-gate errno = ENOTSUP; 7007c478bd9Sstevel@tonic-gate return (ENOTSUP); 7017c478bd9Sstevel@tonic-gate } 7027c478bd9Sstevel@tonic-gate /* 7037c478bd9Sstevel@tonic-gate * Formatting a write-protected or read/write 7047c478bd9Sstevel@tonic-gate * protected cartridge is allowed. 7057c478bd9Sstevel@tonic-gate * This is a vendor specific Format Option. 7067c478bd9Sstevel@tonic-gate */ 7077c478bd9Sstevel@tonic-gate cdb[2] = 0x20; 7087c478bd9Sstevel@tonic-gate break; 7097c478bd9Sstevel@tonic-gate case SM_FORMAT_LONG : 7107c478bd9Sstevel@tonic-gate if (strstr(inq.inq_pid, "jaz")) { 7117c478bd9Sstevel@tonic-gate debug(1, 7127c478bd9Sstevel@tonic-gate "LONG Format of JAZ media not supported\n"); 7137c478bd9Sstevel@tonic-gate errno = ENOTSUP; 7147c478bd9Sstevel@tonic-gate return (ENOTSUP); 7157c478bd9Sstevel@tonic-gate } 7167c478bd9Sstevel@tonic-gate /* 7177c478bd9Sstevel@tonic-gate * Defect list sent is an addition to the existing 7187c478bd9Sstevel@tonic-gate * list of defects. 7197c478bd9Sstevel@tonic-gate */ 7207c478bd9Sstevel@tonic-gate cdb[1] = FMTDATA; 7217c478bd9Sstevel@tonic-gate break; 7227c478bd9Sstevel@tonic-gate default : 7237c478bd9Sstevel@tonic-gate debug(1, "Format option %d not supported!!\n", 7247c478bd9Sstevel@tonic-gate flavor); 7257c478bd9Sstevel@tonic-gate errno = ENOTSUP; 7267c478bd9Sstevel@tonic-gate return (ENOTSUP); 7277c478bd9Sstevel@tonic-gate } 7287c478bd9Sstevel@tonic-gate 7297c478bd9Sstevel@tonic-gate if (mode == SM_FORMAT_IMMEDIATE) { 7307c478bd9Sstevel@tonic-gate data[1] |= IMMED; 7317c478bd9Sstevel@tonic-gate debug(5, "immediate_flag set\n"); 7327c478bd9Sstevel@tonic-gate } 7337c478bd9Sstevel@tonic-gate 7347c478bd9Sstevel@tonic-gate ucmd.uscsi_cdb = (caddr_t)&cdb; 7357c478bd9Sstevel@tonic-gate debug(5, "cdb: %x ", cdb[0]); 7367c478bd9Sstevel@tonic-gate debug(5, "%x %x ", cdb[1], cdb[2]); 7377c478bd9Sstevel@tonic-gate debug(5, "%x %x %x\n", cdb[3], cdb[4], cdb[5]); 7387c478bd9Sstevel@tonic-gate debug(5, "data: %x %x %x %x\n", data[0], data[1], data[2], data[3]); 7397c478bd9Sstevel@tonic-gate 7407c478bd9Sstevel@tonic-gate ucmd.uscsi_cdblen = CDB_GROUP0; 7417c478bd9Sstevel@tonic-gate ucmd.uscsi_bufaddr = (caddr_t)data; 7427c478bd9Sstevel@tonic-gate ucmd.uscsi_buflen = sizeof (data); 7437c478bd9Sstevel@tonic-gate ucmd.uscsi_timeout = FORMAT_TIMEOUT(capacity); 7447c478bd9Sstevel@tonic-gate ucmd.uscsi_rqlen = RQ_LEN; 7457c478bd9Sstevel@tonic-gate ucmd.uscsi_rqbuf = rq_data; 7467c478bd9Sstevel@tonic-gate ret_val = do_uscsi_cmd(fd, &ucmd, USCSI_WRITE|USCSI_RQENABLE); 7477c478bd9Sstevel@tonic-gate if (ret_val || ucmd.uscsi_status) { 7487c478bd9Sstevel@tonic-gate debug(5, "Format failed : %d - uscsi_status = %d errno = %d\n", 7497c478bd9Sstevel@tonic-gate ret_val, 7507c478bd9Sstevel@tonic-gate ucmd.uscsi_status, errno); 7517c478bd9Sstevel@tonic-gate if ((rq_data[2] == KEY_DATA_PROTECT) || 7527c478bd9Sstevel@tonic-gate (rq_data[2] == KEY_ILLEGAL_REQUEST)) 7537c478bd9Sstevel@tonic-gate errno = EINVAL; 7547c478bd9Sstevel@tonic-gate if ((rq_data[2] == KEY_MEDIUM_ERROR) || 7557c478bd9Sstevel@tonic-gate (rq_data[2] == KEY_HARDWARE_ERROR)) 7567c478bd9Sstevel@tonic-gate errno = EIO; 7577c478bd9Sstevel@tonic-gate return (errno); 7587c478bd9Sstevel@tonic-gate } 7597c478bd9Sstevel@tonic-gate 7607c478bd9Sstevel@tonic-gate return (0); 7617c478bd9Sstevel@tonic-gate } 7627c478bd9Sstevel@tonic-gate 7637c478bd9Sstevel@tonic-gate static int32_t 7647c478bd9Sstevel@tonic-gate scsi_ls120_format(uint_t fd, uint_t flavor, uint32_t capacity, 7657c478bd9Sstevel@tonic-gate uint32_t blocksize) 7667c478bd9Sstevel@tonic-gate { 7677c478bd9Sstevel@tonic-gate struct uscsi_cmd ucmd; 7687c478bd9Sstevel@tonic-gate uchar_t cdb[12]; 7697c478bd9Sstevel@tonic-gate int32_t ret_val; 7707c478bd9Sstevel@tonic-gate uchar_t data[12]; 7717c478bd9Sstevel@tonic-gate char rq_data[RQ_LEN]; 7727c478bd9Sstevel@tonic-gate 7737c478bd9Sstevel@tonic-gate debug(5, "scsi_ls120_format:\n"); 7747c478bd9Sstevel@tonic-gate 7757c478bd9Sstevel@tonic-gate (void) memset((void *) &ucmd, 0, sizeof (ucmd)); 7767c478bd9Sstevel@tonic-gate (void) memset((void *) &cdb, 0, sizeof (cdb)); 7777c478bd9Sstevel@tonic-gate (void) memset((void *) &rq_data, 0, sizeof (rq_data)); 7787c478bd9Sstevel@tonic-gate 7797c478bd9Sstevel@tonic-gate cdb[0] = SCMD_FORMAT; 7807c478bd9Sstevel@tonic-gate cdb[1] = (FMTDATA | 0x7); 7817c478bd9Sstevel@tonic-gate cdb[8] = 0x0C; /* parameter list length */ 7827c478bd9Sstevel@tonic-gate 7837c478bd9Sstevel@tonic-gate data[1] = 0x80; 7847c478bd9Sstevel@tonic-gate data[3] = 0x08; 7857c478bd9Sstevel@tonic-gate 7867c478bd9Sstevel@tonic-gate 7877c478bd9Sstevel@tonic-gate data[4] = (capacity >> 24) & 0xff; 7887c478bd9Sstevel@tonic-gate data[5] = (capacity >> 16) & 0xff; 7897c478bd9Sstevel@tonic-gate data[6] = (capacity >> 8) & 0xff; 7907c478bd9Sstevel@tonic-gate data[7] = capacity & 0xff; 7917c478bd9Sstevel@tonic-gate 7927c478bd9Sstevel@tonic-gate 7937c478bd9Sstevel@tonic-gate data[9] = (blocksize >> 16) & 0xff; 7947c478bd9Sstevel@tonic-gate data[10] = (blocksize >> 8) & 0xff; 7957c478bd9Sstevel@tonic-gate data[11] = blocksize & 0xff; 7967c478bd9Sstevel@tonic-gate 7977c478bd9Sstevel@tonic-gate debug(5, "cdb: %x %x %x ... %x", cdb[0], cdb[1], cdb[2], cdb[8]); 7987c478bd9Sstevel@tonic-gate debug(5, "data: %x %x %x %x\n", data[0], data[1], data[2], data[3]); 7997c478bd9Sstevel@tonic-gate debug(5, " : %x %x %x %x\n", data[4], data[5], data[6], data[7]); 8007c478bd9Sstevel@tonic-gate debug(5, " : %x %x %x %x\n", data[8], data[9], data[10], data[11]); 8017c478bd9Sstevel@tonic-gate 8027c478bd9Sstevel@tonic-gate switch (flavor) { 8037c478bd9Sstevel@tonic-gate case SM_FORMAT_QUICK : 8047c478bd9Sstevel@tonic-gate debug(1, "Format not supported\n"); 8057c478bd9Sstevel@tonic-gate errno = ENOTSUP; 8067c478bd9Sstevel@tonic-gate return (-1); 8077c478bd9Sstevel@tonic-gate case SM_FORMAT_FORCE : 8087c478bd9Sstevel@tonic-gate break; 8097c478bd9Sstevel@tonic-gate case SM_FORMAT_LONG : 8107c478bd9Sstevel@tonic-gate break; 8117c478bd9Sstevel@tonic-gate default : 8127c478bd9Sstevel@tonic-gate debug(1, "Format option not specified!!\n"); 8137c478bd9Sstevel@tonic-gate errno = ENOTSUP; 8147c478bd9Sstevel@tonic-gate return (-1); 8157c478bd9Sstevel@tonic-gate } 8167c478bd9Sstevel@tonic-gate 8177c478bd9Sstevel@tonic-gate ucmd.uscsi_cdb = (caddr_t)&cdb; 8187c478bd9Sstevel@tonic-gate 8197c478bd9Sstevel@tonic-gate 8207c478bd9Sstevel@tonic-gate ucmd.uscsi_cdblen = CDB_GROUP5; 8217c478bd9Sstevel@tonic-gate ucmd.uscsi_bufaddr = (caddr_t)data; 8227c478bd9Sstevel@tonic-gate ucmd.uscsi_buflen = sizeof (data); 8237c478bd9Sstevel@tonic-gate ucmd.uscsi_timeout = 0x12c0; 8247c478bd9Sstevel@tonic-gate ucmd.uscsi_rqlen = RQ_LEN; 8257c478bd9Sstevel@tonic-gate ucmd.uscsi_rqbuf = rq_data; 8267c478bd9Sstevel@tonic-gate (void) fflush(stdout); 8277c478bd9Sstevel@tonic-gate 8287c478bd9Sstevel@tonic-gate ret_val = do_uscsi_cmd(fd, &ucmd, USCSI_WRITE|USCSI_RQENABLE); 8297c478bd9Sstevel@tonic-gate if (ret_val || ucmd.uscsi_status) { 8307c478bd9Sstevel@tonic-gate debug(1, "Format failed failed: %d - %d\n", ret_val, 8317c478bd9Sstevel@tonic-gate ucmd.uscsi_status); 8327c478bd9Sstevel@tonic-gate 8337c478bd9Sstevel@tonic-gate if ((rq_data[2] == KEY_DATA_PROTECT) && 8347c478bd9Sstevel@tonic-gate (rq_data[12] == 0x30) && (rq_data[13] == 0)) { 8357c478bd9Sstevel@tonic-gate 8367c478bd9Sstevel@tonic-gate debug(1, "Invalid command for media\n"); 8377c478bd9Sstevel@tonic-gate errno = EINVAL; 8387c478bd9Sstevel@tonic-gate } 8397c478bd9Sstevel@tonic-gate 8407c478bd9Sstevel@tonic-gate if ((rq_data[2] == KEY_NOT_READY) && (rq_data[12] == 0x30)) { 8417c478bd9Sstevel@tonic-gate debug(1, "Incompatible media.\n"); 8427c478bd9Sstevel@tonic-gate errno = EINVAL; 8437c478bd9Sstevel@tonic-gate } 8447c478bd9Sstevel@tonic-gate 8457c478bd9Sstevel@tonic-gate return (-1); 8467c478bd9Sstevel@tonic-gate } 8477c478bd9Sstevel@tonic-gate 8487c478bd9Sstevel@tonic-gate return (0); 8497c478bd9Sstevel@tonic-gate } 8507c478bd9Sstevel@tonic-gate 8517c478bd9Sstevel@tonic-gate static int32_t 8527c478bd9Sstevel@tonic-gate scsi_format(int32_t fd, uint_t flavor, uint_t mode) 8537c478bd9Sstevel@tonic-gate { 8547c478bd9Sstevel@tonic-gate struct uscsi_cmd ucmd; 8557c478bd9Sstevel@tonic-gate struct scsi_inquiry inq; 8567c478bd9Sstevel@tonic-gate uchar_t cdb[12]; 8577c478bd9Sstevel@tonic-gate int32_t ret_val; 8587c478bd9Sstevel@tonic-gate uchar_t data[4]; 8597c478bd9Sstevel@tonic-gate char rq_data[RQ_LEN]; 8607c478bd9Sstevel@tonic-gate uint32_t rc_data[2]; 8617c478bd9Sstevel@tonic-gate uint32_t capacity; 8627c478bd9Sstevel@tonic-gate 8637c478bd9Sstevel@tonic-gate 8647c478bd9Sstevel@tonic-gate 8657c478bd9Sstevel@tonic-gate if ((mode != SM_FORMAT_IMMEDIATE) && 8667c478bd9Sstevel@tonic-gate (mode != SM_FORMAT_BLOCKED)) { 8677c478bd9Sstevel@tonic-gate errno = ENOTSUP; 8687c478bd9Sstevel@tonic-gate return (-1); 8697c478bd9Sstevel@tonic-gate } 8707c478bd9Sstevel@tonic-gate 8717c478bd9Sstevel@tonic-gate /* 8727c478bd9Sstevel@tonic-gate * Do an inquiry and try to figure out if it an 8737c478bd9Sstevel@tonic-gate * IOMEGA JAZ 2GB device. 8747c478bd9Sstevel@tonic-gate */ 8757c478bd9Sstevel@tonic-gate 8767c478bd9Sstevel@tonic-gate (void) memset((void *) &inq, 0, sizeof (inq)); 8777c478bd9Sstevel@tonic-gate (void) memset((void *) &ucmd, 0, sizeof (ucmd)); 8787c478bd9Sstevel@tonic-gate (void) memset((void *) &cdb, 0, sizeof (cdb)); 8797c478bd9Sstevel@tonic-gate (void) memset((void *) &rq_data, 0, sizeof (rq_data)); 8807c478bd9Sstevel@tonic-gate cdb[0] = SCMD_INQUIRY; 8817c478bd9Sstevel@tonic-gate cdb[4] = sizeof (inq); 8827c478bd9Sstevel@tonic-gate ucmd.uscsi_cdb = (caddr_t)&cdb; 8837c478bd9Sstevel@tonic-gate ucmd.uscsi_cdblen = CDB_GROUP0; 8847c478bd9Sstevel@tonic-gate ucmd.uscsi_bufaddr = (caddr_t)&inq; 8857c478bd9Sstevel@tonic-gate ucmd.uscsi_buflen = sizeof (inq); 8867c478bd9Sstevel@tonic-gate ucmd.uscsi_timeout = 120; /* If 0, HBA hangs forever */ 8877c478bd9Sstevel@tonic-gate ucmd.uscsi_rqlen = RQ_LEN; 8887c478bd9Sstevel@tonic-gate ucmd.uscsi_rqbuf = rq_data; 8897c478bd9Sstevel@tonic-gate ret_val = do_uscsi_cmd(fd, &ucmd, USCSI_READ|USCSI_RQENABLE); 8907c478bd9Sstevel@tonic-gate if (ret_val || ucmd.uscsi_status) { 8917c478bd9Sstevel@tonic-gate debug(5, "inquiry failed: %d - %d errno = %d\n", 8927c478bd9Sstevel@tonic-gate ret_val, ucmd.uscsi_status, errno); 8937c478bd9Sstevel@tonic-gate return (ucmd.uscsi_status); 8947c478bd9Sstevel@tonic-gate } 8957c478bd9Sstevel@tonic-gate 8967c478bd9Sstevel@tonic-gate (void) memset((void *) &rc_data, 0, sizeof (rc_data)); 8977c478bd9Sstevel@tonic-gate (void) memset((void *) &ucmd, 0, sizeof (ucmd)); 8987c478bd9Sstevel@tonic-gate (void) memset((void *) &cdb, 0, sizeof (cdb)); 8997c478bd9Sstevel@tonic-gate cdb[0] = SCMD_READ_CAPACITY; 9007c478bd9Sstevel@tonic-gate ucmd.uscsi_cdb = (caddr_t)&cdb; 9017c478bd9Sstevel@tonic-gate ucmd.uscsi_cdblen = CDB_GROUP1; 9027c478bd9Sstevel@tonic-gate ucmd.uscsi_bufaddr = (caddr_t)&rc_data; 9037c478bd9Sstevel@tonic-gate ucmd.uscsi_buflen = sizeof (rc_data); 9047c478bd9Sstevel@tonic-gate ucmd.uscsi_timeout = 120; /* If 0, HBA hangs forever */ 9057c478bd9Sstevel@tonic-gate 9067c478bd9Sstevel@tonic-gate ret_val = do_uscsi_cmd(fd, &ucmd, USCSI_READ); 9077c478bd9Sstevel@tonic-gate if (ret_val || ucmd.uscsi_status) { 9087c478bd9Sstevel@tonic-gate debug(5, "Read capacity : %d - %d errno = %d\n", 9097c478bd9Sstevel@tonic-gate ret_val, ucmd.uscsi_status, errno); 9107c478bd9Sstevel@tonic-gate return (ucmd.uscsi_status); 9117c478bd9Sstevel@tonic-gate } 9127c478bd9Sstevel@tonic-gate 9137c478bd9Sstevel@tonic-gate capacity = ntohl(rc_data[0]); 9147c478bd9Sstevel@tonic-gate 9157c478bd9Sstevel@tonic-gate (void) memset((void *)&data, 0, sizeof (data)); 9167c478bd9Sstevel@tonic-gate (void) memset((void *)&ucmd, 0, sizeof (ucmd)); 9177c478bd9Sstevel@tonic-gate (void) memset((void *)&cdb, 0, sizeof (cdb)); 9187c478bd9Sstevel@tonic-gate cdb[0] = SCMD_FORMAT; 9197c478bd9Sstevel@tonic-gate /* 9207c478bd9Sstevel@tonic-gate * Defect list sent is an addition to the existing 9217c478bd9Sstevel@tonic-gate * list of defects. 9227c478bd9Sstevel@tonic-gate */ 9237c478bd9Sstevel@tonic-gate cdb[1] = FMTDATA; 9247c478bd9Sstevel@tonic-gate /* 9257c478bd9Sstevel@tonic-gate * Target should examine the setting of the DPRY, DCRT, STPF, IP 9267c478bd9Sstevel@tonic-gate * and DSP bits. 9277c478bd9Sstevel@tonic-gate */ 9287c478bd9Sstevel@tonic-gate data[1] = FOV; 9297c478bd9Sstevel@tonic-gate 9307c478bd9Sstevel@tonic-gate if (mode == SM_FORMAT_IMMEDIATE) { 9317c478bd9Sstevel@tonic-gate debug(5, 9327c478bd9Sstevel@tonic-gate "SM_FORMAT_IMMEDIATE specified ignored. Performing a long format!\n"); 9337c478bd9Sstevel@tonic-gate } 9347c478bd9Sstevel@tonic-gate 9357c478bd9Sstevel@tonic-gate switch (flavor) { 9367c478bd9Sstevel@tonic-gate case SM_FORMAT_LONG : 9377c478bd9Sstevel@tonic-gate if (strstr(inq.inq_pid, "jaz")) { 9387c478bd9Sstevel@tonic-gate debug(1, 9397c478bd9Sstevel@tonic-gate "LONG Format of JAZ media not supported\n"); 9407c478bd9Sstevel@tonic-gate errno = ENOTSUP; 9417c478bd9Sstevel@tonic-gate return (ENOTSUP); 9427c478bd9Sstevel@tonic-gate } 9437c478bd9Sstevel@tonic-gate /* 9447c478bd9Sstevel@tonic-gate * Defect list sent is an addition to the existing 9457c478bd9Sstevel@tonic-gate * list of defects. 9467c478bd9Sstevel@tonic-gate */ 9477c478bd9Sstevel@tonic-gate cdb[1] = FMTDATA; 9487c478bd9Sstevel@tonic-gate break; 9497c478bd9Sstevel@tonic-gate default : 9507c478bd9Sstevel@tonic-gate debug(1, "Format option %d not supported!!\n", 9517c478bd9Sstevel@tonic-gate flavor); 9527c478bd9Sstevel@tonic-gate errno = ENOTSUP; 9537c478bd9Sstevel@tonic-gate return (ENOTSUP); 9547c478bd9Sstevel@tonic-gate } 9557c478bd9Sstevel@tonic-gate 9567c478bd9Sstevel@tonic-gate 9577c478bd9Sstevel@tonic-gate ucmd.uscsi_cdb = (caddr_t)&cdb; 9587c478bd9Sstevel@tonic-gate ucmd.uscsi_cdblen = CDB_GROUP0; 9597c478bd9Sstevel@tonic-gate ucmd.uscsi_bufaddr = (caddr_t)data; 9607c478bd9Sstevel@tonic-gate ucmd.uscsi_buflen = sizeof (data); 9617c478bd9Sstevel@tonic-gate ucmd.uscsi_timeout = FORMAT_TIMEOUT(capacity); 9627c478bd9Sstevel@tonic-gate ucmd.uscsi_rqlen = RQ_LEN; 9637c478bd9Sstevel@tonic-gate ucmd.uscsi_rqbuf = rq_data; 9647c478bd9Sstevel@tonic-gate ret_val = do_uscsi_cmd(fd, &ucmd, USCSI_WRITE|USCSI_RQENABLE); 9657c478bd9Sstevel@tonic-gate if (ret_val || ucmd.uscsi_status) { 9667c478bd9Sstevel@tonic-gate debug(5, "Format failed failed: %d - %d errno = %d\n", 9677c478bd9Sstevel@tonic-gate ret_val, ucmd.uscsi_status, errno); 9687c478bd9Sstevel@tonic-gate return (ucmd.uscsi_status); 9697c478bd9Sstevel@tonic-gate } 9707c478bd9Sstevel@tonic-gate 9717c478bd9Sstevel@tonic-gate return (0); 9727c478bd9Sstevel@tonic-gate } 9737c478bd9Sstevel@tonic-gate 9747c478bd9Sstevel@tonic-gate static int32_t 9757c478bd9Sstevel@tonic-gate scsi_media_status(int32_t fd) 9767c478bd9Sstevel@tonic-gate { 9777c478bd9Sstevel@tonic-gate struct mode_header modeh; 9787c478bd9Sstevel@tonic-gate struct uscsi_cmd ucmd; 9797c478bd9Sstevel@tonic-gate union scsi_cdb cdb; 9807c478bd9Sstevel@tonic-gate int32_t ret_val; 9817c478bd9Sstevel@tonic-gate int32_t cur_status; 9827c478bd9Sstevel@tonic-gate char rq_data[RQ_LEN]; 9837c478bd9Sstevel@tonic-gate 9847c478bd9Sstevel@tonic-gate debug(10, "SCSI MEDIA STATUS CALLED \n"); 9857c478bd9Sstevel@tonic-gate 9867c478bd9Sstevel@tonic-gate (void) memset((void *) &modeh, 0, sizeof (modeh)); 9877c478bd9Sstevel@tonic-gate (void) memset((void *) &ucmd, 0, sizeof (ucmd)); 9887c478bd9Sstevel@tonic-gate (void) memset((void *) &cdb, 0, sizeof (union scsi_cdb)); 9897c478bd9Sstevel@tonic-gate cdb.scc_cmd = SCMD_MODE_SENSE; 990910cba4fScg149915 cdb.cdb_opaque[2] = MODEPAGE_ALLPAGES; 9917c478bd9Sstevel@tonic-gate FORMG0COUNT(&cdb, sizeof (modeh)); 992910cba4fScg149915 9937c478bd9Sstevel@tonic-gate ucmd.uscsi_cdb = (caddr_t)&cdb; 9947c478bd9Sstevel@tonic-gate ucmd.uscsi_cdblen = CDB_GROUP0; 9957c478bd9Sstevel@tonic-gate ucmd.uscsi_bufaddr = (caddr_t)&modeh; 9967c478bd9Sstevel@tonic-gate ucmd.uscsi_buflen = sizeof (modeh); 9977c478bd9Sstevel@tonic-gate ucmd.uscsi_timeout = 120; /* If 0, HBA hangs forever */ 9987c478bd9Sstevel@tonic-gate ucmd.uscsi_rqlen = RQ_LEN; 9997c478bd9Sstevel@tonic-gate ucmd.uscsi_rqbuf = rq_data; 10007c478bd9Sstevel@tonic-gate ret_val = do_uscsi_cmd(fd, &ucmd, USCSI_READ|USCSI_RQENABLE); 10017c478bd9Sstevel@tonic-gate if (ret_val || ucmd.uscsi_status) { 1002910cba4fScg149915 debug(5, "Modesense for 0x3f pages failed: %d-%d errno=%d\n", 1003910cba4fScg149915 ret_val, ucmd.uscsi_status, errno); 1004910cba4fScg149915 cdb.cdb_opaque[2] = 0; 1005910cba4fScg149915 ucmd.uscsi_rqlen = RQ_LEN; 1006910cba4fScg149915 FORMG0COUNT(&cdb, sizeof (modeh)); 1007910cba4fScg149915 ret_val = do_uscsi_cmd(fd, &ucmd, USCSI_READ|USCSI_RQENABLE); 1008910cba4fScg149915 if (ret_val || ucmd.uscsi_status) { 10097c478bd9Sstevel@tonic-gate debug(5, "Modesense failed: %d - %d errno = %d\n", 10107c478bd9Sstevel@tonic-gate ret_val, ucmd.uscsi_status, errno); 10117c478bd9Sstevel@tonic-gate return (-1); 10127c478bd9Sstevel@tonic-gate } 1013910cba4fScg149915 } 10147c478bd9Sstevel@tonic-gate 10157c478bd9Sstevel@tonic-gate if (modeh.device_specific & W_E_MASK) { 10167c478bd9Sstevel@tonic-gate cur_status = SM_WRITE_PROTECT_NOPASSWD; 10177c478bd9Sstevel@tonic-gate } else { 10187c478bd9Sstevel@tonic-gate cur_status = SM_WRITE_PROTECT_DISABLE; 10197c478bd9Sstevel@tonic-gate } 10207c478bd9Sstevel@tonic-gate debug(5, "cur status %d\n", cur_status); 10217c478bd9Sstevel@tonic-gate 10227c478bd9Sstevel@tonic-gate return (cur_status); 10237c478bd9Sstevel@tonic-gate } 10247c478bd9Sstevel@tonic-gate 10257c478bd9Sstevel@tonic-gate static int32_t 10267c478bd9Sstevel@tonic-gate scsi_zip_media_status(int32_t fd) 10277c478bd9Sstevel@tonic-gate { 10287c478bd9Sstevel@tonic-gate struct uscsi_cmd ucmd; 10297c478bd9Sstevel@tonic-gate uchar_t cdb[12]; 10307c478bd9Sstevel@tonic-gate int32_t status; 10317c478bd9Sstevel@tonic-gate int32_t mode; 10327c478bd9Sstevel@tonic-gate uchar_t data[64]; 10337c478bd9Sstevel@tonic-gate char rq_data[RQ_LEN]; 10347c478bd9Sstevel@tonic-gate 10357c478bd9Sstevel@tonic-gate debug(10, "Getting media status\n"); 10367c478bd9Sstevel@tonic-gate 10377c478bd9Sstevel@tonic-gate (void) memset((void *)&ucmd, 0, sizeof (ucmd)); 10387c478bd9Sstevel@tonic-gate (void) memset((void *)&cdb, 0, sizeof (cdb)); 10397c478bd9Sstevel@tonic-gate 10407c478bd9Sstevel@tonic-gate cdb[0] = IOMEGA_NONSENSE_CMD; 10417c478bd9Sstevel@tonic-gate cdb[2] = CARTRIDGE_STATUS_PAGE; 10427c478bd9Sstevel@tonic-gate cdb[4] = ND_LENGTH; 10437c478bd9Sstevel@tonic-gate ucmd.uscsi_cdb = (caddr_t)&cdb; 10447c478bd9Sstevel@tonic-gate ucmd.uscsi_cdblen = CDB_GROUP0; 10457c478bd9Sstevel@tonic-gate ucmd.uscsi_bufaddr = (caddr_t)data; 10467c478bd9Sstevel@tonic-gate ucmd.uscsi_buflen = 64; 10477c478bd9Sstevel@tonic-gate ucmd.uscsi_timeout = 120; /* If 0, HBA hangs forever */ 10487c478bd9Sstevel@tonic-gate ucmd.uscsi_rqlen = RQ_LEN; 10497c478bd9Sstevel@tonic-gate ucmd.uscsi_rqbuf = rq_data; 10507c478bd9Sstevel@tonic-gate status = do_uscsi_cmd(fd, &ucmd, USCSI_READ|USCSI_RQENABLE); 10517c478bd9Sstevel@tonic-gate if (status || ucmd.uscsi_status) { 10525363f09cSarutz debug(5, "Cartridge protect operation failed: " 10535363f09cSarutz "rv = %d uscsi_status = %d errno = %d\n", 10547c478bd9Sstevel@tonic-gate status, ucmd.uscsi_status, errno); 10557c478bd9Sstevel@tonic-gate return (-1); 10567c478bd9Sstevel@tonic-gate } 10577c478bd9Sstevel@tonic-gate 10587c478bd9Sstevel@tonic-gate if (data[DISK_STATUS_OFFSET + NON_SENSE_HDR_LEN] == 4) { 10597c478bd9Sstevel@tonic-gate debug(1, "Disk not present. \n"); 10607c478bd9Sstevel@tonic-gate return (-1); 10617c478bd9Sstevel@tonic-gate } 10627c478bd9Sstevel@tonic-gate mode = data[PROTECT_MODE_OFFSET + NON_SENSE_HDR_LEN] & 0xF; 10637c478bd9Sstevel@tonic-gate 10645363f09cSarutz debug(5, "MODE 0x%x / %d.\n", mode, mode); 10657c478bd9Sstevel@tonic-gate 10667c478bd9Sstevel@tonic-gate switch (mode) { 10677c478bd9Sstevel@tonic-gate case UNLOCK_MODE: 10687c478bd9Sstevel@tonic-gate status = SM_WRITE_PROTECT_DISABLE; 10697c478bd9Sstevel@tonic-gate break; 10707c478bd9Sstevel@tonic-gate case WRITE_PROTECT_MODE: 10717c478bd9Sstevel@tonic-gate status = SM_WRITE_PROTECT_NOPASSWD; 10727c478bd9Sstevel@tonic-gate break; 10737c478bd9Sstevel@tonic-gate case PASSWD_WRITE_PROTECT_MODE: 10747c478bd9Sstevel@tonic-gate status = SM_WRITE_PROTECT_PASSWD; 10757c478bd9Sstevel@tonic-gate break; 10767c478bd9Sstevel@tonic-gate case READ_WRITE_PROTECT_MODE: 10777c478bd9Sstevel@tonic-gate status = SM_READ_WRITE_PROTECT; 10787c478bd9Sstevel@tonic-gate break; 10797c478bd9Sstevel@tonic-gate default : 10807c478bd9Sstevel@tonic-gate if (mode & TEMP_UNLOCK_MODE) 10817c478bd9Sstevel@tonic-gate status = SM_TEMP_UNLOCK_MODE; 10827c478bd9Sstevel@tonic-gate else 10837c478bd9Sstevel@tonic-gate status = SM_STATUS_UNKNOWN; 10847c478bd9Sstevel@tonic-gate break; 10857c478bd9Sstevel@tonic-gate } 10867c478bd9Sstevel@tonic-gate 10877c478bd9Sstevel@tonic-gate debug(5, "status %d \n", status); 10887c478bd9Sstevel@tonic-gate return (status); 10897c478bd9Sstevel@tonic-gate } 10907c478bd9Sstevel@tonic-gate 10915363f09cSarutz static int32_t 10927c478bd9Sstevel@tonic-gate scsi_reassign_block(int32_t fd, diskaddr_t block) 10937c478bd9Sstevel@tonic-gate { 10947c478bd9Sstevel@tonic-gate uchar_t data[8]; 10957c478bd9Sstevel@tonic-gate struct uscsi_cmd ucmd; 10967c478bd9Sstevel@tonic-gate char cdb[12]; 10977c478bd9Sstevel@tonic-gate int32_t ret_val; 10987c478bd9Sstevel@tonic-gate char rq_data[RQ_LEN]; 10997c478bd9Sstevel@tonic-gate 11007c478bd9Sstevel@tonic-gate debug(5, "SCSI REASSIGN CALLED block = %lld\n", block); 11017c478bd9Sstevel@tonic-gate 11027c478bd9Sstevel@tonic-gate (void) memset((void *) &data, 0, sizeof (data)); 11037c478bd9Sstevel@tonic-gate (void) memset((void *) &ucmd, 0, sizeof (ucmd)); 11047c478bd9Sstevel@tonic-gate (void) memset((void *) &cdb, 0, sizeof (cdb)); 11057c478bd9Sstevel@tonic-gate cdb[0] = SCMD_REASSIGN_BLOCK; 11067c478bd9Sstevel@tonic-gate data[3] = 4; 11077c478bd9Sstevel@tonic-gate data[4] = ((block & 0xFF000000) >> 24); 11087c478bd9Sstevel@tonic-gate data[5] = ((block & 0xFF0000) >> 16); 11097c478bd9Sstevel@tonic-gate data[6] = ((block & 0xFF00) >> 8); 11107c478bd9Sstevel@tonic-gate data[7] = block & 0xFF; 11117c478bd9Sstevel@tonic-gate 11127c478bd9Sstevel@tonic-gate ucmd.uscsi_cdb = (caddr_t)&cdb; 11137c478bd9Sstevel@tonic-gate ucmd.uscsi_cdblen = CDB_GROUP0; 11147c478bd9Sstevel@tonic-gate ucmd.uscsi_bufaddr = (caddr_t)data; 11157c478bd9Sstevel@tonic-gate ucmd.uscsi_buflen = sizeof (data); 11167c478bd9Sstevel@tonic-gate ucmd.uscsi_timeout = 120; /* If 0, HBA hangs forever */ 11177c478bd9Sstevel@tonic-gate ucmd.uscsi_rqlen = RQ_LEN; 11187c478bd9Sstevel@tonic-gate ucmd.uscsi_rqbuf = rq_data; 11197c478bd9Sstevel@tonic-gate ret_val = do_uscsi_cmd(fd, &ucmd, USCSI_WRITE|USCSI_RQENABLE); 11207c478bd9Sstevel@tonic-gate if (ret_val || ucmd.uscsi_status) { 11217c478bd9Sstevel@tonic-gate debug(5, "Reassign block failed: %d - %d errno = %d\n", 11227c478bd9Sstevel@tonic-gate ret_val, ucmd.uscsi_status, errno); 11237c478bd9Sstevel@tonic-gate return (-1); 11247c478bd9Sstevel@tonic-gate } 11257c478bd9Sstevel@tonic-gate 11267c478bd9Sstevel@tonic-gate return (0); 11277c478bd9Sstevel@tonic-gate } 11287c478bd9Sstevel@tonic-gate 11295363f09cSarutz static int32_t 11307c478bd9Sstevel@tonic-gate get_mode_page(int32_t fd, uchar_t pc, uchar_t page_code, 11317c478bd9Sstevel@tonic-gate uchar_t *md_data, uchar_t data_len) 11327c478bd9Sstevel@tonic-gate { 11337c478bd9Sstevel@tonic-gate struct uscsi_cmd ucmd; 11347c478bd9Sstevel@tonic-gate uchar_t cdb[12]; 11357c478bd9Sstevel@tonic-gate int32_t ret_val; 11367c478bd9Sstevel@tonic-gate char rq_data[RQ_LEN]; 11377c478bd9Sstevel@tonic-gate 11385363f09cSarutz debug(10, "MODE SENSE(6) - page_code = 0x%x\n", page_code); 11397c478bd9Sstevel@tonic-gate 11407c478bd9Sstevel@tonic-gate (void) memset((void *) md_data, 0, sizeof (data_len)); 11417c478bd9Sstevel@tonic-gate (void) memset((void *) &ucmd, 0, sizeof (ucmd)); 11427c478bd9Sstevel@tonic-gate (void) memset((void *) &cdb, 0, sizeof (cdb)); 11437c478bd9Sstevel@tonic-gate cdb[0] = SCMD_MODE_SENSE; 11447c478bd9Sstevel@tonic-gate cdb[2] = (pc << 6) | page_code; 11457c478bd9Sstevel@tonic-gate cdb[4] = data_len; 11467c478bd9Sstevel@tonic-gate 11477c478bd9Sstevel@tonic-gate ucmd.uscsi_cdb = (caddr_t)&cdb; 11487c478bd9Sstevel@tonic-gate ucmd.uscsi_cdblen = CDB_GROUP0; 11497c478bd9Sstevel@tonic-gate ucmd.uscsi_bufaddr = (caddr_t)md_data; 11507c478bd9Sstevel@tonic-gate ucmd.uscsi_buflen = data_len; 11517c478bd9Sstevel@tonic-gate ucmd.uscsi_timeout = 120; /* If 0, HBA hangs forever */ 11527c478bd9Sstevel@tonic-gate ucmd.uscsi_rqlen = RQ_LEN; 11537c478bd9Sstevel@tonic-gate ucmd.uscsi_rqbuf = rq_data; 11547c478bd9Sstevel@tonic-gate ret_val = do_uscsi_cmd(fd, &ucmd, USCSI_READ|USCSI_RQENABLE); 11557c478bd9Sstevel@tonic-gate if (ret_val || ucmd.uscsi_status) { 11567c478bd9Sstevel@tonic-gate debug(5, "Modesense failed: %d - %d errno = %d\n", 11577c478bd9Sstevel@tonic-gate ret_val, ucmd.uscsi_status, errno); 11587c478bd9Sstevel@tonic-gate return (-2); 11597c478bd9Sstevel@tonic-gate } 11607c478bd9Sstevel@tonic-gate 11617c478bd9Sstevel@tonic-gate return (0); 11627c478bd9Sstevel@tonic-gate } 11637c478bd9Sstevel@tonic-gate 11647c478bd9Sstevel@tonic-gate static int32_t 11657c478bd9Sstevel@tonic-gate scsi_zip_write_protect(int32_t fd, smwp_state_t *wp) 11667c478bd9Sstevel@tonic-gate { 11677c478bd9Sstevel@tonic-gate struct uscsi_cmd ucmd; 11687c478bd9Sstevel@tonic-gate struct scsi_inquiry inq; 11697c478bd9Sstevel@tonic-gate uchar_t cdb[12]; 11707c478bd9Sstevel@tonic-gate int32_t status; 11717c478bd9Sstevel@tonic-gate int32_t new_mode; 11727c478bd9Sstevel@tonic-gate char rq_data[RQ_LEN]; 11737c478bd9Sstevel@tonic-gate int32_t wa_bit; 11747c478bd9Sstevel@tonic-gate char *tmp_passwd = NULL; 11757c478bd9Sstevel@tonic-gate 11767c478bd9Sstevel@tonic-gate debug(10, "SCSI ZIP WRITE PROTECT CALLED \n"); 11777c478bd9Sstevel@tonic-gate 11787c478bd9Sstevel@tonic-gate /* 11797c478bd9Sstevel@tonic-gate * Do an inquiry and try to figure out if it an 11807c478bd9Sstevel@tonic-gate * ATAPI or SCSI device. 11817c478bd9Sstevel@tonic-gate */ 11827c478bd9Sstevel@tonic-gate 11837c478bd9Sstevel@tonic-gate (void) memset((void *) &inq, 0, sizeof (inq)); 11847c478bd9Sstevel@tonic-gate (void) memset((void *) &ucmd, 0, sizeof (ucmd)); 11857c478bd9Sstevel@tonic-gate (void) memset((void *) &cdb, 0, sizeof (cdb)); 11867c478bd9Sstevel@tonic-gate (void) memset((void *) &rq_data, 0, sizeof (rq_data)); 11877c478bd9Sstevel@tonic-gate cdb[0] = SCMD_INQUIRY; 11887c478bd9Sstevel@tonic-gate cdb[4] = sizeof (inq); 11897c478bd9Sstevel@tonic-gate ucmd.uscsi_cdb = (caddr_t)&cdb; 11907c478bd9Sstevel@tonic-gate ucmd.uscsi_cdblen = CDB_GROUP0; 11917c478bd9Sstevel@tonic-gate ucmd.uscsi_bufaddr = (caddr_t)&inq; 11927c478bd9Sstevel@tonic-gate ucmd.uscsi_buflen = sizeof (inq); 11937c478bd9Sstevel@tonic-gate ucmd.uscsi_timeout = 120; /* If 0, HBA hangs forever */ 11947c478bd9Sstevel@tonic-gate ucmd.uscsi_rqlen = RQ_LEN; 11957c478bd9Sstevel@tonic-gate ucmd.uscsi_rqbuf = rq_data; 11967c478bd9Sstevel@tonic-gate status = do_uscsi_cmd(fd, &ucmd, USCSI_READ|USCSI_RQENABLE); 11977c478bd9Sstevel@tonic-gate if (status || ucmd.uscsi_status) { 11987c478bd9Sstevel@tonic-gate debug(5, "inquiry failed: %d - %d errno = %d\n", 11997c478bd9Sstevel@tonic-gate status, ucmd.uscsi_status, errno); 12007c478bd9Sstevel@tonic-gate return (-1); 12017c478bd9Sstevel@tonic-gate } 12027c478bd9Sstevel@tonic-gate 12037c478bd9Sstevel@tonic-gate if (inq.inq_ansi > 0) { 12047c478bd9Sstevel@tonic-gate wa_bit = 0; 12057c478bd9Sstevel@tonic-gate debug(5, "SCSI device\n"); 12067c478bd9Sstevel@tonic-gate } else { 12077c478bd9Sstevel@tonic-gate wa_bit = 1; 12087c478bd9Sstevel@tonic-gate debug(5, "ATAPI device\n"); 12097c478bd9Sstevel@tonic-gate } 12107c478bd9Sstevel@tonic-gate 12117c478bd9Sstevel@tonic-gate switch (wp->sm_new_state) { 12127c478bd9Sstevel@tonic-gate case SM_WRITE_PROTECT_DISABLE : 12137c478bd9Sstevel@tonic-gate new_mode = 0x0; 12147c478bd9Sstevel@tonic-gate break; 12157c478bd9Sstevel@tonic-gate case SM_WRITE_PROTECT_NOPASSWD : 12167c478bd9Sstevel@tonic-gate new_mode = 0x2; 12177c478bd9Sstevel@tonic-gate break; 12187c478bd9Sstevel@tonic-gate case SM_WRITE_PROTECT_PASSWD : 12197c478bd9Sstevel@tonic-gate new_mode = 0x3; 12207c478bd9Sstevel@tonic-gate break; 12217c478bd9Sstevel@tonic-gate case SM_READ_WRITE_PROTECT : 12227c478bd9Sstevel@tonic-gate new_mode = 0x5; 12237c478bd9Sstevel@tonic-gate break; 12247c478bd9Sstevel@tonic-gate case SM_TEMP_UNLOCK_MODE : 12257c478bd9Sstevel@tonic-gate new_mode = 0x8; 12267c478bd9Sstevel@tonic-gate break; 12277c478bd9Sstevel@tonic-gate default : 12287c478bd9Sstevel@tonic-gate debug(1, "Invalid mode 0x%x specified\n", 12297c478bd9Sstevel@tonic-gate wp->sm_new_state); 12307c478bd9Sstevel@tonic-gate errno = ENOTSUP; 12317c478bd9Sstevel@tonic-gate return (-1); 12327c478bd9Sstevel@tonic-gate } 12337c478bd9Sstevel@tonic-gate 12347c478bd9Sstevel@tonic-gate 12357c478bd9Sstevel@tonic-gate (void) memset((void *)&ucmd, 0, sizeof (ucmd)); 12367c478bd9Sstevel@tonic-gate (void) memset((void *)&cdb, 0, sizeof (cdb)); 12377c478bd9Sstevel@tonic-gate (void) memset((void *) &rq_data, 0, sizeof (rq_data)); 12387c478bd9Sstevel@tonic-gate cdb[0] = IOMEGA_CATRIDGE_PROTECT; 12397c478bd9Sstevel@tonic-gate cdb[1] |= new_mode; 12407c478bd9Sstevel@tonic-gate if (wa_bit) 12417c478bd9Sstevel@tonic-gate cdb[1] |= WA_BIT; 12427c478bd9Sstevel@tonic-gate cdb[4] = wp->sm_passwd_len; 12437c478bd9Sstevel@tonic-gate ucmd.uscsi_cdb = (caddr_t)&cdb; 12447c478bd9Sstevel@tonic-gate ucmd.uscsi_cdblen = CDB_GROUP0; 12457c478bd9Sstevel@tonic-gate if (wa_bit && (wp->sm_passwd_len & 1)) { 12467c478bd9Sstevel@tonic-gate /* 12477c478bd9Sstevel@tonic-gate * Oops, ATAPI device with an odd length passwd! 12487c478bd9Sstevel@tonic-gate * Allocate a buffer to hold one extra byte. 12497c478bd9Sstevel@tonic-gate */ 12507c478bd9Sstevel@tonic-gate debug(5, "Odd len passwd for ATAPI device!\n"); 12517c478bd9Sstevel@tonic-gate errno = 0; 12527c478bd9Sstevel@tonic-gate tmp_passwd = (char *)malloc(wp->sm_passwd_len+1); 12537c478bd9Sstevel@tonic-gate if (tmp_passwd == NULL) { 12547c478bd9Sstevel@tonic-gate if (errno == 0) 12557c478bd9Sstevel@tonic-gate errno = ENOMEM; 12567c478bd9Sstevel@tonic-gate return (-1); 12577c478bd9Sstevel@tonic-gate } 12587c478bd9Sstevel@tonic-gate (void) memset(tmp_passwd, 0, wp->sm_passwd_len+1); 12597c478bd9Sstevel@tonic-gate (void) memcpy(tmp_passwd, wp->sm_passwd, wp->sm_passwd_len); 12607c478bd9Sstevel@tonic-gate ucmd.uscsi_bufaddr = (caddr_t)tmp_passwd; 12617c478bd9Sstevel@tonic-gate ucmd.uscsi_buflen = wp->sm_passwd_len+1; 12627c478bd9Sstevel@tonic-gate } else { 12637c478bd9Sstevel@tonic-gate ucmd.uscsi_bufaddr = (caddr_t)wp->sm_passwd; 12647c478bd9Sstevel@tonic-gate ucmd.uscsi_buflen = wp->sm_passwd_len; 12657c478bd9Sstevel@tonic-gate } 12667c478bd9Sstevel@tonic-gate ucmd.uscsi_timeout = 120; /* If 0, HBA hangs forever */ 12677c478bd9Sstevel@tonic-gate ucmd.uscsi_rqlen = RQ_LEN; 12687c478bd9Sstevel@tonic-gate ucmd.uscsi_rqbuf = rq_data; 12697c478bd9Sstevel@tonic-gate status = do_uscsi_cmd(fd, &ucmd, USCSI_WRITE|USCSI_RQENABLE); 12707c478bd9Sstevel@tonic-gate if (tmp_passwd != NULL) { 12717c478bd9Sstevel@tonic-gate free(tmp_passwd); 12727c478bd9Sstevel@tonic-gate } 12737c478bd9Sstevel@tonic-gate if (status || ucmd.uscsi_status) { 12745363f09cSarutz debug(5, "Cartridge-protect operation failed: rv " 12755363f09cSarutz "= %d uscsi_status = %d errno = %d\n", status, 12765363f09cSarutz ucmd.uscsi_status, errno); 12777c478bd9Sstevel@tonic-gate if ((rq_data[2] & 0xF) == KEY_ILLEGAL_REQUEST) { 12787c478bd9Sstevel@tonic-gate if (rq_data[12] == 0x26) { 12797c478bd9Sstevel@tonic-gate /* Wrong passwd */ 12805363f09cSarutz debug(5, "Protection Request with wrong " 12815363f09cSarutz "passwd. errno is being set to EACCES.\n"); 12827c478bd9Sstevel@tonic-gate errno = EACCES; 12837c478bd9Sstevel@tonic-gate } 12847c478bd9Sstevel@tonic-gate } 12857c478bd9Sstevel@tonic-gate return (-1); 12867c478bd9Sstevel@tonic-gate } 12877c478bd9Sstevel@tonic-gate 12887c478bd9Sstevel@tonic-gate return (0); 12897c478bd9Sstevel@tonic-gate } 12907c478bd9Sstevel@tonic-gate 12917c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 12927c478bd9Sstevel@tonic-gate static int32_t 12937c478bd9Sstevel@tonic-gate scsi_write_protect(int32_t fd, smwp_state_t *wp) 12947c478bd9Sstevel@tonic-gate { 12957c478bd9Sstevel@tonic-gate errno = ENOTSUP; 12967c478bd9Sstevel@tonic-gate return (-1); 12977c478bd9Sstevel@tonic-gate } 12987c478bd9Sstevel@tonic-gate 12995363f09cSarutz /* 13005363f09cSarutz * This thread becomes the server-side thread used in 13015363f09cSarutz * the implementation of a door_call between a client 13025363f09cSarutz * and the Client Door. 13035363f09cSarutz * 13045363f09cSarutz * This thread is customized both by the door_server_create(3c) 13055363f09cSarutz * function sm_door_server_create, as well as by itself. 13065363f09cSarutz * 13075363f09cSarutz * This thread needs to synchronize with the 13085363f09cSarutz * main_servproc[SMEDIA_CNUM_OPEN_FD] door_call in terms of 13095363f09cSarutz * both successful and failure scenarios. main_servproc 13105363f09cSarutz * locks dd_lock before calling door_create. This thread 13115363f09cSarutz * then attempts to lock, but will block until main_servproc 13125363f09cSarutz * has either created all doors it requires, or until a 13135363f09cSarutz * door_create has failed (door_create's return and the 13145363f09cSarutz * creation of an associated thread are asynchronous). 13155363f09cSarutz * 13165363f09cSarutz * If door_create failed, this thread will be able to obtain 13175363f09cSarutz * dd_lock and call pthread_exit. If all door_create's succeed, 13185363f09cSarutz * this thread will obtain dd_lock and commence with 13195363f09cSarutz * customizing the thread's attributes. door_bind is called to 13205363f09cSarutz * bind this thread to the per-door private thread pool, and 13215363f09cSarutz * main_servproc is cond_signal'd to avail it of this fact. 13225363f09cSarutz * 13235363f09cSarutz * Finally, this thread calls door_return, which causes it to 13245363f09cSarutz * commence its lifetime as a server-side thread in implementation 13255363f09cSarutz * of a Client Door door_call. 13265363f09cSarutz */ 13277c478bd9Sstevel@tonic-gate static void * 13285363f09cSarutz sm_server_thread(void *arg) 13297c478bd9Sstevel@tonic-gate { 13307c478bd9Sstevel@tonic-gate door_data_t *door_dp; 13317c478bd9Sstevel@tonic-gate struct sigaction act; 13325363f09cSarutz int i; 13335363f09cSarutz int err; 13347c478bd9Sstevel@tonic-gate 13357c478bd9Sstevel@tonic-gate door_dp = (door_data_t *)arg; 13367c478bd9Sstevel@tonic-gate 13377c478bd9Sstevel@tonic-gate if (door_dp == NULL) { 13385363f09cSarutz fatal("sm_server_thread[%d]: argument is NULL!!\n", 13397c478bd9Sstevel@tonic-gate pthread_self()); 13407c478bd9Sstevel@tonic-gate exit(-1); 13417c478bd9Sstevel@tonic-gate } 13427c478bd9Sstevel@tonic-gate 13435363f09cSarutz /* Wait for Client Door to be created */ 13447c478bd9Sstevel@tonic-gate (void) mutex_lock(&door_dp->dd_lock); 13455363f09cSarutz if (door_dp->dd_cdoor_descriptor < 0) { 13465363f09cSarutz debug(5, "sm_server_thread[%d]: door_create() failed", 13475363f09cSarutz pthread_self()); 13485363f09cSarutz (void) mutex_unlock(&door_dp->dd_lock); 13495363f09cSarutz pthread_exit((void *)-2); 13505363f09cSarutz } 13517c478bd9Sstevel@tonic-gate (void) mutex_unlock(&door_dp->dd_lock); 13527c478bd9Sstevel@tonic-gate 13537c478bd9Sstevel@tonic-gate for (i = 0; i < N_BADSIGS; i++) { 13547c478bd9Sstevel@tonic-gate act.sa_sigaction = server_badsig_handler; 13557c478bd9Sstevel@tonic-gate (void) sigemptyset(&act.sa_mask); 13567c478bd9Sstevel@tonic-gate act.sa_flags = SA_SIGINFO; 13577c478bd9Sstevel@tonic-gate if (sigaction(badsigs[i], &act, NULL) == -1) 13587c478bd9Sstevel@tonic-gate warning(gettext(SIGACT_FAILED), strsignal(badsigs[i]), 13597c478bd9Sstevel@tonic-gate strerror(errno)); 13607c478bd9Sstevel@tonic-gate } 13617c478bd9Sstevel@tonic-gate if (sigemptyset(&door_dp->dd_newset) != 0) 13627c478bd9Sstevel@tonic-gate warning(gettext("sigemptyset failed. errno = %d\n"), 13637c478bd9Sstevel@tonic-gate errno); 13645363f09cSarutz if ((err = pthread_sigmask(SIG_BLOCK, &door_dp->dd_newset, NULL)) != 0) 13655363f09cSarutz warning(gettext("pthread_sigmask failed = %d\n"), err); 13667c478bd9Sstevel@tonic-gate 13675363f09cSarutz /* Bind thread with pool associated with Client Door */ 13687c478bd9Sstevel@tonic-gate 13695363f09cSarutz if (door_bind(door_dp->dd_cdoor_descriptor) < 0) { 13707c478bd9Sstevel@tonic-gate fatal("door_bind"); 13717c478bd9Sstevel@tonic-gate exit(-1); 13727c478bd9Sstevel@tonic-gate } 13735363f09cSarutz debug(5, "thr[%d] bound to Client Door[%d]", pthread_self(), 13745363f09cSarutz door_dp->dd_cdoor_descriptor); 13755363f09cSarutz 13767c478bd9Sstevel@tonic-gate /* 13775363f09cSarutz * Set these two cancellation(5) attributes. Ensure that the 13785363f09cSarutz * pthread we create has cancellation(5) DISABLED and DEFERRED, 13795363f09cSarutz * as our implementation is based on this. DEFERRED is the 13805363f09cSarutz * default, but set it anyways, in case the defaults change in 13815363f09cSarutz * the future. 13827c478bd9Sstevel@tonic-gate */ 13835363f09cSarutz if ((err = pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL)) != 0) 13845363f09cSarutz warning(gettext("pthread_setcancelstate(PTHREAD_CANCEL_DISABLE)" 13855363f09cSarutz " failed = %d\n"), err); 13865363f09cSarutz if ((err = pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, 13875363f09cSarutz NULL)) != 0) 13885363f09cSarutz warning(gettext("pthread_setcanceltype(DEFERRED) " 13895363f09cSarutz "failed = %d\n"), err); 13905363f09cSarutz 13915363f09cSarutz /* Inform main_servproc that door_bind() is complete. */ 13927c478bd9Sstevel@tonic-gate (void) cond_signal(&door_dp->dd_cv_bind); 13935363f09cSarutz 13945363f09cSarutz /* 13955363f09cSarutz * Per doors protocol, transfer control to the doors-runtime in 13965363f09cSarutz * order to make this thread available to answer future door_call()'s. 13975363f09cSarutz */ 13987c478bd9Sstevel@tonic-gate (void) door_return(NULL, 0, NULL, 0); 13997c478bd9Sstevel@tonic-gate return (NULL); 14007c478bd9Sstevel@tonic-gate } 14017c478bd9Sstevel@tonic-gate 14025363f09cSarutz /* 14035363f09cSarutz * This function cleans up all per-connection resources. 14045363f09cSarutz * 14055363f09cSarutz * This function is called when the Client Door's service procedure 14065363f09cSarutz * (client_servproc) is called w/ DOOR_UNREF_DATA, which is the 14075363f09cSarutz * doors protocol convention stating that the number of file 14085363f09cSarutz * descriptors referring to this door has dropped to one. 14095363f09cSarutz * client_servproc is passed DOOR_UNREF_DATA because the Client Door 14105363f09cSarutz * was door_create'd with the DOOR_UNREF bitflag. 14115363f09cSarutz */ 14127c478bd9Sstevel@tonic-gate static void 14137c478bd9Sstevel@tonic-gate cleanup(door_data_t *door_dp) 14147c478bd9Sstevel@tonic-gate { 14155363f09cSarutz /* do door_revoke() of Death Door */ 14165363f09cSarutz if (door_dp->dd_ddoor_descriptor >= 0) { 14175363f09cSarutz debug(1, "cleanup[%d]: door_revoke() Death Door[%d]", 14185363f09cSarutz pthread_self(), door_dp->dd_ddoor_descriptor); 14197c478bd9Sstevel@tonic-gate 14205363f09cSarutz if (door_revoke(door_dp->dd_ddoor_descriptor) < 0) { 14215363f09cSarutz warning(gettext("cleanup[%d]: door_revoke() of Death " 14225363f09cSarutz "Door(%d) failed = %d"), pthread_self(), 14235363f09cSarutz door_dp->dd_ddoor_descriptor, errno); 14245363f09cSarutz } else { 14255363f09cSarutz door_dp->dd_ddoor_descriptor = -1; 14267c478bd9Sstevel@tonic-gate } 14275363f09cSarutz } 14285363f09cSarutz 14295363f09cSarutz /* release memory that is shared between client and (our) server */ 14305363f09cSarutz if (door_dp->dd_buffd >= 0) { 14315363f09cSarutz debug(1, "cleanup[%d]: release shared memory", pthread_self()); 14327c478bd9Sstevel@tonic-gate (void) munmap(door_dp->dd_buf, door_dp->dd_buf_len); 14337c478bd9Sstevel@tonic-gate (void) close(door_dp->dd_buffd); 14345363f09cSarutz 14355363f09cSarutz door_dp->dd_buffd = -1; 14367c478bd9Sstevel@tonic-gate door_dp->dd_buf = NULL; 14377c478bd9Sstevel@tonic-gate door_dp->dd_buf_len = 0; 14387c478bd9Sstevel@tonic-gate } 14397c478bd9Sstevel@tonic-gate 14405363f09cSarutz /* close the (target) device that the Client is operating on */ 14415363f09cSarutz if (door_dp->dd_fd >= 0) { 14425363f09cSarutz debug(1, "cleanup[%d]: close(%d) target device", pthread_self(), 14435363f09cSarutz door_dp->dd_fd); 14447c478bd9Sstevel@tonic-gate if (close(door_dp->dd_fd) < 0) { 14455363f09cSarutz warning(gettext("cleanup[%d]: close() of target device" 14465363f09cSarutz "failed = %d\n"), pthread_self(), errno); 14477c478bd9Sstevel@tonic-gate } 14487c478bd9Sstevel@tonic-gate } 14497c478bd9Sstevel@tonic-gate 14505363f09cSarutz /* 14515363f09cSarutz * Unbind the current thread from the Client Door's private 14525363f09cSarutz * thread pool. 14535363f09cSarutz */ 14545363f09cSarutz debug(1, "cleanup[%d]: door_unbind() of Client Door[%d]", 14555363f09cSarutz pthread_self(), door_dp->dd_cdoor_descriptor); 14565363f09cSarutz if (door_unbind() < 0) 14575363f09cSarutz warning("door_unbind() of Client Door[%d] failed = " 14585363f09cSarutz "%d", door_dp->dd_cdoor_descriptor, errno); 14595363f09cSarutz 14605363f09cSarutz /* Disallow any future requests to the Client Door */ 14615363f09cSarutz if (door_dp->dd_cdoor_descriptor >= 0) { 14625363f09cSarutz debug(1, "cleanup[%d]: door_revoke() Client Door[%d]", 14635363f09cSarutz pthread_self(), door_dp->dd_cdoor_descriptor); 14645363f09cSarutz 14655363f09cSarutz if (door_revoke(door_dp->dd_cdoor_descriptor) < 0) { 14665363f09cSarutz warning(gettext("cleanup[%d]: door_revoke() of " 14675363f09cSarutz "Client Door[%d] failed = %d"), pthread_self(), 14685363f09cSarutz door_dp->dd_cdoor_descriptor, errno); 14695363f09cSarutz } 14705363f09cSarutz } 14715363f09cSarutz 14725363f09cSarutz free(door_dp); 14735363f09cSarutz debug(5, "cleanup[%d] ...exiting\n", pthread_self()); 14745363f09cSarutz } 14755363f09cSarutz 14765363f09cSarutz /* 14775363f09cSarutz * This is the door_server_create(3c) function used to customize 14785363f09cSarutz * creation of the threads used in the handling of our daemon's 14795363f09cSarutz * door_call(3c)'s. 14805363f09cSarutz * 14815363f09cSarutz * This function is called synchronously as part of door_create(3c). 14825363f09cSarutz * Note that door_create(), however, is not synchronous; it can return 14835363f09cSarutz * with the created door file descriptor before any associated 14845363f09cSarutz * thread has been created. As a result, synchronization is needed 14855363f09cSarutz * between door_create() caller and the created pthread. This is 14865363f09cSarutz * needed both when each activity succeeds or when either activity 14875363f09cSarutz * fails. 14885363f09cSarutz * 14895363f09cSarutz * Specifically, this function ensures that each "connection" 14905363f09cSarutz * with the client creates only one thread in the per-door, 14915363f09cSarutz * private thread pool. This function locks dd_threadlock and 14925363f09cSarutz * then calls pthread_create(). If that succeeds, dd_thread 14935363f09cSarutz * is assigned the thread id, and dd_threadlock is unlocked. 14945363f09cSarutz * Any per-connection door_create that causes control to flow 14955363f09cSarutz * to this function will eventually find that dd_thread is 14965363f09cSarutz * non-zero, and control will exit this function. 14975363f09cSarutz * 14985363f09cSarutz * In the current implementation, the door_create for the Client Door 14995363f09cSarutz * is called first, and the Death Door is door_create'd second. 15005363f09cSarutz * As a result, the following function can safely make the static 15015363f09cSarutz * assumption that the first door (within a connection) is the 15025363f09cSarutz * Client Door. A connection's Client Door and Death Door share 15035363f09cSarutz * the same thread as well as the same door_data_t instance. 15045363f09cSarutz */ 15057c478bd9Sstevel@tonic-gate static void 15065363f09cSarutz sm_door_server_create(door_info_t *dip) 15077c478bd9Sstevel@tonic-gate { 15087c478bd9Sstevel@tonic-gate door_data_t *door_dp; 15097c478bd9Sstevel@tonic-gate pthread_t tid; 15107c478bd9Sstevel@tonic-gate pthread_attr_t attr; 15117c478bd9Sstevel@tonic-gate int ret_val; 15125363f09cSarutz int err; 15137c478bd9Sstevel@tonic-gate 15147c478bd9Sstevel@tonic-gate if (dip == NULL) { 15157c478bd9Sstevel@tonic-gate return; 15167c478bd9Sstevel@tonic-gate } 1517360e6f5eSmathue door_dp = (door_data_t *)(uintptr_t)dip->di_data; 15187c478bd9Sstevel@tonic-gate 15195363f09cSarutz debug(10, "sm_door_server_create[%d]: entering...\n", pthread_self()); 15207c478bd9Sstevel@tonic-gate 15217c478bd9Sstevel@tonic-gate /* create one thread for this door */ 15227c478bd9Sstevel@tonic-gate 15237c478bd9Sstevel@tonic-gate (void) mutex_lock(&door_dp->dd_threadlock); 15247c478bd9Sstevel@tonic-gate 15257c478bd9Sstevel@tonic-gate if (door_dp->dd_thread != 0) { 15265363f09cSarutz debug(8, "sm_door_server_create[%d]: Exiting without creating " 15275363f09cSarutz "thread.\n", pthread_self()); 15287c478bd9Sstevel@tonic-gate (void) mutex_unlock(&door_dp->dd_threadlock); 15297c478bd9Sstevel@tonic-gate return; 15307c478bd9Sstevel@tonic-gate } 15317c478bd9Sstevel@tonic-gate 15327c478bd9Sstevel@tonic-gate (void) pthread_attr_init(&attr); 15337c478bd9Sstevel@tonic-gate 15345363f09cSarutz if ((err = pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM)) != 0) 15355363f09cSarutz warning(gettext("pthread_attr_setscope failed = %d\n"), err); 15365363f09cSarutz if ((err = pthread_attr_setdetachstate(&attr, 15375363f09cSarutz PTHREAD_CREATE_DETACHED)) != 0) 15385363f09cSarutz warning(gettext("pthread_attr_setdetachstate failed = %d\n"), 15395363f09cSarutz err); 15405363f09cSarutz 15415363f09cSarutz ret_val = pthread_create(&tid, &attr, sm_server_thread, 15425363f09cSarutz (void *)(uintptr_t)(dip->di_data)); 15437c478bd9Sstevel@tonic-gate if (ret_val != 0) { 15445363f09cSarutz warning(gettext("sm_door_server_create[%d]: pthread_create " 15455363f09cSarutz "failed = %d\n"), pthread_self(), ret_val); 15467c478bd9Sstevel@tonic-gate (void) mutex_unlock(&door_dp->dd_threadlock); 15477c478bd9Sstevel@tonic-gate (void) pthread_attr_destroy(&attr); 15487c478bd9Sstevel@tonic-gate return; 15497c478bd9Sstevel@tonic-gate } 15507c478bd9Sstevel@tonic-gate (void) pthread_attr_destroy(&attr); 15517c478bd9Sstevel@tonic-gate door_dp->dd_thread = tid; 15527c478bd9Sstevel@tonic-gate 15537c478bd9Sstevel@tonic-gate (void) mutex_unlock(&door_dp->dd_threadlock); 15545363f09cSarutz debug(5, "Exiting sm_door_server_create[%d] after creating thr[%d].\n", 15555363f09cSarutz pthread_self(), tid); 15567c478bd9Sstevel@tonic-gate } 15577c478bd9Sstevel@tonic-gate 15587c478bd9Sstevel@tonic-gate static void 15597c478bd9Sstevel@tonic-gate door_ret_err(smedia_reterror_t *reterror, int32_t err) 15607c478bd9Sstevel@tonic-gate { 15617c478bd9Sstevel@tonic-gate reterror->cnum = SMEDIA_CNUM_ERROR; 15627c478bd9Sstevel@tonic-gate reterror->errnum = err; 15637c478bd9Sstevel@tonic-gate (void) door_return((char *)reterror, sizeof (smedia_reterror_t), 0, 0); 15647c478bd9Sstevel@tonic-gate } 15657c478bd9Sstevel@tonic-gate 15667c478bd9Sstevel@tonic-gate static void 15677c478bd9Sstevel@tonic-gate my_door_return(char *data_ptr, size_t data_size, 15687c478bd9Sstevel@tonic-gate door_desc_t *desc_ptr, uint_t num_desc) 15697c478bd9Sstevel@tonic-gate { 15707c478bd9Sstevel@tonic-gate (void) door_return(data_ptr, data_size, desc_ptr, num_desc); 15717c478bd9Sstevel@tonic-gate } 15727c478bd9Sstevel@tonic-gate 15737c478bd9Sstevel@tonic-gate static int32_t 15747c478bd9Sstevel@tonic-gate raw_read(door_data_t *door_dp, smedia_services_t *req) 15757c478bd9Sstevel@tonic-gate { 15767c478bd9Sstevel@tonic-gate struct uscsi_cmd ucmd; 15777c478bd9Sstevel@tonic-gate union scsi_cdb cdb; 15787c478bd9Sstevel@tonic-gate int32_t ret_val; 15797c478bd9Sstevel@tonic-gate int32_t num_sectors, sector_size; 15807c478bd9Sstevel@tonic-gate int32_t rc_data[2]; 15817c478bd9Sstevel@tonic-gate char rq_data[RQ_LEN]; 15827c478bd9Sstevel@tonic-gate 15837c478bd9Sstevel@tonic-gate (void) memset((void *) &rc_data, 0, sizeof (rc_data)); 15847c478bd9Sstevel@tonic-gate (void) memset((void *) &ucmd, 0, sizeof (ucmd)); 15857c478bd9Sstevel@tonic-gate (void) memset((void *) &cdb, 0, sizeof (union scsi_cdb)); 15867c478bd9Sstevel@tonic-gate 15877c478bd9Sstevel@tonic-gate if (door_dp->dd_sector_size == 0) { 15887c478bd9Sstevel@tonic-gate sector_size = get_sector_size(door_dp->dd_fd); 15897c478bd9Sstevel@tonic-gate door_dp->dd_sector_size = sector_size; 15907c478bd9Sstevel@tonic-gate } else sector_size = door_dp->dd_sector_size; 15917c478bd9Sstevel@tonic-gate 15927c478bd9Sstevel@tonic-gate if ((req->reqraw_read.nbytes > door_dp->dd_buf_len) || 15937c478bd9Sstevel@tonic-gate (door_dp->dd_buf == NULL)) { 15947c478bd9Sstevel@tonic-gate errno = EINVAL; 15957c478bd9Sstevel@tonic-gate return (-1); 15967c478bd9Sstevel@tonic-gate } 15977c478bd9Sstevel@tonic-gate if ((!req->reqraw_read.nbytes) || 15987c478bd9Sstevel@tonic-gate (req->reqraw_read.nbytes % sector_size)) { 15997c478bd9Sstevel@tonic-gate errno = EINVAL; 16007c478bd9Sstevel@tonic-gate return (-1); 16017c478bd9Sstevel@tonic-gate } 16027c478bd9Sstevel@tonic-gate 16037c478bd9Sstevel@tonic-gate (void) memset((void *) &cdb, 0, sizeof (cdb)); 16047c478bd9Sstevel@tonic-gate num_sectors = (uint32_t)req->reqraw_read.nbytes/sector_size; 16057c478bd9Sstevel@tonic-gate 16067c478bd9Sstevel@tonic-gate cdb.scc_cmd = SCMD_READ_G1; 16077c478bd9Sstevel@tonic-gate FORMG1ADDR(&cdb, (uint32_t)req->reqraw_read.blockno); 16087c478bd9Sstevel@tonic-gate FORMG1COUNT(&cdb, num_sectors); 16097c478bd9Sstevel@tonic-gate 16107c478bd9Sstevel@tonic-gate ucmd.uscsi_cdb = (caddr_t)&cdb; 16117c478bd9Sstevel@tonic-gate ucmd.uscsi_cdblen = CDB_GROUP1; 16127c478bd9Sstevel@tonic-gate ucmd.uscsi_bufaddr = (caddr_t)door_dp->dd_buf; 16137c478bd9Sstevel@tonic-gate ucmd.uscsi_buflen = (uint32_t)req->reqraw_read.nbytes; 16147c478bd9Sstevel@tonic-gate ucmd.uscsi_timeout = 120; /* If 0, HBA hangs forever */ 16157c478bd9Sstevel@tonic-gate ucmd.uscsi_rqlen = RQ_LEN; 16167c478bd9Sstevel@tonic-gate ucmd.uscsi_rqbuf = rq_data; 16177c478bd9Sstevel@tonic-gate ret_val = do_uscsi_cmd(door_dp->dd_fd, 16187c478bd9Sstevel@tonic-gate &ucmd, USCSI_READ|USCSI_RQENABLE); 16197c478bd9Sstevel@tonic-gate if (ret_val || ucmd.uscsi_status) { 16207c478bd9Sstevel@tonic-gate debug(5, "read failed: %d - %d errno = %d\n", 16217c478bd9Sstevel@tonic-gate ret_val, ucmd.uscsi_status, errno); 16227c478bd9Sstevel@tonic-gate debug(5, "buflen = 0x%x resid = 0x%x sector size = %d\n", 16237c478bd9Sstevel@tonic-gate ucmd.uscsi_buflen, ucmd.uscsi_resid, sector_size); 16247c478bd9Sstevel@tonic-gate debug(5, "cdb addr: %x %x %x %x \n", cdb.g1_addr3, 16257c478bd9Sstevel@tonic-gate cdb.g1_addr2, cdb.g1_addr1, cdb.g1_addr0); 16267c478bd9Sstevel@tonic-gate debug(5, "cdb count: %x %x\n", cdb.g1_count1, 16277c478bd9Sstevel@tonic-gate cdb.g1_count0); 16287c478bd9Sstevel@tonic-gate return (-1); 16297c478bd9Sstevel@tonic-gate } 16307c478bd9Sstevel@tonic-gate ret_val = ucmd.uscsi_buflen - ucmd.uscsi_resid; 16317c478bd9Sstevel@tonic-gate return (ret_val); 16327c478bd9Sstevel@tonic-gate } 16337c478bd9Sstevel@tonic-gate 16347c478bd9Sstevel@tonic-gate static int32_t 16357c478bd9Sstevel@tonic-gate raw_write(door_data_t *door_dp, smedia_services_t *req) 16367c478bd9Sstevel@tonic-gate { 16377c478bd9Sstevel@tonic-gate struct uscsi_cmd ucmd; 16387c478bd9Sstevel@tonic-gate union scsi_cdb cdb; 16397c478bd9Sstevel@tonic-gate int32_t ret_val; 16407c478bd9Sstevel@tonic-gate int32_t num_sectors, sector_size; 16417c478bd9Sstevel@tonic-gate int32_t rc_data[2]; 16427c478bd9Sstevel@tonic-gate char rq_data[RQ_LEN]; 16437c478bd9Sstevel@tonic-gate 16447c478bd9Sstevel@tonic-gate (void) memset((void *) &rc_data, 0, sizeof (rc_data)); 16457c478bd9Sstevel@tonic-gate (void) memset((void *) &ucmd, 0, sizeof (ucmd)); 16467c478bd9Sstevel@tonic-gate (void) memset((void *) &cdb, 0, sizeof (union scsi_cdb)); 16477c478bd9Sstevel@tonic-gate 16487c478bd9Sstevel@tonic-gate if (door_dp->dd_sector_size == 0) { 16497c478bd9Sstevel@tonic-gate sector_size = get_sector_size(door_dp->dd_fd); 16507c478bd9Sstevel@tonic-gate door_dp->dd_sector_size = sector_size; 16517c478bd9Sstevel@tonic-gate } else sector_size = door_dp->dd_sector_size; 16527c478bd9Sstevel@tonic-gate 16537c478bd9Sstevel@tonic-gate 16547c478bd9Sstevel@tonic-gate if ((req->reqraw_write.nbytes > door_dp->dd_buf_len) || 16557c478bd9Sstevel@tonic-gate (door_dp->dd_buf == NULL)) { 16567c478bd9Sstevel@tonic-gate errno = EINVAL; 16577c478bd9Sstevel@tonic-gate return (-1); 16587c478bd9Sstevel@tonic-gate } 16597c478bd9Sstevel@tonic-gate if ((req->reqraw_write.nbytes % sector_size)) { 16607c478bd9Sstevel@tonic-gate errno = EINVAL; 16617c478bd9Sstevel@tonic-gate return (-1); 16627c478bd9Sstevel@tonic-gate } 16637c478bd9Sstevel@tonic-gate 16647c478bd9Sstevel@tonic-gate (void) memset((void *) &cdb, 0, sizeof (cdb)); 16657c478bd9Sstevel@tonic-gate num_sectors = (uint32_t)req->reqraw_write.nbytes/sector_size; 16667c478bd9Sstevel@tonic-gate 16677c478bd9Sstevel@tonic-gate cdb.scc_cmd = SCMD_WRITE_G1; 16687c478bd9Sstevel@tonic-gate FORMG1ADDR(&cdb, (uint32_t)req->reqraw_write.blockno); 16697c478bd9Sstevel@tonic-gate FORMG1COUNT(&cdb, num_sectors); 16707c478bd9Sstevel@tonic-gate 16717c478bd9Sstevel@tonic-gate ucmd.uscsi_cdb = (caddr_t)&cdb; 16727c478bd9Sstevel@tonic-gate ucmd.uscsi_cdblen = CDB_GROUP1; 16737c478bd9Sstevel@tonic-gate ucmd.uscsi_bufaddr = (caddr_t)door_dp->dd_buf; 16747c478bd9Sstevel@tonic-gate ucmd.uscsi_buflen = (uint32_t)req->reqraw_write.nbytes; 16757c478bd9Sstevel@tonic-gate ucmd.uscsi_timeout = 120; /* If 0, HBA hangs forever */ 16767c478bd9Sstevel@tonic-gate ucmd.uscsi_rqlen = RQ_LEN; 16777c478bd9Sstevel@tonic-gate ucmd.uscsi_rqbuf = rq_data; 16787c478bd9Sstevel@tonic-gate ret_val = do_uscsi_cmd(door_dp->dd_fd, 16797c478bd9Sstevel@tonic-gate &ucmd, USCSI_WRITE|USCSI_RQENABLE); 16807c478bd9Sstevel@tonic-gate if (ret_val || ucmd.uscsi_status) { 16817c478bd9Sstevel@tonic-gate debug(5, "write failed: %d - %d errno = %d\n", 16827c478bd9Sstevel@tonic-gate ret_val, ucmd.uscsi_status, errno); 16837c478bd9Sstevel@tonic-gate debug(5, "buflen = 0x%x resid = 0x%x sector size = %d\n", 16847c478bd9Sstevel@tonic-gate ucmd.uscsi_buflen, ucmd.uscsi_resid, sector_size); 16857c478bd9Sstevel@tonic-gate debug(5, "cdb addr: %x %x %x %x \n", cdb.g1_addr3, 16867c478bd9Sstevel@tonic-gate cdb.g1_addr2, cdb.g1_addr1, cdb.g1_addr0); 16877c478bd9Sstevel@tonic-gate debug(5, "cdb count: %x %x\n", cdb.g1_count1, 16887c478bd9Sstevel@tonic-gate cdb.g1_count0); 16897c478bd9Sstevel@tonic-gate return (-1); 16907c478bd9Sstevel@tonic-gate } 16917c478bd9Sstevel@tonic-gate ret_val = ucmd.uscsi_buflen - ucmd.uscsi_resid; 16927c478bd9Sstevel@tonic-gate return (ret_val); 16937c478bd9Sstevel@tonic-gate } 16947c478bd9Sstevel@tonic-gate 16957c478bd9Sstevel@tonic-gate static int32_t 16967c478bd9Sstevel@tonic-gate set_protection_status(door_data_t *door_dp, smedia_services_t *req) 16977c478bd9Sstevel@tonic-gate { 16987c478bd9Sstevel@tonic-gate int32_t ret_val, saved_errno, status; 16997c478bd9Sstevel@tonic-gate struct scsi_inquiry inq; 17007c478bd9Sstevel@tonic-gate char vid[9]; 17017c478bd9Sstevel@tonic-gate char pid[17]; 17027c478bd9Sstevel@tonic-gate struct passwd *pwd; 17037c478bd9Sstevel@tonic-gate char uname[MAXUGNAME + 1]; 17047c478bd9Sstevel@tonic-gate char *new_state, *old_state; 17057c478bd9Sstevel@tonic-gate 17067c478bd9Sstevel@tonic-gate /* 17077c478bd9Sstevel@tonic-gate * Read the current protection state before modifiying. 17087c478bd9Sstevel@tonic-gate * Needed for audit purposes. 17097c478bd9Sstevel@tonic-gate */ 17107c478bd9Sstevel@tonic-gate switch (get_device_type_scsi(door_dp->dd_fd, &inq)) { 17117c478bd9Sstevel@tonic-gate case SCSI_IOMEGA: 17127c478bd9Sstevel@tonic-gate status = scsi_zip_media_status(door_dp->dd_fd); 17137c478bd9Sstevel@tonic-gate ret_val = scsi_zip_write_protect(door_dp->dd_fd, 17147c478bd9Sstevel@tonic-gate &req->reqset_protection_status.prot_state); 17157c478bd9Sstevel@tonic-gate break; 17167c478bd9Sstevel@tonic-gate case SCSI_FLOPPY: 17177c478bd9Sstevel@tonic-gate info("Formatting floppy"); 17187c478bd9Sstevel@tonic-gate status = scsi_floppy_media_status(door_dp->dd_fd); 17197c478bd9Sstevel@tonic-gate ret_val = scsi_floppy_write_protect(door_dp->dd_fd, 17207c478bd9Sstevel@tonic-gate &req->reqset_protection_status.prot_state); 17217c478bd9Sstevel@tonic-gate break; 17227c478bd9Sstevel@tonic-gate case SCSI_GENERIC: 17237c478bd9Sstevel@tonic-gate status = scsi_media_status(door_dp->dd_fd); 17247c478bd9Sstevel@tonic-gate ret_val = scsi_write_protect(door_dp->dd_fd, 17257c478bd9Sstevel@tonic-gate &req->reqset_protection_status.prot_state); 17267c478bd9Sstevel@tonic-gate break; 17277c478bd9Sstevel@tonic-gate } 17287c478bd9Sstevel@tonic-gate 17297c478bd9Sstevel@tonic-gate saved_errno = errno; 17307c478bd9Sstevel@tonic-gate new_state = xlate_state( 17317c478bd9Sstevel@tonic-gate req->reqset_protection_status.prot_state.sm_new_state); 17327c478bd9Sstevel@tonic-gate old_state = xlate_state(status); 17337c478bd9Sstevel@tonic-gate 17347c478bd9Sstevel@tonic-gate if (can_audit()) { 17357c478bd9Sstevel@tonic-gate (void) audit_save_me(door_dp); 17367c478bd9Sstevel@tonic-gate door_dp->audit_text[0] = 0; 17377c478bd9Sstevel@tonic-gate door_dp->audit_text1[0] = 0; 17387c478bd9Sstevel@tonic-gate door_dp->audit_event = AUE_smserverd; 17397c478bd9Sstevel@tonic-gate } 17407c478bd9Sstevel@tonic-gate (void) strlcpy(vid, inq.inq_vid, sizeof (vid)); 17417c478bd9Sstevel@tonic-gate (void) strlcpy(pid, inq.inq_pid, sizeof (pid)); 17427c478bd9Sstevel@tonic-gate if (ret_val < 0) { 17437c478bd9Sstevel@tonic-gate if (errno == EACCES) { 17447c478bd9Sstevel@tonic-gate pwd = getpwuid(door_dp->dd_cred.dc_ruid); 17457c478bd9Sstevel@tonic-gate if (pwd != NULL) { 17467c478bd9Sstevel@tonic-gate (void) strlcpy(uname, 17477c478bd9Sstevel@tonic-gate pwd->pw_name, MAXUGNAME); 17487c478bd9Sstevel@tonic-gate } else uname[0] = 0; 17497c478bd9Sstevel@tonic-gate 17507c478bd9Sstevel@tonic-gate if (can_audit()) { 17517c478bd9Sstevel@tonic-gate (void) snprintf(door_dp->audit_text, 17527c478bd9Sstevel@tonic-gate sizeof (door_dp->audit_text), 17537c478bd9Sstevel@tonic-gate dgettext(TEXT_DOMAIN, "from %s to %s"), 17547c478bd9Sstevel@tonic-gate old_state, new_state); 17557c478bd9Sstevel@tonic-gate 17567c478bd9Sstevel@tonic-gate (void) snprintf(door_dp->audit_text1, 17577c478bd9Sstevel@tonic-gate sizeof (door_dp->audit_text1), 17587c478bd9Sstevel@tonic-gate "%s %s (%d,%d)", vid, pid, 17597c478bd9Sstevel@tonic-gate (int)major(door_dp->dd_stat.st_rdev), 17607c478bd9Sstevel@tonic-gate (int)minor(door_dp->dd_stat.st_rdev)); 17617c478bd9Sstevel@tonic-gate 17627c478bd9Sstevel@tonic-gate door_dp->audit_sorf = 1; 17637c478bd9Sstevel@tonic-gate if (audit_audit(door_dp) == -1) 17647c478bd9Sstevel@tonic-gate warning("Error in writing audit info\n"); 17657c478bd9Sstevel@tonic-gate } 17667c478bd9Sstevel@tonic-gate } /* errno == EACCES */ 17677c478bd9Sstevel@tonic-gate errno = saved_errno; 17687c478bd9Sstevel@tonic-gate return (-1); 17697c478bd9Sstevel@tonic-gate } 17707c478bd9Sstevel@tonic-gate if (can_audit()) { 17717c478bd9Sstevel@tonic-gate (void) snprintf(door_dp->audit_text, 17727c478bd9Sstevel@tonic-gate sizeof (door_dp->audit_text), 17737c478bd9Sstevel@tonic-gate dgettext(TEXT_DOMAIN, "from %s to %s"), 17747c478bd9Sstevel@tonic-gate old_state, new_state); 17757c478bd9Sstevel@tonic-gate 17767c478bd9Sstevel@tonic-gate (void) snprintf(door_dp->audit_text1, 17777c478bd9Sstevel@tonic-gate sizeof (door_dp->audit_text1), 17787c478bd9Sstevel@tonic-gate "%s %s (%d,%d)", vid, pid, 17797c478bd9Sstevel@tonic-gate (int)major(door_dp->dd_stat.st_rdev), 17807c478bd9Sstevel@tonic-gate (int)minor(door_dp->dd_stat.st_rdev)); 17817c478bd9Sstevel@tonic-gate 17827c478bd9Sstevel@tonic-gate door_dp->audit_sorf = 0; 17837c478bd9Sstevel@tonic-gate if (audit_audit(door_dp) == -1) 17847c478bd9Sstevel@tonic-gate warning("Error in writing audit info\n"); 17857c478bd9Sstevel@tonic-gate } 17867c478bd9Sstevel@tonic-gate errno = saved_errno; 17877c478bd9Sstevel@tonic-gate return (0); 17887c478bd9Sstevel@tonic-gate } 17897c478bd9Sstevel@tonic-gate 17907c478bd9Sstevel@tonic-gate static int32_t 17917c478bd9Sstevel@tonic-gate set_shfd(door_data_t *door_dp, int32_t fd, smedia_services_t *req) 17927c478bd9Sstevel@tonic-gate { 17937c478bd9Sstevel@tonic-gate void *fbuf; 17945363f09cSarutz int32_t ret_val = 0; 17957c478bd9Sstevel@tonic-gate 17965363f09cSarutz if ((door_dp->dd_buffd != -1) && (door_dp->dd_buf != NULL)) { 17975363f09cSarutz ret_val = munmap(door_dp->dd_buf, door_dp->dd_buf_len); 17987c478bd9Sstevel@tonic-gate if (ret_val == -1) 17995363f09cSarutz warning(gettext("munmap failed. errno=%d\n"), 18007c478bd9Sstevel@tonic-gate errno); 18017c478bd9Sstevel@tonic-gate (void) close(door_dp->dd_buffd); 18025363f09cSarutz 18037c478bd9Sstevel@tonic-gate door_dp->dd_buffd = -1; 18047c478bd9Sstevel@tonic-gate door_dp->dd_buf = 0; 18057c478bd9Sstevel@tonic-gate door_dp->dd_buf_len = 0; 18067c478bd9Sstevel@tonic-gate } 18075363f09cSarutz 18087c478bd9Sstevel@tonic-gate fbuf = mmap(0, req->reqset_shfd.fdbuf_len, 18097c478bd9Sstevel@tonic-gate PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); 18105363f09cSarutz if (fbuf == MAP_FAILED) { 18115363f09cSarutz ret_val = errno; 18127c478bd9Sstevel@tonic-gate debug(5, "mmap failed. errno=%d\n", errno); 18135363f09cSarutz return (ret_val); 18147c478bd9Sstevel@tonic-gate } 18157c478bd9Sstevel@tonic-gate door_dp->dd_buffd = fd; 18167c478bd9Sstevel@tonic-gate door_dp->dd_buf = fbuf; 18177c478bd9Sstevel@tonic-gate door_dp->dd_buf_len = req->reqset_shfd.fdbuf_len; 18185363f09cSarutz 18197c478bd9Sstevel@tonic-gate return (0); 18207c478bd9Sstevel@tonic-gate } 18217c478bd9Sstevel@tonic-gate 18227c478bd9Sstevel@tonic-gate static int32_t 18237c478bd9Sstevel@tonic-gate reassign_block(door_data_t *door_dp, smedia_services_t *req) 18247c478bd9Sstevel@tonic-gate { 18257c478bd9Sstevel@tonic-gate struct uscsi_cmd ucmd; 18267c478bd9Sstevel@tonic-gate union scsi_cdb cdb; 18277c478bd9Sstevel@tonic-gate int32_t ret_val; 18287c478bd9Sstevel@tonic-gate int32_t sector_size; 18297c478bd9Sstevel@tonic-gate char *read_buf; 18307c478bd9Sstevel@tonic-gate uchar_t mode_data[MD_LEN]; 18317c478bd9Sstevel@tonic-gate 18327c478bd9Sstevel@tonic-gate if (get_mode_page(door_dp->dd_fd, 0, 1, 18337c478bd9Sstevel@tonic-gate mode_data, MD_LEN) < 0) { 18347c478bd9Sstevel@tonic-gate debug(5, "Mode sense failed\n"); 18357c478bd9Sstevel@tonic-gate ret_val = scsi_reassign_block(door_dp->dd_fd, 18367c478bd9Sstevel@tonic-gate req->reqreassign_block.blockno); 18377c478bd9Sstevel@tonic-gate if (ret_val != 0) 18387c478bd9Sstevel@tonic-gate return (-1); 18397c478bd9Sstevel@tonic-gate return (0); 18407c478bd9Sstevel@tonic-gate } 18417c478bd9Sstevel@tonic-gate 18427c478bd9Sstevel@tonic-gate /* 18437c478bd9Sstevel@tonic-gate * No need to check if enough data is returned for 18447c478bd9Sstevel@tonic-gate * AWRE bit or not. 18457c478bd9Sstevel@tonic-gate * It will be 0 otherwise which needs to reassign the block. 18467c478bd9Sstevel@tonic-gate */ 18477c478bd9Sstevel@tonic-gate if (!(mode_data[AWRE_OFFSET] & AWRE)) { 18487c478bd9Sstevel@tonic-gate debug(5, "AWRE bit not set\n"); 18497c478bd9Sstevel@tonic-gate ret_val = scsi_reassign_block(door_dp->dd_fd, 18507c478bd9Sstevel@tonic-gate req->reqreassign_block.blockno); 18517c478bd9Sstevel@tonic-gate if (ret_val != 0) 18527c478bd9Sstevel@tonic-gate return (-1); 18537c478bd9Sstevel@tonic-gate return (0); 18547c478bd9Sstevel@tonic-gate } 18557c478bd9Sstevel@tonic-gate sector_size = (mode_data[BLOCK_LEN_OFFSET] << 16) | 18567c478bd9Sstevel@tonic-gate (mode_data[BLOCK_LEN_OFFSET + 1] << 8) | 18577c478bd9Sstevel@tonic-gate mode_data[BLOCK_LEN_OFFSET + 2]; 18587c478bd9Sstevel@tonic-gate 18597c478bd9Sstevel@tonic-gate debug(5, "REASSIGN BLOCK: sec size = 0x%x\n", sector_size); 18607c478bd9Sstevel@tonic-gate read_buf = (char *)malloc(sector_size); 18617c478bd9Sstevel@tonic-gate if (read_buf == NULL) { 18627c478bd9Sstevel@tonic-gate /* Alloc failed. Atleast reassign the block */ 18637c478bd9Sstevel@tonic-gate ret_val = scsi_reassign_block(door_dp->dd_fd, 18647c478bd9Sstevel@tonic-gate req->reqreassign_block.blockno); 18657c478bd9Sstevel@tonic-gate if (ret_val != 0) 18667c478bd9Sstevel@tonic-gate return (-1); 18677c478bd9Sstevel@tonic-gate return (0); 18687c478bd9Sstevel@tonic-gate } 18697c478bd9Sstevel@tonic-gate 18707c478bd9Sstevel@tonic-gate (void) memset(read_buf, 0, sector_size); 18717c478bd9Sstevel@tonic-gate /* Read the sector */ 18727c478bd9Sstevel@tonic-gate debug(5, "Reading the block %d\n", 18737c478bd9Sstevel@tonic-gate (uint32_t)req->reqreassign_block.blockno); 18747c478bd9Sstevel@tonic-gate 18757c478bd9Sstevel@tonic-gate (void) memset((void *) &ucmd, 0, sizeof (ucmd)); 18767c478bd9Sstevel@tonic-gate (void) memset((void *) &cdb, 0, sizeof (union scsi_cdb)); 18777c478bd9Sstevel@tonic-gate 18787c478bd9Sstevel@tonic-gate cdb.scc_cmd = SCMD_READ_G1; 18797c478bd9Sstevel@tonic-gate FORMG1ADDR(&cdb, req->reqreassign_block.blockno); 18807c478bd9Sstevel@tonic-gate FORMG1COUNT(&cdb, 1); /* One block */ 18817c478bd9Sstevel@tonic-gate 18827c478bd9Sstevel@tonic-gate ucmd.uscsi_cdb = (caddr_t)&cdb; 18837c478bd9Sstevel@tonic-gate ucmd.uscsi_cdblen = CDB_GROUP1; 18847c478bd9Sstevel@tonic-gate ucmd.uscsi_bufaddr = (caddr_t)read_buf; 18857c478bd9Sstevel@tonic-gate ucmd.uscsi_buflen = sector_size; 18867c478bd9Sstevel@tonic-gate ucmd.uscsi_timeout = 120; /* If 0, HBA hangs forever */ 18877c478bd9Sstevel@tonic-gate (void) do_uscsi_cmd(door_dp->dd_fd, &ucmd, USCSI_READ); 18887c478bd9Sstevel@tonic-gate 18897c478bd9Sstevel@tonic-gate /* Write the data back */ 18907c478bd9Sstevel@tonic-gate 18917c478bd9Sstevel@tonic-gate debug(5, "Writing the block %d\n", 18927c478bd9Sstevel@tonic-gate (uint32_t)req->reqreassign_block.blockno); 18937c478bd9Sstevel@tonic-gate (void) memset((void *) &ucmd, 0, sizeof (ucmd)); 18947c478bd9Sstevel@tonic-gate (void) memset((void *) &cdb, 0, sizeof (cdb)); 18957c478bd9Sstevel@tonic-gate 18967c478bd9Sstevel@tonic-gate cdb.scc_cmd = SCMD_WRITE_G1; 18977c478bd9Sstevel@tonic-gate FORMG1ADDR(&cdb, req->reqreassign_block.blockno); 18987c478bd9Sstevel@tonic-gate FORMG1COUNT(&cdb, 1); /* One block */ 18997c478bd9Sstevel@tonic-gate 19007c478bd9Sstevel@tonic-gate ucmd.uscsi_cdb = (caddr_t)&cdb; 19017c478bd9Sstevel@tonic-gate ucmd.uscsi_cdblen = CDB_GROUP1; 19027c478bd9Sstevel@tonic-gate ucmd.uscsi_bufaddr = (caddr_t)read_buf; 19037c478bd9Sstevel@tonic-gate ucmd.uscsi_buflen = sector_size; 19047c478bd9Sstevel@tonic-gate ucmd.uscsi_timeout = 120; /* If 0, HBA hangs forever */ 19057c478bd9Sstevel@tonic-gate ret_val = do_uscsi_cmd(door_dp->dd_fd, &ucmd, USCSI_WRITE); 19067c478bd9Sstevel@tonic-gate free(read_buf); 19077c478bd9Sstevel@tonic-gate if (ret_val || ucmd.uscsi_status) { 19087c478bd9Sstevel@tonic-gate debug(5, "Reassign failed: %d - %d errno = %d\n", 19097c478bd9Sstevel@tonic-gate ret_val, ucmd.uscsi_status, errno); 19107c478bd9Sstevel@tonic-gate ret_val = scsi_reassign_block(door_dp->dd_fd, 19117c478bd9Sstevel@tonic-gate req->reqreassign_block.blockno); 19127c478bd9Sstevel@tonic-gate if (ret_val != 0) 19137c478bd9Sstevel@tonic-gate return (-1); 19147c478bd9Sstevel@tonic-gate return (0); 19157c478bd9Sstevel@tonic-gate } 19167c478bd9Sstevel@tonic-gate 19177c478bd9Sstevel@tonic-gate return (0); 19187c478bd9Sstevel@tonic-gate } 19197c478bd9Sstevel@tonic-gate 19207c478bd9Sstevel@tonic-gate static void 19217c478bd9Sstevel@tonic-gate close_door_descs(door_desc_t *dp, uint_t ndesc) 19227c478bd9Sstevel@tonic-gate { 19237c478bd9Sstevel@tonic-gate while (ndesc > 0) { 19247c478bd9Sstevel@tonic-gate int fd = dp->d_data.d_desc.d_descriptor; 19257c478bd9Sstevel@tonic-gate if (dp->d_attributes & DOOR_DESCRIPTOR) 19267c478bd9Sstevel@tonic-gate (void) close(fd); 19277c478bd9Sstevel@tonic-gate dp++; 19287c478bd9Sstevel@tonic-gate ndesc--; 19297c478bd9Sstevel@tonic-gate } 19307c478bd9Sstevel@tonic-gate } 19317c478bd9Sstevel@tonic-gate 19325363f09cSarutz /* 19335363f09cSarutz * This is a Death Door's service procedure. 19345363f09cSarutz * 19355363f09cSarutz * This procedure is a NOP because the Death Door functionality 19365363f09cSarutz * is no longer used and will be removed in the future. 19375363f09cSarutz */ 19385363f09cSarutz /*ARGSUSED*/ 19397c478bd9Sstevel@tonic-gate static void 19405363f09cSarutz death_servproc(void *cookie, char *argp, size_t arg_size, 19415363f09cSarutz door_desc_t *dp, uint_t ndesc) 19425363f09cSarutz { 19435363f09cSarutz debug(1, "death_servproc[%d]: argp = 0x%p " 19445363f09cSarutz "Death Door[%d]\n", pthread_self(), (void *)argp, 19455363f09cSarutz ((door_data_t *)cookie)->dd_ddoor_descriptor); 19465363f09cSarutz 19475363f09cSarutz (void) door_return(NULL, 0, NULL, 0); 19485363f09cSarutz } 19495363f09cSarutz 19505363f09cSarutz /* 19515363f09cSarutz * This is a Client Door's service procedure. 19525363f09cSarutz * 19535363f09cSarutz * This procedure is specified in the door_create() of a Client Door, 19545363f09cSarutz * and its functionality represents the bulk of services that the 19555363f09cSarutz * rpc.smserverd daemon offers. 19565363f09cSarutz */ 19575363f09cSarutz static void 19585363f09cSarutz client_servproc(void *cookie, char *argp, size_t arg_size, 19597c478bd9Sstevel@tonic-gate door_desc_t *dp, uint_t ndesc) 19607c478bd9Sstevel@tonic-gate { 19617c478bd9Sstevel@tonic-gate smedia_services_t *req; 19627c478bd9Sstevel@tonic-gate smedia_services_t rmsvc; 19637c478bd9Sstevel@tonic-gate smedia_reterror_t reterror; 19647c478bd9Sstevel@tonic-gate smedia_retraw_read_t retraw_read; 19657c478bd9Sstevel@tonic-gate struct scsi_inquiry inq; 19667c478bd9Sstevel@tonic-gate struct dk_minfo media_info; 19677c478bd9Sstevel@tonic-gate struct dk_geom dkgeom; 19687c478bd9Sstevel@tonic-gate int32_t status; 19697c478bd9Sstevel@tonic-gate uchar_t data[18]; 19707c478bd9Sstevel@tonic-gate int32_t completed = 0; 19717c478bd9Sstevel@tonic-gate door_data_t *door_dp; 19727c478bd9Sstevel@tonic-gate size_t retbuf_size; 19737c478bd9Sstevel@tonic-gate struct uscsi_cmd ucmd; 19747c478bd9Sstevel@tonic-gate union scsi_cdb cdb; 19757c478bd9Sstevel@tonic-gate int32_t ret_val, err; 19767c478bd9Sstevel@tonic-gate char rq_data[RQ_LEN]; 19775363f09cSarutz uint_t nexpected_desc; 19787c478bd9Sstevel@tonic-gate struct vtoc vtoc; 1979*342440ecSPrasad Singamsetty struct extvtoc extvtoc; 19807c478bd9Sstevel@tonic-gate 19817c478bd9Sstevel@tonic-gate door_dp = (door_data_t *)cookie; 19827c478bd9Sstevel@tonic-gate req = (smedia_services_t *)((void *)argp); 19837c478bd9Sstevel@tonic-gate 19845363f09cSarutz debug(10, "client_servproc[%d]...\n", pthread_self()); 19857c478bd9Sstevel@tonic-gate 19867c478bd9Sstevel@tonic-gate if (argp == DOOR_UNREF_DATA) { 19875363f09cSarutz debug(5, "client_servproc[%d]: req = DOOR_UNREF_DATA\n", 19887c478bd9Sstevel@tonic-gate pthread_self()); 19897c478bd9Sstevel@tonic-gate debug(5, "Client has exited. Cleaning up resources\n"); 19905363f09cSarutz 19917c478bd9Sstevel@tonic-gate (void) mutex_lock(&svcstate_lock); 19927c478bd9Sstevel@tonic-gate svccount--; 19937c478bd9Sstevel@tonic-gate (void) mutex_unlock(&svcstate_lock); 19945363f09cSarutz 19957c478bd9Sstevel@tonic-gate cleanup(door_dp); 19965363f09cSarutz return; 19977c478bd9Sstevel@tonic-gate } 19985363f09cSarutz 19997c478bd9Sstevel@tonic-gate (void) mutex_lock(&svcstate_lock); 20007c478bd9Sstevel@tonic-gate svcstate = _SERVED; 20017c478bd9Sstevel@tonic-gate (void) mutex_unlock(&svcstate_lock); 20027c478bd9Sstevel@tonic-gate 20037c478bd9Sstevel@tonic-gate rmsvc.in.cnum = req->in.cnum; 20045363f09cSarutz debug(5, "client_servproc[%d]: req = %s\n", pthread_self(), 20057c478bd9Sstevel@tonic-gate xlate_cnum(req->in.cnum)); 20067c478bd9Sstevel@tonic-gate 20077c478bd9Sstevel@tonic-gate /* 20087c478bd9Sstevel@tonic-gate * Our caller may have passed more descriptors than we expected. 20097c478bd9Sstevel@tonic-gate * If so, we silently close (and ignore) them. 20107c478bd9Sstevel@tonic-gate */ 20115363f09cSarutz nexpected_desc = (req->in.cnum == SMEDIA_CNUM_SET_SHFD) ? 1 : 0; 20125363f09cSarutz if (ndesc > nexpected_desc) { 20135363f09cSarutz close_door_descs(dp + nexpected_desc, ndesc - nexpected_desc); 20145363f09cSarutz } 20157c478bd9Sstevel@tonic-gate 20167c478bd9Sstevel@tonic-gate switch (req->in.cnum) { 20177c478bd9Sstevel@tonic-gate default: 20185363f09cSarutz debug(5, "client_servproc: unknown command %d\n", req->in.cnum); 20197c478bd9Sstevel@tonic-gate door_ret_err(&reterror, ENOTSUP); 20207c478bd9Sstevel@tonic-gate break; 20217c478bd9Sstevel@tonic-gate 20227c478bd9Sstevel@tonic-gate case SMEDIA_CNUM_SET_SHFD: 20237c478bd9Sstevel@tonic-gate if (ndesc == 0) 20247c478bd9Sstevel@tonic-gate door_ret_err(&reterror, EINVAL); 20257c478bd9Sstevel@tonic-gate /* 20265363f09cSarutz * Allocate shared memory for this connection. 20275363f09cSarutz * If this connection already has shared memory, 20285363f09cSarutz * deallocate before doing the allocation. 20297c478bd9Sstevel@tonic-gate */ 20305363f09cSarutz ret_val = set_shfd(door_dp, dp->d_data.d_desc.d_descriptor, 20315363f09cSarutz req); 20327c478bd9Sstevel@tonic-gate if (ret_val == 0) { 20337c478bd9Sstevel@tonic-gate reterror.cnum = SMEDIA_CNUM_SET_SHFD; 20347c478bd9Sstevel@tonic-gate reterror.errnum = 0; 20355363f09cSarutz 20367c478bd9Sstevel@tonic-gate my_door_return((char *)&reterror, 20377c478bd9Sstevel@tonic-gate sizeof (smedia_reterror_t), 0, 0); 20387c478bd9Sstevel@tonic-gate } else { 20397c478bd9Sstevel@tonic-gate (void) close(dp->d_data.d_desc.d_descriptor); 20405363f09cSarutz door_ret_err(&reterror, ret_val); 20417c478bd9Sstevel@tonic-gate } 20427c478bd9Sstevel@tonic-gate break; 20437c478bd9Sstevel@tonic-gate 20447c478bd9Sstevel@tonic-gate case SMEDIA_CNUM_RAW_READ: 20457c478bd9Sstevel@tonic-gate debug(10, " arg size = %d blk num=0x%x nbytes = 0x%x \n", 20467c478bd9Sstevel@tonic-gate (int)arg_size, 20477c478bd9Sstevel@tonic-gate (uint32_t)req->reqraw_read.blockno, 20487c478bd9Sstevel@tonic-gate req->reqraw_read.nbytes); 20497c478bd9Sstevel@tonic-gate retbuf_size = sizeof (smedia_retraw_read_t); 20507c478bd9Sstevel@tonic-gate if (req->reqraw_read.nbytes == 0) { 20517c478bd9Sstevel@tonic-gate /* Nothing to write */ 20527c478bd9Sstevel@tonic-gate rmsvc.retraw_write.nbytes = 0; 20537c478bd9Sstevel@tonic-gate my_door_return((char *)&rmsvc, 20547c478bd9Sstevel@tonic-gate sizeof (smedia_retraw_write_t), 0, 0); 20557c478bd9Sstevel@tonic-gate } 20567c478bd9Sstevel@tonic-gate retraw_read.cnum = SMEDIA_CNUM_RAW_READ; 20577c478bd9Sstevel@tonic-gate ret_val = raw_read(door_dp, req); 20587c478bd9Sstevel@tonic-gate if (ret_val == -1) { 20597c478bd9Sstevel@tonic-gate door_ret_err(&reterror, errno); 20607c478bd9Sstevel@tonic-gate } 20617c478bd9Sstevel@tonic-gate retraw_read.nbytes = ret_val; 20627c478bd9Sstevel@tonic-gate my_door_return((char *)&retraw_read, retbuf_size, 0, 0); 20637c478bd9Sstevel@tonic-gate break; 20647c478bd9Sstevel@tonic-gate 20657c478bd9Sstevel@tonic-gate case SMEDIA_CNUM_USCSI_CMD: 20667c478bd9Sstevel@tonic-gate retbuf_size = sizeof (smedia_retuscsi_cmd_t); 20677c478bd9Sstevel@tonic-gate rmsvc.retuscsi_cmd.cnum = SMEDIA_CNUM_USCSI_CMD; 20687c478bd9Sstevel@tonic-gate ucmd.uscsi_flags = req->requscsi_cmd.uscsi_flags; 20697c478bd9Sstevel@tonic-gate ucmd.uscsi_cdb = (caddr_t)&req->requscsi_cmd.uscsi_cdb; 20707c478bd9Sstevel@tonic-gate ucmd.uscsi_cdblen = req->requscsi_cmd.uscsi_cdblen; 20717c478bd9Sstevel@tonic-gate ucmd.uscsi_bufaddr = (caddr_t)door_dp->dd_buf; 20727c478bd9Sstevel@tonic-gate ucmd.uscsi_buflen = req->requscsi_cmd.uscsi_buflen; 20737c478bd9Sstevel@tonic-gate ucmd.uscsi_timeout = req->requscsi_cmd.uscsi_timeout; 20747c478bd9Sstevel@tonic-gate ucmd.uscsi_rqlen = req->requscsi_cmd.uscsi_rqlen; 20757c478bd9Sstevel@tonic-gate ucmd.uscsi_rqbuf = (caddr_t)&rmsvc.retuscsi_cmd.uscsi_rqbuf; 20765363f09cSarutz debug(5, "USCSI CMD 0x%x requested.\n", 20777c478bd9Sstevel@tonic-gate req->requscsi_cmd.uscsi_cdb[0]); 20787c478bd9Sstevel@tonic-gate /* 20797c478bd9Sstevel@tonic-gate * Check the device type and invalid flags specified. 20807c478bd9Sstevel@tonic-gate * We permit operations only on CDROM devices types. 20817c478bd9Sstevel@tonic-gate */ 20825363f09cSarutz errno = invalid_uscsi_operation(door_dp, &ucmd); 20837c478bd9Sstevel@tonic-gate if (errno) { 20847c478bd9Sstevel@tonic-gate door_ret_err(&reterror, errno); 20857c478bd9Sstevel@tonic-gate } 20867c478bd9Sstevel@tonic-gate 20877c478bd9Sstevel@tonic-gate if ((req->requscsi_cmd.uscsi_buflen) && 20887c478bd9Sstevel@tonic-gate ((req->requscsi_cmd.uscsi_buflen > door_dp->dd_buf_len) || 20897c478bd9Sstevel@tonic-gate (door_dp->dd_buf == NULL))) { 20905363f09cSarutz debug(5, "uscsi_cmd failed: uscsi_buflen=0x%x " 20915363f09cSarutz "dd_buf_len=0x%x dd_buf=0x%p\n", 20927c478bd9Sstevel@tonic-gate req->requscsi_cmd.uscsi_buflen, 20937c478bd9Sstevel@tonic-gate door_dp->dd_buf_len, 20947c478bd9Sstevel@tonic-gate door_dp->dd_buf); 20957c478bd9Sstevel@tonic-gate errno = EINVAL; 20967c478bd9Sstevel@tonic-gate door_ret_err(&reterror, errno); 20977c478bd9Sstevel@tonic-gate } 20987c478bd9Sstevel@tonic-gate ret_val = do_uscsi_cmd(door_dp->dd_fd, 20997c478bd9Sstevel@tonic-gate &ucmd, req->requscsi_cmd.uscsi_flags); 21007c478bd9Sstevel@tonic-gate rmsvc.retuscsi_cmd.uscsi_status = ucmd.uscsi_status; 21017c478bd9Sstevel@tonic-gate rmsvc.retuscsi_cmd.uscsi_resid = ucmd.uscsi_resid; 21027c478bd9Sstevel@tonic-gate rmsvc.retuscsi_cmd.uscsi_rqstatus = ucmd.uscsi_rqstatus; 21037c478bd9Sstevel@tonic-gate rmsvc.retuscsi_cmd.uscsi_rqresid = ucmd.uscsi_rqresid; 21047c478bd9Sstevel@tonic-gate rmsvc.retuscsi_cmd.uscsi_retval = ret_val; 21057c478bd9Sstevel@tonic-gate rmsvc.retuscsi_cmd.uscsi_errno = errno; 21067c478bd9Sstevel@tonic-gate if (ret_val || ucmd.uscsi_status) { 21077c478bd9Sstevel@tonic-gate debug(5, "uscsi_cmd failed: %d - %d errno = %d\n", 21087c478bd9Sstevel@tonic-gate ret_val, ucmd.uscsi_status, errno); 21097c478bd9Sstevel@tonic-gate } 21107c478bd9Sstevel@tonic-gate my_door_return((char *)&rmsvc, retbuf_size, 0, 0); 21117c478bd9Sstevel@tonic-gate break; 21127c478bd9Sstevel@tonic-gate 21137c478bd9Sstevel@tonic-gate case SMEDIA_CNUM_RAW_WRITE: 21147c478bd9Sstevel@tonic-gate if (req->reqraw_write.nbytes == 0) { 21157c478bd9Sstevel@tonic-gate /* Nothing to write */ 21167c478bd9Sstevel@tonic-gate rmsvc.retraw_write.nbytes = 0; 21177c478bd9Sstevel@tonic-gate my_door_return((char *)&rmsvc, 21187c478bd9Sstevel@tonic-gate sizeof (smedia_retraw_write_t), 0, 0); 21197c478bd9Sstevel@tonic-gate } 21207c478bd9Sstevel@tonic-gate ret_val = raw_write(door_dp, req); 21217c478bd9Sstevel@tonic-gate if (ret_val == -1) 21227c478bd9Sstevel@tonic-gate door_ret_err(&reterror, errno); 21237c478bd9Sstevel@tonic-gate rmsvc.retraw_write.nbytes = ret_val; 21247c478bd9Sstevel@tonic-gate my_door_return((char *)&rmsvc, sizeof (smedia_retraw_write_t), 21257c478bd9Sstevel@tonic-gate 0, 0); 21267c478bd9Sstevel@tonic-gate break; 21277c478bd9Sstevel@tonic-gate 21287c478bd9Sstevel@tonic-gate case SMEDIA_CNUM_GET_DEVICE_INFO: 21297c478bd9Sstevel@tonic-gate 21307c478bd9Sstevel@tonic-gate (void) memset((void *) &inq, 0, sizeof (inq)); 21317c478bd9Sstevel@tonic-gate (void) memset((void *) &ucmd, 0, sizeof (ucmd)); 21327c478bd9Sstevel@tonic-gate (void) memset((void *) &cdb, 0, sizeof (union scsi_cdb)); 21337c478bd9Sstevel@tonic-gate cdb.scc_cmd = SCMD_INQUIRY; 21347c478bd9Sstevel@tonic-gate FORMG0COUNT(&cdb, sizeof (inq)); 21357c478bd9Sstevel@tonic-gate ucmd.uscsi_cdb = (caddr_t)&cdb; 21367c478bd9Sstevel@tonic-gate ucmd.uscsi_cdblen = CDB_GROUP0; 21377c478bd9Sstevel@tonic-gate ucmd.uscsi_bufaddr = (caddr_t)&inq; 21387c478bd9Sstevel@tonic-gate ucmd.uscsi_buflen = sizeof (inq); 21397c478bd9Sstevel@tonic-gate ucmd.uscsi_timeout = 120; /* If 0, HBA hangs forever */ 21407c478bd9Sstevel@tonic-gate ucmd.uscsi_rqlen = RQ_LEN; 21417c478bd9Sstevel@tonic-gate ucmd.uscsi_rqbuf = rq_data; 21427c478bd9Sstevel@tonic-gate ret_val = do_uscsi_cmd(door_dp->dd_fd, 21437c478bd9Sstevel@tonic-gate &ucmd, USCSI_READ|USCSI_RQENABLE); 21447c478bd9Sstevel@tonic-gate if (ret_val || ucmd.uscsi_status) { 21457c478bd9Sstevel@tonic-gate debug(5, "inquiry failed: %d - %d errno = %d\n", 21467c478bd9Sstevel@tonic-gate ret_val, ucmd.uscsi_status, errno); 21477c478bd9Sstevel@tonic-gate door_ret_err(&reterror, errno); 21487c478bd9Sstevel@tonic-gate } 21497c478bd9Sstevel@tonic-gate 21507c478bd9Sstevel@tonic-gate debug(5, "%s\n", inq.inq_vid); 21517c478bd9Sstevel@tonic-gate debug(5, "%s\n", rmsvc.retget_device_info.sm_vendor_name); 21527c478bd9Sstevel@tonic-gate 21537c478bd9Sstevel@tonic-gate (void) strlcpy(rmsvc.retget_device_info.sm_vendor_name, 21547c478bd9Sstevel@tonic-gate inq.inq_vid, 8); 21557c478bd9Sstevel@tonic-gate rmsvc.retget_device_info.sm_vendor_name[8] = 0; 21567c478bd9Sstevel@tonic-gate (void) strlcpy(rmsvc.retget_device_info.sm_product_name, 21577c478bd9Sstevel@tonic-gate inq.inq_pid, 16); 21587c478bd9Sstevel@tonic-gate rmsvc.retget_device_info.sm_product_name[16] = 0; 21597c478bd9Sstevel@tonic-gate (void) strlcpy(rmsvc.retget_device_info.sm_firmware_version, 21607c478bd9Sstevel@tonic-gate inq.inq_revision, 4); 21617c478bd9Sstevel@tonic-gate rmsvc.retget_device_info.sm_firmware_version[4] = ' '; 21627c478bd9Sstevel@tonic-gate (void) strlcpy( 21637c478bd9Sstevel@tonic-gate &rmsvc.retget_device_info.sm_firmware_version[5], 21647c478bd9Sstevel@tonic-gate inq.inq_serial, 12); 21657c478bd9Sstevel@tonic-gate rmsvc.retget_device_info.sm_product_name[17] = 0; 21667c478bd9Sstevel@tonic-gate 21677c478bd9Sstevel@tonic-gate rmsvc.retget_device_info.sm_interface_type = IF_SCSI; 21687c478bd9Sstevel@tonic-gate 21695363f09cSarutz debug(5, "Vendor name = %s\n", 21705363f09cSarutz rmsvc.retget_device_info.sm_vendor_name); 21715363f09cSarutz debug(5, "product name = %s\n", 21725363f09cSarutz rmsvc.retget_device_info.sm_product_name); 21735363f09cSarutz debug(5, "Firmware revision = %s\n", 21745363f09cSarutz rmsvc.retget_device_info.sm_firmware_version); 21755363f09cSarutz 21767c478bd9Sstevel@tonic-gate my_door_return((char *)&rmsvc.retget_device_info, 21777c478bd9Sstevel@tonic-gate sizeof (smedia_retget_device_info_t), 0, 0); 21787c478bd9Sstevel@tonic-gate break; 21797c478bd9Sstevel@tonic-gate 21807c478bd9Sstevel@tonic-gate case SMEDIA_CNUM_GET_MEDIUM_PROPERTY: 21817c478bd9Sstevel@tonic-gate 21827c478bd9Sstevel@tonic-gate (void) memset((void *)&rmsvc.retget_medium_property.smprop, 21837c478bd9Sstevel@tonic-gate 0, sizeof (smmedium_prop_t)); 21847c478bd9Sstevel@tonic-gate 21857c478bd9Sstevel@tonic-gate ret_val = ioctl(door_dp->dd_fd, DKIOCGMEDIAINFO, &media_info); 21867c478bd9Sstevel@tonic-gate 21877c478bd9Sstevel@tonic-gate if (ret_val < 0) { 21887c478bd9Sstevel@tonic-gate uint32_t capacity; 21897c478bd9Sstevel@tonic-gate uint32_t blocksize; 21907c478bd9Sstevel@tonic-gate /* 21917c478bd9Sstevel@tonic-gate * Devices may fail DKIOCGMEDIAINFO if an unformed 21927c478bd9Sstevel@tonic-gate * media is inserted. We can get the capacity 21937c478bd9Sstevel@tonic-gate * information from the SCMD_READ_FORMAT_CAP command. 21947c478bd9Sstevel@tonic-gate */ 21957c478bd9Sstevel@tonic-gate 21965363f09cSarutz debug(5, "DKIOCGMEDIAINFO failed; using " 21975363f09cSarutz "SCMD_READ_FORMAT_CAP"); 21987c478bd9Sstevel@tonic-gate ret_val = get_media_capacity(door_dp->dd_fd, 21997c478bd9Sstevel@tonic-gate &capacity, &blocksize); 22007c478bd9Sstevel@tonic-gate 22017c478bd9Sstevel@tonic-gate if (ret_val >= 0) { 22027c478bd9Sstevel@tonic-gate media_info.dki_lbsize = blocksize; 22037c478bd9Sstevel@tonic-gate media_info.dki_capacity = capacity; 22047c478bd9Sstevel@tonic-gate } else { 22057c478bd9Sstevel@tonic-gate debug(5, "SCMD_READ_FORMAT_CAP failed"); 22067c478bd9Sstevel@tonic-gate door_ret_err(&reterror, errno); 22077c478bd9Sstevel@tonic-gate } 22087c478bd9Sstevel@tonic-gate } 22097c478bd9Sstevel@tonic-gate rmsvc.retget_medium_property.smprop.sm_blocksize = 22107c478bd9Sstevel@tonic-gate media_info.dki_lbsize; 22117c478bd9Sstevel@tonic-gate rmsvc.retget_medium_property.smprop.sm_capacity = 22127c478bd9Sstevel@tonic-gate media_info.dki_capacity; 22137c478bd9Sstevel@tonic-gate 22147c478bd9Sstevel@tonic-gate rmsvc.retget_medium_property.smprop.sm_media_type = 22157c478bd9Sstevel@tonic-gate media_info.dki_media_type; 22167c478bd9Sstevel@tonic-gate /* 22177c478bd9Sstevel@tonic-gate * These devices show as SCSI devices but we need to treat it 22187c478bd9Sstevel@tonic-gate * differently. so we need a seperate class. 22197c478bd9Sstevel@tonic-gate */ 22207c478bd9Sstevel@tonic-gate if (get_device_type_scsi(door_dp->dd_fd, &inq) == SCSI_FLOPPY) { 22217c478bd9Sstevel@tonic-gate rmsvc.retget_medium_property.smprop.sm_media_type = 22227c478bd9Sstevel@tonic-gate SM_SCSI_FLOPPY; 22237c478bd9Sstevel@tonic-gate } 22247c478bd9Sstevel@tonic-gate 22257c478bd9Sstevel@tonic-gate /* Check for EFI type because DKIOCGGEOM does not support EFI */ 2226*342440ecSPrasad Singamsetty ret_val = ioctl(door_dp->dd_fd, DKIOCGEXTVTOC, &extvtoc); 2227*342440ecSPrasad Singamsetty if (ret_val < 0 && errno == ENOTTY) 22287c478bd9Sstevel@tonic-gate ret_val = ioctl(door_dp->dd_fd, DKIOCGVTOC, &vtoc); 2229*342440ecSPrasad Singamsetty 22307c478bd9Sstevel@tonic-gate if (!((ret_val < 0) && (errno == ENOTSUP))) { 22317c478bd9Sstevel@tonic-gate ret_val = ioctl(door_dp->dd_fd, DKIOCGGEOM, &dkgeom); 22327c478bd9Sstevel@tonic-gate if (ret_val < 0) { 22337c478bd9Sstevel@tonic-gate /* 22347c478bd9Sstevel@tonic-gate * DKIOCGGEOM may fail for unformed floppies. 22357c478bd9Sstevel@tonic-gate * We need to generate the appropriate geometry 22367c478bd9Sstevel@tonic-gate * information. 22377c478bd9Sstevel@tonic-gate */ 22387c478bd9Sstevel@tonic-gate if (rmsvc.retget_medium_property.smprop. 22397c478bd9Sstevel@tonic-gate sm_media_type == SM_SCSI_FLOPPY) { 22407c478bd9Sstevel@tonic-gate ret_val = get_floppy_geom( 22417c478bd9Sstevel@tonic-gate door_dp->dd_fd, 22427c478bd9Sstevel@tonic-gate media_info.dki_capacity, &dkgeom); 22437c478bd9Sstevel@tonic-gate 22447c478bd9Sstevel@tonic-gate if (ret_val < 0) { 22457c478bd9Sstevel@tonic-gate debug(5, "Cannot determine " 22467c478bd9Sstevel@tonic-gate "media size"); 22477c478bd9Sstevel@tonic-gate door_ret_err(&reterror, errno); 22487c478bd9Sstevel@tonic-gate } 22497c478bd9Sstevel@tonic-gate } else { 22507c478bd9Sstevel@tonic-gate #ifdef sparc 22517c478bd9Sstevel@tonic-gate debug(5, "DKIOCGGEOM ioctl failed"); 22527c478bd9Sstevel@tonic-gate door_ret_err(&reterror, errno); 22537c478bd9Sstevel@tonic-gate #else /* !sparc */ 22547c478bd9Sstevel@tonic-gate /* 22557c478bd9Sstevel@tonic-gate * Try getting Physical geometry on x86. 22567c478bd9Sstevel@tonic-gate */ 22577c478bd9Sstevel@tonic-gate ret_val = ioctl(door_dp->dd_fd, 22587c478bd9Sstevel@tonic-gate DKIOCG_PHYGEOM, &dkgeom); 22597c478bd9Sstevel@tonic-gate if (ret_val < 0) { 22607c478bd9Sstevel@tonic-gate debug(5, "DKIOCG_PHYGEOM " 22617c478bd9Sstevel@tonic-gate "ioctl failed"); 22627c478bd9Sstevel@tonic-gate door_ret_err(&reterror, errno); 22637c478bd9Sstevel@tonic-gate } 22647c478bd9Sstevel@tonic-gate #endif /* sparc */ 22657c478bd9Sstevel@tonic-gate } 22667c478bd9Sstevel@tonic-gate } 22677c478bd9Sstevel@tonic-gate 22687c478bd9Sstevel@tonic-gate 22697c478bd9Sstevel@tonic-gate /* 22707c478bd9Sstevel@tonic-gate * Some faked geometry may not have pcyl filled in so 22717c478bd9Sstevel@tonic-gate * later calculations using this field will be 22727c478bd9Sstevel@tonic-gate * incorrect. We will substitute it with the number of 22737c478bd9Sstevel@tonic-gate * available cylinders. 22747c478bd9Sstevel@tonic-gate */ 22757c478bd9Sstevel@tonic-gate if (dkgeom.dkg_pcyl == 0) 22767c478bd9Sstevel@tonic-gate rmsvc.retget_medium_property.smprop.sm_pcyl = 22777c478bd9Sstevel@tonic-gate dkgeom.dkg_ncyl; 22787c478bd9Sstevel@tonic-gate else 22797c478bd9Sstevel@tonic-gate rmsvc.retget_medium_property.smprop.sm_pcyl = 22807c478bd9Sstevel@tonic-gate dkgeom.dkg_pcyl; 22817c478bd9Sstevel@tonic-gate 22827c478bd9Sstevel@tonic-gate rmsvc.retget_medium_property.smprop.sm_nhead = 22837c478bd9Sstevel@tonic-gate dkgeom.dkg_nhead; 22847c478bd9Sstevel@tonic-gate rmsvc.retget_medium_property.smprop.sm_nsect = 22857c478bd9Sstevel@tonic-gate dkgeom.dkg_nsect; 22867c478bd9Sstevel@tonic-gate } 22877c478bd9Sstevel@tonic-gate 22887c478bd9Sstevel@tonic-gate debug(1, "properties are: lbasize = %d, cap = %llu", 22897c478bd9Sstevel@tonic-gate media_info.dki_lbsize, media_info.dki_capacity); 22907c478bd9Sstevel@tonic-gate 22917c478bd9Sstevel@tonic-gate my_door_return((char *)&rmsvc.retget_medium_property, 22927c478bd9Sstevel@tonic-gate sizeof (smedia_retget_medium_property_t), 0, 0); 22937c478bd9Sstevel@tonic-gate break; 22947c478bd9Sstevel@tonic-gate 22957c478bd9Sstevel@tonic-gate case SMEDIA_CNUM_GET_PROTECTION_STATUS: 22967c478bd9Sstevel@tonic-gate switch (get_device_type_scsi(door_dp->dd_fd, &inq)) { 22977c478bd9Sstevel@tonic-gate case SCSI_FLOPPY: 22987c478bd9Sstevel@tonic-gate status = scsi_floppy_media_status(door_dp->dd_fd); 22997c478bd9Sstevel@tonic-gate break; 23007c478bd9Sstevel@tonic-gate case SCSI_IOMEGA: 23017c478bd9Sstevel@tonic-gate status = scsi_zip_media_status(door_dp->dd_fd); 23027c478bd9Sstevel@tonic-gate break; 23037c478bd9Sstevel@tonic-gate case SCSI_GENERIC: 23047c478bd9Sstevel@tonic-gate status = scsi_media_status(door_dp->dd_fd); 23057c478bd9Sstevel@tonic-gate break; 23067c478bd9Sstevel@tonic-gate default: 23077c478bd9Sstevel@tonic-gate door_ret_err(&reterror, errno); 23087c478bd9Sstevel@tonic-gate } 23097c478bd9Sstevel@tonic-gate if (status < 0) 23107c478bd9Sstevel@tonic-gate door_ret_err(&reterror, errno); 23117c478bd9Sstevel@tonic-gate 23127c478bd9Sstevel@tonic-gate rmsvc.retget_protection_status.prot_state.sm_new_state = 23137c478bd9Sstevel@tonic-gate status; 23147c478bd9Sstevel@tonic-gate 23157c478bd9Sstevel@tonic-gate my_door_return((char *)&rmsvc.retget_protection_status, 23167c478bd9Sstevel@tonic-gate sizeof (smedia_retget_protection_status_t), 0, 0); 23177c478bd9Sstevel@tonic-gate break; 23187c478bd9Sstevel@tonic-gate 23197c478bd9Sstevel@tonic-gate case SMEDIA_CNUM_SET_PROTECTION_STATUS: 23207c478bd9Sstevel@tonic-gate 23217c478bd9Sstevel@tonic-gate ret_val = set_protection_status(door_dp, req); 23227c478bd9Sstevel@tonic-gate if (ret_val == -1) 23237c478bd9Sstevel@tonic-gate door_ret_err(&reterror, errno); 23247c478bd9Sstevel@tonic-gate else 23257c478bd9Sstevel@tonic-gate my_door_return((char *)&rmsvc.retset_protection_status, 23267c478bd9Sstevel@tonic-gate sizeof (smedia_retset_protection_status_t), 23277c478bd9Sstevel@tonic-gate 0, 0); 23287c478bd9Sstevel@tonic-gate break; 23297c478bd9Sstevel@tonic-gate 23307c478bd9Sstevel@tonic-gate case SMEDIA_CNUM_FORMAT: 23317c478bd9Sstevel@tonic-gate switch (get_device_type_scsi(door_dp->dd_fd, &inq)) { 23327c478bd9Sstevel@tonic-gate case SCSI_FLOPPY: 23337c478bd9Sstevel@tonic-gate info("formatting floppy"); 23347c478bd9Sstevel@tonic-gate err = scsi_floppy_format(door_dp->dd_fd, 23357c478bd9Sstevel@tonic-gate req->reqformat.flavor, req->reqformat.mode); 23367c478bd9Sstevel@tonic-gate 23377c478bd9Sstevel@tonic-gate break; 23387c478bd9Sstevel@tonic-gate case SCSI_IOMEGA: 23397c478bd9Sstevel@tonic-gate err = scsi_zip_format(door_dp->dd_fd, 23407c478bd9Sstevel@tonic-gate req->reqformat.flavor, req->reqformat.mode); 23417c478bd9Sstevel@tonic-gate break; 23427c478bd9Sstevel@tonic-gate case SCSI_GENERIC: 23437c478bd9Sstevel@tonic-gate err = scsi_format(door_dp->dd_fd, 23447c478bd9Sstevel@tonic-gate req->reqformat.flavor, req->reqformat.mode); 23457c478bd9Sstevel@tonic-gate break; 23467c478bd9Sstevel@tonic-gate default: 23477c478bd9Sstevel@tonic-gate door_ret_err(&reterror, ENOTSUP); 23487c478bd9Sstevel@tonic-gate } 23497c478bd9Sstevel@tonic-gate 23507c478bd9Sstevel@tonic-gate if (err) 23517c478bd9Sstevel@tonic-gate door_ret_err(&reterror, errno); 23527c478bd9Sstevel@tonic-gate my_door_return((char *)&rmsvc.retformat, 23537c478bd9Sstevel@tonic-gate sizeof (smedia_retformat_t), 0, 0); 23547c478bd9Sstevel@tonic-gate 23557c478bd9Sstevel@tonic-gate break; 23567c478bd9Sstevel@tonic-gate 23577c478bd9Sstevel@tonic-gate case SMEDIA_CNUM_CHECK_FORMAT_STATUS: 23587c478bd9Sstevel@tonic-gate 23597c478bd9Sstevel@tonic-gate (void) memset((void *) &cdb, 0, sizeof (union scsi_cdb)); 23607c478bd9Sstevel@tonic-gate (void) memset((void *) &ucmd, 0, sizeof (ucmd)); 23617c478bd9Sstevel@tonic-gate (void) memset((void *) &data, 0, sizeof (data)); 23627c478bd9Sstevel@tonic-gate cdb.scc_cmd = SCMD_REQUEST_SENSE; 23637c478bd9Sstevel@tonic-gate cdb.g0_count0 = sizeof (data); 23647c478bd9Sstevel@tonic-gate ucmd.uscsi_cdb = (caddr_t)&cdb; 23657c478bd9Sstevel@tonic-gate ucmd.uscsi_cdblen = CDB_GROUP0; 23667c478bd9Sstevel@tonic-gate ucmd.uscsi_bufaddr = (caddr_t)&data; 23677c478bd9Sstevel@tonic-gate ucmd.uscsi_buflen = sizeof (data); 23687c478bd9Sstevel@tonic-gate ucmd.uscsi_timeout = 120; /* If 0, HBA hangs forever */ 23697c478bd9Sstevel@tonic-gate ucmd.uscsi_rqlen = RQ_LEN; 23707c478bd9Sstevel@tonic-gate ucmd.uscsi_rqbuf = rq_data; 23717c478bd9Sstevel@tonic-gate ret_val = do_uscsi_cmd(door_dp->dd_fd, 23727c478bd9Sstevel@tonic-gate &ucmd, USCSI_READ|USCSI_RQENABLE); 23737c478bd9Sstevel@tonic-gate if (ret_val || ucmd.uscsi_status) { 23747c478bd9Sstevel@tonic-gate debug(5, "Request sense failed: %d - %d errno = %d\n", 23757c478bd9Sstevel@tonic-gate ret_val, ucmd.uscsi_status, errno); 23767c478bd9Sstevel@tonic-gate door_ret_err(&reterror, errno); 23777c478bd9Sstevel@tonic-gate } 23787c478bd9Sstevel@tonic-gate 23797c478bd9Sstevel@tonic-gate if ((data[0] & 0x7F) == DEFERRED_ERROR) { 23807c478bd9Sstevel@tonic-gate /* Deffered error. The format must have failed */ 23817c478bd9Sstevel@tonic-gate debug(5, "format failed!\n"); 23827c478bd9Sstevel@tonic-gate door_ret_err(&reterror, EIO); 23837c478bd9Sstevel@tonic-gate } 23847c478bd9Sstevel@tonic-gate 23857c478bd9Sstevel@tonic-gate if (data[SKSV_OFFSET] & SKSV_FIELD) { 23867c478bd9Sstevel@tonic-gate completed = 23877c478bd9Sstevel@tonic-gate (data[FORMAT_PROGRESS_INDICATOR_OFFSET_0] << 8) 23887c478bd9Sstevel@tonic-gate | data[FORMAT_PROGRESS_INDICATOR_OFFSET_1]; 23897c478bd9Sstevel@tonic-gate completed = (completed*100/65536); 23907c478bd9Sstevel@tonic-gate } else { 23917c478bd9Sstevel@tonic-gate completed = (100); 23927c478bd9Sstevel@tonic-gate } 23937c478bd9Sstevel@tonic-gate rmsvc.retcheck_format_status.percent_complete = completed; 23947c478bd9Sstevel@tonic-gate my_door_return((char *)&rmsvc.retcheck_format_status, 23957c478bd9Sstevel@tonic-gate sizeof (smedia_retcheck_format_status_t), 0, 0); 23967c478bd9Sstevel@tonic-gate break; 23977c478bd9Sstevel@tonic-gate 23987c478bd9Sstevel@tonic-gate case SMEDIA_CNUM_REASSIGN_BLOCK: 23997c478bd9Sstevel@tonic-gate 24007c478bd9Sstevel@tonic-gate ret_val = reassign_block(door_dp, req); 24017c478bd9Sstevel@tonic-gate if (ret_val == -1) 24027c478bd9Sstevel@tonic-gate door_ret_err(&reterror, errno); 24037c478bd9Sstevel@tonic-gate my_door_return((char *)&rmsvc.retreassign_block, 24047c478bd9Sstevel@tonic-gate sizeof (smedia_retreassign_block_t), 0, 0); 24057c478bd9Sstevel@tonic-gate break; 24067c478bd9Sstevel@tonic-gate 24077c478bd9Sstevel@tonic-gate } /* end of switch */ 24087c478bd9Sstevel@tonic-gate 24097c478bd9Sstevel@tonic-gate debug(10, "Exiting client server...\n"); 24107c478bd9Sstevel@tonic-gate my_door_return((char *)&reterror, sizeof (smedia_reterror_t), 0, 0); 24117c478bd9Sstevel@tonic-gate } 24127c478bd9Sstevel@tonic-gate 24135363f09cSarutz /* 24145363f09cSarutz * This is the service procedure for the door that is associated with 24155363f09cSarutz * the (doorfs) filesystem Door that is created at 'smedia_service'. 24165363f09cSarutz */ 24177c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 24187c478bd9Sstevel@tonic-gate static void 24195363f09cSarutz main_servproc(void *server_data, char *argp, size_t arg_size, 24207c478bd9Sstevel@tonic-gate door_desc_t *dp, uint_t ndesc) 24217c478bd9Sstevel@tonic-gate { 24227c478bd9Sstevel@tonic-gate smedia_services_t *req; 24237c478bd9Sstevel@tonic-gate door_cred_t door_credentials; 24247c478bd9Sstevel@tonic-gate int ret_val; 24257c478bd9Sstevel@tonic-gate door_data_t *ddata; 24267c478bd9Sstevel@tonic-gate smedia_reterror_t reterror; 24277c478bd9Sstevel@tonic-gate smedia_reterror_t retok; 24287c478bd9Sstevel@tonic-gate struct stat stat; 24297c478bd9Sstevel@tonic-gate door_desc_t *didpp; 24307c478bd9Sstevel@tonic-gate struct dk_cinfo dkinfo; 24315363f09cSarutz uint_t nexpected_desc; 24327c478bd9Sstevel@tonic-gate 24335363f09cSarutz debug(10, "Entering main_servproc[%d].\n", pthread_self()); 24347c478bd9Sstevel@tonic-gate 24357c478bd9Sstevel@tonic-gate didpp = dp; 24367c478bd9Sstevel@tonic-gate (void) mutex_lock(&svcstate_lock); 24377c478bd9Sstevel@tonic-gate svcstate = _SERVED; 24387c478bd9Sstevel@tonic-gate (void) mutex_unlock(&svcstate_lock); 24397c478bd9Sstevel@tonic-gate 24407c478bd9Sstevel@tonic-gate reterror.cnum = SMEDIA_CNUM_ERROR; 24417c478bd9Sstevel@tonic-gate reterror.errnum = SMEDIA_FAILURE; 24425363f09cSarutz 24437c478bd9Sstevel@tonic-gate if (argp == NULL) { 24447c478bd9Sstevel@tonic-gate debug(5, "argp is NULL\n"); 24457c478bd9Sstevel@tonic-gate if (ndesc > 0) 24467c478bd9Sstevel@tonic-gate close_door_descs(dp, ndesc); 24477c478bd9Sstevel@tonic-gate my_door_return((char *)&reterror, 24487c478bd9Sstevel@tonic-gate sizeof (smedia_reterror_t), 0, 0); 24497c478bd9Sstevel@tonic-gate } 24507c478bd9Sstevel@tonic-gate 24517c478bd9Sstevel@tonic-gate req = (smedia_services_t *)((void *)argp); 24525363f09cSarutz 24537c478bd9Sstevel@tonic-gate retok.cnum = req->in.cnum; 24547c478bd9Sstevel@tonic-gate retok.errnum = 0; 24557c478bd9Sstevel@tonic-gate 24567c478bd9Sstevel@tonic-gate debug(5, "req = %s arg_size = 0x%x \n", 24577c478bd9Sstevel@tonic-gate xlate_cnum(req->reqopen.cnum), arg_size); 24587c478bd9Sstevel@tonic-gate 24597c478bd9Sstevel@tonic-gate /* 24607c478bd9Sstevel@tonic-gate * Our caller may have passed more descriptors than we expected. 24617c478bd9Sstevel@tonic-gate * If so, we silently close (and ignore) them. 24627c478bd9Sstevel@tonic-gate */ 24635363f09cSarutz nexpected_desc = (req->in.cnum == SMEDIA_CNUM_OPEN_FD) ? 1 : 0; 24645363f09cSarutz if (ndesc > nexpected_desc) { 24655363f09cSarutz close_door_descs(dp + nexpected_desc, ndesc - nexpected_desc); 24665363f09cSarutz } 24677c478bd9Sstevel@tonic-gate 24687c478bd9Sstevel@tonic-gate switch (req->in.cnum) { 24697c478bd9Sstevel@tonic-gate default: 24705363f09cSarutz debug(5, "main_servproc: unknown command 0x%x\n", 24715363f09cSarutz req->reqopen.cnum); 24727c478bd9Sstevel@tonic-gate break; 24737c478bd9Sstevel@tonic-gate 24747c478bd9Sstevel@tonic-gate case SMEDIA_CNUM_PING: 24757c478bd9Sstevel@tonic-gate /* 24767c478bd9Sstevel@tonic-gate * This service is to indicate that server is up and 24777c478bd9Sstevel@tonic-gate * running. It is usually called from another instance of 24787c478bd9Sstevel@tonic-gate * server that is started. 24797c478bd9Sstevel@tonic-gate */ 24807c478bd9Sstevel@tonic-gate reterror.cnum = SMEDIA_CNUM_PING; 24817c478bd9Sstevel@tonic-gate reterror.errnum = 0; 24827c478bd9Sstevel@tonic-gate my_door_return((char *)&reterror, 24837c478bd9Sstevel@tonic-gate sizeof (smedia_reterror_t), 0, 0); 24847c478bd9Sstevel@tonic-gate break; 24857c478bd9Sstevel@tonic-gate 24867c478bd9Sstevel@tonic-gate 24877c478bd9Sstevel@tonic-gate case SMEDIA_CNUM_OPEN_FD: 24887c478bd9Sstevel@tonic-gate 24897c478bd9Sstevel@tonic-gate debug(5, "ndesc = %d\n", ndesc); 24907c478bd9Sstevel@tonic-gate if (ndesc == 0) { 24917c478bd9Sstevel@tonic-gate my_door_return((char *)&reterror, 24927c478bd9Sstevel@tonic-gate sizeof (smedia_reterror_t), 0, 0); 24937c478bd9Sstevel@tonic-gate } 24945363f09cSarutz debug(5, "Checking file descriptor of target device\n"); 24957c478bd9Sstevel@tonic-gate if (fstat(didpp->d_data.d_desc.d_descriptor, &stat) < 0) { 24965363f09cSarutz warning(gettext("main_servproc:fstat failed. " 24975363f09cSarutz "errno = %d\n"), errno); 24987c478bd9Sstevel@tonic-gate (void) close(didpp->d_data.d_desc.d_descriptor); 24997c478bd9Sstevel@tonic-gate my_door_return((char *)&reterror, 25007c478bd9Sstevel@tonic-gate sizeof (smedia_reterror_t), 0, 0); 25017c478bd9Sstevel@tonic-gate } 25027c478bd9Sstevel@tonic-gate debug(5, "descriptor = %d st_mode = 0x%lx\n", 25037c478bd9Sstevel@tonic-gate didpp->d_data.d_desc.d_descriptor, 25047c478bd9Sstevel@tonic-gate stat.st_mode); 25057c478bd9Sstevel@tonic-gate 25067c478bd9Sstevel@tonic-gate /* Obtain the credentials of the user */ 25077c478bd9Sstevel@tonic-gate ret_val = door_cred(&door_credentials); 25087c478bd9Sstevel@tonic-gate if (ret_val < 0) { 25095363f09cSarutz warning(gettext("main_servproc:door_cred " 25105363f09cSarutz "failed. errno = %d\n"), errno); 25117c478bd9Sstevel@tonic-gate (void) close(didpp->d_data.d_desc.d_descriptor); 25127c478bd9Sstevel@tonic-gate my_door_return((char *)&reterror, 25137c478bd9Sstevel@tonic-gate sizeof (smedia_reterror_t), 0, 0); 25147c478bd9Sstevel@tonic-gate } 25157c478bd9Sstevel@tonic-gate if (ioctl(didpp->d_data.d_desc.d_descriptor, DKIOCINFO, 25167c478bd9Sstevel@tonic-gate &dkinfo) == -1) { 25175363f09cSarutz warning(gettext("main_servproc:DKIOCINFO failed. " 25185363f09cSarutz "errno = %d\n"), errno); 25197c478bd9Sstevel@tonic-gate (void) close(didpp->d_data.d_desc.d_descriptor); 25207c478bd9Sstevel@tonic-gate my_door_return((char *)&reterror, 25217c478bd9Sstevel@tonic-gate sizeof (smedia_reterror_t), 0, 0); 25227c478bd9Sstevel@tonic-gate } 25237c478bd9Sstevel@tonic-gate 25247c478bd9Sstevel@tonic-gate ddata = (door_data_t *)calloc(1, sizeof (door_data_t)); 25257c478bd9Sstevel@tonic-gate if (ddata == NULL) { 25265363f09cSarutz warning(gettext("main_servproc:calloc failed. " 25275363f09cSarutz "errno = %d\n"), errno); 25287c478bd9Sstevel@tonic-gate (void) close(didpp->d_data.d_desc.d_descriptor); 25297c478bd9Sstevel@tonic-gate my_door_return((char *)&reterror, 25307c478bd9Sstevel@tonic-gate sizeof (smedia_reterror_t), 0, 0); 25317c478bd9Sstevel@tonic-gate } 25327c478bd9Sstevel@tonic-gate ddata->dd_stat = stat; 25337c478bd9Sstevel@tonic-gate ddata->dd_cred = door_credentials; 25347c478bd9Sstevel@tonic-gate ddata->dd_fd = didpp->d_data.d_desc.d_descriptor; 25357c478bd9Sstevel@tonic-gate ddata->dd_buf = NULL; 25367c478bd9Sstevel@tonic-gate ddata->dd_buf_len = 0; 25377c478bd9Sstevel@tonic-gate ddata->dd_buffd = -1; 25387c478bd9Sstevel@tonic-gate ddata->dd_sector_size = 0; 25397c478bd9Sstevel@tonic-gate ddata->dd_dkinfo = dkinfo; 25405363f09cSarutz debug(5, "ddata = 0x%p \n", (void *)ddata); 25417c478bd9Sstevel@tonic-gate 25425363f09cSarutz /* specify a function that'll customize our door threads */ 25435363f09cSarutz (void) door_server_create(sm_door_server_create); 25447c478bd9Sstevel@tonic-gate debug(5, "door_server_create called.\n"); 25457c478bd9Sstevel@tonic-gate 25467c478bd9Sstevel@tonic-gate (void) mutex_lock(&ddata->dd_lock); 25477c478bd9Sstevel@tonic-gate 25485363f09cSarutz /* create Client Door */ 25495363f09cSarutz ddata->dd_cdoor_descriptor = 25505363f09cSarutz door_create(client_servproc, 25515363f09cSarutz (void *)ddata, DOOR_PRIVATE | DOOR_NO_CANCEL | DOOR_UNREF); 25525363f09cSarutz 25535363f09cSarutz if (ddata->dd_cdoor_descriptor < 0) { 25545363f09cSarutz /* then door_create() failed */ 25555363f09cSarutz int err = errno; 25565363f09cSarutz 25575363f09cSarutz (void) mutex_unlock(&ddata->dd_lock); 25585363f09cSarutz 25595363f09cSarutz warning(gettext("main_servproc: door_create of Client " 25605363f09cSarutz "Door failed = %d\n"), err); 25617c478bd9Sstevel@tonic-gate free(ddata); 25625363f09cSarutz 25635363f09cSarutz /* close target device */ 25647c478bd9Sstevel@tonic-gate (void) close(didpp->d_data.d_desc.d_descriptor); 25655363f09cSarutz my_door_return((char *)&reterror, 25665363f09cSarutz sizeof (smedia_reterror_t), 0, 0); 25677c478bd9Sstevel@tonic-gate } 25685363f09cSarutz 25695363f09cSarutz /* create Death Door */ 25705363f09cSarutz ddata->dd_ddoor_descriptor = 25715363f09cSarutz door_create(death_servproc, (void *)ddata, 25725363f09cSarutz DOOR_REFUSE_DESC | DOOR_NO_CANCEL); 25735363f09cSarutz if (ddata->dd_ddoor_descriptor < 0) { 25745363f09cSarutz warning(gettext("main_servproc: door_create of Death " 25755363f09cSarutz "Door failed = %d\n"), errno); 25765363f09cSarutz } else { 25775363f09cSarutz (void) door_setparam(ddata->dd_ddoor_descriptor, 25785363f09cSarutz DOOR_PARAM_DATA_MAX, 0); 25797c478bd9Sstevel@tonic-gate } 25805363f09cSarutz 25815363f09cSarutz debug(5, "main_servproc[%d]: Client Door = %d, " 25825363f09cSarutz "Death Door = %d", pthread_self(), 25835363f09cSarutz ddata->dd_cdoor_descriptor, ddata->dd_ddoor_descriptor); 25847c478bd9Sstevel@tonic-gate 25857c478bd9Sstevel@tonic-gate audit_init(ddata); 25867c478bd9Sstevel@tonic-gate 25875363f09cSarutz /* wait until sm_server_thread does door_bind() */ 25887c478bd9Sstevel@tonic-gate (void) cond_wait(&ddata->dd_cv_bind, &ddata->dd_lock); 25895363f09cSarutz 25907c478bd9Sstevel@tonic-gate (void) mutex_unlock(&ddata->dd_lock); 25917c478bd9Sstevel@tonic-gate 25927c478bd9Sstevel@tonic-gate (void) mutex_lock(&svcstate_lock); 25937c478bd9Sstevel@tonic-gate svccount++; 25947c478bd9Sstevel@tonic-gate (void) mutex_unlock(&svcstate_lock); 25957c478bd9Sstevel@tonic-gate 25965363f09cSarutz if (ddata->dd_ddoor_descriptor < 0) { 25975363f09cSarutz /* Return only the Client Door to the client. */ 25985363f09cSarutz ddata->dd_cdoor.d_attributes = (DOOR_DESCRIPTOR); 25995363f09cSarutz my_door_return((char *)&reterror, 26005363f09cSarutz sizeof (smedia_reterror_t), &ddata->dd_desc[0], 1); 26015363f09cSarutz } else { 26025363f09cSarutz /* 26035363f09cSarutz * Return the Client Door and Death Door 26045363f09cSarutz * to the client. 26055363f09cSarutz */ 26065363f09cSarutz debug(5, "retok.cnum = 0x%x\n", retok.cnum); 26075363f09cSarutz ddata->dd_cdoor.d_attributes = (DOOR_DESCRIPTOR); 26085363f09cSarutz ddata->dd_ddoor.d_attributes = (DOOR_DESCRIPTOR); 26095363f09cSarutz my_door_return((char *)&retok, 26105363f09cSarutz sizeof (smedia_reterror_t), &ddata->dd_desc[0], 2); 26115363f09cSarutz } 26127c478bd9Sstevel@tonic-gate break; 26137c478bd9Sstevel@tonic-gate } 26147c478bd9Sstevel@tonic-gate 26155363f09cSarutz debug(10, "exiting main_servproc. \n"); 26167c478bd9Sstevel@tonic-gate my_door_return((char *)&reterror, sizeof (smedia_reterror_t), 0, 0); 26177c478bd9Sstevel@tonic-gate } 26187c478bd9Sstevel@tonic-gate 26197c478bd9Sstevel@tonic-gate /* ARGSUSED */ 26207c478bd9Sstevel@tonic-gate static void 26217c478bd9Sstevel@tonic-gate term_handler(int sig, siginfo_t *siginfo, void *sigctx) 26227c478bd9Sstevel@tonic-gate { 26237c478bd9Sstevel@tonic-gate warning(gettext("thread[%d]: Received signal %d. Ignoring it.\n"), 26247c478bd9Sstevel@tonic-gate pthread_self(), 26257c478bd9Sstevel@tonic-gate sig); 26267c478bd9Sstevel@tonic-gate } 26277c478bd9Sstevel@tonic-gate 26287c478bd9Sstevel@tonic-gate /* ARGSUSED */ 26297c478bd9Sstevel@tonic-gate static void 26307c478bd9Sstevel@tonic-gate hup_handler(int sig, siginfo_t *siginfo, void *sigctx) 26317c478bd9Sstevel@tonic-gate { 26327c478bd9Sstevel@tonic-gate warning(gettext("thread[%d]: Received signal %d. Ignoring it.\n"), 26337c478bd9Sstevel@tonic-gate pthread_self(), 26347c478bd9Sstevel@tonic-gate sig); 26357c478bd9Sstevel@tonic-gate } 26367c478bd9Sstevel@tonic-gate 26377c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 26387c478bd9Sstevel@tonic-gate static void 26397c478bd9Sstevel@tonic-gate sig_handler(int sig, siginfo_t *siginfo, void *sigctx) 26407c478bd9Sstevel@tonic-gate { 26417c478bd9Sstevel@tonic-gate warning(gettext("thread[%d]: Received signal %d. Ignoring it.\n"), 26427c478bd9Sstevel@tonic-gate pthread_self(), 26437c478bd9Sstevel@tonic-gate sig); 26447c478bd9Sstevel@tonic-gate } 26457c478bd9Sstevel@tonic-gate 26467c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 26477c478bd9Sstevel@tonic-gate static void 26487c478bd9Sstevel@tonic-gate badsig_handler(int sig, siginfo_t *siginfo, void *sigctx) 26497c478bd9Sstevel@tonic-gate { 26507c478bd9Sstevel@tonic-gate fatal(BADSIG_MSG, pthread_self(), sig, siginfo->si_addr, 26517c478bd9Sstevel@tonic-gate siginfo->si_trapno, 26527c478bd9Sstevel@tonic-gate siginfo->si_pc); 26537c478bd9Sstevel@tonic-gate } 26547c478bd9Sstevel@tonic-gate 26557c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 26565363f09cSarutz static void * 26577c478bd9Sstevel@tonic-gate init_server(void *argp) 26587c478bd9Sstevel@tonic-gate { 26597c478bd9Sstevel@tonic-gate int i, fd; 26607c478bd9Sstevel@tonic-gate struct sigaction act; 26617c478bd9Sstevel@tonic-gate struct rlimit rlim; 26627c478bd9Sstevel@tonic-gate 26637c478bd9Sstevel@tonic-gate debug(10, "init_server running\n"); 26647c478bd9Sstevel@tonic-gate 26657c478bd9Sstevel@tonic-gate (void) setlocale(LC_ALL, ""); 26667c478bd9Sstevel@tonic-gate #if !defined(TEXT_DOMAIN) 26677c478bd9Sstevel@tonic-gate #define TEXT_DOMAIN "SYS_TEST" 26687c478bd9Sstevel@tonic-gate #endif 26697c478bd9Sstevel@tonic-gate (void) textdomain(TEXT_DOMAIN); 26707c478bd9Sstevel@tonic-gate 26717c478bd9Sstevel@tonic-gate 26727c478bd9Sstevel@tonic-gate if (geteuid() != 0) fatal("Must be root to execute smserverd\n"); 26737c478bd9Sstevel@tonic-gate 26747c478bd9Sstevel@tonic-gate 26757c478bd9Sstevel@tonic-gate /* 26767c478bd9Sstevel@tonic-gate * setup signal handlers. 26777c478bd9Sstevel@tonic-gate */ 26787c478bd9Sstevel@tonic-gate 26797c478bd9Sstevel@tonic-gate for (i = 0; i < N_BADSIGS; i++) { 26807c478bd9Sstevel@tonic-gate act.sa_sigaction = badsig_handler; 26817c478bd9Sstevel@tonic-gate (void) sigemptyset(&act.sa_mask); 26827c478bd9Sstevel@tonic-gate act.sa_flags = SA_SIGINFO; 26837c478bd9Sstevel@tonic-gate if (sigaction(badsigs[i], &act, NULL) == -1) 26847c478bd9Sstevel@tonic-gate warning(gettext(SIGACT_FAILED), strsignal(badsigs[i]), 26857c478bd9Sstevel@tonic-gate strerror(errno)); 26867c478bd9Sstevel@tonic-gate } 26877c478bd9Sstevel@tonic-gate 26887c478bd9Sstevel@tonic-gate /* 26897c478bd9Sstevel@tonic-gate * Ignore SIGHUP until all the initialization is done. 26907c478bd9Sstevel@tonic-gate */ 26917c478bd9Sstevel@tonic-gate act.sa_handler = SIG_IGN; 26927c478bd9Sstevel@tonic-gate (void) sigemptyset(&act.sa_mask); 26937c478bd9Sstevel@tonic-gate act.sa_flags = 0; 26947c478bd9Sstevel@tonic-gate if (sigaction(SIGHUP, &act, NULL) == -1) 26957c478bd9Sstevel@tonic-gate warning(gettext(SIGACT_FAILED), strsignal(SIGHUP), 26967c478bd9Sstevel@tonic-gate strerror(errno)); 26977c478bd9Sstevel@tonic-gate /* 26987c478bd9Sstevel@tonic-gate * Increase file descriptor limit to the most it can possibly 26997c478bd9Sstevel@tonic-gate * be. 27007c478bd9Sstevel@tonic-gate */ 27017c478bd9Sstevel@tonic-gate if (getrlimit(RLIMIT_NOFILE, &rlim) < 0) { 27027c478bd9Sstevel@tonic-gate warning(gettext("getrlimit for fd's failed; %m\n")); 27037c478bd9Sstevel@tonic-gate } 27047c478bd9Sstevel@tonic-gate 27057c478bd9Sstevel@tonic-gate rlim.rlim_cur = rlim.rlim_max; 27067c478bd9Sstevel@tonic-gate 27077c478bd9Sstevel@tonic-gate if (setrlimit(RLIMIT_NOFILE, &rlim) < 0) { 27087c478bd9Sstevel@tonic-gate warning(gettext("setrlimit for fd's failed; %m\n")); 27097c478bd9Sstevel@tonic-gate } 2710004388ebScasper (void) enable_extended_FILE_stdio(-1, -1); 27117c478bd9Sstevel@tonic-gate 27125363f09cSarutz server_door = door_create(main_servproc, (void *)&server_data, 0); 27137c478bd9Sstevel@tonic-gate if (server_door == -1) { 27147c478bd9Sstevel@tonic-gate debug(1, "main door_create"); 27157c478bd9Sstevel@tonic-gate exit(1); 27167c478bd9Sstevel@tonic-gate } 27177c478bd9Sstevel@tonic-gate 27187c478bd9Sstevel@tonic-gate (void) unlink(smedia_service); 27197c478bd9Sstevel@tonic-gate fd = open(smedia_service, O_RDWR|O_CREAT|O_EXCL, 0644); 27207c478bd9Sstevel@tonic-gate if (fd < 0) { 27217c478bd9Sstevel@tonic-gate debug(5, "could not open %s.\n", smedia_service); 27227c478bd9Sstevel@tonic-gate exit(1); 27237c478bd9Sstevel@tonic-gate } 27247c478bd9Sstevel@tonic-gate (void) close(fd); 27257c478bd9Sstevel@tonic-gate server_fd = fattach(server_door, smedia_service); 27267c478bd9Sstevel@tonic-gate if (server_fd == -1) { 27277c478bd9Sstevel@tonic-gate debug(1, "main fattach"); 27287c478bd9Sstevel@tonic-gate exit(1); 27297c478bd9Sstevel@tonic-gate } 27307c478bd9Sstevel@tonic-gate server_data.sd_door = server_door; 27317c478bd9Sstevel@tonic-gate server_data.sd_fd = server_fd; 27327c478bd9Sstevel@tonic-gate 27337c478bd9Sstevel@tonic-gate /* 27347c478bd9Sstevel@tonic-gate * setup signal handlers for post-init 27357c478bd9Sstevel@tonic-gate */ 27367c478bd9Sstevel@tonic-gate 27377c478bd9Sstevel@tonic-gate act.sa_sigaction = hup_handler; 27387c478bd9Sstevel@tonic-gate (void) sigemptyset(&act.sa_mask); 27397c478bd9Sstevel@tonic-gate act.sa_flags = SA_SIGINFO; 27407c478bd9Sstevel@tonic-gate if (sigaction(SIGHUP, &act, NULL) == -1) 27417c478bd9Sstevel@tonic-gate warning(gettext(SIGACT_FAILED), strsignal(SIGHUP), 27427c478bd9Sstevel@tonic-gate strerror(errno)); 27437c478bd9Sstevel@tonic-gate 27447c478bd9Sstevel@tonic-gate act.sa_sigaction = term_handler; 27457c478bd9Sstevel@tonic-gate (void) sigemptyset(&act.sa_mask); 27467c478bd9Sstevel@tonic-gate act.sa_flags = SA_SIGINFO; 27477c478bd9Sstevel@tonic-gate if (sigaction(SIGTERM, &act, NULL) == -1) 27487c478bd9Sstevel@tonic-gate warning(gettext(SIGACT_FAILED), strsignal(SIGTERM), 27497c478bd9Sstevel@tonic-gate strerror(errno)); 27507c478bd9Sstevel@tonic-gate 27517c478bd9Sstevel@tonic-gate act.sa_sigaction = sig_handler; 27527c478bd9Sstevel@tonic-gate (void) sigemptyset(&act.sa_mask); 27537c478bd9Sstevel@tonic-gate act.sa_flags = SA_SIGINFO; 27547c478bd9Sstevel@tonic-gate if (sigaction(SIGINT, &act, NULL) == -1) 27557c478bd9Sstevel@tonic-gate warning(gettext(SIGACT_FAILED), strsignal(SIGHUP), 27567c478bd9Sstevel@tonic-gate strerror(errno)); 27577c478bd9Sstevel@tonic-gate 27587c478bd9Sstevel@tonic-gate act.sa_sigaction = sig_handler; 27597c478bd9Sstevel@tonic-gate (void) sigemptyset(&act.sa_mask); 27607c478bd9Sstevel@tonic-gate act.sa_flags = SA_SIGINFO; 27617c478bd9Sstevel@tonic-gate if (sigaction(SIGQUIT, &act, NULL) == -1) 27627c478bd9Sstevel@tonic-gate warning(gettext(SIGACT_FAILED), strsignal(SIGHUP), 27637c478bd9Sstevel@tonic-gate strerror(errno)); 27647c478bd9Sstevel@tonic-gate debug(10, "init_server completed successfully\n"); 27657c478bd9Sstevel@tonic-gate 27667c478bd9Sstevel@tonic-gate server_data.sd_init_state = INIT_DONE; 27677c478bd9Sstevel@tonic-gate return (NULL); 27687c478bd9Sstevel@tonic-gate } 27697c478bd9Sstevel@tonic-gate 27707c478bd9Sstevel@tonic-gate static int 27717c478bd9Sstevel@tonic-gate server_exists() 27727c478bd9Sstevel@tonic-gate { 27737c478bd9Sstevel@tonic-gate door_arg_t darg; 27747c478bd9Sstevel@tonic-gate smedia_reqping_t req_ping; 27757c478bd9Sstevel@tonic-gate smedia_retping_t *ret_ping; 27767c478bd9Sstevel@tonic-gate int doorh; 27777c478bd9Sstevel@tonic-gate door_info_t dinfo; 27787c478bd9Sstevel@tonic-gate char rbuf[sizeof (smedia_services_t) + sizeof (door_desc_t)]; 27797c478bd9Sstevel@tonic-gate 27807c478bd9Sstevel@tonic-gate doorh = open(smedia_service, O_RDONLY); 27817c478bd9Sstevel@tonic-gate if (doorh < 0) 27827c478bd9Sstevel@tonic-gate return (0); 27837c478bd9Sstevel@tonic-gate if (door_info(doorh, &dinfo) < 0) { 27847c478bd9Sstevel@tonic-gate (void) close(doorh); 27857c478bd9Sstevel@tonic-gate return (0); 27867c478bd9Sstevel@tonic-gate } 27877c478bd9Sstevel@tonic-gate if (dinfo.di_attributes & DOOR_REVOKED) { 27887c478bd9Sstevel@tonic-gate (void) close(doorh); 27897c478bd9Sstevel@tonic-gate return (0); 27907c478bd9Sstevel@tonic-gate } 27917c478bd9Sstevel@tonic-gate 27927c478bd9Sstevel@tonic-gate req_ping.cnum = SMEDIA_CNUM_PING; 27937c478bd9Sstevel@tonic-gate 27947c478bd9Sstevel@tonic-gate darg.data_ptr = (char *)&req_ping; 27957c478bd9Sstevel@tonic-gate darg.data_size = sizeof (smedia_reqping_t); 27967c478bd9Sstevel@tonic-gate darg.desc_ptr = NULL; 27977c478bd9Sstevel@tonic-gate darg.desc_num = 0; 27987c478bd9Sstevel@tonic-gate darg.rbuf = rbuf; 27997c478bd9Sstevel@tonic-gate darg.rsize = sizeof (rbuf); 28007c478bd9Sstevel@tonic-gate 28017c478bd9Sstevel@tonic-gate if (door_call(doorh, &darg) < 0) { 28027c478bd9Sstevel@tonic-gate (void) close(doorh); 28037c478bd9Sstevel@tonic-gate return (0); 28047c478bd9Sstevel@tonic-gate } 28057c478bd9Sstevel@tonic-gate ret_ping = (smedia_retping_t *)((void *)darg.data_ptr); 28067c478bd9Sstevel@tonic-gate if (ret_ping->cnum != SMEDIA_CNUM_PING) { 28077c478bd9Sstevel@tonic-gate (void) close(doorh); 28087c478bd9Sstevel@tonic-gate return (0); 28097c478bd9Sstevel@tonic-gate } 28107c478bd9Sstevel@tonic-gate 28117c478bd9Sstevel@tonic-gate (void) close(doorh); 28127c478bd9Sstevel@tonic-gate return (1); 28137c478bd9Sstevel@tonic-gate } 28147c478bd9Sstevel@tonic-gate 28157c478bd9Sstevel@tonic-gate static int 28167c478bd9Sstevel@tonic-gate get_run_level() 28177c478bd9Sstevel@tonic-gate { 28187c478bd9Sstevel@tonic-gate int run_level; 28197c478bd9Sstevel@tonic-gate struct utmpx *utmpp; 28207c478bd9Sstevel@tonic-gate 28217c478bd9Sstevel@tonic-gate setutxent(); 28227c478bd9Sstevel@tonic-gate while ((utmpp = getutxent()) != NULL) { 28237c478bd9Sstevel@tonic-gate if (utmpp->ut_type == RUN_LVL) { 28247c478bd9Sstevel@tonic-gate run_level = atoi( 28257c478bd9Sstevel@tonic-gate &utmpp->ut_line[strlen("run-level ")]); 28267c478bd9Sstevel@tonic-gate } 28277c478bd9Sstevel@tonic-gate } 28287c478bd9Sstevel@tonic-gate return (run_level); 28297c478bd9Sstevel@tonic-gate } 28307c478bd9Sstevel@tonic-gate 28317c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 28327c478bd9Sstevel@tonic-gate static void * 28337c478bd9Sstevel@tonic-gate closedown(void *arg) 28347c478bd9Sstevel@tonic-gate { 28357c478bd9Sstevel@tonic-gate 28367c478bd9Sstevel@tonic-gate int current_run_level; 28377c478bd9Sstevel@tonic-gate 28387c478bd9Sstevel@tonic-gate /*CONSTCOND*/ 28397c478bd9Sstevel@tonic-gate #ifndef lint 28407c478bd9Sstevel@tonic-gate while (1) { 28417c478bd9Sstevel@tonic-gate #endif 28427c478bd9Sstevel@tonic-gate (void) sleep(SVC_CLOSEDOWN/2); 28437c478bd9Sstevel@tonic-gate 28447c478bd9Sstevel@tonic-gate /* 28457c478bd9Sstevel@tonic-gate * If the server was started at init level 1 28467c478bd9Sstevel@tonic-gate * and the current init level is 1 then 28477c478bd9Sstevel@tonic-gate * do not exit from server. This server will run 28487c478bd9Sstevel@tonic-gate * until it is explicitly stopped by the user. 28497c478bd9Sstevel@tonic-gate */ 28507c478bd9Sstevel@tonic-gate if (svcstart_level == 1) { 28517c478bd9Sstevel@tonic-gate current_run_level = get_run_level(); 28527c478bd9Sstevel@tonic-gate if (current_run_level == 1) 28537c478bd9Sstevel@tonic-gate #ifndef lint 28547c478bd9Sstevel@tonic-gate continue; 28557c478bd9Sstevel@tonic-gate #else 28567c478bd9Sstevel@tonic-gate return (NULL); 28577c478bd9Sstevel@tonic-gate #endif 28587c478bd9Sstevel@tonic-gate /* 28597c478bd9Sstevel@tonic-gate * who ever started the server at level 1 has 28607c478bd9Sstevel@tonic-gate * forgotten to stop the server. we will kill ourself. 28617c478bd9Sstevel@tonic-gate */ 28627c478bd9Sstevel@tonic-gate debug(5, 28637c478bd9Sstevel@tonic-gate "Terminating the server started at init level 1\n"); 28647c478bd9Sstevel@tonic-gate exit(0); 28657c478bd9Sstevel@tonic-gate } 28667c478bd9Sstevel@tonic-gate 28677c478bd9Sstevel@tonic-gate if (mutex_trylock(&svcstate_lock) != 0) 28687c478bd9Sstevel@tonic-gate #ifndef lint 28697c478bd9Sstevel@tonic-gate continue; 28707c478bd9Sstevel@tonic-gate #else 28717c478bd9Sstevel@tonic-gate return (NULL); 28727c478bd9Sstevel@tonic-gate #endif 28737c478bd9Sstevel@tonic-gate if (svcstate == _IDLE && svccount == 0) { 28747c478bd9Sstevel@tonic-gate int size; 28757c478bd9Sstevel@tonic-gate int i, openfd = 0; 28767c478bd9Sstevel@tonic-gate 28777c478bd9Sstevel@tonic-gate size = svc_max_pollfd; 28787c478bd9Sstevel@tonic-gate for (i = 0; i < size && openfd < 2; i++) 28797c478bd9Sstevel@tonic-gate if (svc_pollfd[i].fd >= 0) 28807c478bd9Sstevel@tonic-gate openfd++; 28817c478bd9Sstevel@tonic-gate if (openfd <= 1) { 28827c478bd9Sstevel@tonic-gate debug(5, 28837c478bd9Sstevel@tonic-gate "Exiting the server from closedown routine.\n"); 28847c478bd9Sstevel@tonic-gate exit(0); 28857c478bd9Sstevel@tonic-gate } 28867c478bd9Sstevel@tonic-gate } else 28877c478bd9Sstevel@tonic-gate svcstate = _IDLE; 28887c478bd9Sstevel@tonic-gate 28897c478bd9Sstevel@tonic-gate (void) mutex_unlock(&svcstate_lock); 28907c478bd9Sstevel@tonic-gate #ifndef lint 28917c478bd9Sstevel@tonic-gate } 28927c478bd9Sstevel@tonic-gate #else 28937c478bd9Sstevel@tonic-gate return (NULL); 28947c478bd9Sstevel@tonic-gate #endif 28957c478bd9Sstevel@tonic-gate 28967c478bd9Sstevel@tonic-gate } 28977c478bd9Sstevel@tonic-gate 28987c478bd9Sstevel@tonic-gate static void 28997c478bd9Sstevel@tonic-gate usage() 29007c478bd9Sstevel@tonic-gate { 29017c478bd9Sstevel@tonic-gate warning(gettext("usage: %s [-L loglevel] level of debug information\n"), 29027c478bd9Sstevel@tonic-gate prog_name); 29037c478bd9Sstevel@tonic-gate } 29047c478bd9Sstevel@tonic-gate 29057c478bd9Sstevel@tonic-gate 29067c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 2907360e6f5eSmathue int 29087c478bd9Sstevel@tonic-gate main(int argc, char **argv) 29097c478bd9Sstevel@tonic-gate { 29107c478bd9Sstevel@tonic-gate int c; 29117c478bd9Sstevel@tonic-gate pthread_attr_t attr; 29127c478bd9Sstevel@tonic-gate 29137c478bd9Sstevel@tonic-gate (void) setlocale(LC_ALL, ""); 29147c478bd9Sstevel@tonic-gate #if !defined(TEXT_DOMAIN) 29157c478bd9Sstevel@tonic-gate #define TEXT_DOMAIN "SYS_TEST" 29167c478bd9Sstevel@tonic-gate #endif 29177c478bd9Sstevel@tonic-gate (void) textdomain(TEXT_DOMAIN); 29187c478bd9Sstevel@tonic-gate 29197c478bd9Sstevel@tonic-gate prog_name = argv[0]; 29207c478bd9Sstevel@tonic-gate 29217c478bd9Sstevel@tonic-gate (void) sigset(SIGPIPE, SIG_IGN); 29227c478bd9Sstevel@tonic-gate 29237c478bd9Sstevel@tonic-gate while ((c = getopt(argc, argv, "L:")) != -1) { 29247c478bd9Sstevel@tonic-gate switch (c) { 29257c478bd9Sstevel@tonic-gate case 'L': 29267c478bd9Sstevel@tonic-gate debug_level = atoi((char *)optarg); 29277c478bd9Sstevel@tonic-gate break; 29287c478bd9Sstevel@tonic-gate default: 29297c478bd9Sstevel@tonic-gate usage(); 29307c478bd9Sstevel@tonic-gate break; 29317c478bd9Sstevel@tonic-gate } 29327c478bd9Sstevel@tonic-gate } 29337c478bd9Sstevel@tonic-gate 29347c478bd9Sstevel@tonic-gate /* 29357c478bd9Sstevel@tonic-gate * If stdin looks like a TLI endpoint, we assume 29367c478bd9Sstevel@tonic-gate * that we were started by a port monitor. If 29377c478bd9Sstevel@tonic-gate * t_getstate fails with TBADF, this is not a 29387c478bd9Sstevel@tonic-gate * TLI endpoint. 29397c478bd9Sstevel@tonic-gate */ 29407c478bd9Sstevel@tonic-gate if (t_getstate(0) != -1 || t_errno != TBADF) { 29417c478bd9Sstevel@tonic-gate char *netid; 29427c478bd9Sstevel@tonic-gate struct netconfig *nconf = NULL; 29437c478bd9Sstevel@tonic-gate SVCXPRT *transp; 29447c478bd9Sstevel@tonic-gate int pmclose; 29457c478bd9Sstevel@tonic-gate 29467c478bd9Sstevel@tonic-gate openlog(prog_name, LOG_PID, LOG_DAEMON); 29477c478bd9Sstevel@tonic-gate 29487c478bd9Sstevel@tonic-gate debug(1, gettext("server started by port monitor.\n")); 29497c478bd9Sstevel@tonic-gate if ((netid = getenv("NLSPROVIDER")) == NULL) { 29507c478bd9Sstevel@tonic-gate /* started from inetd */ 29517c478bd9Sstevel@tonic-gate pmclose = 1; 29527c478bd9Sstevel@tonic-gate } else { 29537c478bd9Sstevel@tonic-gate if ((nconf = getnetconfigent(netid)) == NULL) 29547c478bd9Sstevel@tonic-gate syslog(LOG_ERR, gettext( 29557c478bd9Sstevel@tonic-gate "cannot get transport info")); 29567c478bd9Sstevel@tonic-gate 29577c478bd9Sstevel@tonic-gate pmclose = (t_getstate(0) != T_DATAXFER); 29587c478bd9Sstevel@tonic-gate } 29597c478bd9Sstevel@tonic-gate if ((transp = svc_tli_create(0, nconf, NULL, 0, 0)) == NULL) { 29607c478bd9Sstevel@tonic-gate syslog(LOG_ERR, gettext("cannot create server handle")); 29617c478bd9Sstevel@tonic-gate exit(1); 29627c478bd9Sstevel@tonic-gate } 29637c478bd9Sstevel@tonic-gate if (nconf) 29647c478bd9Sstevel@tonic-gate freenetconfigent(nconf); 29657c478bd9Sstevel@tonic-gate if (!svc_reg(transp, SMSERVERPROG, SMSERVERVERS, 29667c478bd9Sstevel@tonic-gate smserverprog_1, 0)) { 29677c478bd9Sstevel@tonic-gate syslog(LOG_ERR, gettext( 29687c478bd9Sstevel@tonic-gate "unable to register (SMSERVERPROG, SMSERVERVERS).")); 29697c478bd9Sstevel@tonic-gate exit(1); 29707c478bd9Sstevel@tonic-gate } 29717c478bd9Sstevel@tonic-gate svcstart_level = get_run_level(); 29727c478bd9Sstevel@tonic-gate if (pmclose) { 29737c478bd9Sstevel@tonic-gate (void) pthread_attr_init(&attr); 29747c478bd9Sstevel@tonic-gate (void) pthread_attr_setscope(&attr, 2975d4204c85Sraf PTHREAD_SCOPE_SYSTEM); 2976d4204c85Sraf (void) pthread_attr_setdetachstate(&attr, 2977d4204c85Sraf PTHREAD_CREATE_DETACHED); 29787c478bd9Sstevel@tonic-gate if (pthread_create(NULL, &attr, closedown, NULL) != 0) { 29797c478bd9Sstevel@tonic-gate syslog(LOG_ERR, gettext( 29807c478bd9Sstevel@tonic-gate "cannot create closedown thread")); 29817c478bd9Sstevel@tonic-gate exit(1); 29827c478bd9Sstevel@tonic-gate } 29837c478bd9Sstevel@tonic-gate (void) pthread_attr_destroy(&attr); 29847c478bd9Sstevel@tonic-gate } 29857c478bd9Sstevel@tonic-gate svc_run(); 29867c478bd9Sstevel@tonic-gate exit(1); 29877c478bd9Sstevel@tonic-gate /* NOTREACHED */ 29887c478bd9Sstevel@tonic-gate } else { 29897c478bd9Sstevel@tonic-gate /* 29907c478bd9Sstevel@tonic-gate * Started by library or manually. 29917c478bd9Sstevel@tonic-gate */ 29927c478bd9Sstevel@tonic-gate /* 29937c478bd9Sstevel@tonic-gate * Check to see if the server is already running. 29947c478bd9Sstevel@tonic-gate * There is no need to log messages in the syslog file 29957c478bd9Sstevel@tonic-gate * because server will get launched each time libsmedia 29967c478bd9Sstevel@tonic-gate * library calls are made at init 1 level. 29977c478bd9Sstevel@tonic-gate * We ensure that only one copy will run. 29987c478bd9Sstevel@tonic-gate */ 29997c478bd9Sstevel@tonic-gate debug(1, gettext("server started manually.\n")); 30007c478bd9Sstevel@tonic-gate if (server_exists()) { 30017c478bd9Sstevel@tonic-gate exit(0); 30027c478bd9Sstevel@tonic-gate } 30037c478bd9Sstevel@tonic-gate svcstart_level = get_run_level(); 30047c478bd9Sstevel@tonic-gate (void) pthread_attr_init(&attr); 30057c478bd9Sstevel@tonic-gate (void) pthread_attr_setscope(&attr, 3006d4204c85Sraf PTHREAD_SCOPE_SYSTEM); 3007d4204c85Sraf (void) pthread_attr_setdetachstate(&attr, 3008d4204c85Sraf PTHREAD_CREATE_DETACHED); 30097c478bd9Sstevel@tonic-gate if (pthread_create(NULL, &attr, closedown, NULL) != 0) { 30107c478bd9Sstevel@tonic-gate syslog(LOG_ERR, gettext( 30117c478bd9Sstevel@tonic-gate "cannot create closedown thread")); 30127c478bd9Sstevel@tonic-gate exit(1); 30137c478bd9Sstevel@tonic-gate } 30147c478bd9Sstevel@tonic-gate (void) pthread_attr_destroy(&attr); 30157c478bd9Sstevel@tonic-gate (void) init_server(NULL); 30167c478bd9Sstevel@tonic-gate for (;;) (void) pause(); 30177c478bd9Sstevel@tonic-gate } 3018360e6f5eSmathue return (0); 30197c478bd9Sstevel@tonic-gate } 30207c478bd9Sstevel@tonic-gate 30217c478bd9Sstevel@tonic-gate 30227c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 30237c478bd9Sstevel@tonic-gate static int32_t 30247c478bd9Sstevel@tonic-gate scsi_floppy_write_protect(int32_t fd, smwp_state_t *wp) 30257c478bd9Sstevel@tonic-gate { 30267c478bd9Sstevel@tonic-gate debug(5, "Invalid mode\n"); 30277c478bd9Sstevel@tonic-gate errno = ENOTSUP; 30287c478bd9Sstevel@tonic-gate 30297c478bd9Sstevel@tonic-gate return (-1); 30307c478bd9Sstevel@tonic-gate } 30317c478bd9Sstevel@tonic-gate 30327c478bd9Sstevel@tonic-gate /* 30337c478bd9Sstevel@tonic-gate * Generate standard geometry information for SCSI floppy devices. And 30347c478bd9Sstevel@tonic-gate * register the geometry with the SCSI driver. This will expand as more 30357c478bd9Sstevel@tonic-gate * formats are added. 30367c478bd9Sstevel@tonic-gate */ 30377c478bd9Sstevel@tonic-gate 30387c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 30397c478bd9Sstevel@tonic-gate static int32_t 30407c478bd9Sstevel@tonic-gate get_floppy_geom(int32_t fd, uint32_t capacity, struct dk_geom *dkgeom) 30417c478bd9Sstevel@tonic-gate { 30427c478bd9Sstevel@tonic-gate 30437c478bd9Sstevel@tonic-gate 30447c478bd9Sstevel@tonic-gate debug(5, "get_floppy_geom: capacity = 0x%x\n", capacity); 30457c478bd9Sstevel@tonic-gate 30467c478bd9Sstevel@tonic-gate switch (capacity) { 30477c478bd9Sstevel@tonic-gate 30487c478bd9Sstevel@tonic-gate case 0x5A0: 30497c478bd9Sstevel@tonic-gate /* Double Density 720K */ 30507c478bd9Sstevel@tonic-gate dkgeom->dkg_pcyl = 80; 30517c478bd9Sstevel@tonic-gate dkgeom->dkg_ncyl = 80; 30527c478bd9Sstevel@tonic-gate dkgeom->dkg_nhead = 2; 30537c478bd9Sstevel@tonic-gate dkgeom->dkg_nsect = 9; 30547c478bd9Sstevel@tonic-gate break; 30557c478bd9Sstevel@tonic-gate case 0x4D0: 30567c478bd9Sstevel@tonic-gate /* High Density 1.25MB */ 30577c478bd9Sstevel@tonic-gate dkgeom->dkg_pcyl = 77; 30587c478bd9Sstevel@tonic-gate dkgeom->dkg_ncyl = 77; 30597c478bd9Sstevel@tonic-gate dkgeom->dkg_nhead = 2; 30607c478bd9Sstevel@tonic-gate dkgeom->dkg_nsect = 9; 30617c478bd9Sstevel@tonic-gate break; 30627c478bd9Sstevel@tonic-gate case 0xB40: 30637c478bd9Sstevel@tonic-gate /* High Density 1.44MB */ 30647c478bd9Sstevel@tonic-gate 30657c478bd9Sstevel@tonic-gate dkgeom->dkg_pcyl = 80; 30667c478bd9Sstevel@tonic-gate dkgeom->dkg_ncyl = 80; 30677c478bd9Sstevel@tonic-gate dkgeom->dkg_nhead = 2; 30687c478bd9Sstevel@tonic-gate dkgeom->dkg_nsect = 18; 30697c478bd9Sstevel@tonic-gate break; 30707c478bd9Sstevel@tonic-gate case 0x3C300: 30717c478bd9Sstevel@tonic-gate /* Ultra High density ls-120 120MB */ 30727c478bd9Sstevel@tonic-gate dkgeom->dkg_pcyl = 963; 30737c478bd9Sstevel@tonic-gate dkgeom->dkg_ncyl = 963; 30747c478bd9Sstevel@tonic-gate dkgeom->dkg_nhead = 8; 30757c478bd9Sstevel@tonic-gate dkgeom->dkg_nsect = 32; 30767c478bd9Sstevel@tonic-gate break; 30777c478bd9Sstevel@tonic-gate default: 30787c478bd9Sstevel@tonic-gate debug(5, "unknown capacity type %d\n", capacity); 30797c478bd9Sstevel@tonic-gate return (-1); 30807c478bd9Sstevel@tonic-gate 30817c478bd9Sstevel@tonic-gate } 30827c478bd9Sstevel@tonic-gate debug(5, "get_floppy_geom: setting cyl = %d, nsect = %d, head = %d", 30837c478bd9Sstevel@tonic-gate dkgeom->dkg_pcyl, dkgeom->dkg_nhead, dkgeom->dkg_nsect); 30847c478bd9Sstevel@tonic-gate return (0); 30857c478bd9Sstevel@tonic-gate 30867c478bd9Sstevel@tonic-gate } 30877c478bd9Sstevel@tonic-gate /* ARGSUSED */ 30885363f09cSarutz static int32_t 30897c478bd9Sstevel@tonic-gate scsi_floppy_format(int32_t fd, uint_t flavor, uint_t mode) 30907c478bd9Sstevel@tonic-gate { 30917c478bd9Sstevel@tonic-gate struct uscsi_cmd ucmd; 30927c478bd9Sstevel@tonic-gate uchar_t cdb[12]; 30937c478bd9Sstevel@tonic-gate int32_t ret_val; 30947c478bd9Sstevel@tonic-gate uint32_t capacity, blocksize; 30957c478bd9Sstevel@tonic-gate uchar_t data[12]; 30967c478bd9Sstevel@tonic-gate char rq_data[RQ_LEN]; 30977c478bd9Sstevel@tonic-gate int i; 30987c478bd9Sstevel@tonic-gate struct dk_geom dkgeom; 30997c478bd9Sstevel@tonic-gate 31007c478bd9Sstevel@tonic-gate debug(5, "scsi_floppy_format:\n"); 31017c478bd9Sstevel@tonic-gate 31027c478bd9Sstevel@tonic-gate if ((mode != SM_FORMAT_IMMEDIATE) && (mode != SM_FORMAT_BLOCKED)) { 31037c478bd9Sstevel@tonic-gate errno = ENOTSUP; 31047c478bd9Sstevel@tonic-gate 31057c478bd9Sstevel@tonic-gate return (-1); 31067c478bd9Sstevel@tonic-gate } 31077c478bd9Sstevel@tonic-gate 31087c478bd9Sstevel@tonic-gate switch (flavor) { 31097c478bd9Sstevel@tonic-gate case SM_FORMAT_QUICK : 31107c478bd9Sstevel@tonic-gate debug(1, "Format not supported\n"); 31117c478bd9Sstevel@tonic-gate errno = ENOTSUP; 31127c478bd9Sstevel@tonic-gate return (-1); 31137c478bd9Sstevel@tonic-gate case SM_FORMAT_FORCE : 31147c478bd9Sstevel@tonic-gate break; 31157c478bd9Sstevel@tonic-gate case SM_FORMAT_LONG : 31167c478bd9Sstevel@tonic-gate break; 31177c478bd9Sstevel@tonic-gate 31187c478bd9Sstevel@tonic-gate default : 31197c478bd9Sstevel@tonic-gate debug(1, "Format option not specified!!\n"); 31207c478bd9Sstevel@tonic-gate errno = ENOTSUP; 31217c478bd9Sstevel@tonic-gate return (-1); 31227c478bd9Sstevel@tonic-gate } 31237c478bd9Sstevel@tonic-gate 31247c478bd9Sstevel@tonic-gate ret_val = get_media_capacity(fd, &capacity, &blocksize); 31257c478bd9Sstevel@tonic-gate 31267c478bd9Sstevel@tonic-gate if (capacity >= 0x3C300) { 31277c478bd9Sstevel@tonic-gate /* 31287c478bd9Sstevel@tonic-gate * It's an LS-120 media, it does not support track 31297c478bd9Sstevel@tonic-gate * formatting. 31307c478bd9Sstevel@tonic-gate */ 31317c478bd9Sstevel@tonic-gate return (scsi_ls120_format(fd, flavor, capacity, blocksize)); 31327c478bd9Sstevel@tonic-gate } 31337c478bd9Sstevel@tonic-gate 31347c478bd9Sstevel@tonic-gate ret_val = get_floppy_geom(fd, capacity, &dkgeom); 31357c478bd9Sstevel@tonic-gate if (ret_val) { 31367c478bd9Sstevel@tonic-gate errno = ENOTSUP; 31377c478bd9Sstevel@tonic-gate return (-1); 31387c478bd9Sstevel@tonic-gate } 31397c478bd9Sstevel@tonic-gate 31407c478bd9Sstevel@tonic-gate (void) memset((void *)&data, 0, sizeof (data)); 31417c478bd9Sstevel@tonic-gate (void) memset((void *)&ucmd, 0, sizeof (ucmd)); 31427c478bd9Sstevel@tonic-gate (void) memset((void *)&cdb, 0, sizeof (cdb)); 31437c478bd9Sstevel@tonic-gate 31447c478bd9Sstevel@tonic-gate /* retrieve size discriptor of inserted media */ 31457c478bd9Sstevel@tonic-gate cdb[0] = SCMD_FORMAT; /* format */ 31467c478bd9Sstevel@tonic-gate 31477c478bd9Sstevel@tonic-gate /* 31487c478bd9Sstevel@tonic-gate * Defect list sent by initiator is a complete list of defects. 31497c478bd9Sstevel@tonic-gate */ 31507c478bd9Sstevel@tonic-gate 31517c478bd9Sstevel@tonic-gate cdb[1] = (FMTDATA | 0x7); 31527c478bd9Sstevel@tonic-gate 31537c478bd9Sstevel@tonic-gate cdb[8] = 0xC; /* parameter list length */ 31547c478bd9Sstevel@tonic-gate data[3] = 0x8; /* should be always 8 */ 31557c478bd9Sstevel@tonic-gate 31567c478bd9Sstevel@tonic-gate data[4] = (uchar_t)(capacity >> 24); 31577c478bd9Sstevel@tonic-gate data[5] = (uchar_t)(capacity >> 16); 31587c478bd9Sstevel@tonic-gate data[6] = (uchar_t)(capacity >> 8); 31597c478bd9Sstevel@tonic-gate data[7] = (uchar_t)capacity; 31607c478bd9Sstevel@tonic-gate 31617c478bd9Sstevel@tonic-gate data[9] = (uchar_t)(blocksize >> 16); 31627c478bd9Sstevel@tonic-gate data[10] = (uchar_t)(blocksize >> 8); 31637c478bd9Sstevel@tonic-gate data[11] = (uchar_t)blocksize; 31647c478bd9Sstevel@tonic-gate 31657c478bd9Sstevel@tonic-gate ucmd.uscsi_cdb = (caddr_t)&cdb; 31667c478bd9Sstevel@tonic-gate ucmd.uscsi_cdblen = CDB_GROUP5; 31677c478bd9Sstevel@tonic-gate ucmd.uscsi_bufaddr = (caddr_t)data; 31687c478bd9Sstevel@tonic-gate ucmd.uscsi_buflen = sizeof (data); 31697c478bd9Sstevel@tonic-gate ucmd.uscsi_timeout = 0x15; 31707c478bd9Sstevel@tonic-gate ucmd.uscsi_rqlen = RQ_LEN; 31717c478bd9Sstevel@tonic-gate ucmd.uscsi_rqbuf = rq_data; 31727c478bd9Sstevel@tonic-gate 31737c478bd9Sstevel@tonic-gate debug(5, "cdb: %x %x %x ... %x", cdb[0], cdb[1], cdb[2], cdb[8]); 31747c478bd9Sstevel@tonic-gate debug(5, "data: %x %x %x %x\n", data[0], data[1], data[2], data[3]); 31757c478bd9Sstevel@tonic-gate debug(5, " : %x %x %x %x\n", data[4], data[5], data[6], data[7]); 31767c478bd9Sstevel@tonic-gate debug(5, " : %x %x %x %x\n", data[8], data[9], data[10], data[11]); 31777c478bd9Sstevel@tonic-gate 31787c478bd9Sstevel@tonic-gate for (i = 0; i < dkgeom.dkg_pcyl; i++) { /* number of tracks */ 31797c478bd9Sstevel@tonic-gate data[1] = (0xb0 | FOV); 31807c478bd9Sstevel@tonic-gate cdb[2] = i; 31817c478bd9Sstevel@tonic-gate 31827c478bd9Sstevel@tonic-gate (void) fflush(stdout); 31837c478bd9Sstevel@tonic-gate ret_val = do_uscsi_cmd(fd, &ucmd, USCSI_WRITE|USCSI_RQENABLE); 31847c478bd9Sstevel@tonic-gate info("format side 0 returned : 0x%x\n", ret_val); 31857c478bd9Sstevel@tonic-gate 31867c478bd9Sstevel@tonic-gate if (ret_val || ucmd.uscsi_status) { 31877c478bd9Sstevel@tonic-gate debug(5, "Retrieving media info failed: %d - %d\n", 31887c478bd9Sstevel@tonic-gate ret_val, ucmd.uscsi_status); 31897c478bd9Sstevel@tonic-gate if ((rq_data[2] == KEY_DATA_PROTECT) && 31907c478bd9Sstevel@tonic-gate (rq_data[12] == 0x30) && (rq_data[13] == 0)) { 31917c478bd9Sstevel@tonic-gate debug(5, "Invalid command for media\n"); 31927c478bd9Sstevel@tonic-gate errno = EINVAL; 31937c478bd9Sstevel@tonic-gate } 31947c478bd9Sstevel@tonic-gate 31957c478bd9Sstevel@tonic-gate if ((rq_data[2] == KEY_NOT_READY) && 31967c478bd9Sstevel@tonic-gate (rq_data[12] == 0x30)) { 31977c478bd9Sstevel@tonic-gate debug(5, "Incompatible media.\n"); 31987c478bd9Sstevel@tonic-gate errno = EINVAL; 31997c478bd9Sstevel@tonic-gate } 32007c478bd9Sstevel@tonic-gate 32017c478bd9Sstevel@tonic-gate return (-1); 32027c478bd9Sstevel@tonic-gate } 32037c478bd9Sstevel@tonic-gate data[1] = (0xb0 | FOV) + 1; 32047c478bd9Sstevel@tonic-gate ret_val = do_uscsi_cmd(fd, &ucmd, USCSI_WRITE|USCSI_RQENABLE); 32057c478bd9Sstevel@tonic-gate info("format side 1 returned : 0x%x\n", ret_val); 32067c478bd9Sstevel@tonic-gate 32077c478bd9Sstevel@tonic-gate if (ret_val || ucmd.uscsi_status) { 32087c478bd9Sstevel@tonic-gate debug(5, "Retrieving media info failed: %d - %d\n", 32097c478bd9Sstevel@tonic-gate ret_val, ucmd.uscsi_status); 32107c478bd9Sstevel@tonic-gate if ((rq_data[2] == KEY_DATA_PROTECT) && 32117c478bd9Sstevel@tonic-gate (rq_data[12] == 0x30) && (rq_data[13] == 0)) { 32127c478bd9Sstevel@tonic-gate (void) info("Invalid command for media\n"); 32137c478bd9Sstevel@tonic-gate errno = EINVAL; 32147c478bd9Sstevel@tonic-gate } 32157c478bd9Sstevel@tonic-gate 32167c478bd9Sstevel@tonic-gate if ((rq_data[2] == KEY_NOT_READY) && 32177c478bd9Sstevel@tonic-gate (rq_data[12] == 0x30)) { 32187c478bd9Sstevel@tonic-gate debug(5, "Incompatible media.\n"); 32197c478bd9Sstevel@tonic-gate errno = EINVAL; 32207c478bd9Sstevel@tonic-gate } 32217c478bd9Sstevel@tonic-gate 32227c478bd9Sstevel@tonic-gate return (-1); 32237c478bd9Sstevel@tonic-gate } 32247c478bd9Sstevel@tonic-gate } 32257c478bd9Sstevel@tonic-gate 32267c478bd9Sstevel@tonic-gate debug(5, "formatting done!"); 32277c478bd9Sstevel@tonic-gate return (0); 32287c478bd9Sstevel@tonic-gate } 32297c478bd9Sstevel@tonic-gate 32307c478bd9Sstevel@tonic-gate 32317c478bd9Sstevel@tonic-gate /* ARGSUSED */ 32325363f09cSarutz static int32_t 32337c478bd9Sstevel@tonic-gate scsi_floppy_media_status(int32_t fd) 32347c478bd9Sstevel@tonic-gate { 32357c478bd9Sstevel@tonic-gate struct mode_header_g1 modeh; 32367c478bd9Sstevel@tonic-gate struct uscsi_cmd ucmd; 32377c478bd9Sstevel@tonic-gate uchar_t cdb[10]; 32387c478bd9Sstevel@tonic-gate int32_t ret_val; 32397c478bd9Sstevel@tonic-gate int32_t cur_status; 32407c478bd9Sstevel@tonic-gate char rq_data[RQ_LEN]; 32417c478bd9Sstevel@tonic-gate 32427c478bd9Sstevel@tonic-gate debug(5, "SCSI MEDIA STATUS CALLED \n"); 32437c478bd9Sstevel@tonic-gate 32447c478bd9Sstevel@tonic-gate (void) memset((void *) &modeh, 0, sizeof (modeh)); 32457c478bd9Sstevel@tonic-gate (void) memset((void *) &ucmd, 0, sizeof (ucmd)); 32467c478bd9Sstevel@tonic-gate (void) memset(cdb, 0, sizeof (cdb)); 32477c478bd9Sstevel@tonic-gate /* 32487c478bd9Sstevel@tonic-gate * issue 10 byte mode sense (0x5A) 32497c478bd9Sstevel@tonic-gate */ 32507c478bd9Sstevel@tonic-gate cdb[0] = SCMD_MODE_SENSE_G1; 32517c478bd9Sstevel@tonic-gate cdb[7] = sizeof (modeh) >> 8; 32527c478bd9Sstevel@tonic-gate cdb[8] = sizeof (modeh) & 0xff; 32537c478bd9Sstevel@tonic-gate 32547c478bd9Sstevel@tonic-gate ucmd.uscsi_cdb = (caddr_t)cdb; 32557c478bd9Sstevel@tonic-gate ucmd.uscsi_cdblen = CDB_GROUP1; 32567c478bd9Sstevel@tonic-gate ucmd.uscsi_bufaddr = (caddr_t)&modeh; 32577c478bd9Sstevel@tonic-gate ucmd.uscsi_buflen = sizeof (modeh); 32587c478bd9Sstevel@tonic-gate ucmd.uscsi_timeout = 120; /* If 0, HBA hangs forever */ 32597c478bd9Sstevel@tonic-gate ucmd.uscsi_rqlen = RQ_LEN; 32607c478bd9Sstevel@tonic-gate ucmd.uscsi_rqbuf = rq_data; 32617c478bd9Sstevel@tonic-gate ret_val = do_uscsi_cmd(fd, &ucmd, USCSI_READ|USCSI_RQENABLE); 32627c478bd9Sstevel@tonic-gate if (ret_val || ucmd.uscsi_status) { 32637c478bd9Sstevel@tonic-gate /* 32647c478bd9Sstevel@tonic-gate * UFI devices may not respond to the 0 mode page. 32657c478bd9Sstevel@tonic-gate * retry with the error recovery page(0x01) 32667c478bd9Sstevel@tonic-gate */ 32677c478bd9Sstevel@tonic-gate if (ucmd.uscsi_status & STATUS_CHECK) { 32687c478bd9Sstevel@tonic-gate cdb[2] = 0x1; /* page code */ 32697c478bd9Sstevel@tonic-gate ret_val = do_uscsi_cmd(fd, &ucmd, 32707c478bd9Sstevel@tonic-gate USCSI_READ|USCSI_RQENABLE); 32717c478bd9Sstevel@tonic-gate } 32727c478bd9Sstevel@tonic-gate if (ret_val || ucmd.uscsi_status) { 32737c478bd9Sstevel@tonic-gate debug(1, "Modesense failed: %d - %d\n", 32747c478bd9Sstevel@tonic-gate ret_val, ucmd.uscsi_status); 32757c478bd9Sstevel@tonic-gate return (-1); 32767c478bd9Sstevel@tonic-gate } 32777c478bd9Sstevel@tonic-gate } 32787c478bd9Sstevel@tonic-gate debug(5, "Modesense succeeded: 0x%x\n", modeh.device_specific); 32797c478bd9Sstevel@tonic-gate 32807c478bd9Sstevel@tonic-gate if (modeh.device_specific & 0x80) { 32817c478bd9Sstevel@tonic-gate cur_status = SM_WRITE_PROTECT_NOPASSWD; 32827c478bd9Sstevel@tonic-gate } else { 32837c478bd9Sstevel@tonic-gate cur_status = SM_WRITE_PROTECT_DISABLE; 32847c478bd9Sstevel@tonic-gate } 32857c478bd9Sstevel@tonic-gate return (cur_status); 32867c478bd9Sstevel@tonic-gate } 3287