Index: cam/cam_ccb.h =================================================================== RCS file: /dump/FreeBSD-CVS/src/sys/cam/cam_ccb.h,v retrieving revision 1.28 diff -u -r1.28 cam_ccb.h --- cam/cam_ccb.h 5 Jan 2005 22:34:34 -0000 1.28 +++ cam/cam_ccb.h 30 Nov 2005 01:49:25 -0000 @@ -44,6 +44,17 @@ #include +#ifdef _KERNEL +#define _CAM_XCCB_HDR xccb_hdr +#define _CAM_XCCB xccb +#define _CAM_XCCB_SIZE (sizeof(union ccb) - sizeof(struct ccb_hdr) + \ + sizeof(struct xccb_hdr)) +#else +#define _CAM_XCCB_HDR ccb_hdr +#define _CAM_XCCB ccb +#define _CAM_XCCB_SIZE (sizeof(union ccb)) +#endif + /* General allocation length definitions for CCB structures */ #define IOCDBLEN CAM_MAX_CDBLEN /* Space for CDB bytes/pointer */ #define VUHBALEN 14 /* Vendor Unique HBA length */ @@ -235,6 +246,7 @@ #define XPORT_VERSION_UNSPECIFIED UINT_MAX #endif /* CAM_NEW_TRAN_CODE */ +#ifdef _KERNEL typedef union { LIST_ENTRY(ccb_hdr) le; SLIST_ENTRY(ccb_hdr) sle; @@ -277,8 +289,26 @@ ccb_ppriv_area periph_priv; ccb_spriv_area sim_priv; u_int32_t timeout; /* Timeout value */ - struct callout_handle timeout_ch; - /* Callout handle used for timeouts */ + struct callout timeout_ch; /* Callout handle used for timeouts */ +}; +#endif + +/* External version of struct ccb_hdr. */ +struct _CAM_XCCB_HDR { + cam_pinfo pinfo; /* Info for priority scheduling */ + void *spare1[6]; /* compatibility with old ccb_hdr */ + u_int32_t retry_count; + void *spare2; /* compatibility with old ccb_hdr */ + xpt_opcode func_code; /* XPT function code */ + u_int32_t status; /* Status returned by CAM subsystem */ + struct cam_path *path; /* Compiled path for this ccb */ + path_id_t path_id; /* Path ID for the request */ + target_id_t target_id; /* Target device ID */ + lun_id_t target_lun; /* Target LUN number */ + u_int32_t flags; /* ccb_flags */ + void *spare3[4]; /* compatibility with old ccb_hdr */ + u_int32_t timeout; /* Timeout value */ + void *spare4; /* compatibility with old ccb_hdr */ }; /* Get Device Information CCB */ @@ -923,6 +953,14 @@ struct ccb_debug cdbg; }; +#ifdef _KERNEL +/* Convenience union for kernel manipulation of external xccbs. */ +union xccb { + struct xccb_hdr xccb_h; + char bytes[_CAM_XCCB_SIZE]; +}; +#endif + __BEGIN_DECLS static __inline void cam_fill_csio(struct ccb_scsiio *csio, u_int32_t retries, Index: cam/cam_sim.c =================================================================== RCS file: /dump/FreeBSD-CVS/src/sys/cam/cam_sim.c,v retrieving revision 1.9 diff -u -r1.9 cam_sim.c --- cam/cam_sim.c 1 Jul 2005 15:21:29 -0000 1.9 +++ cam/cam_sim.c 27 Nov 2005 11:54:17 -0000 @@ -87,7 +87,7 @@ sim->max_tagged_dev_openings = max_tagged_dev_transactions; sim->max_dev_openings = max_dev_transactions; sim->flags = 0; - callout_handle_init(&sim->c_handle); + callout_init(&sim->c_handle, 0); sim->devq = queue; } Index: cam/cam_sim.h =================================================================== RCS file: /dump/FreeBSD-CVS/src/sys/cam/cam_sim.h,v retrieving revision 1.6 diff -u -r1.6 cam_sim.h --- cam/cam_sim.h 5 Jan 2005 22:34:34 -0000 1.6 +++ cam/cam_sim.h 27 Nov 2005 11:53:49 -0000 @@ -97,7 +97,7 @@ int max_dev_openings; u_int32_t flags; #define CAM_SIM_REL_TIMEOUT_PENDING 0x01 - struct callout_handle c_handle; + struct callout c_handle; struct cam_devq *devq; /* Device Queue to use for this SIM */ }; Index: cam/cam_xpt.c =================================================================== RCS file: /dump/FreeBSD-CVS/src/sys/cam/cam_xpt.c,v retrieving revision 1.155 diff -u -r1.155 cam_xpt.c --- cam/cam_xpt.c 1 Jul 2005 15:21:29 -0000 1.155 +++ cam/cam_xpt.c 2 Jan 2006 04:47:34 -0000 @@ -155,7 +155,7 @@ #define CAM_TAG_DELAY_COUNT 5 u_int32_t tag_saved_openings; u_int32_t refcount; - struct callout_handle c_handle; + struct callout c_handle; }; /* @@ -742,7 +742,6 @@ static void xpt_run_dev_allocq(struct cam_eb *bus); static void xpt_run_dev_sendq(struct cam_eb *bus); static timeout_t xpt_release_devq_timeout; -static timeout_t xpt_release_simq_timeout; static void xpt_release_bus(struct cam_eb *bus); static void xpt_release_devq_device(struct cam_ed *dev, u_int count, int run_queue); @@ -1041,15 +1040,15 @@ */ case CAMIOCOMMAND: { union ccb *ccb; - union ccb *inccb; + union xccb *inccb; - inccb = (union ccb *)addr; + inccb = (union xccb *)addr; - switch(inccb->ccb_h.func_code) { + switch(inccb->xccb_h.func_code) { case XPT_SCAN_BUS: case XPT_RESET_BUS: - if ((inccb->ccb_h.target_id != CAM_TARGET_WILDCARD) - || (inccb->ccb_h.target_lun != CAM_LUN_WILDCARD)) { + if ((inccb->xccb_h.target_id != CAM_TARGET_WILDCARD) + || (inccb->xccb_h.target_lun != CAM_LUN_WILDCARD)) { error = EINVAL; break; } @@ -1065,9 +1064,9 @@ * user passed in. */ if (xpt_create_path(&ccb->ccb_h.path, xpt_periph, - inccb->ccb_h.path_id, - inccb->ccb_h.target_id, - inccb->ccb_h.target_lun) != + inccb->xccb_h.path_id, + inccb->xccb_h.target_id, + inccb->xccb_h.target_lun) != CAM_REQ_CMP){ error = EINVAL; xpt_free_ccb(ccb); @@ -1075,11 +1074,11 @@ } /* Ensure all of our fields are correct */ xpt_setup_ccb(&ccb->ccb_h, ccb->ccb_h.path, - inccb->ccb_h.pinfo.priority); - xpt_merge_ccb(ccb, inccb); + inccb->xccb_h.pinfo.priority); + xpt_xccb_to_ccb(inccb, ccb); ccb->ccb_h.cbfcnp = xptdone; cam_periph_runccb(ccb, NULL, 0, 0, NULL); - bcopy(ccb, inccb, sizeof(union ccb)); + xpt_ccb_to_xccb(ccb, inccb); xpt_free_path(ccb->ccb_h.path); xpt_free_ccb(ccb); break; @@ -1097,50 +1096,46 @@ * user passed in. */ if (xpt_create_path(&ccb.ccb_h.path, xpt_periph, - inccb->ccb_h.path_id, - inccb->ccb_h.target_id, - inccb->ccb_h.target_lun) != + inccb->xccb_h.path_id, + inccb->xccb_h.target_id, + inccb->xccb_h.target_lun) != CAM_REQ_CMP){ error = EINVAL; break; } /* Ensure all of our fields are correct */ xpt_setup_ccb(&ccb.ccb_h, ccb.ccb_h.path, - inccb->ccb_h.pinfo.priority); - xpt_merge_ccb(&ccb, inccb); + inccb->xccb_h.pinfo.priority); + xpt_xccb_to_ccb(inccb, &ccb); ccb.ccb_h.cbfcnp = xptdone; xpt_action(&ccb); - bcopy(&ccb, inccb, sizeof(union ccb)); + xpt_ccb_to_xccb(&ccb, inccb); xpt_free_path(ccb.ccb_h.path); break; } case XPT_DEV_MATCH: { + union ccb ccb; struct cam_periph_map_info mapinfo; - struct cam_path *old_path; /* * We can't deal with physical addresses for this * type of transaction. */ - if (inccb->ccb_h.flags & CAM_DATA_PHYS) { + if (inccb->xccb_h.flags & CAM_DATA_PHYS) { error = EINVAL; break; } /* - * Save this in case the caller had it set to - * something in particular. - */ - old_path = inccb->ccb_h.path; - - /* * We really don't need a path for the matching * code. The path is needed because of the * debugging statements in xpt_action(). They * assume that the CCB has a valid path. */ - inccb->ccb_h.path = xpt_periph->path; + xpt_setup_ccb(&ccb.ccb_h, xpt_periph->path, + inccb->xccb_h.pinfo.priority); + xpt_xccb_to_ccb(inccb, &ccb); bzero(&mapinfo, sizeof(mapinfo)); @@ -1148,24 +1143,21 @@ * Map the pattern and match buffers into kernel * virtual address space. */ - error = cam_periph_mapmem(inccb, &mapinfo); + error = cam_periph_mapmem(&ccb, &mapinfo); - if (error) { - inccb->ccb_h.path = old_path; + if (error) break; - } /* * This is an immediate CCB, we can send it on directly. */ - xpt_action(inccb); + xpt_action(&ccb); /* * Map the buffers back into user space. */ - cam_periph_unmapmem(inccb, &mapinfo); - - inccb->ccb_h.path = old_path; + cam_periph_unmapmem(&ccb, &mapinfo); + xpt_ccb_to_xccb(&ccb, inccb); error = 0; break; @@ -1191,7 +1183,8 @@ * */ case CAMGETPASSTHRU: { - union ccb *ccb; + union ccb ccb; + union xccb *xccb; struct cam_periph *periph; struct periph_driver **p_drv; char *name; @@ -1201,9 +1194,10 @@ int splbreaknum; int s; - ccb = (union ccb *)addr; - unit = ccb->cgdl.unit_number; - name = ccb->cgdl.periph_name; + xccb = (union xccb *)addr; + xpt_xccb_to_ccb(xccb, &ccb); + unit = ccb.cgdl.unit_number; + name = ccb.cgdl.periph_name; /* * Every 100 devices, we want to drop our spl protection to * give the software interrupt handler a chance to run. @@ -1213,15 +1207,13 @@ */ splbreaknum = 100; - ccb = (union ccb *)addr; - base_periph_found = 0; /* * Sanity check -- make sure we don't get a null peripheral * driver name. */ - if (*ccb->cgdl.periph_name == '\0') { + if (*ccb.cgdl.periph_name == '\0') { error = EINVAL; break; } @@ -1238,10 +1230,11 @@ if (*p_drv == NULL) { splx(s); - ccb->ccb_h.status = CAM_REQ_CMP_ERR; - ccb->cgdl.status = CAM_GDEVLIST_ERROR; - *ccb->cgdl.periph_name = '\0'; - ccb->cgdl.unit_number = 0; + ccb.ccb_h.status = CAM_REQ_CMP_ERR; + ccb.cgdl.status = CAM_GDEVLIST_ERROR; + *ccb.cgdl.periph_name = '\0'; + ccb.cgdl.unit_number = 0; + xpt_ccb_to_xccb(&ccb, xccb); error = ENOENT; break; } @@ -1288,30 +1281,30 @@ /* * Fill in the getdevlist fields. */ - strcpy(ccb->cgdl.periph_name, + strcpy(ccb.cgdl.periph_name, periph->periph_name); - ccb->cgdl.unit_number = + ccb.cgdl.unit_number = periph->unit_number; if (SLIST_NEXT(periph, periph_links)) - ccb->cgdl.status = + ccb.cgdl.status = CAM_GDEVLIST_MORE_DEVS; else - ccb->cgdl.status = + ccb.cgdl.status = CAM_GDEVLIST_LAST_DEVICE; - ccb->cgdl.generation = + ccb.cgdl.generation = device->generation; - ccb->cgdl.index = i; + ccb.cgdl.index = i; /* * Fill in some CCB header fields * that the user may want. */ - ccb->ccb_h.path_id = + ccb.ccb_h.path_id = periph->path->bus->path_id; - ccb->ccb_h.target_id = + ccb.ccb_h.target_id = periph->path->target->target_id; - ccb->ccb_h.target_lun = + ccb.ccb_h.target_lun = periph->path->device->lun_id; - ccb->ccb_h.status = CAM_REQ_CMP; + ccb.ccb_h.status = CAM_REQ_CMP; break; } } @@ -1330,10 +1323,10 @@ * we return ENOENT, since we couldn't find something. */ if (periph == NULL) { - ccb->ccb_h.status = CAM_REQ_CMP_ERR; - ccb->cgdl.status = CAM_GDEVLIST_ERROR; - *ccb->cgdl.periph_name = '\0'; - ccb->cgdl.unit_number = 0; + ccb.ccb_h.status = CAM_REQ_CMP_ERR; + ccb.cgdl.status = CAM_GDEVLIST_ERROR; + *ccb.cgdl.periph_name = '\0'; + ccb.cgdl.unit_number = 0; error = ENOENT; /* * It is unfortunate that this is even necessary, @@ -1349,6 +1342,7 @@ "your kernel config file\n"); } } + xpt_ccb_to_xccb(&ccb, xccb); splx(s); break; } @@ -3484,17 +3478,15 @@ * is sufficient for releasing the queue. */ start_ccb->ccb_h.flags &= ~CAM_DEV_QFREEZE; - untimeout(xpt_release_devq_timeout, - dev, dev->c_handle); + callout_stop(&dev->c_handle); } else { start_ccb->ccb_h.flags |= CAM_DEV_QFREEZE; } - dev->c_handle = - timeout(xpt_release_devq_timeout, - dev, - (crs->release_timeout * hz) / 1000); + callout_reset(&dev->c_handle, + (crs->release_timeout * hz) / 1000, + xpt_release_devq_timeout, dev); dev->flags |= CAM_DEV_REL_TIMEOUT_PENDING; @@ -3963,24 +3955,42 @@ } /* - * This function merges stuff from the slave ccb into the master ccb, while - * keeping important fields in the master ccb constant. + * Convert a user xccb to a kernel ccb, preserving kernel-specific + * fields in the destination ccb. */ void -xpt_merge_ccb(union ccb *master_ccb, union ccb *slave_ccb) +xpt_xccb_to_ccb(union xccb *xccb, union ccb *ccb) { GIANT_REQUIRED; /* * Pull fields that are valid for peripheral drivers to set - * into the master CCB along with the CCB "payload". + * into the kernel CCB along with the CCB "payload". */ - master_ccb->ccb_h.retry_count = slave_ccb->ccb_h.retry_count; - master_ccb->ccb_h.func_code = slave_ccb->ccb_h.func_code; - master_ccb->ccb_h.timeout = slave_ccb->ccb_h.timeout; - master_ccb->ccb_h.flags = slave_ccb->ccb_h.flags; - bcopy(&(&slave_ccb->ccb_h)[1], &(&master_ccb->ccb_h)[1], - sizeof(union ccb) - sizeof(struct ccb_hdr)); + ccb->ccb_h.retry_count = xccb->xccb_h.retry_count; + ccb->ccb_h.func_code = xccb->xccb_h.func_code; + ccb->ccb_h.timeout = xccb->xccb_h.timeout; + ccb->ccb_h.flags = xccb->xccb_h.flags; + bcopy(&(&xccb->xccb_h)[1], &(&ccb->ccb_h)[1], sizeof(union ccb) - + sizeof(struct ccb_hdr)); +} + +/* + * Convert a kernel ccb back to a user xccb. + */ +void +xpt_ccb_to_xccb(union ccb *ccb, union xccb *xccb) +{ + GIANT_REQUIRED; + + xccb->xccb_h.pinfo = ccb->ccb_h.pinfo; + xccb->xccb_h.retry_count = ccb->ccb_h.retry_count; + xccb->xccb_h.func_code = ccb->ccb_h.func_code; + xccb->xccb_h.timeout = ccb->ccb_h.timeout; + xccb->xccb_h.status = ccb->ccb_h.status; + xccb->xccb_h.flags = ccb->ccb_h.flags; + bcopy(&(&ccb->ccb_h)[1], &(&xccb->xccb_h)[1], sizeof(union ccb) - + sizeof(struct ccb_hdr)); } void @@ -3989,6 +3999,7 @@ GIANT_REQUIRED; CAM_DEBUG(path, CAM_DEBUG_TRACE, ("xpt_setup_ccb\n")); + callout_init(&ccb_h->timeout_ch, 0); ccb_h->pinfo.priority = priority; ccb_h->path = path; ccb_h->path_id = path->bus->path_id; @@ -4759,8 +4770,7 @@ * to release this queue. */ if ((dev->flags & CAM_DEV_REL_TIMEOUT_PENDING) != 0) { - untimeout(xpt_release_devq_timeout, dev, - dev->c_handle); + callout_stop(&dev->c_handle); dev->flags &= ~CAM_DEV_REL_TIMEOUT_PENDING; } @@ -4804,8 +4814,7 @@ * already at 0. */ if ((sim->flags & CAM_SIM_REL_TIMEOUT_PENDING) != 0){ - untimeout(xpt_release_simq_timeout, sim, - sim->c_handle); + callout_stop(&sim->c_handle); sim->flags &= ~CAM_SIM_REL_TIMEOUT_PENDING; } bus = xpt_find_bus(sim->path_id); @@ -4824,15 +4833,6 @@ splx(s); } -static void -xpt_release_simq_timeout(void *arg) -{ - struct cam_sim *sim; - - sim = (struct cam_sim *)arg; - xpt_release_simq(sim, /* run_queue */ TRUE); -} - void xpt_done(union ccb *done_ccb) { @@ -4915,7 +4915,6 @@ splx(s); return (NULL); } - callout_handle_init(&new_ccb->ccb_h.timeout_ch); SLIST_INSERT_HEAD(&ccb_freeq, &new_ccb->ccb_h, xpt_links.sle); xpt_ccb_count++; @@ -5055,7 +5054,7 @@ device->tag_delay_count = 0; device->tag_saved_openings = 0; device->refcount = 1; - callout_handle_init(&device->c_handle); + callout_init(&device->c_handle, 0); /* * Hold a reference to our parent target so it @@ -5109,8 +5108,7 @@ panic("Removing device while still queued for ccbs"); if ((device->flags & CAM_DEV_REL_TIMEOUT_PENDING) != 0) - untimeout(xpt_release_devq_timeout, device, - device->c_handle); + callout_stop(&device->c_handle); TAILQ_REMOVE(&target->ed_entries, device,links); target->generation++; Index: cam/cam_xpt.h =================================================================== RCS file: /dump/FreeBSD-CVS/src/sys/cam/cam_xpt.h,v retrieving revision 1.5 diff -u -r1.5 cam_xpt.h --- cam/cam_xpt.h 5 Jan 2005 22:34:34 -0000 1.5 +++ cam/cam_xpt.h 4 Dec 2005 23:56:13 -0000 @@ -49,11 +49,10 @@ #ifdef _KERNEL void xpt_action(union ccb *new_ccb); +void xpt_ccb_to_xccb(union ccb *ccb, union xccb *xccb); void xpt_setup_ccb(struct ccb_hdr *ccb_h, struct cam_path *path, u_int32_t priority); -void xpt_merge_ccb(union ccb *master_ccb, - union ccb *slave_ccb); cam_status xpt_create_path(struct cam_path **new_path_ptr, struct cam_periph *perph, path_id_t path_id, @@ -69,6 +68,7 @@ lun_id_t xpt_path_lun_id(struct cam_path *path); struct cam_sim *xpt_path_sim(struct cam_path *path); struct cam_periph *xpt_path_periph(struct cam_path *path); +void xpt_xccb_to_ccb(union xccb *xccb, union ccb *ccb); void xpt_async(u_int32_t async_code, struct cam_path *path, void *async_arg); #endif /* _KERNEL */ Index: cam/scsi/scsi_pass.c =================================================================== RCS file: /dump/FreeBSD-CVS/src/sys/cam/scsi/scsi_pass.c,v retrieving revision 1.43 diff -u -r1.43 scsi_pass.c --- cam/scsi/scsi_pass.c 22 Jan 2005 07:21:25 -0000 1.43 +++ cam/scsi/scsi_pass.c 5 Dec 2005 00:31:27 -0000 @@ -94,7 +94,7 @@ static int passerror(union ccb *ccb, u_int32_t cam_flags, u_int32_t sense_flags); static int passsendccb(struct cam_periph *periph, union ccb *ccb, - union ccb *inccb); + union xccb *inccb); static struct periph_driver passdriver = { @@ -465,20 +465,20 @@ case CAMIOCOMMAND: { - union ccb *inccb; + union xccb *inccb; union ccb *ccb; int ccb_malloced; - inccb = (union ccb *)addr; + inccb = (union xccb *)addr; /* * Some CCB types, like scan bus and scan lun can only go * through the transport layer device. */ - if (inccb->ccb_h.func_code & XPT_FC_XPT_ONLY) { + if (inccb->xccb_h.func_code & XPT_FC_XPT_ONLY) { xpt_print_path(periph->path); printf("CCB function code %#x is restricted to the " - "XPT device\n", inccb->ccb_h.func_code); + "XPT device\n", inccb->xccb_h.func_code); error = ENODEV; break; } @@ -489,17 +489,17 @@ * Immediate CCBs and user-supplied CCBs should just be * malloced. */ - if ((inccb->ccb_h.func_code & XPT_FC_QUEUED) - && ((inccb->ccb_h.func_code & XPT_FC_USER_CCB) == 0)) { + if ((inccb->xccb_h.func_code & XPT_FC_QUEUED) + && ((inccb->xccb_h.func_code & XPT_FC_USER_CCB) == 0)) { ccb = cam_periph_getccb(periph, - inccb->ccb_h.pinfo.priority); + inccb->xccb_h.pinfo.priority); ccb_malloced = 0; } else { ccb = xpt_alloc_ccb(); if (ccb != NULL) xpt_setup_ccb(&ccb->ccb_h, periph->path, - inccb->ccb_h.pinfo.priority); + inccb->xccb_h.pinfo.priority); ccb_malloced = 1; } @@ -532,7 +532,7 @@ * should be the CCB that is copied in from the user. */ static int -passsendccb(struct cam_periph *periph, union ccb *ccb, union ccb *inccb) +passsendccb(struct cam_periph *periph, union ccb *ccb, union xccb *inccb) { struct pass_softc *softc; struct cam_periph_map_info mapinfo; @@ -546,7 +546,7 @@ * There are some fields in the CCB header that need to be * preserved, the rest we get from the user. */ - xpt_merge_ccb(ccb, inccb); + xpt_xccb_to_ccb(inccb, ccb); /* * There's no way for the user to have a completion @@ -603,9 +603,7 @@ if (need_unmap != 0) cam_periph_unmapmem(ccb, &mapinfo); - ccb->ccb_h.cbfcnp = NULL; - ccb->ccb_h.periph_priv = inccb->ccb_h.periph_priv; - bcopy(ccb, inccb, sizeof(union ccb)); + xpt_ccb_to_xccb(ccb, inccb); return(error); } Index: cam/scsi/scsi_pass.h =================================================================== RCS file: /dump/FreeBSD-CVS/src/sys/cam/scsi/scsi_pass.h,v retrieving revision 1.5 diff -u -r1.5 scsi_pass.h --- cam/scsi/scsi_pass.h 5 Jan 2005 22:34:34 -0000 1.5 +++ cam/scsi/scsi_pass.h 30 Nov 2005 01:50:14 -0000 @@ -36,7 +36,7 @@ * Convert to using a pointer to a ccb in the next major version. * This should allow us to avoid an extra copy of the CCB data. */ -#define CAMIOCOMMAND _IOWR(CAM_VERSION, 2, union ccb) -#define CAMGETPASSTHRU _IOWR(CAM_VERSION, 3, union ccb) +#define CAMIOCOMMAND _IOWR(CAM_VERSION, 2, union _CAM_XCCB) +#define CAMGETPASSTHRU _IOWR(CAM_VERSION, 3, union _CAM_XCCB) #endif