From 2d11776afc7a2a29c7c08b84caa777391a53509c Mon Sep 17 00:00:00 2001 From: emaste Date: Thu, 20 Mar 2008 17:59:19 +0000 Subject: Add ioctls FSACTL_SEND_LARGE_FIB, FSACTL_SEND_RAW_SRB, FSACTL_LNX_SEND_LARGE_FIB, and FSACTL_LNX_SEND_RAW_SRB, and correct size checks on FIBs passed in from userspace. Both changes were obtained from Adaptec's driver build 15317. Adaptec's commandline RAID tool arcconf uses these ioctls when creating a RAID-10 array (and probably other operations too). --- sys/dev/aac/aac.c | 39 +++++++++++++++++++++++++++++++-------- 1 file changed, 31 insertions(+), 8 deletions(-) (limited to 'sys/dev/aac') diff --git a/sys/dev/aac/aac.c b/sys/dev/aac/aac.c index ce84273..816c53e 100644 --- a/sys/dev/aac/aac.c +++ b/sys/dev/aac/aac.c @@ -213,6 +213,7 @@ static d_close_t aac_close; static d_ioctl_t aac_ioctl; static d_poll_t aac_poll; static int aac_ioctl_sendfib(struct aac_softc *sc, caddr_t ufib); +static int aac_ioctl_send_raw_srb(struct aac_softc *sc, caddr_t arg); static void aac_handle_aif(struct aac_softc *sc, struct aac_fib *fib); static int aac_rev_check(struct aac_softc *sc, caddr_t udata); @@ -1693,6 +1694,11 @@ aac_check_firmware(struct aac_softc *sc) sc->aac_max_fib_size = PAGE_SIZE; sc->aac_max_fibs_alloc = PAGE_SIZE / sc->aac_max_fib_size; + if (sc->aac_max_fib_size > sizeof(struct aac_fib)) { + sc->flags |= AAC_FLAGS_RAW_IO; + device_printf(sc->aac_dev, "Enable Raw I/O\n"); + } + return (0); } @@ -2887,11 +2893,19 @@ aac_ioctl(struct cdev *dev, u_long cmd, caddr_t arg, int flag, d_thread_t *td) break; case FSACTL_SENDFIB: + case FSACTL_SEND_LARGE_FIB: arg = *(caddr_t*)arg; case FSACTL_LNX_SENDFIB: + case FSACTL_LNX_SEND_LARGE_FIB: debug(1, "FSACTL_SENDFIB"); error = aac_ioctl_sendfib(sc, arg); break; + case FSACTL_SEND_RAW_SRB: + arg = *(caddr_t*)arg; + case FSACTL_LNX_SEND_RAW_SRB: + debug(1, "FSACTL_SEND_RAW_SRB"); + error = aac_ioctl_send_raw_srb(sc, arg); + break; case FSACTL_AIF_THREAD: case FSACTL_LNX_AIF_THREAD: debug(1, "FSACTL_AIF_THREAD"); @@ -3035,10 +3049,10 @@ aac_ioctl_sendfib(struct aac_softc *sc, caddr_t ufib) sizeof(struct aac_fib_header))) != 0) goto out; size = cm->cm_fib->Header.Size + sizeof(struct aac_fib_header); - if (size > sizeof(struct aac_fib)) { - device_printf(sc->aac_dev, "incoming FIB oversized (%d > %zd)\n", - size, sizeof(struct aac_fib)); - size = sizeof(struct aac_fib); + if (size > sc->aac_max_fib_size) { + device_printf(sc->aac_dev, "incoming FIB oversized (%d > %d)\n", + size, sc->aac_max_fib_size); + size = sc->aac_max_fib_size; } if ((error = copyin(ufib, cm->cm_fib, size)) != 0) goto out; @@ -3061,10 +3075,10 @@ aac_ioctl_sendfib(struct aac_softc *sc, caddr_t ufib) * Copy the FIB and data back out to the caller. */ size = cm->cm_fib->Header.Size; - if (size > sizeof(struct aac_fib)) { - device_printf(sc->aac_dev, "outbound FIB oversized (%d > %zd)\n", - size, sizeof(struct aac_fib)); - size = sizeof(struct aac_fib); + if (size > sc->aac_max_fib_size) { + device_printf(sc->aac_dev, "outbound FIB oversized (%d > %d)\n", + size, sc->aac_max_fib_size); + size = sc->aac_max_fib_size; } error = copyout(cm->cm_fib, ufib, size); @@ -3078,6 +3092,15 @@ out: } /* + * Send a passthrough FIB supplied from userspace + */ +static int +aac_ioctl_send_raw_srb(struct aac_softc *sc, caddr_t arg) +{ + return (EINVAL); +} + +/* * Handle an AIF sent to us by the controller; queue it for later reference. * If the queue fills up, then drop the older entries. */ -- cgit v1.1