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