summaryrefslogtreecommitdiffstats
path: root/sys/dev/amr
diff options
context:
space:
mode:
authorambrisko <ambrisko@FreeBSD.org>2004-08-16 17:23:09 +0000
committerambrisko <ambrisko@FreeBSD.org>2004-08-16 17:23:09 +0000
commit0e837443e770e7f7ded55057d6b522cd361a7b8b (patch)
treee40e6934ddf76e74c88539e5522c704ec6c37f3d /sys/dev/amr
parent455e6a16528b332f31ed1e68b965ccc61bdce71d (diff)
downloadFreeBSD-src-0e837443e770e7f7ded55057d6b522cd361a7b8b.zip
FreeBSD-src-0e837443e770e7f7ded55057d6b522cd361a7b8b.tar.gz
Allow i386 binaries to do amr ioctls such as LSI's megamgr on amd64 and
ia64. PR: 63155 Submitted by: Mikhail Teterin Tested on: i386, amd64 (via 64bit Xeon system)
Diffstat (limited to 'sys/dev/amr')
-rw-r--r--sys/dev/amr/amr.c209
-rw-r--r--sys/dev/amr/amrio.h13
2 files changed, 134 insertions, 88 deletions
diff --git a/sys/dev/amr/amr.c b/sys/dev/amr/amr.c
index f1060ff..a4e0fce 100644
--- a/sys/dev/amr/amr.c
+++ b/sys/dev/amr/amr.c
@@ -398,119 +398,152 @@ static int
amr_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int32_t flag, d_thread_t *td)
{
struct amr_softc *sc = (struct amr_softc *)dev->si_drv1;
- int *arg = (int *)addr;
- struct amr_user_ioctl *au = (struct amr_user_ioctl *)addr;
+ union {
+ void *_p;
+ struct amr_user_ioctl *au;
+#ifdef AMR_IO_COMMAND32
+ struct amr_user_ioctl32 *au32;
+#endif
+ int *result;
+ } arg;
struct amr_command *ac;
struct amr_mailbox_ioctl *mbi;
struct amr_passthrough *ap;
- void *dp;
+ void *dp, *au_buffer;
+ unsigned long au_length;
+ unsigned char *au_cmd;
+ int *au_statusp, au_direction;
int error;
debug_called(1);
- error = 0;
- dp = NULL;
- ap = NULL;
- ac = NULL;
+ arg._p = (void *)addr;
+
switch(cmd) {
case AMR_IO_VERSION:
debug(1, "AMR_IO_VERSION");
- *arg = AMR_IO_VERSION_NUMBER;
+ *arg.result = AMR_IO_VERSION_NUMBER;
+ return(0);
+
+#ifdef AMR_IO_COMMAND32
+ /*
+ * Accept ioctl-s from 32-bit binaries on non-32-bit
+ * platforms, such as AMD. LSI's MEGAMGR utility is
+ * the only example known today... -mi
+ */
+ case AMR_IO_COMMAND32:
+ debug(1, "AMR_IO_COMMAND32 0x%x", arg.au32->au_cmd[0]);
+ au_cmd = arg.au32->au_cmd;
+ au_buffer = (void *)(u_int64_t)arg.au32->au_buffer;
+ au_length = arg.au32->au_length;
+ au_direction = arg.au32->au_direction;
+ au_statusp = &arg.au32->au_status;
break;
+#endif
case AMR_IO_COMMAND:
- debug(1, "AMR_IO_COMMAND 0x%x", au->au_cmd[0]);
- /* handle inbound data buffer */
- if (au->au_length != 0) {
- if ((dp = malloc(au->au_length, M_DEVBUF, M_WAITOK)) == NULL) {
- error = ENOMEM;
- break;
- }
- if ((error = copyin(au->au_buffer, dp, au->au_length)) != 0)
- break;
- debug(2, "copyin %ld bytes from %p -> %p", au->au_length, au->au_buffer, dp);
- }
+ debug(1, "AMR_IO_COMMAND 0x%x", arg.au->au_cmd[0]);
+ au_cmd = arg.au->au_cmd;
+ au_buffer = (void *)arg.au->au_buffer;
+ au_length = arg.au->au_length;
+ au_direction = arg.au->au_direction;
+ au_statusp = &arg.au->au_status;
+ break;
- if ((ac = amr_alloccmd(sc)) == NULL) {
- error = ENOMEM;
- break;
- }
+ default:
+ debug(1, "unknown ioctl 0x%lx", cmd);
+ return(ENOIOCTL);
+ }
- /* handle SCSI passthrough command */
- if (au->au_cmd[0] == AMR_CMD_PASS) {
- if ((ap = malloc(sizeof(*ap), M_DEVBUF, M_WAITOK | M_ZERO)) == NULL) {
- error = ENOMEM;
- break;
- }
+ error = 0;
+ dp = NULL;
+ ap = NULL;
+ ac = NULL;
- /* copy cdb */
- ap->ap_cdb_length = au->au_cmd[2];
- bcopy(&au->au_cmd[3], &ap->ap_cdb[0], ap->ap_cdb_length);
-
- /* build passthrough */
- ap->ap_timeout = au->au_cmd[ap->ap_cdb_length + 3] & 0x07;
- ap->ap_ars = (au->au_cmd[ap->ap_cdb_length + 3] & 0x08) ? 1 : 0;
- ap->ap_islogical = (au->au_cmd[ap->ap_cdb_length + 3] & 0x80) ? 1 : 0;
- ap->ap_logical_drive_no = au->au_cmd[ap->ap_cdb_length + 4];
- ap->ap_channel = au->au_cmd[ap->ap_cdb_length + 5];
- ap->ap_scsi_id = au->au_cmd[ap->ap_cdb_length + 6];
- ap->ap_request_sense_length = 14;
- ap->ap_data_transfer_length = au->au_length;
- /* XXX what about the request-sense area? does the caller want it? */
-
- /* build command */
- ac->ac_data = ap;
- ac->ac_length = sizeof(*ap);
- ac->ac_flags |= AMR_CMD_DATAOUT;
- ac->ac_ccb_data = dp;
- ac->ac_ccb_length = au->au_length;
- if (au->au_direction & AMR_IO_READ)
- ac->ac_flags |= AMR_CMD_CCB_DATAIN;
- if (au->au_direction & AMR_IO_WRITE)
- ac->ac_flags |= AMR_CMD_CCB_DATAOUT;
+ /* handle inbound data buffer */
+ if (au_length != 0) {
+ if ((dp = malloc(au_length, M_DEVBUF, M_WAITOK)) == NULL)
+ return(ENOMEM);
- ac->ac_mailbox.mb_command = AMR_CMD_PASS;
+ if ((error = copyin(au_buffer, dp, au_length)) != 0)
+ goto out;
+ debug(2, "copyin %ld bytes from %p -> %p", au_length, au_buffer, dp);
+ }
- } else {
- /* direct command to controller */
- mbi = (struct amr_mailbox_ioctl *)&ac->ac_mailbox;
-
- /* copy pertinent mailbox items */
- mbi->mb_command = au->au_cmd[0];
- mbi->mb_channel = au->au_cmd[1];
- mbi->mb_param = au->au_cmd[2];
- mbi->mb_pad[0] = au->au_cmd[3];
- mbi->mb_drive = au->au_cmd[4];
-
- /* build the command */
- ac->ac_data = dp;
- ac->ac_length = au->au_length;
- if (au->au_direction & AMR_IO_READ)
- ac->ac_flags |= AMR_CMD_DATAIN;
- if (au->au_direction & AMR_IO_WRITE)
- ac->ac_flags |= AMR_CMD_DATAOUT;
+ if ((ac = amr_alloccmd(sc)) == NULL) {
+ error = ENOMEM;
+ goto out;
+ }
+
+ /* handle SCSI passthrough command */
+ if (au_cmd[0] == AMR_CMD_PASS) {
+ if ((ap = malloc(sizeof(*ap), M_DEVBUF, M_WAITOK | M_ZERO)) == NULL) {
+ error = ENOMEM;
+ goto out;
}
- /* run the command */
- if ((error = amr_wait_command(ac)) != 0)
- break;
+ /* copy cdb */
+ ap->ap_cdb_length = au_cmd[2];
+ bcopy(au_cmd + 3, ap->ap_cdb, ap->ap_cdb_length);
+
+ /* build passthrough */
+ ap->ap_timeout = au_cmd[ap->ap_cdb_length + 3] & 0x07;
+ ap->ap_ars = (au_cmd[ap->ap_cdb_length + 3] & 0x08) ? 1 : 0;
+ ap->ap_islogical = (au_cmd[ap->ap_cdb_length + 3] & 0x80) ? 1 : 0;
+ ap->ap_logical_drive_no = au_cmd[ap->ap_cdb_length + 4];
+ ap->ap_channel = au_cmd[ap->ap_cdb_length + 5];
+ ap->ap_scsi_id = au_cmd[ap->ap_cdb_length + 6];
+ ap->ap_request_sense_length = 14;
+ ap->ap_data_transfer_length = au_length;
+ /* XXX what about the request-sense area? does the caller want it? */
+
+ /* build command */
+ ac->ac_data = ap;
+ ac->ac_length = sizeof(*ap);
+ ac->ac_flags |= AMR_CMD_DATAOUT;
+ ac->ac_ccb_data = dp;
+ ac->ac_ccb_length = au_length;
+ if (au_direction & AMR_IO_READ)
+ ac->ac_flags |= AMR_CMD_CCB_DATAIN;
+ if (au_direction & AMR_IO_WRITE)
+ ac->ac_flags |= AMR_CMD_CCB_DATAOUT;
- /* copy out data and set status */
- if (au->au_length != 0)
- error = copyout(dp, au->au_buffer, au->au_length);
- debug(2, "copyout %ld bytes from %p -> %p", au->au_length, dp, au->au_buffer);
- if (dp != NULL)
- debug(2, "%16d", (int)dp);
- au->au_status = ac->ac_status;
- break;
+ ac->ac_mailbox.mb_command = AMR_CMD_PASS;
- default:
- debug(1, "unknown ioctl 0x%lx", cmd);
- error = ENOIOCTL;
- break;
+ } else {
+ /* direct command to controller */
+ mbi = (struct amr_mailbox_ioctl *)&ac->ac_mailbox;
+
+ /* copy pertinent mailbox items */
+ mbi->mb_command = au_cmd[0];
+ mbi->mb_channel = au_cmd[1];
+ mbi->mb_param = au_cmd[2];
+ mbi->mb_pad[0] = au_cmd[3];
+ mbi->mb_drive = au_cmd[4];
+
+ /* build the command */
+ ac->ac_data = dp;
+ ac->ac_length = au_length;
+ if (au_direction & AMR_IO_READ)
+ ac->ac_flags |= AMR_CMD_DATAIN;
+ if (au_direction & AMR_IO_WRITE)
+ ac->ac_flags |= AMR_CMD_DATAOUT;
}
+ /* run the command */
+ if ((error = amr_wait_command(ac)) != 0)
+ goto out;
+
+ /* copy out data and set status */
+ if (au_length != 0)
+ error = copyout(dp, au_buffer, au_length);
+ debug(2, "copyout %ld bytes from %p -> %p", au_length, dp, au_buffer);
+ if (dp != NULL)
+ debug(2, "%16d", (int)dp);
+ *au_statusp = ac->ac_status;
+
+out:
if (dp != NULL)
free(dp, M_DEVBUF);
if (ap != NULL)
diff --git a/sys/dev/amr/amrio.h b/sys/dev/amr/amrio.h
index 48ec4e8..e14ade4 100644
--- a/sys/dev/amr/amrio.h
+++ b/sys/dev/amr/amrio.h
@@ -60,6 +60,7 @@
*/
#include <sys/ioccom.h>
+#include <sys/param.h>
/*
* Fetch the driver's interface version.
@@ -107,3 +108,15 @@ struct amr_user_ioctl {
#define AMR_IO_COMMAND _IOWR('A', 0x201, struct amr_user_ioctl)
+#if defined(__amd64__) || defined(__ia64__)
+
+struct amr_user_ioctl32 {
+ unsigned char au_cmd[32]; /* command text from userspace */
+ u_int32_t au_buffer; /* 32-bit pointer to uspace buf */
+ u_int32_t au_length; /* length of the uspace buffer */
+ int32_t au_direction; /* data transfer direction */
+ int32_t au_status; /* command status returned by adapter */
+};
+
+# define AMR_IO_COMMAND32 _IOWR('A', 0x201, struct amr_user_ioctl32)
+#endif
OpenPOWER on IntegriCloud