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