summaryrefslogtreecommitdiff
path: root/sys/cam/cam_periph.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/cam/cam_periph.c')
-rw-r--r--sys/cam/cam_periph.c109
1 files changed, 53 insertions, 56 deletions
diff --git a/sys/cam/cam_periph.c b/sys/cam/cam_periph.c
index 57ac5338e28b8..6d6fe291cf1f3 100644
--- a/sys/cam/cam_periph.c
+++ b/sys/cam/cam_periph.c
@@ -26,14 +26,14 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: cam_periph.c,v 1.8 1998/12/16 21:00:06 ken Exp $
+ * $Id: cam_periph.c,v 1.4 1998/10/13 21:41:32 ken Exp $
*/
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/types.h>
#include <sys/malloc.h>
-#include <sys/linker_set.h>
+#include <sys/kernel.h>
#include <sys/buf.h>
#include <sys/proc.h>
#include <sys/devicestat.h>
@@ -62,11 +62,10 @@ static void camperiphdone(struct cam_periph *periph,
static void camperiphfree(struct cam_periph *periph);
cam_status
-cam_periph_alloc(periph_ctor_t *periph_ctor,
- periph_oninv_t *periph_oninvalidate,
- periph_dtor_t *periph_dtor, periph_start_t *periph_start,
- char *name, cam_periph_type type, struct cam_path *path,
- ac_callback_t *ac_callback, ac_code code, void *arg)
+cam_periph_alloc(periph_ctor_t *periph_ctor, periph_dtor_t *periph_dtor,
+ periph_start_t *periph_start, char *name, cam_periph_type type,
+ struct cam_path *path, ac_callback_t *ac_callback,
+ ac_code code, void *arg)
{
struct periph_driver **p_drv;
struct cam_periph *periph;
@@ -123,7 +122,6 @@ cam_periph_alloc(periph_ctor_t *periph_ctor,
cam_init_pinfo(&periph->pinfo);
periph->periph_start = periph_start;
periph->periph_dtor = periph_dtor;
- periph->periph_oninval = periph_oninvalidate;
periph->type = type;
periph->periph_name = name;
periph->unit_number = camperiphunit(*p_drv, path_id, target_id, lun_id);
@@ -374,19 +372,10 @@ cam_periph_invalidate(struct cam_periph *periph)
{
int s;
- s = splsoftcam();
- /*
- * We only call this routine the first time a peripheral is
- * invalidated. The oninvalidate() routine is always called at
- * splsoftcam().
- */
- if (((periph->flags & CAM_PERIPH_INVALID) == 0)
- && (periph->periph_oninval != NULL))
- periph->periph_oninval(periph);
-
periph->flags |= CAM_PERIPH_INVALID;
periph->flags &= ~CAM_PERIPH_NEW_DEV_FOUND;
+ s = splsoftcam();
if (periph->refcount == 0)
camperiphfree(periph);
else if (periph->refcount < 0)
@@ -490,14 +479,24 @@ cam_periph_unlock(struct cam_periph *periph)
int
cam_periph_mapmem(union ccb *ccb, struct cam_periph_map_info *mapinfo)
{
- int numbufs, i;
- int flags[CAM_PERIPH_MAXMAPS];
+ int flags, numbufs, i;
u_int8_t **data_ptrs[CAM_PERIPH_MAXMAPS];
u_int32_t lengths[CAM_PERIPH_MAXMAPS];
u_int32_t dirs[CAM_PERIPH_MAXMAPS];
switch(ccb->ccb_h.func_code) {
case XPT_DEV_MATCH:
+ if (ccb->cdm.pattern_buf_len > MAXPHYS) {
+ printf("cam_periph_mapmem: attempt to map %u bytes, "
+ "which is greater than MAXPHYS(%d)\n",
+ ccb->cdm.pattern_buf_len, MAXPHYS);
+ return(E2BIG);
+ } else if (ccb->cdm.match_buf_len > MAXPHYS) {
+ printf("cam_periph_mapmem: attempt to map %u bytes, "
+ "which is greater than MAXPHYS(%d)\n",
+ ccb->cdm.match_buf_len, MAXPHYS);
+ return(E2BIG);
+ }
if (ccb->cdm.match_buf_len == 0) {
printf("cam_periph_mapmem: invalid match buffer "
"length 0\n");
@@ -519,11 +518,18 @@ cam_periph_mapmem(union ccb *ccb, struct cam_periph_map_info *mapinfo)
}
break;
case XPT_SCSI_IO:
+ if (ccb->csio.dxfer_len > MAXPHYS) {
+ printf("cam_periph_mapmem: attempt to map %u bytes, "
+ "which is greater than MAXPHYS(%d)\n",
+ ccb->csio.dxfer_len, MAXPHYS);
+ return(E2BIG);
+ }
+
if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_NONE)
return(0);
data_ptrs[0] = &ccb->csio.data_ptr;
- lengths[0] = ccb->csio.dxfer_len;
+ lengths[0] = ccb->csio.dxfer_len;;
dirs[0] = ccb->ccb_h.flags & CAM_DIR_MASK;
numbufs = 1;
break;
@@ -532,40 +538,32 @@ cam_periph_mapmem(union ccb *ccb, struct cam_periph_map_info *mapinfo)
break; /* NOTREACHED */
}
+ /* this keeps the current process from getting swapped */
/*
- * Check the transfer length and permissions first, so we don't
- * have to unmap any previously mapped buffers.
+ * XXX KDM should I use P_NOSWAP instead?
*/
- for (i = 0; i < numbufs; i++) {
-
- flags[i] = 0;
+ curproc->p_flag |= P_PHYSIO;
- /*
- * The userland data pointer passed in may not be page
- * aligned. vmapbuf() truncates the address to a page
- * boundary, so if the address isn't page aligned, we'll
- * need enough space for the given transfer length, plus
- * whatever extra space is necessary to make it to the page
- * boundary.
- */
- if ((lengths[i] +
- (((vm_offset_t)(*data_ptrs[i])) & PAGE_MASK)) > DFLTPHYS){
- printf("cam_periph_mapmem: attempt to map %u bytes, "
- "which is greater than DFLTPHYS(%d)\n",
- lengths[i] +
- (((vm_offset_t)(*data_ptrs[i])) & PAGE_MASK),
- DFLTPHYS);
- return(E2BIG);
- }
+ for (i = 0; i < numbufs; i++) {
+ flags = 0;
if (dirs[i] & CAM_DIR_IN) {
- flags[i] = B_READ;
+ flags = B_READ;
if (useracc(*data_ptrs[i], lengths[i], B_READ) == 0){
printf("cam_periph_mapmem: error, "
"address %p, length %lu isn't "
"user accessible for READ\n",
(void *)*data_ptrs[i],
(u_long)lengths[i]);
+ /*
+ * If we've already mapped one or more
+ * buffers for this CCB, unmap it (them).
+ */
+ if (i > 0)
+ cam_periph_unmapmem(ccb, mapinfo);
+ else
+ curproc->p_flag &= ~P_PHYSIO;
+
return(EACCES);
}
}
@@ -575,27 +573,26 @@ cam_periph_mapmem(union ccb *ccb, struct cam_periph_map_info *mapinfo)
* is all 0's, and so it is "set" all the time.
*/
if (dirs[i] & CAM_DIR_OUT) {
- flags[i] |= B_WRITE;
+ flags |= B_WRITE;
if (useracc(*data_ptrs[i], lengths[i], B_WRITE) == 0){
printf("cam_periph_mapmem: error, "
"address %p, length %lu isn't "
"user accessible for WRITE\n",
(void *)*data_ptrs[i],
(u_long)lengths[i]);
+ /*
+ * If we've already mapped one or more
+ * buffers for this CCB, unmap it (them).
+ */
+ if (i > 0)
+ cam_periph_unmapmem(ccb, mapinfo);
+ else
+ curproc->p_flag &= ~P_PHYSIO;
return(EACCES);
}
}
- }
-
- /* this keeps the current process from getting swapped */
- /*
- * XXX KDM should I use P_NOSWAP instead?
- */
- curproc->p_flag |= P_PHYSIO;
-
- for (i = 0; i < numbufs; i++) {
/*
* Get the buffer.
*/
@@ -607,11 +604,11 @@ cam_periph_mapmem(union ccb *ccb, struct cam_periph_map_info *mapinfo)
/* put our pointer in the data slot */
mapinfo->bp[i]->b_data = *data_ptrs[i];
- /* set the transfer length, we know it's < DFLTPHYS */
+ /* set the transfer length, we know it's < 64K */
mapinfo->bp[i]->b_bufsize = lengths[i];
/* set the flags */
- mapinfo->bp[i]->b_flags = flags[i] | B_PHYS | B_BUSY;
+ mapinfo->bp[i]->b_flags = flags | B_PHYS | B_BUSY;
/* map the buffer into kernel memory */
vmapbuf(mapinfo->bp[i]);