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