Date: Wed, 4 Apr 2007 13:26:33 GMT From: Roman Divacky <rdivacky@FreeBSD.org> To: Perforce Change Reviews <perforce@FreeBSD.org> Subject: PERFORCE change 117345 for review Message-ID: <200704041326.l34DQXaT051315@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=117345 Change 117345 by rdivacky@rdivacky_witten on 2007/04/04 13:25:44 Stubs for linux sg support. More to come. Obtained from: netbsd Affected files ... .. //depot/projects/linuxolator/src/sys/compat/linux/linux_ioctl.c#2 edit .. //depot/projects/linuxolator/src/sys/compat/linux/linux_ioctl.h#2 edit .. //depot/projects/linuxolator/src/sys/modules/linux/Makefile#6 edit Differences ... ==== //depot/projects/linuxolator/src/sys/compat/linux/linux_ioctl.c#2 (text+ko) ==== @@ -59,6 +59,14 @@ #include <net/if.h> #include <net/if_dl.h> #include <net/if_types.h> + +/* for sg device */ +#include <cam/cam.h> +#include <cam/cam_ccb.h> +#include <cam/cam_sim.h> +#include <cam/cam_xpt_sim.h> +#include <cam/cam_debug.h> +#include <cam/scsi/scsi_all.h> #include "opt_compat.h" @@ -87,6 +95,7 @@ static linux_ioctl_function_t linux_ioctl_private; static linux_ioctl_function_t linux_ioctl_drm; static linux_ioctl_function_t linux_ioctl_special; +static linux_ioctl_function_t linux_ioctl_sg; static struct linux_ioctl_handler cdrom_handler = { linux_ioctl_cdrom, LINUX_IOCTL_CDROM_MIN, LINUX_IOCTL_CDROM_MAX }; @@ -108,6 +117,8 @@ { linux_ioctl_private, LINUX_IOCTL_PRIVATE_MIN, LINUX_IOCTL_PRIVATE_MAX }; static struct linux_ioctl_handler drm_handler = { linux_ioctl_drm, LINUX_IOCTL_DRM_MIN, LINUX_IOCTL_DRM_MAX }; +static struct linux_ioctl_handler sg_handler = +{ linux_ioctl_sg, LINUX_IOCTL_SG_MIN, LINUX_IOCTL_SG_MAX }; DATA_SET(linux_ioctl_handler_set, cdrom_handler); DATA_SET(linux_ioctl_handler_set, vfat_handler); @@ -119,6 +130,7 @@ DATA_SET(linux_ioctl_handler_set, termio_handler); DATA_SET(linux_ioctl_handler_set, private_handler); DATA_SET(linux_ioctl_handler_set, drm_handler); +DATA_SET(linux_ioctl_handler_set, sg_handler); struct handler_element { @@ -2550,6 +2562,254 @@ return (error); } +int linux_sg_version = 30125; + +#ifdef LINUX_SG_DEBUG +#define DPRINTF(a) do { \ + if (ldebug(ioctl)) \ + printf(a); \ +} while (0) +#else +#define DPRINTF(a) +#endif + +#ifdef LINUX_SG_DEBUG +static void dump_sg_io(struct linux_sg_io_hdr *); +static void dump_scsireq(struct scsireq *); +#endif + +//static int bsd_to_linux_host_status(int); +//static int bsd_to_linux_driver_status(int); + +/* + * Sg ioctl handler + */ +static int +linux_ioctl_sg(struct thread *td, struct linux_ioctl_args *args) +{ + struct file *fp; + u_long com = args->cmd; + int error = 0; + //struct linux_sg_io_hdr lreq; + //union ccb req; + + if ((error = fget(td, args->fd, &fp)) != 0) + return (error); + + td->td_retval[0] = 0; + DPRINTF(("Command = %lx\n", com)); + switch (com) { + case LINUX_SG_GET_VERSION_NUM: + error = copyout(&version, (void *)args->arg, sizeof(linux_sg_version)); + break; +#if 0 + case LINUX_SG_IO: + error = copyin((void *)args->arg, &lreq, sizeof(lreq)); + if (error) { + DPRINTF(("failed to copy in request data %d\n", error)); + break; + } + +#ifdef LINUX_SG_DEBUG + dump_sg_io(&lreq); +#endif + (void)memset(&req, 0, sizeof(req)); + switch (lreq.dxfer_direction) { + case SG_DXFER_TO_DEV: + req.flags = SCCMD_WRITE; + break; + case SG_DXFER_FROM_DEV: + req.flags = SCCMD_READ; + break; + default: + DPRINTF(("unknown direction %d\n", + lreq.dxfer_direction)); + error = EINVAL; + goto done; + } + if (lreq.iovec_count != 0) { + /* XXX: Not yet */ + error = EOPNOTSUPP; + DPRINTF(("scatter/gather not supported\n")); + break; + } + + if (lreq.cmd_len > sizeof(req.cmd)) { + DPRINTF(("invalid command length %d\n", lreq.cmd_len)); + error = EINVAL; + break; + } + + error = copyin(lreq.cmdp, req.cmd, lreq.cmd_len); + if (error) { + DPRINTF(("failed to copy in cmd data %d\n", error)); + break; + } + + req.timeout = lreq.timeout; + req.cmdlen = lreq.cmd_len; + req.datalen = lreq.dxfer_len; + req.databuf = lreq.dxferp; + + error = fo_ioctl(fp, CAMIOCOMMAND, (void *)&req, td->td_ucred, td); + if (error) { + DPRINTF(("SCIOCCOMMAND failed %d\n", error)); + break; + } +#ifdef LINUX_SG_DEBUG + dump_scsireq(&req); +#endif + if (req.senselen_used) { + if (req.senselen > lreq.mx_sb_len) + req.senselen = lreq.mx_sb_len; + lreq.sb_len_wr = req.senselen; + error = copyout(req.sense, lreq.sbp, req.senselen); + if (error) { + DPRINTF(("sense copyout failed %d\n", error)); + break; + } + } else { + lreq.sb_len_wr = 0; + } + + lreq.status = req.status; + lreq.masked_status = 0; /* XXX */ + lreq.host_status = bsd_to_linux_host_status(req.retsts); + lreq.sb_len_wr = req.datalen_used; + lreq.driver_status = bsd_to_linux_driver_status(req.error); + lreq.resid = req.datalen - req.datalen_used; + lreq.duration = req.timeout; /* XXX */ + lreq.info = 0; /* XXX */ + error = copyout(&lreq, args->data, sizeof(lreq)); + if (error) { + DPRINTF(("failed to copy out req data %d\n", error)); + } + break; +#endif + case LINUX_SG_EMULATED_HOST: + case LINUX_SG_SET_TRANSFORM: + case LINUX_SG_GET_TRANSFORM: + case LINUX_SG_GET_NUM_WAITING: + case LINUX_SG_SCSI_RESET: + case LINUX_SG_GET_REQUEST_TABLE: + case LINUX_SG_SET_KEEP_ORPHAN: + case LINUX_SG_GET_KEEP_ORPHAN: + case LINUX_SG_GET_ACCESS_COUNT: + case LINUX_SG_SET_FORCE_LOW_DMA: + case LINUX_SG_GET_LOW_DMA: + case LINUX_SG_GET_SG_TABLESIZE: + case LINUX_SG_GET_SCSI_ID: + case LINUX_SG_SET_FORCE_PACK_ID: + case LINUX_SG_GET_PACK_ID: + case LINUX_SG_SET_RESERVED_SIZE: + case LINUX_SG_GET_RESERVED_SIZE: + error = ENODEV; + break; + + /* version 2 interfaces */ + case LINUX_SG_SET_TIMEOUT: + break; + case LINUX_SG_GET_TIMEOUT: + /* ioctl returns value..., grr. */ + td->td_retval[0] = 60; + break; + case LINUX_SG_GET_COMMAND_Q: + case LINUX_SG_SET_COMMAND_Q: + case LINUX_SG_SET_DEBUG: + case LINUX_SG_NEXT_CMD_LEN: + error = ENODEV; + break; + } + +//done: + fdrop(fp, td); + + DPRINTF(("Return=%d\n", error)); + return error; +} + +#if 0 +static int +bsd_to_linux_driver_status(int bs) +{ + switch (bs) { + default: + case XS_NOERROR: + return 0; + case XS_SENSE: + case XS_SHORTSENSE: + return LINUX_DRIVER_SENSE; + case XS_RESOURCE_SHORTAGE: + return LINUX_DRIVER_SOFT; + case XS_DRIVER_STUFFUP: + return LINUX_DRIVER_ERROR; + case XS_SELTIMEOUT: + case XS_TIMEOUT: + return LINUX_DRIVER_TIMEOUT; + case XS_BUSY: + return LINUX_DRIVER_BUSY; + case XS_RESET: + return LINUX_SUGGEST_ABORT; + case XS_REQUEUE: + return LINUX_SUGGEST_RETRY; + } +} + +static int +bsd_to_linux_host_status(int bs) +{ + switch (bs) { + case SCCMD_OK: + case SCCMD_SENSE: + return LINUX_DID_OK; + case SCCMD_TIMEOUT: + return LINUX_DID_TIME_OUT; + case SCCMD_BUSY: + return LINUX_DID_BUS_BUSY; + case SCCMD_UNKNOWN: + default: + return LINUX_DID_ERROR; + } +} +#endif + +#ifdef LINUX_SG_DEBUG +static void +dump_sg_io(struct linux_sg_io_hdr *lr) +{ + printf("linuxreq [interface_id=%x, dxfer_direction=%d, cmd_len=%d, " + "mx_sb_len=%d, iovec_count=%d, dxfer_len=%d, dxferp=%p, " + "cmdp=%p, sbp=%p, timeout=%u, flags=%d, pack_id=%d, " + "usr_ptr=%p, status=%u, masked_status=%u, sb_len_wr=%u, " + "host_status=%u, driver_status=%u, resid=%d, duration=%u, " + "info=%u]\n", + lr->interface_id, lr->dxfer_direction, lr->cmd_len, + lr->mx_sb_len, lr->iovec_count, lr->dxfer_len, lr->dxferp, + lr->cmdp, lr->sbp, lr->timeout, lr->flags, lr->pack_id, + lr->usr_ptr, lr->status, lr->masked_status, lr->sb_len_wr, + lr->host_status, lr->driver_status, lr->resid, lr->duration, + lr->info); +} + +static void +dump_scsireq(struct scsireq *br) +{ + int i; + printf("bsdreq [flags=%lx, timeout=%lu, cmd=[ ", + br->flags, br->timeout); + for (i = 0; i < sizeof(br->cmd) / sizeof(br->cmd[0]); i++) + printf("%.2u ", br->cmd[i]); + printf("], cmdlen=%u, databuf=%p, datalen=%lu, datalen_used=%lu, " + "sense=[ ", + br->cmdlen, br->databuf, br->datalen, br->datalen_used); + for (i = 0; i < sizeof(br->sense) / sizeof(br->sense[0]); i++) + printf("%.2u ", br->sense[i]); + printf("], senselen=%u, senselen_used=%u, status=%u, retsts=%u, " + "error=%d]\n", + br->senselen, br->senselen_used, br->status, br->retsts, br->error); +} +#endif + /* * main ioctl syscall function */ ==== //depot/projects/linuxolator/src/sys/compat/linux/linux_ioctl.h#2 (text+ko) ==== @@ -51,6 +51,111 @@ #define LINUX_IOCTL_DISK_MAX LINUX_BLKSSZGET /* + * sg + */ +#define LINUX_SG_SET_TIMEOUT 0x2201 +#define LINUX_SG_GET_TIMEOUT 0x2202 +#define LINUX_SG_EMULATED_HOST 0x2203 +#define LINUX_SG_SET_TRANSFORM 0x2204 +#define LINUX_SG_GET_TRANSFORM 0x2205 +#define LINUX_SG_GET_COMMAND_Q 0x2270 +#define LINUX_SG_SET_COMMAND_Q 0x2271 +#define LINUX_SG_SET_RESERVED_SIZE 0x2275 +#define LINUX_SG_GET_RESERVED_SIZE 0x2272 +#define LINUX_SG_GET_SCSI_ID 0x2276 +#define LINUX_SG_SET_FORCE_LOW_DMA 0x2279 +#define LINUX_SG_GET_LOW_DMA 0x227a +#define LINUX_SG_SET_FORCE_PACK_ID 0x227b +#define LINUX_SG_GET_PACK_ID 0x227c +#define LINUX_SG_GET_NUM_WAITING 0x227d +#define LINUX_SG_SET_DEBUG 0x227e +#define LINUX_SG_GET_SG_TABLESIZE 0x227f +#define LINUX_SG_GET_VERSION_NUM 0x2282 +#define LINUX_SG_NEXT_CMD_LEN 0x2283 +#define LINUX_SG_SCSI_RESET 0x2284 +#define LINUX_SG_IO 0x2285 +#define LINUX_SG_GET_REQUEST_TABLE 0x2286 +#define LINUX_SG_SET_KEEP_ORPHAN 0x2287 +#define LINUX_SG_GET_KEEP_ORPHAN 0x2288 +#define LINUX_SG_GET_ACCESS_COUNT 0x2289 + +#define LINUX_IOCTL_SG_MIN LINUX_SG_GET_TIMEOUT +#define LINUX_IOCTL_SG_MAX LINUX_SG_GET_ACCESS_COUNT + +struct linux_sg_io_hdr { + int interface_id; +#define SG_DXFER_NONE -1 +#define SG_DXFER_TO_DEV -2 +#define SG_DXFER_FROM_DEV -3 +#define SG_DXFER_TO_FROM_DEV -4 +#define SG_DXFER_UNKNOWN -5 + int dxfer_direction; + unsigned char cmd_len; + unsigned char mx_sb_len; + unsigned short iovec_count; + unsigned int dxfer_len; + void *dxferp; + unsigned char *cmdp; + unsigned char *sbp; + unsigned int timeout; + unsigned int flags; + int pack_id; + void *usr_ptr; + unsigned char status; + unsigned char masked_status; + unsigned char msg_status; + unsigned char sb_len_wr; + unsigned short host_status; + unsigned short driver_status; + int resid; + unsigned int duration; + unsigned int info; +}; + +#define SG_MAX_SENSE 16 + +/* + * Host codes + */ +#define LINUX_DID_OK 0x00 /* OK */ +#define LINUX_DID_NO_CONNECT 0x01 /* timeout during connect */ +#define LINUX_DID_BUS_BUSY 0x02 /* timeout during command */ +#define LINUX_DID_TIME_OUT 0x03 /* other timeout */ +#define LINUX_DID_BAD_TARGET 0x04 /* bad target */ +#define LINUX_DID_ABORT 0x05 /* abort */ +#define LINUX_DID_PARITY 0x06 /* parity error */ +#define LINUX_DID_ERROR 0x07 /* internal error */ +#define LINUX_DID_RESET 0x08 /* reset by somebody */ +#define LINUX_DID_BAD_INTR 0x09 /* unexpected interrupt */ +#define LINUX_DID_PASSTHROUGH 0x0a /* passthrough */ +#define LINUX_DID_SOFT_ERROR 0x0b /* low driver wants retry */ +#define LINUX_DID_IMM_RETRY 0x0c /* retry without decreasing retrycnt */ + +/* + * Driver codes + */ +#define LINUX_DRIVER_BUSY 0x01 +#define LINUX_DRIVER_SOFT 0x02 +#define LINUX_DRIVER_MEDIA 0x03 +#define LINUX_DRIVER_ERROR 0x04 + +#define LINUX_DRIVER_INVALID 0x05 +#define LINUX_DRIVER_TIMEOUT 0x06 +#define LINUX_DRIVER_HARD 0x07 +#define LINUX_DRIVER_SENSE 0x08 + +#define LINUX_SUGGEST_RETRY 0x10 +#define LINUX_SUGGEST_ABORT 0x20 +#define LINUX_SUGGEST_REMAP 0x30 +#define LINUX_SUGGEST_DIE 0x40 +#define LINUX_SUGGEST_SENSE 0x80 +#define LINUX_SUGGEST_IS_OK 0xff + +#define LINUX_DRIVER_MASK 0x0f +#define LINUX_SUGGEST_MASK 0xf0 + + +/* * hdio */ #define LINUX_HDIO_GET_GEO 0x0301 ==== //depot/projects/linuxolator/src/sys/modules/linux/Makefile#6 (text+ko) ==== @@ -14,7 +14,7 @@ linux_socket.c linux_stats.c linux_sysctl.c linux${SFX}_sysent.c \ linux${SFX}_sysvec.c linux_uid16.c linux_util.c linux_time.c \ opt_inet6.h opt_mac.h opt_compat.h opt_posix.h vnode_if.h \ - device_if.h bus_if.h + device_if.h bus_if.h opt_cam.h OBJS= linux${SFX}_locore.o .if ${MACHINE_ARCH} == "i386"
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200704041326.l34DQXaT051315>