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