1 /* 2 * Copyright (c) 1997, 1998, 2000 Justin T. Gibbs. 3 * Copyright (c) 1997, 1998, 1999 Kenneth D. Merry. 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions, and the following disclaimer, 11 * without modification, immediately at the beginning of the file. 12 * 2. The name of the author may not be used to endorse or promote products 13 * derived from this software without specific prior written permission. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR 19 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 * 27 * $FreeBSD$ 28 */ 29 30 #include <sys/param.h> 31 #include <sys/systm.h> 32 #include <sys/kernel.h> 33 #include <sys/types.h> 34 #include <sys/bio.h> 35 #include <sys/malloc.h> 36 #include <sys/fcntl.h> 37 #include <sys/conf.h> 38 #include <sys/errno.h> 39 #include <sys/devicestat.h> 40 #include <sys/proc.h> 41 42 #include <cam/cam.h> 43 #include <cam/cam_ccb.h> 44 #include <cam/cam_periph.h> 45 #include <cam/cam_queue.h> 46 #include <cam/cam_xpt_periph.h> 47 #include <cam/cam_debug.h> 48 49 #include <cam/scsi/scsi_all.h> 50 #include <cam/scsi/scsi_pass.h> 51 52 typedef enum { 53 PASS_FLAG_OPEN = 0x01, 54 PASS_FLAG_LOCKED = 0x02, 55 PASS_FLAG_INVALID = 0x04 56 } pass_flags; 57 58 typedef enum { 59 PASS_STATE_NORMAL 60 } pass_state; 61 62 typedef enum { 63 PASS_CCB_BUFFER_IO, 64 PASS_CCB_WAITING 65 } pass_ccb_types; 66 67 #define ccb_type ppriv_field0 68 #define ccb_bp ppriv_ptr1 69 70 struct pass_softc { 71 pass_state state; 72 pass_flags flags; 73 u_int8_t pd_type; 74 union ccb saved_ccb; 75 struct devstat *device_stats; 76 dev_t dev; 77 }; 78 79 #define PASS_CDEV_MAJOR 31 80 81 static d_open_t passopen; 82 static d_close_t passclose; 83 static d_ioctl_t passioctl; 84 85 static periph_init_t passinit; 86 static periph_ctor_t passregister; 87 static periph_oninv_t passoninvalidate; 88 static periph_dtor_t passcleanup; 89 static periph_start_t passstart; 90 static void passasync(void *callback_arg, u_int32_t code, 91 struct cam_path *path, void *arg); 92 static void passdone(struct cam_periph *periph, 93 union ccb *done_ccb); 94 static int passerror(union ccb *ccb, u_int32_t cam_flags, 95 u_int32_t sense_flags); 96 static int passsendccb(struct cam_periph *periph, union ccb *ccb, 97 union ccb *inccb); 98 99 static struct periph_driver passdriver = 100 { 101 passinit, "pass", 102 TAILQ_HEAD_INITIALIZER(passdriver.units), /* generation */ 0 103 }; 104 105 PERIPHDRIVER_DECLARE(pass, passdriver); 106 107 static struct cdevsw pass_cdevsw = { 108 .d_open = passopen, 109 .d_close = passclose, 110 .d_ioctl = passioctl, 111 .d_name = "pass", 112 .d_maj = PASS_CDEV_MAJOR, 113 }; 114 115 static void 116 passinit(void) 117 { 118 cam_status status; 119 struct cam_path *path; 120 121 /* 122 * Install a global async callback. This callback will 123 * receive async callbacks like "new device found". 124 */ 125 status = xpt_create_path(&path, /*periph*/NULL, CAM_XPT_PATH_ID, 126 CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD); 127 128 if (status == CAM_REQ_CMP) { 129 struct ccb_setasync csa; 130 131 xpt_setup_ccb(&csa.ccb_h, path, /*priority*/5); 132 csa.ccb_h.func_code = XPT_SASYNC_CB; 133 csa.event_enable = AC_FOUND_DEVICE; 134 csa.callback = passasync; 135 csa.callback_arg = NULL; 136 xpt_action((union ccb *)&csa); 137 status = csa.ccb_h.status; 138 xpt_free_path(path); 139 } 140 141 if (status != CAM_REQ_CMP) { 142 printf("pass: Failed to attach master async callback " 143 "due to status 0x%x!\n", status); 144 } 145 146 } 147 148 static void 149 passoninvalidate(struct cam_periph *periph) 150 { 151 struct pass_softc *softc; 152 struct ccb_setasync csa; 153 154 softc = (struct pass_softc *)periph->softc; 155 156 /* 157 * De-register any async callbacks. 158 */ 159 xpt_setup_ccb(&csa.ccb_h, periph->path, 160 /* priority */ 5); 161 csa.ccb_h.func_code = XPT_SASYNC_CB; 162 csa.event_enable = 0; 163 csa.callback = passasync; 164 csa.callback_arg = periph; 165 xpt_action((union ccb *)&csa); 166 167 softc->flags |= PASS_FLAG_INVALID; 168 169 /* 170 * XXX Return all queued I/O with ENXIO. 171 * XXX Handle any transactions queued to the card 172 * with XPT_ABORT_CCB. 173 */ 174 175 if (bootverbose) { 176 xpt_print_path(periph->path); 177 printf("lost device\n"); 178 } 179 180 } 181 182 static void 183 passcleanup(struct cam_periph *periph) 184 { 185 struct pass_softc *softc; 186 187 softc = (struct pass_softc *)periph->softc; 188 189 devstat_remove_entry(softc->device_stats); 190 191 destroy_dev(softc->dev); 192 193 if (bootverbose) { 194 xpt_print_path(periph->path); 195 printf("removing device entry\n"); 196 } 197 free(softc, M_DEVBUF); 198 } 199 200 static void 201 passasync(void *callback_arg, u_int32_t code, 202 struct cam_path *path, void *arg) 203 { 204 struct cam_periph *periph; 205 206 periph = (struct cam_periph *)callback_arg; 207 208 switch (code) { 209 case AC_FOUND_DEVICE: 210 { 211 struct ccb_getdev *cgd; 212 cam_status status; 213 214 cgd = (struct ccb_getdev *)arg; 215 if (cgd == NULL) 216 break; 217 218 /* 219 * Allocate a peripheral instance for 220 * this device and start the probe 221 * process. 222 */ 223 status = cam_periph_alloc(passregister, passoninvalidate, 224 passcleanup, passstart, "pass", 225 CAM_PERIPH_BIO, cgd->ccb_h.path, 226 passasync, AC_FOUND_DEVICE, cgd); 227 228 if (status != CAM_REQ_CMP 229 && status != CAM_REQ_INPROG) { 230 const struct cam_status_entry *entry; 231 232 entry = cam_fetch_status_entry(status); 233 234 printf("passasync: Unable to attach new device " 235 "due to status %#x: %s\n", status, entry ? 236 entry->status_text : "Unknown"); 237 } 238 239 break; 240 } 241 default: 242 cam_periph_async(periph, code, path, arg); 243 break; 244 } 245 } 246 247 static cam_status 248 passregister(struct cam_periph *periph, void *arg) 249 { 250 struct pass_softc *softc; 251 struct ccb_setasync csa; 252 struct ccb_getdev *cgd; 253 int no_tags; 254 255 cgd = (struct ccb_getdev *)arg; 256 if (periph == NULL) { 257 printf("passregister: periph was NULL!!\n"); 258 return(CAM_REQ_CMP_ERR); 259 } 260 261 if (cgd == NULL) { 262 printf("passregister: no getdev CCB, can't register device\n"); 263 return(CAM_REQ_CMP_ERR); 264 } 265 266 softc = (struct pass_softc *)malloc(sizeof(*softc), 267 M_DEVBUF, M_NOWAIT); 268 269 if (softc == NULL) { 270 printf("passregister: Unable to probe new device. " 271 "Unable to allocate softc\n"); 272 return(CAM_REQ_CMP_ERR); 273 } 274 275 bzero(softc, sizeof(*softc)); 276 softc->state = PASS_STATE_NORMAL; 277 softc->pd_type = SID_TYPE(&cgd->inq_data); 278 279 periph->softc = softc; 280 281 /* 282 * We pass in 0 for a blocksize, since we don't 283 * know what the blocksize of this device is, if 284 * it even has a blocksize. 285 */ 286 no_tags = (cgd->inq_data.flags & SID_CmdQue) == 0; 287 softc->device_stats = devstat_new_entry("pass", periph->unit_number, 0, 288 DEVSTAT_NO_BLOCKSIZE 289 | (no_tags ? DEVSTAT_NO_ORDERED_TAGS : 0), 290 softc->pd_type | 291 DEVSTAT_TYPE_IF_SCSI | 292 DEVSTAT_TYPE_PASS, 293 DEVSTAT_PRIORITY_PASS); 294 295 /* Register the device */ 296 softc->dev = make_dev(&pass_cdevsw, periph->unit_number, UID_ROOT, 297 GID_OPERATOR, 0600, "%s%d", periph->periph_name, 298 periph->unit_number); 299 softc->dev->si_drv1 = periph; 300 301 /* 302 * Add an async callback so that we get 303 * notified if this device goes away. 304 */ 305 xpt_setup_ccb(&csa.ccb_h, periph->path, /* priority */ 5); 306 csa.ccb_h.func_code = XPT_SASYNC_CB; 307 csa.event_enable = AC_LOST_DEVICE; 308 csa.callback = passasync; 309 csa.callback_arg = periph; 310 xpt_action((union ccb *)&csa); 311 312 if (bootverbose) 313 xpt_announce_periph(periph, NULL); 314 315 return(CAM_REQ_CMP); 316 } 317 318 static int 319 passopen(dev_t dev, int flags, int fmt, struct thread *td) 320 { 321 struct cam_periph *periph; 322 struct pass_softc *softc; 323 int error; 324 int s; 325 326 error = 0; /* default to no error */ 327 328 periph = (struct cam_periph *)dev->si_drv1; 329 if (periph == NULL) 330 return (ENXIO); 331 332 softc = (struct pass_softc *)periph->softc; 333 334 s = splsoftcam(); 335 if (softc->flags & PASS_FLAG_INVALID) { 336 splx(s); 337 return(ENXIO); 338 } 339 340 /* 341 * Don't allow access when we're running at a high securelevel. 342 */ 343 error = securelevel_gt(td->td_ucred, 1); 344 if (error) { 345 splx(s); 346 return(error); 347 } 348 349 /* 350 * Only allow read-write access. 351 */ 352 if (((flags & FWRITE) == 0) || ((flags & FREAD) == 0)) { 353 splx(s); 354 return(EPERM); 355 } 356 357 /* 358 * We don't allow nonblocking access. 359 */ 360 if ((flags & O_NONBLOCK) != 0) { 361 xpt_print_path(periph->path); 362 printf("can't do nonblocking accesss\n"); 363 splx(s); 364 return(EINVAL); 365 } 366 367 if ((error = cam_periph_lock(periph, PRIBIO | PCATCH)) != 0) { 368 splx(s); 369 return (error); 370 } 371 372 splx(s); 373 374 if ((softc->flags & PASS_FLAG_OPEN) == 0) { 375 if (cam_periph_acquire(periph) != CAM_REQ_CMP) 376 return(ENXIO); 377 softc->flags |= PASS_FLAG_OPEN; 378 } 379 380 cam_periph_unlock(periph); 381 382 return (error); 383 } 384 385 static int 386 passclose(dev_t dev, int flag, int fmt, struct thread *td) 387 { 388 struct cam_periph *periph; 389 struct pass_softc *softc; 390 int error; 391 392 periph = (struct cam_periph *)dev->si_drv1; 393 if (periph == NULL) 394 return (ENXIO); 395 396 softc = (struct pass_softc *)periph->softc; 397 398 if ((error = cam_periph_lock(periph, PRIBIO)) != 0) 399 return (error); 400 401 softc->flags &= ~PASS_FLAG_OPEN; 402 403 cam_periph_unlock(periph); 404 cam_periph_release(periph); 405 406 return (0); 407 } 408 409 static void 410 passstart(struct cam_periph *periph, union ccb *start_ccb) 411 { 412 struct pass_softc *softc; 413 int s; 414 415 softc = (struct pass_softc *)periph->softc; 416 417 switch (softc->state) { 418 case PASS_STATE_NORMAL: 419 s = splbio(); 420 start_ccb->ccb_h.ccb_type = PASS_CCB_WAITING; 421 SLIST_INSERT_HEAD(&periph->ccb_list, &start_ccb->ccb_h, 422 periph_links.sle); 423 periph->immediate_priority = CAM_PRIORITY_NONE; 424 splx(s); 425 wakeup(&periph->ccb_list); 426 break; 427 } 428 } 429 430 static void 431 passdone(struct cam_periph *periph, union ccb *done_ccb) 432 { 433 struct pass_softc *softc; 434 struct ccb_scsiio *csio; 435 436 softc = (struct pass_softc *)periph->softc; 437 csio = &done_ccb->csio; 438 switch (csio->ccb_h.ccb_type) { 439 case PASS_CCB_WAITING: 440 /* Caller will release the CCB */ 441 wakeup(&done_ccb->ccb_h.cbfcnp); 442 return; 443 } 444 xpt_release_ccb(done_ccb); 445 } 446 447 static int 448 passioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, struct thread *td) 449 { 450 struct cam_periph *periph; 451 struct pass_softc *softc; 452 int error; 453 454 periph = (struct cam_periph *)dev->si_drv1; 455 if (periph == NULL) 456 return(ENXIO); 457 458 softc = (struct pass_softc *)periph->softc; 459 460 error = 0; 461 462 switch (cmd) { 463 464 case CAMIOCOMMAND: 465 { 466 union ccb *inccb; 467 union ccb *ccb; 468 int ccb_malloced; 469 470 inccb = (union ccb *)addr; 471 472 /* 473 * Some CCB types, like scan bus and scan lun can only go 474 * through the transport layer device. 475 */ 476 if (inccb->ccb_h.func_code & XPT_FC_XPT_ONLY) { 477 xpt_print_path(periph->path); 478 printf("CCB function code %#x is restricted to the " 479 "XPT device\n", inccb->ccb_h.func_code); 480 error = ENODEV; 481 break; 482 } 483 484 /* 485 * Non-immediate CCBs need a CCB from the per-device pool 486 * of CCBs, which is scheduled by the transport layer. 487 * Immediate CCBs and user-supplied CCBs should just be 488 * malloced. 489 */ 490 if ((inccb->ccb_h.func_code & XPT_FC_QUEUED) 491 && ((inccb->ccb_h.func_code & XPT_FC_USER_CCB) == 0)) { 492 ccb = cam_periph_getccb(periph, 493 inccb->ccb_h.pinfo.priority); 494 ccb_malloced = 0; 495 } else { 496 ccb = xpt_alloc_ccb(); 497 498 if (ccb != NULL) 499 xpt_setup_ccb(&ccb->ccb_h, periph->path, 500 inccb->ccb_h.pinfo.priority); 501 ccb_malloced = 1; 502 } 503 504 if (ccb == NULL) { 505 xpt_print_path(periph->path); 506 printf("unable to allocate CCB\n"); 507 error = ENOMEM; 508 break; 509 } 510 511 error = passsendccb(periph, ccb, inccb); 512 513 if (ccb_malloced) 514 xpt_free_ccb(ccb); 515 else 516 xpt_release_ccb(ccb); 517 518 break; 519 } 520 default: 521 error = cam_periph_ioctl(periph, cmd, addr, passerror); 522 break; 523 } 524 525 return(error); 526 } 527 528 /* 529 * Generally, "ccb" should be the CCB supplied by the kernel. "inccb" 530 * should be the CCB that is copied in from the user. 531 */ 532 static int 533 passsendccb(struct cam_periph *periph, union ccb *ccb, union ccb *inccb) 534 { 535 struct pass_softc *softc; 536 struct cam_periph_map_info mapinfo; 537 int error, need_unmap; 538 539 softc = (struct pass_softc *)periph->softc; 540 541 need_unmap = 0; 542 543 /* 544 * There are some fields in the CCB header that need to be 545 * preserved, the rest we get from the user. 546 */ 547 xpt_merge_ccb(ccb, inccb); 548 549 /* 550 * There's no way for the user to have a completion 551 * function, so we put our own completion function in here. 552 */ 553 ccb->ccb_h.cbfcnp = passdone; 554 555 /* 556 * We only attempt to map the user memory into kernel space 557 * if they haven't passed in a physical memory pointer, 558 * and if there is actually an I/O operation to perform. 559 * Right now cam_periph_mapmem() only supports SCSI and device 560 * match CCBs. For the SCSI CCBs, we only pass the CCB in if 561 * there's actually data to map. cam_periph_mapmem() will do the 562 * right thing, even if there isn't data to map, but since CCBs 563 * without data are a reasonably common occurance (e.g. test unit 564 * ready), it will save a few cycles if we check for it here. 565 */ 566 if (((ccb->ccb_h.flags & CAM_DATA_PHYS) == 0) 567 && (((ccb->ccb_h.func_code == XPT_SCSI_IO) 568 && ((ccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE)) 569 || (ccb->ccb_h.func_code == XPT_DEV_MATCH))) { 570 571 bzero(&mapinfo, sizeof(mapinfo)); 572 573 error = cam_periph_mapmem(ccb, &mapinfo); 574 575 /* 576 * cam_periph_mapmem returned an error, we can't continue. 577 * Return the error to the user. 578 */ 579 if (error) 580 return(error); 581 582 /* 583 * We successfully mapped the memory in, so we need to 584 * unmap it when the transaction is done. 585 */ 586 need_unmap = 1; 587 } 588 589 /* 590 * If the user wants us to perform any error recovery, then honor 591 * that request. Otherwise, it's up to the user to perform any 592 * error recovery. 593 */ 594 error = cam_periph_runccb(ccb, 595 (ccb->ccb_h.flags & CAM_PASS_ERR_RECOVER) ? 596 passerror : NULL, 597 /* cam_flags */ CAM_RETRY_SELTO, 598 /* sense_flags */SF_RETRY_UA, 599 softc->device_stats); 600 601 if (need_unmap != 0) 602 cam_periph_unmapmem(ccb, &mapinfo); 603 604 ccb->ccb_h.cbfcnp = NULL; 605 ccb->ccb_h.periph_priv = inccb->ccb_h.periph_priv; 606 bcopy(ccb, inccb, sizeof(union ccb)); 607 608 return(error); 609 } 610 611 static int 612 passerror(union ccb *ccb, u_int32_t cam_flags, u_int32_t sense_flags) 613 { 614 struct cam_periph *periph; 615 struct pass_softc *softc; 616 617 periph = xpt_path_periph(ccb->ccb_h.path); 618 softc = (struct pass_softc *)periph->softc; 619 620 return(cam_periph_error(ccb, cam_flags, sense_flags, 621 &softc->saved_ccb)); 622 } 623