Deleted Added
full compact
cam_periph.c (40603) cam_periph.c (41877)
1/*
2 * Common functions for CAM "type" (peripheral) drivers.
3 *
4 * Copyright (c) 1997, 1998 Justin T. Gibbs.
5 * Copyright (c) 1997, 1998 Kenneth D. Merry.
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without

--- 12 unchanged lines hidden (view full) ---

21 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 *
1/*
2 * Common functions for CAM "type" (peripheral) drivers.
3 *
4 * Copyright (c) 1997, 1998 Justin T. Gibbs.
5 * Copyright (c) 1997, 1998 Kenneth D. Merry.
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without

--- 12 unchanged lines hidden (view full) ---

21 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 *
29 * $Id: cam_periph.c,v 1.5 1998/10/15 17:46:18 ken Exp $
29 * $Id: cam_periph.c,v 1.6 1998/10/22 22:16:48 ken Exp $
30 */
31
32#include <sys/param.h>
33#include <sys/systm.h>
34#include <sys/types.h>
35#include <sys/malloc.h>
36#include <sys/kernel.h>
37#include <sys/buf.h>

--- 447 unchanged lines hidden (view full) ---

485 * access the memory. This won't work on physical pointers, for now it's
486 * up to the caller to check for that. (XXX KDM -- should we do that here
487 * instead?) This also only works for up to MAXPHYS memory. Since we use
488 * buffers to map stuff in and out, we're limited to the buffer size.
489 */
490int
491cam_periph_mapmem(union ccb *ccb, struct cam_periph_map_info *mapinfo)
492{
30 */
31
32#include <sys/param.h>
33#include <sys/systm.h>
34#include <sys/types.h>
35#include <sys/malloc.h>
36#include <sys/kernel.h>
37#include <sys/buf.h>

--- 447 unchanged lines hidden (view full) ---

485 * access the memory. This won't work on physical pointers, for now it's
486 * up to the caller to check for that. (XXX KDM -- should we do that here
487 * instead?) This also only works for up to MAXPHYS memory. Since we use
488 * buffers to map stuff in and out, we're limited to the buffer size.
489 */
490int
491cam_periph_mapmem(union ccb *ccb, struct cam_periph_map_info *mapinfo)
492{
493 int flags, numbufs, i;
493 int numbufs, i;
494 int flags[CAM_PERIPH_MAXMAPS];
494 u_int8_t **data_ptrs[CAM_PERIPH_MAXMAPS];
495 u_int32_t lengths[CAM_PERIPH_MAXMAPS];
496 u_int32_t dirs[CAM_PERIPH_MAXMAPS];
497
498 switch(ccb->ccb_h.func_code) {
499 case XPT_DEV_MATCH:
495 u_int8_t **data_ptrs[CAM_PERIPH_MAXMAPS];
496 u_int32_t lengths[CAM_PERIPH_MAXMAPS];
497 u_int32_t dirs[CAM_PERIPH_MAXMAPS];
498
499 switch(ccb->ccb_h.func_code) {
500 case XPT_DEV_MATCH:
500 if (ccb->cdm.pattern_buf_len > MAXPHYS) {
501 printf("cam_periph_mapmem: attempt to map %u bytes, "
502 "which is greater than MAXPHYS(%d)\n",
503 ccb->cdm.pattern_buf_len, MAXPHYS);
504 return(E2BIG);
505 } else if (ccb->cdm.match_buf_len > MAXPHYS) {
506 printf("cam_periph_mapmem: attempt to map %u bytes, "
507 "which is greater than MAXPHYS(%d)\n",
508 ccb->cdm.match_buf_len, MAXPHYS);
509 return(E2BIG);
510 }
511 if (ccb->cdm.match_buf_len == 0) {
512 printf("cam_periph_mapmem: invalid match buffer "
513 "length 0\n");
514 return(EINVAL);
515 }
516 if (ccb->cdm.pattern_buf_len > 0) {
517 data_ptrs[0] = (u_int8_t **)&ccb->cdm.patterns;
518 lengths[0] = ccb->cdm.pattern_buf_len;

--- 5 unchanged lines hidden (view full) ---

524 } else {
525 data_ptrs[0] = (u_int8_t **)&ccb->cdm.matches;
526 lengths[0] = ccb->cdm.match_buf_len;
527 dirs[0] = CAM_DIR_IN;
528 numbufs = 1;
529 }
530 break;
531 case XPT_SCSI_IO:
501 if (ccb->cdm.match_buf_len == 0) {
502 printf("cam_periph_mapmem: invalid match buffer "
503 "length 0\n");
504 return(EINVAL);
505 }
506 if (ccb->cdm.pattern_buf_len > 0) {
507 data_ptrs[0] = (u_int8_t **)&ccb->cdm.patterns;
508 lengths[0] = ccb->cdm.pattern_buf_len;

--- 5 unchanged lines hidden (view full) ---

514 } else {
515 data_ptrs[0] = (u_int8_t **)&ccb->cdm.matches;
516 lengths[0] = ccb->cdm.match_buf_len;
517 dirs[0] = CAM_DIR_IN;
518 numbufs = 1;
519 }
520 break;
521 case XPT_SCSI_IO:
532 if (ccb->csio.dxfer_len > MAXPHYS) {
533 printf("cam_periph_mapmem: attempt to map %u bytes, "
534 "which is greater than MAXPHYS(%d)\n",
535 ccb->csio.dxfer_len, MAXPHYS);
536 return(E2BIG);
537 }
538
539 if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_NONE)
540 return(0);
541
542 data_ptrs[0] = &ccb->csio.data_ptr;
522 if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_NONE)
523 return(0);
524
525 data_ptrs[0] = &ccb->csio.data_ptr;
543 lengths[0] = ccb->csio.dxfer_len;;
526 lengths[0] = ccb->csio.dxfer_len;
544 dirs[0] = ccb->ccb_h.flags & CAM_DIR_MASK;
545 numbufs = 1;
546 break;
547 default:
548 return(EINVAL);
549 break; /* NOTREACHED */
550 }
551
527 dirs[0] = ccb->ccb_h.flags & CAM_DIR_MASK;
528 numbufs = 1;
529 break;
530 default:
531 return(EINVAL);
532 break; /* NOTREACHED */
533 }
534
552 /* this keeps the current process from getting swapped */
553 /*
535 /*
554 * XXX KDM should I use P_NOSWAP instead?
536 * Check the transfer length and permissions first, so we don't
537 * have to unmap any previously mapped buffers.
555 */
538 */
556 curproc->p_flag |= P_PHYSIO;
557
558 for (i = 0; i < numbufs; i++) {
539 for (i = 0; i < numbufs; i++) {
559 flags = 0;
560
540
541 flags[i] = 0;
542
543 /*
544 * The userland data pointer passed in may not be page
545 * aligned. vmapbuf() truncates the address to a page
546 * boundary, so if the address isn't page aligned, we'll
547 * need enough space for the given transfer length, plus
548 * whatever extra space is necessary to make it to the page
549 * boundary.
550 */
551 if ((lengths[i] +
552 (((vm_offset_t)(*data_ptrs[i])) & PAGE_MASK)) > MAXPHYS){
553 printf("cam_periph_mapmem: attempt to map %u bytes, "
554 "which is greater than MAXPHYS(%d)\n",
555 lengths[i] +
556 (((vm_offset_t)(*data_ptrs[i])) & PAGE_MASK),
557 MAXPHYS);
558 return(E2BIG);
559 }
560
561 if (dirs[i] & CAM_DIR_IN) {
561 if (dirs[i] & CAM_DIR_IN) {
562 flags = B_READ;
562 flags[i] = B_READ;
563 if (useracc(*data_ptrs[i], lengths[i], B_READ) == 0){
564 printf("cam_periph_mapmem: error, "
565 "address %p, length %lu isn't "
566 "user accessible for READ\n",
567 (void *)*data_ptrs[i],
568 (u_long)lengths[i]);
563 if (useracc(*data_ptrs[i], lengths[i], B_READ) == 0){
564 printf("cam_periph_mapmem: error, "
565 "address %p, length %lu isn't "
566 "user accessible for READ\n",
567 (void *)*data_ptrs[i],
568 (u_long)lengths[i]);
569 /*
570 * If we've already mapped one or more
571 * buffers for this CCB, unmap it (them).
572 */
573 if (i > 0)
574 cam_periph_unmapmem(ccb, mapinfo);
575 else
576 curproc->p_flag &= ~P_PHYSIO;
577
578 return(EACCES);
579 }
580 }
581
582 /*
583 * XXX this check is really bogus, since B_WRITE currently
584 * is all 0's, and so it is "set" all the time.
585 */
586 if (dirs[i] & CAM_DIR_OUT) {
569 return(EACCES);
570 }
571 }
572
573 /*
574 * XXX this check is really bogus, since B_WRITE currently
575 * is all 0's, and so it is "set" all the time.
576 */
577 if (dirs[i] & CAM_DIR_OUT) {
587 flags |= B_WRITE;
578 flags[i] |= B_WRITE;
588 if (useracc(*data_ptrs[i], lengths[i], B_WRITE) == 0){
589 printf("cam_periph_mapmem: error, "
590 "address %p, length %lu isn't "
591 "user accessible for WRITE\n",
592 (void *)*data_ptrs[i],
593 (u_long)lengths[i]);
579 if (useracc(*data_ptrs[i], lengths[i], B_WRITE) == 0){
580 printf("cam_periph_mapmem: error, "
581 "address %p, length %lu isn't "
582 "user accessible for WRITE\n",
583 (void *)*data_ptrs[i],
584 (u_long)lengths[i]);
594 /*
595 * If we've already mapped one or more
596 * buffers for this CCB, unmap it (them).
597 */
598 if (i > 0)
599 cam_periph_unmapmem(ccb, mapinfo);
600 else
601 curproc->p_flag &= ~P_PHYSIO;
602
603 return(EACCES);
604 }
605 }
606
585
586 return(EACCES);
587 }
588 }
589
590 }
591
592 /* this keeps the current process from getting swapped */
593 /*
594 * XXX KDM should I use P_NOSWAP instead?
595 */
596 curproc->p_flag |= P_PHYSIO;
597
598 for (i = 0; i < numbufs; i++) {
607 /*
608 * Get the buffer.
609 */
610 mapinfo->bp[i] = getpbuf();
611
612 /* save the buffer's data address */
613 mapinfo->bp[i]->b_saveaddr = mapinfo->bp[i]->b_data;
614
615 /* put our pointer in the data slot */
616 mapinfo->bp[i]->b_data = *data_ptrs[i];
617
599 /*
600 * Get the buffer.
601 */
602 mapinfo->bp[i] = getpbuf();
603
604 /* save the buffer's data address */
605 mapinfo->bp[i]->b_saveaddr = mapinfo->bp[i]->b_data;
606
607 /* put our pointer in the data slot */
608 mapinfo->bp[i]->b_data = *data_ptrs[i];
609
618 /* set the transfer length, we know it's < 64K */
610 /* set the transfer length, we know it's < MAXPHYS */
619 mapinfo->bp[i]->b_bufsize = lengths[i];
620
621 /* set the flags */
611 mapinfo->bp[i]->b_bufsize = lengths[i];
612
613 /* set the flags */
622 mapinfo->bp[i]->b_flags = flags | B_PHYS | B_BUSY;
614 mapinfo->bp[i]->b_flags = flags[i] | B_PHYS | B_BUSY;
623
624 /* map the buffer into kernel memory */
625 vmapbuf(mapinfo->bp[i]);
626
627 /* set our pointer to the new mapped area */
628 *data_ptrs[i] = mapinfo->bp[i]->b_data;
629
630 mapinfo->num_bufs_used++;

--- 937 unchanged lines hidden ---
615
616 /* map the buffer into kernel memory */
617 vmapbuf(mapinfo->bp[i]);
618
619 /* set our pointer to the new mapped area */
620 *data_ptrs[i] = mapinfo->bp[i]->b_data;
621
622 mapinfo->num_bufs_used++;

--- 937 unchanged lines hidden ---