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 --- |