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