Ejemplo n.º 1
0
/**
 * ioctl() entry point from the I/O manager
 *
 */
int SEC2xIoctl(struct inode  *nd,
               struct file   *fil,
               unsigned int   code,
               unsigned long  param)
{
    int               status;
    RQ_TYPE           rqType;
    RMstatus          rmstat;
    RMexecMessage    *localMsg;
    wait_queue_head_t wq;
    wait_queue_t      wqent;
    volatile int      blockst;
    int               i;
    MALLOC_REQ       *mem;
    KBUF_MULTI       *kbm;
    PTRTYPE           memtype;


    status = SEC2_SUCCESS;

    switch (code)
    {

        /* standard request type */
        case IOCTL_PROC_REQ:
        case IOCTL_PROC_REQ_VIRTUAL:

            /* Check the param block */
            if (param == (int)NULL)
            {
                status = SEC2_INVALID_ADDRESS;
                break;
            }

            /* Figure out the memory type we have to deal with */
            /* If virtual specified, we have to figure out which type */
            if (code == IOCTL_PROC_REQ_VIRTUAL)
                if (fil == NULL)
                    memtype = PTR_KERNEL_VIRTUAL;
                else
                    memtype = PTR_USER_VIRTUAL;
            else
                memtype = PTR_LOGICAL;

            /* Allocate a request message from the "pool" */
            localMsg = getExecMsg();
            if (localMsg == NULL)
                return SEC2_INSUFFICIENT_REQS;

            /* Construct a list of descriptors from the input */
            status = constructDPDlist((GENERIC_REQ *)param, localMsg, memtype);
            if (status != SEC2_SUCCESS)
                return status;

            /* Set up completion handlers here. For a non-blocking */
            /* request like this, we have to do all releasing from */
            /* inside the handler itself, because this function    */
            /* may exit before the request completes               */
            localMsg->messageReleaseHandler = sec2xAsyncReleaseHandler;
            localMsg->releaseArgument       = localMsg;
            localMsg->buftype               = (uint8_t)memtype;

            /* Save off parameter block, process ID, signal values */
            localMsg->initialRQ             = (void *)param;
            if (fil != NULL)
            {
                localMsg->rqID                  = current->pid;
                localMsg->sigval[0]             = (int)(((GENERIC_REQ *)param)->notify);
                localMsg->sigval[1]             = (int)(((GENERIC_REQ *)param)->notify_on_error);
            }
            else
                localMsg->rqID = 0;

            /* Set the RM to processing our request */
            rmstat = xwcRMqueueRequest(ifctx, localMsg, &msgID);

            /* report error if the RM no can do... */
            if (rmstat)
            {
                printk("t23xsec2:ioctl() - error 0x%08x from RM, request not initiated\n", rmstat);
                status = SEC2_UNKNOWN_ERROR;
                releaseDPDlist(localMsg, memtype);
                freeExecMsg(localMsg);
            }

            /* Return status to the user and go home. If queueRequest()   */
            /* worked OK, now it's processing, and it's up to the release */
            /* handler to free resources and translate/report errors      */
            return status;
            break;


        /* blocking request types, should ONLY come from usermode */
        case IOCTL_PROC_REQ_BLOCK:
        case IOCTL_PROC_REQ_BLOCK_VIRTUAL:
            /* check the presence of a param block */
            if (param == (int)NULL)
            {
                status = SEC2_INVALID_ADDRESS;
                break;
            }

            if (fil == NULL) /* only valid from usermode */
            {
                status = SEC2_INVALID_REQUEST_MODE;
                break;
            }
            else
                rqType = RQ_USER_BLOCK;

            if (code == IOCTL_PROC_REQ_BLOCK_VIRTUAL)
                memtype = PTR_USER_VIRTUAL;
            else
                memtype = PTR_LOGICAL;

            /* Allocate a request message from the "pool" */
            localMsg = getExecMsg();
            if (localMsg == NULL)
                return SEC2_INSUFFICIENT_REQS;

            /* Construct a list of descriptors from the input */
            status = constructDPDlist((GENERIC_REQ *)param, localMsg, memtype);
            if (status != SEC2_SUCCESS)
                return status;

            /* Set up completion action & waitqueue entry for this request */
            blockst                         = BLOCK_RQ_PENDING;
            localMsg->messageReleaseHandler = sec2xBlockReleaseHandler;
            localMsg->releaseArgument       = (void *)&blockst;

            init_waitqueue_head(&wq);
            init_waitqueue_entry(&wqent, current);
            add_wait_queue(&wq, &wqent);
            localMsg->waitingTask = &wq;
            set_current_state(TASK_INTERRUPTIBLE);

            /* Pass constructed request off to the RM for processing */
            rmstat = xwcRMqueueRequest(ifctx, localMsg, &msgID);

            /* report error, else spin on the waitqueue */
            if (rmstat)
            {
                status = SEC2_UNKNOWN_ERROR; /* worst case error */
                if (rmstat == RM_NO_CAPABILITY)     /* maybe no such CHA? */
                    status = SEC2_INVALID_CHA_TYPE;
                set_current_state(TASK_RUNNING);
            }
            else
            {
                while(1)
                {
                    set_current_state(TASK_INTERRUPTIBLE);
                    if (blockst == BLOCK_RQ_PENDING)
                        schedule();
                    else
                        break;
                }
                set_current_state(TASK_RUNNING);
            }

            /* Release the DPD list. */
            releaseDPDlist(localMsg, memtype);

            /* If error from the waitqueue hold, return it */
            if (status)
                return status;

            /* If no error from the waitqueue hold, then check our exec */
            /* message for error registers, and translate */
            if (!status)
                status = sec2xTranslateError(localMsg);

            /* all done with this exec msg */
            freeExecMsg(localMsg);
            return status;

            break;

        case IOCTL_GET_STATUS:
            status = SEC2_UNIMPLEMENTED;
            break;

        case IOCTL_RESERVE_CHANNEL_STATIC:
#ifdef UNIMPLEMENTED
            status = ReserveChannelStatic((unsigned char *)param,
                    (int)taskIdSelf());
#endif
            status = SEC2_UNIMPLEMENTED;
            break;

        case IOCTL_RELEASE_CHANNEL:
#ifdef UNIMPLEMENTED
            status = ReleaseChannel(*(unsigned char *)param, (int)taskIdSelf(), FALSE);
#endif
            status = SEC2_UNIMPLEMENTED;
            break;


        case IOCTL_MALLOC:
            if ((((MALLOC_REQ *)param)->ptr =
                        kmalloc(((MALLOC_REQ *)param)->sz, GFP_KERNEL | GFP_DMA)) == 0)
            {
                status = SEC2_MALLOC_FAILED;
                break;
            }
            memset(((MALLOC_REQ *)param)->ptr, 0, ((MALLOC_REQ *)param)->sz);
            status = SEC2_SUCCESS;
            break;

        case IOCTL_COPYFROM:
            mem = (MALLOC_REQ *)param;
            mem->pid = current->pid;
            copy_from_user(mem->to, mem->from, mem->sz);
            status = SEC2_SUCCESS;
            break;

        case IOCTL_COPYTO:
            mem = (MALLOC_REQ *)param;
            mem->pid = current->pid;
            copy_to_user(mem->to, mem->from, mem->sz);
            status = SEC2_SUCCESS;
            break;

        case IOCTL_FREE:
            kfree((void *)param);
            break;

        case IOCTL_KBUF_MULTI_PUSH:
            kbm = (KBUF_MULTI *)param;
            for (i = 0; i < MAX_PAIRS; i++)
            {
                if ((kbm->pair[i].local != NULL) &&
                        (kbm->pair[i].kbuf != NULL) &&
                        (kbm->pair[i].size > 0))
                    copy_from_user(kbm->pair[i].kbuf,   /* destination */
                            kbm->pair[i].local,  /* source      */
                            kbm->pair[i].size);
            }
            break;

        case IOCTL_KBUF_MULTI_PULL:
            kbm = (KBUF_MULTI *)param;
            for (i = 0; i < MAX_PAIRS; i++)
            {
                if ((kbm->pair[i].local != NULL) &&
                        (kbm->pair[i].kbuf != NULL) &&
                        (kbm->pair[i].size > 0))
                    copy_to_user(kbm->pair[i].local,   /* destination */
                            kbm->pair[i].kbuf,    /* source      */
                            kbm->pair[i].size);
            }
            break;

        case IOCTL_KBUF_MULTI_ALLOC:
            kbm = (KBUF_MULTI *)param;
            for (i = 0; i < MAX_PAIRS; i++)
            {
                /* If size spec'ed nonzero, allocate buffer */
                if (kbm->pair[i].size)
                {
                    kbm->pair[i].kbuf = kmalloc(kbm->pair[i].size, GFP_KERNEL | GFP_DMA);
                    /* If allocate error, unwind any other allocs and exit */
                    if (kbm->pair[i].kbuf == NULL)
                    {
                        while (i >= 0)
                        {
                            if (kbm->pair[i].kbuf != NULL)
                                kfree(kbm->pair[i].kbuf);
                            i--;
                        }
                        status = SEC2_MALLOC_FAILED;
                        break;
                    } /* end allocation error */
                } /* end if (nonzero size) */
            }
            status = SEC2_SUCCESS;
            break;


        case IOCTL_KBUF_MULTI_FREE:
            kbm = (KBUF_MULTI *)param;
            for (i = 0; i < MAX_PAIRS; i++)
                if (kbm->pair[i].kbuf != NULL)
                    kfree(kbm->pair[i].kbuf);
            break;



        case IOCTL_INSTALL_AUX_HANDLER:
#ifdef UNIMPLEMENTED
            chan = ((AUX_HANDLER_SPEC *)param)->channel;
            /* see if requested channel is valid */
            if ((chan <= 0) || (chan > TotalChannels))
            {
                status = SEC2_INVALID_CHANNEL;
                break;
            }

            /* channel is valid, is it reserved (and not busy)? */
            if (ChannelAssignments[chan - 1].assignment != CHANNEL_STATIC_ASSIGNED)
            {
                status = SEC2_CHANNEL_NOT_AVAILABLE;
                break;
            }


            /* Channel spec is in range, and is reserved for use. Notice that */
            /* we really don't have any good means to identify the requestor  */
            /* for validity (could be the kernel itself), so will assume that */
            /* channel ownership is not an issue. Now register/remove the     */
            /* handler                                                        */

            ChannelAssignments[chan - 1].auxHandler = ((AUX_HANDLER_SPEC *)param)->auxHandler;
#endif
            status = SEC2_UNIMPLEMENTED;
            break;

    } /* switch (code) */


    return status;
}
Ejemplo n.º 2
0
int SEC2_ioctl(int devDesc, register int ioctlCode, register void *param)
#endif
{
    int status, chan;


#ifdef __KERNEL__
    MALLOC_REQ *mem;
#endif
    status = SEC2_SUCCESS;
    
    switch (ioctlCode)
    {
    case IOCTL_PROC_REQ:
        if (param == (int)NULL)
        {
            status = SEC2_INVALID_ADDRESS;
            break;
        }
        status = ProcessRequest((GENERIC_REQ *)param, (int)taskIdSelf());
        break;

    case IOCTL_GET_STATUS:
        GetStatus((STATUS_REQ *)param, (int)taskIdSelf());
        break;

    case IOCTL_RESERVE_CHANNEL_STATIC:
        status = ReserveChannelStatic((unsigned char *)param, (int)taskIdSelf());
        break;

    case IOCTL_RELEASE_CHANNEL:
        status = ReleaseChannel(*(unsigned char *)param, (int)taskIdSelf(), FALSE);
        break;


#ifdef __KERNEL__
    case IOCTL_MALLOC:
        if ((((MALLOC_REQ *)param)->ptr = malloc(((MALLOC_REQ *)param)->sz)) == 0) {
            status = SEC2_MALLOC_FAILED;
            break;
        }
        memset(((MALLOC_REQ *)param)->ptr, 0, ((MALLOC_REQ *)param)->sz);
        status = SEC2_SUCCESS;
        break;

    case IOCTL_COPYFROM:
        mem = (MALLOC_REQ *)param;
        mem->pid = current->pid;
        copy_from_user(mem->to, mem->from, mem->sz);
        status = SEC2_SUCCESS;
        break;

    case IOCTL_COPYTO:
        mem = (MALLOC_REQ *)param;
        mem->pid = current->pid;
        copy_to_user(mem->to, mem->from, mem->sz);
        status = SEC2_SUCCESS;
        break;

    case IOCTL_FREE:
        free((void *)param);
        break;
#endif

    case IOCTL_INSTALL_AUX_HANDLER:
        chan = ((AUX_HANDLER_SPEC *)param)->channel;
#ifdef DBG
        SEC2Dump(DBGTXT_SETRQ,
                 ("installAuxHandler(): requsted handler 0x%08x on channel %d\n",
                  (unsigned long)(((AUX_HANDLER_SPEC *)param)->auxHandler),
                  chan));
#endif
        /* see if requested channel is valid */
        if ((chan <= 0) || (chan > NUM_CHANNELS))
        {
            status = SEC2_INVALID_CHANNEL;
            break;
        }
        
        /* channel is valid, is it reserved (and not busy)? */
        if (ChannelAssignments[chan - 1].assignment != CHANNEL_STATIC_ASSIGNED)
        {
            status = SEC2_CHANNEL_NOT_AVAILABLE;
            break;
        }


        /* Channel spec is in range, and is reserved for use. Notice that */
        /* we really don't have any good means to identify the requestor  */
        /* for validity (could be the kernel itself), so will assume that */
        /* channel ownership is not an issue. Now register/remove the     */
        /* handler                                                        */
        
        ChannelAssignments[chan - 1].auxHandler = ((AUX_HANDLER_SPEC *)param)->auxHandler;

        break;



    default:
        /* invalide IOCTL code, return an error */
        /* need OS-specific error value here */
        return (S_ioLib_UNKNOWN_REQUEST);
    } /* end switch (ioctlCode) */

    return (status);
}