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