int SEC2Close(struct inode *nd, struct file *fil) #endif { int channel; QUEUE_ENTRY *QueueEntry; int callingTaskId = (int)taskIdSelf(); #ifdef DBG SEC2Dump(DBGTXT_SETRQ, ("SEC2Close() called\n")); #endif QueueEntry = ProcessQueueTop; while (QueueEntry->pReq != NULL) { if (QueueEntry->requestingTaskId == callingTaskId) { ((GENERIC_REQ*)QueueEntry->pReq)->status = SEC2_CANCELLED_REQUEST; QueueEntry->pReq = NULL; } QueueEntry = QueueEntry->next; } IOLockChannelAssignment(); /* release any leftover reserved channels associated with this descriptor */ for (channel=0; channel<NUM_CHANNELS; channel++) if (ChannelAssignments[channel].ownerTaskId == callingTaskId) /* release this channel */ ReleaseChannel(channel+1, callingTaskId, TRUE); IOUnLockChannelAssignment(); ScheduleNext(); #ifdef __KERNEL__ MOD_DEC_USE_COUNT; #endif return SEC2_SUCCESS; }
/** * 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; }
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); }