Changeset View
Changeset View
Standalone View
Standalone View
head/sys/cam/cam_periph.c
Show First 20 Lines • Show All 766 Lines • ▼ Show 20 Lines | camperiphfree(struct cam_periph *periph) | ||||
free(periph, M_CAMPERIPH); | free(periph, M_CAMPERIPH); | ||||
xpt_lock_buses(); | xpt_lock_buses(); | ||||
} | } | ||||
/* | /* | ||||
* Map user virtual pointers into kernel virtual address space, so we can | * Map user virtual pointers into kernel virtual address space, so we can | ||||
* access the memory. This is now a generic function that centralizes most | * access the memory. This is now a generic function that centralizes most | ||||
* of the sanity checks on the data flags, if any. | * of the sanity checks on the data flags, if any. | ||||
* This also only works for up to MAXPHYS memory. Since we use | * This also only works for up to maxphys memory. Since we use | ||||
* buffers to map stuff in and out, we're limited to the buffer size. | * buffers to map stuff in and out, we're limited to the buffer size. | ||||
*/ | */ | ||||
int | int | ||||
cam_periph_mapmem(union ccb *ccb, struct cam_periph_map_info *mapinfo, | cam_periph_mapmem(union ccb *ccb, struct cam_periph_map_info *mapinfo, | ||||
u_int maxmap) | u_int maxmap) | ||||
{ | { | ||||
int numbufs, i; | int numbufs, i; | ||||
u_int8_t **data_ptrs[CAM_PERIPH_MAXMAPS]; | u_int8_t **data_ptrs[CAM_PERIPH_MAXMAPS]; | ||||
u_int32_t lengths[CAM_PERIPH_MAXMAPS]; | u_int32_t lengths[CAM_PERIPH_MAXMAPS]; | ||||
u_int32_t dirs[CAM_PERIPH_MAXMAPS]; | u_int32_t dirs[CAM_PERIPH_MAXMAPS]; | ||||
bool misaligned[CAM_PERIPH_MAXMAPS]; | bool misaligned[CAM_PERIPH_MAXMAPS]; | ||||
bzero(mapinfo, sizeof(*mapinfo)); | bzero(mapinfo, sizeof(*mapinfo)); | ||||
if (maxmap == 0) | if (maxmap == 0) | ||||
maxmap = DFLTPHYS; /* traditional default */ | maxmap = DFLTPHYS; /* traditional default */ | ||||
else if (maxmap > MAXPHYS) | else if (maxmap > maxphys) | ||||
maxmap = MAXPHYS; /* for safety */ | maxmap = maxphys; /* for safety */ | ||||
switch(ccb->ccb_h.func_code) { | switch(ccb->ccb_h.func_code) { | ||||
case XPT_DEV_MATCH: | case XPT_DEV_MATCH: | ||||
if (ccb->cdm.match_buf_len == 0) { | if (ccb->cdm.match_buf_len == 0) { | ||||
printf("cam_periph_mapmem: invalid match buffer " | printf("cam_periph_mapmem: invalid match buffer " | ||||
"length 0\n"); | "length 0\n"); | ||||
return(EINVAL); | return(EINVAL); | ||||
} | } | ||||
if (ccb->cdm.pattern_buf_len > 0) { | if (ccb->cdm.pattern_buf_len > 0) { | ||||
data_ptrs[0] = (u_int8_t **)&ccb->cdm.patterns; | data_ptrs[0] = (u_int8_t **)&ccb->cdm.patterns; | ||||
lengths[0] = ccb->cdm.pattern_buf_len; | lengths[0] = ccb->cdm.pattern_buf_len; | ||||
dirs[0] = CAM_DIR_OUT; | dirs[0] = CAM_DIR_OUT; | ||||
data_ptrs[1] = (u_int8_t **)&ccb->cdm.matches; | data_ptrs[1] = (u_int8_t **)&ccb->cdm.matches; | ||||
lengths[1] = ccb->cdm.match_buf_len; | lengths[1] = ccb->cdm.match_buf_len; | ||||
dirs[1] = CAM_DIR_IN; | dirs[1] = CAM_DIR_IN; | ||||
numbufs = 2; | numbufs = 2; | ||||
} else { | } else { | ||||
data_ptrs[0] = (u_int8_t **)&ccb->cdm.matches; | data_ptrs[0] = (u_int8_t **)&ccb->cdm.matches; | ||||
lengths[0] = ccb->cdm.match_buf_len; | lengths[0] = ccb->cdm.match_buf_len; | ||||
dirs[0] = CAM_DIR_IN; | dirs[0] = CAM_DIR_IN; | ||||
numbufs = 1; | numbufs = 1; | ||||
} | } | ||||
/* | /* | ||||
* This request will not go to the hardware, no reason | * This request will not go to the hardware, no reason | ||||
* to be so strict. vmapbuf() is able to map up to MAXPHYS. | * to be so strict. vmapbuf() is able to map up to maxphys. | ||||
*/ | */ | ||||
maxmap = MAXPHYS; | maxmap = maxphys; | ||||
break; | break; | ||||
case XPT_SCSI_IO: | case XPT_SCSI_IO: | ||||
case XPT_CONT_TARGET_IO: | case XPT_CONT_TARGET_IO: | ||||
if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_NONE) | if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_NONE) | ||||
return(0); | return(0); | ||||
if ((ccb->ccb_h.flags & CAM_DATA_MASK) != CAM_DATA_VADDR) | if ((ccb->ccb_h.flags & CAM_DATA_MASK) != CAM_DATA_VADDR) | ||||
return (EINVAL); | return (EINVAL); | ||||
data_ptrs[0] = &ccb->csio.data_ptr; | data_ptrs[0] = &ccb->csio.data_ptr; | ||||
▲ Show 20 Lines • Show All 49 Lines • ▼ Show 20 Lines | case XPT_DEV_ADVINFO: | ||||
data_ptrs[0] = (uint8_t **)&ccb->cdai.buf; | data_ptrs[0] = (uint8_t **)&ccb->cdai.buf; | ||||
lengths[0] = ccb->cdai.bufsiz; | lengths[0] = ccb->cdai.bufsiz; | ||||
dirs[0] = CAM_DIR_IN; | dirs[0] = CAM_DIR_IN; | ||||
numbufs = 1; | numbufs = 1; | ||||
/* | /* | ||||
* This request will not go to the hardware, no reason | * This request will not go to the hardware, no reason | ||||
* to be so strict. vmapbuf() is able to map up to MAXPHYS. | * to be so strict. vmapbuf() is able to map up to maxphys. | ||||
*/ | */ | ||||
maxmap = MAXPHYS; | maxmap = maxphys; | ||||
break; | break; | ||||
default: | default: | ||||
return(EINVAL); | return(EINVAL); | ||||
break; /* NOTREACHED */ | break; /* NOTREACHED */ | ||||
} | } | ||||
/* | /* | ||||
* Check the transfer length and permissions first, so we don't | * Check the transfer length and permissions first, so we don't | ||||
Show All 11 Lines | for (i = 0; i < numbufs; i++) { | ||||
* The userland data pointer passed in may not be page | * The userland data pointer passed in may not be page | ||||
* aligned. vmapbuf() truncates the address to a page | * aligned. vmapbuf() truncates the address to a page | ||||
* boundary, so if the address isn't page aligned, we'll | * boundary, so if the address isn't page aligned, we'll | ||||
* need enough space for the given transfer length, plus | * need enough space for the given transfer length, plus | ||||
* whatever extra space is necessary to make it to the page | * whatever extra space is necessary to make it to the page | ||||
* boundary. | * boundary. | ||||
*/ | */ | ||||
misaligned[i] = (lengths[i] + | misaligned[i] = (lengths[i] + | ||||
(((vm_offset_t)(*data_ptrs[i])) & PAGE_MASK) > MAXPHYS); | (((vm_offset_t)(*data_ptrs[i])) & PAGE_MASK) > maxphys); | ||||
} | } | ||||
/* | /* | ||||
* This keeps the kernel stack of current thread from getting | * This keeps the kernel stack of current thread from getting | ||||
* swapped. In low-memory situations where the kernel stack might | * swapped. In low-memory situations where the kernel stack might | ||||
* otherwise get swapped out, this holds it and allows the thread | * otherwise get swapped out, this holds it and allows the thread | ||||
* to make progress and release the kernel mapped pages sooner. | * to make progress and release the kernel mapped pages sooner. | ||||
* | * | ||||
▲ Show 20 Lines • Show All 1,245 Lines • Show Last 20 Lines |